add-coder 0.3.25 → 0.3.27

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.
Files changed (132) hide show
  1. package/README.md +36 -10
  2. package/dist/index.js +481 -209
  3. package/package.json +14 -4
  4. package/templates/.add-coder-src-hash.json +129 -106
  5. package/templates/adapters/claude/hooks/doc-format-guard.sh +114 -33
  6. package/templates/adapters/claude/hooks/lib/common.sh +46 -87
  7. package/templates/adapters/claude/hooks/lib/context-inject.sh +2 -2
  8. package/templates/adapters/claude/hooks/lib/notify.sh +6 -4
  9. package/templates/adapters/claude/hooks/lib/preload-templates.sh +27 -2
  10. package/templates/adapters/claude/hooks/lib/state-detect.sh +8 -112
  11. package/templates/adapters/claude/hooks/lib/vocabulary.sh +13 -7
  12. package/templates/adapters/claude/hooks/prompt-submit.sh +1 -1
  13. package/templates/adapters/claude/hooks/stop-check.sh +9 -0
  14. package/templates/adapters/codex/config.toml.example +12 -0
  15. package/templates/adapters/codex/hooks/doc-format-guard.sh +123 -41
  16. package/templates/adapters/codex/hooks/lib/common.sh +47 -99
  17. package/templates/adapters/codex/hooks/lib/context-inject.sh +4 -4
  18. package/templates/adapters/codex/hooks/lib/notify.sh +6 -4
  19. package/templates/adapters/codex/hooks/lib/preload-templates.sh +27 -6
  20. package/templates/adapters/codex/hooks/lib/state-detect.sh +5 -114
  21. package/templates/adapters/codex/hooks/lib/vocabulary.sh +3 -8
  22. package/templates/adapters/codex/hooks/notification.sh +3 -18
  23. package/templates/adapters/codex/hooks/post-tool-use.sh +24 -119
  24. package/templates/adapters/codex/hooks/pre-tool-use.sh +97 -184
  25. package/templates/adapters/codex/hooks/prompt-submit.sh +8 -3
  26. package/templates/adapters/codex/hooks/session-start.sh +19 -9
  27. package/templates/adapters/codex/hooks/stop-check.sh +44 -18
  28. package/templates/adapters/codex/hooks.json +67 -1
  29. package/templates/adapters/qoder/hooks/doc-format-guard.sh +121 -40
  30. package/templates/adapters/qoder/hooks/lib/common.sh +49 -87
  31. package/templates/adapters/qoder/hooks/lib/context-inject.sh +2 -2
  32. package/templates/adapters/qoder/hooks/lib/notify.sh +6 -4
  33. package/templates/adapters/qoder/hooks/lib/preload-templates.sh +27 -2
  34. package/templates/adapters/qoder/hooks/lib/state-detect.sh +8 -112
  35. package/templates/adapters/qoder/hooks/lib/vocabulary.sh +13 -7
  36. package/templates/adapters/qoder/hooks/prompt-submit.sh +1 -1
  37. package/templates/adapters/qoder/hooks/session-start.sh +1 -1
  38. package/templates/adapters/qoder/hooks/stop-check.sh +11 -0
  39. package/templates/adapters/trae/hooks/doc-format-guard.sh +122 -40
  40. package/templates/adapters/trae/hooks/lib/common.sh +46 -87
  41. package/templates/adapters/trae/hooks/lib/context-inject.sh +2 -2
  42. package/templates/adapters/trae/hooks/lib/notify.sh +5 -3
  43. package/templates/adapters/trae/hooks/lib/preload-templates.sh +27 -2
  44. package/templates/adapters/trae/hooks/lib/state-detect.sh +8 -115
  45. package/templates/adapters/trae/hooks/lib/vocabulary.sh +13 -7
  46. package/templates/adapters/trae/hooks/pre-tool-use.sh +14 -8
  47. package/templates/adapters/trae/hooks/stop-check.sh +9 -0
  48. package/templates/adapters/vscode/hooks/doc-format-guard.sh +114 -33
  49. package/templates/adapters/vscode/hooks/lib/common.sh +46 -87
  50. package/templates/adapters/vscode/hooks/lib/context-inject.sh +2 -2
  51. package/templates/adapters/vscode/hooks/lib/notify.sh +6 -4
  52. package/templates/adapters/vscode/hooks/lib/preload-templates.sh +27 -2
  53. package/templates/adapters/vscode/hooks/lib/state-detect.sh +8 -112
  54. package/templates/adapters/vscode/hooks/lib/vocabulary.sh +13 -7
  55. package/templates/adapters/vscode/hooks/notification.sh +3 -5
  56. package/templates/adapters/vscode/hooks/prompt-submit.sh +1 -1
  57. package/templates/adapters/vscode/hooks/stop-check.sh +9 -0
  58. package/templates/core/docs/ADD-governance-claude-code.md +1 -1
  59. package/templates/core/docs/ADD-governance-codex.md +1 -1
  60. package/templates/core/docs/ADD-governance-qoder-cn.md +1 -1
  61. package/templates/core/docs/ADD-governance-trae.md +1 -1
  62. package/templates/core/docs/ADD-governance-vscode-copilot.md +1 -1
  63. package/templates/core/hooks/doc-format-guard.sh +122 -40
  64. package/templates/core/hooks/lib/common.sh +46 -87
  65. package/templates/core/hooks/lib/context-inject.sh +2 -2
  66. package/templates/core/hooks/lib/notify.sh +5 -3
  67. package/templates/core/hooks/lib/preload-templates.sh +27 -2
  68. package/templates/core/hooks/lib/state-detect.sh +8 -115
  69. package/templates/core/hooks/lib/vocabulary.sh +13 -7
  70. package/templates/core/hooks/pre-tool-use.sh +14 -8
  71. package/templates/core/hooks/stop-check.sh +9 -0
  72. package/templates/core/prisma/add.prisma +140 -82
  73. package/templates/core/rules/project_rules.md +27 -24
  74. package/templates/core/scripts/db-ensure.sh +8 -0
  75. package/templates/core/scripts/gen-plan-index.sh +4 -15
  76. package/templates/core/scripts/mcp-server/notifications/hitl.ts +9 -1
  77. package/templates/core/scripts/mcp-server/notifications/hook.ts +25 -9
  78. package/templates/core/scripts/mcp-server/resources/hitl-approval-widget.ts +34 -0
  79. package/templates/core/scripts/mcp-server/resources/hook-events-report.ts +14 -2
  80. package/templates/core/scripts/mcp-server/resources/index.ts +2 -0
  81. package/templates/core/scripts/mcp-server/sampling/review.ts +25 -10
  82. package/templates/core/scripts/mcp-server/shared/db-types.ts +33 -8
  83. package/templates/core/scripts/mcp-server/shared/dps-scoring.strategy.ts +1 -1
  84. package/templates/core/scripts/mcp-server/shared/env.ts +28 -8
  85. package/templates/core/scripts/mcp-server/shared/fs.ts +3 -0
  86. package/templates/core/scripts/mcp-server/shared/hitl-interaction.strategy.ts +2 -3
  87. package/templates/core/scripts/mcp-server/shared/hitl-lifecycle-mutation.ts +129 -0
  88. package/templates/core/scripts/mcp-server/shared/hitl-proposal-mutation.ts +98 -0
  89. package/templates/core/scripts/mcp-server/shared/hitl-ui.ts +3 -0
  90. package/templates/core/scripts/mcp-server/shared/plan-lifecycle-events.ts +62 -0
  91. package/templates/core/scripts/mcp-server/shared/plan-lifecycle-mutation.ts +78 -0
  92. package/templates/core/scripts/mcp-server/shared/plan-lifecycle-subscriber.ts +145 -0
  93. package/templates/core/scripts/mcp-server/shared/plan-lifecycle.ts +153 -0
  94. package/templates/core/scripts/mcp-server/shared/plan-round-events.ts +56 -0
  95. package/templates/core/scripts/mcp-server/shared/plan-round-mutation.ts +143 -0
  96. package/templates/core/scripts/mcp-server/shared/plan-round-store.ts +47 -0
  97. package/templates/core/scripts/mcp-server/shared/plan-round-subscriber.ts +99 -0
  98. package/templates/core/scripts/mcp-server/shared/plan-status-store.ts +37 -0
  99. package/templates/core/scripts/mcp-server/shared/plan-tracking-mutation.ts +71 -0
  100. package/templates/core/scripts/mcp-server/shared/prisma.ts +12 -6
  101. package/templates/core/scripts/mcp-server/shared/project-root-strategy.ts +1 -2
  102. package/templates/core/scripts/mcp-server/shared/quant-recheck.strategy.ts +16 -0
  103. package/templates/core/scripts/mcp-server/shared/redact.ts +28 -0
  104. package/templates/core/scripts/mcp-server/shared/response.ts +3 -2
  105. package/templates/core/scripts/mcp-server/shared/runtime-context.ts +77 -0
  106. package/templates/core/scripts/mcp-server/shared/schema-topology.ts +159 -0
  107. package/templates/core/scripts/mcp-server/tools/audit.ts +49 -7
  108. package/templates/core/scripts/mcp-server/tools/context.ts +117 -121
  109. package/templates/core/scripts/mcp-server/tools/contract.ts +34 -9
  110. package/templates/core/scripts/mcp-server/tools/gateway/check_add_route_status.ts +50 -3
  111. package/templates/core/scripts/mcp-server/tools/gateway/check_doc_similarity.ts +218 -0
  112. package/templates/core/scripts/mcp-server/tools/gateway/check_dps.ts +22 -7
  113. package/templates/core/scripts/mcp-server/tools/gateway/check_rahs.ts +75 -4
  114. package/templates/core/scripts/mcp-server/tools/gateway/check_spec_sync.ts +19 -6
  115. package/templates/core/scripts/mcp-server/tools/gateway/index.ts +2 -0
  116. package/templates/core/scripts/mcp-server/tools/hitl.ts +160 -75
  117. package/templates/core/scripts/mcp-server/tools/hook-event-report.ts +9 -2
  118. package/templates/core/scripts/mcp-server/tools/index.ts +69 -3
  119. package/templates/core/scripts/mcp-server/tools/plan.ts +140 -15
  120. package/templates/core/scripts/mcp-server/tools/review.ts +44 -15
  121. package/templates/core/scripts/mcp-server.ts +60 -1
  122. package/templates/core/scripts/plan-status-bridge.ts +26 -0
  123. package/templates/core/skills/add-paradigm/SKILL.md +2 -2
  124. package/templates/core/templates/add-route-template.schema.json +24 -56
  125. package/templates/core/templates/collab-contract-template.md +1 -1
  126. package/templates/core/templates/handoff-multi-round-template.schema.json +48 -0
  127. package/templates/core/templates/handoff-single-round-template.schema.json +92 -0
  128. package/templates/core/templates/handoff-single-round.schema.json +1 -1
  129. package/templates/core/templates/hitl-approval-widget.html +222 -37
  130. package/templates/core/templates/spec-template.schema.json +9 -46
  131. package/templates/core/templates/standard-plan-template.schema.json +1 -1
  132. package/templates/core/templates/tasks-template.schema.json +13 -54
@@ -4,11 +4,11 @@
4
4
  # @Date : 2026-07-17 13:19:01
5
5
  # @LastEditors : xiaomingming wujixmm@gmail.com
6
6
  # @LastEditTime : 2026-07-17 13:21:29
7
- # @FilePath : /add-coder/templates/core/hooks/lib/preload-templates.sh
7
+ # @FilePath : /add-coder/templates/adapters/codex/hooks/lib/preload-templates.sh
8
8
  # @Description : ADD 模板预读脚本
9
9
  ###
10
10
  # preload-templates.sh — ADD 模板预读脚本
11
- # 路径: templates/core/hooks/lib/preload-templates.sh
11
+ # 路径: templates/adapters/codex/hooks/lib/preload-templates.sh
12
12
  #
13
13
  # 用法:
14
14
  # preload-templates.sh --index # 输出模板清单(文件名 + 用途)
@@ -16,14 +16,14 @@
16
16
  # preload-templates.sh --full --top 5 # 输出前 5 个最常用模板全文
17
17
  # preload-templates.sh --full --mark # 全文输出 + 落 tpl-injected 标记
18
18
  #
19
- # SessionStart(--index)和 UserPromptSubmit(--full)调用。
19
+ # 可由 Codex 生命周期 hook 或人工按需调用。
20
20
  # tpl-injected 标记文件用于去重——同会话二次命中时不重复注入。
21
21
 
22
22
  set -euo pipefail
23
23
 
24
- # 模板目录(相对于本脚本)
24
+ # core 标准模板在分发期物化到 `.codex/templates`;生成态只读取当前 adapter 本地副本。
25
25
  SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
26
- TEMPLATES_DIR="${SCRIPT_DIR}/../../../core/templates"
26
+ TEMPLATES_DIR="${SCRIPT_DIR}/../../templates"
27
27
 
28
28
  # tpl-injected 标记文件路径(项目级,/tmp 下按项目 hash 区分)
29
29
  PROJECT_HASH=$(echo "${PROJECT_DIR:-$PWD}" | md5sum 2>/dev/null | cut -c1-8 || echo "default")
@@ -74,6 +74,25 @@ PRIORITY_ORDER=(
74
74
  "TERMINOLOGY.md"
75
75
  )
76
76
 
77
+ validate_templates_dir() {
78
+ if [ ! -d "$TEMPLATES_DIR" ]; then
79
+ echo "[ADD preload] 模板目录不存在: $TEMPLATES_DIR" >&2
80
+ exit 1
81
+ fi
82
+
83
+ local available=0
84
+ local tmpl
85
+ for tmpl in "${PRIORITY_ORDER[@]}"; do
86
+ if [ -f "$TEMPLATES_DIR/$tmpl" ]; then
87
+ available=$((available + 1))
88
+ fi
89
+ done
90
+ if [ "$available" -eq 0 ]; then
91
+ echo "[ADD preload] 模板目录中未找到 ADD 标准模板: $TEMPLATES_DIR" >&2
92
+ exit 1
93
+ fi
94
+ }
95
+
77
96
  # 读取模板文件内容(strip frontmatter)
78
97
  read_template_content() {
79
98
  local file="$1"
@@ -99,7 +118,7 @@ output_index() {
99
118
  for tmpl in "${PRIORITY_ORDER[@]}"; do
100
119
  if [ -f "$TEMPLATES_DIR/$tmpl" ]; then
101
120
  echo "| $i | $tmpl | ${TEMPLATES[$tmpl]:-模板文件} |"
102
- ((i++))
121
+ i=$((i + 1))
103
122
  fi
104
123
  done
105
124
  }
@@ -165,6 +184,8 @@ main() {
165
184
  esac
166
185
  done
167
186
 
187
+ validate_templates_dir
188
+
168
189
  case "$mode" in
169
190
  index)
170
191
  output_index
@@ -1,117 +1,8 @@
1
1
  #!/bin/bash
2
- # state-detect.sh — ADD 活跃流程检测 + dev action 追踪
3
- # 共享库
2
+ # state-detect.sh — 兼容入口;状态裁决统一委托 common.sh,禁止维护第二套 magicDir 探测。
4
3
 
5
- PROJECT_DIR="$PWD"
6
-
7
- # 动态探测 MAGIC_DIR(兼容多 adapter,source 自 hook 脚本时继承调用者的 HOOK_DIR)
8
- if [ -z "${MAGIC_DIR:-}" ]; then
9
- if [ -n "${HOOK_DIR:-}" ]; then
10
- MAGIC_DIR="$(basename "$(dirname "$HOOK_DIR")")"
11
- else
12
- for m in ".claude" ".qoder" ".vscode" ".add"; do
13
- [ -d "$PROJECT_DIR/$m" ] && { MAGIC_DIR="$m"; break; }
14
- done
15
- MAGIC_DIR="${MAGIC_DIR:-.add}"
16
- fi
4
+ if ! type detect_active_add >/dev/null 2>&1; then
5
+ HOOK_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ # shellcheck source=common.sh
7
+ source "$HOOK_LIB_DIR/common.sh"
17
8
  fi
18
-
19
- MAGIC_PATH="$PROJECT_DIR/$MAGIC_DIR"
20
- PLANS_DIR="$MAGIC_PATH/plans"
21
-
22
- # dev action 标记文件(项目级,PreToolUse 写入,Stop 读取)
23
- DEV_FLAG="/tmp/add_dev_$(echo "$PROJECT_DIR" | md5sum 2>/dev/null | cut -c1-8 || echo "default")"
24
-
25
- # 检测活跃 ADD 流程
26
- # 返回: "plan_keyword::step_x/total::round_n/total_r::handoff_path::add_route_path" 或 ""
27
- detect_active_add() {
28
- local handoff=""
29
- local today_dir="$PLANS_DIR/$(date +%Y-%m)"
30
- [ -d "$today_dir" ] && handoff=$(find "$today_dir" -name "*handoff*.md" -mtime -7 -type f 2>/dev/null | head -1)
31
- [ -z "$handoff" ] && handoff=$(find "$PLANS_DIR" -name "*handoff*.md" -mtime -7 -type f 2>/dev/null | head -1)
32
- [ -z "$handoff" ] && return 1
33
-
34
- local plan_kw=$(basename "$handoff" | sed 's/-handoff.*//')
35
-
36
- # add-route
37
- local add_route=$(find "$PLANS_DIR" -name "*add-route*.md" -type f 2>/dev/null | head -1)
38
-
39
- # Step 统计(从 add-route)
40
- local step_info="?"
41
- if [ -f "$add_route" ]; then
42
- local ck=$(grep -c '\[x\]' "$add_route" 2>/dev/null || true)
43
- local uc=$(grep -c '\[ \]' "$add_route" 2>/dev/null || true)
44
- ck=${ck:-0}; uc=${uc:-0}
45
- local total=$((ck + uc))
46
- [ "$total" -gt 0 ] && step_info="${ck}/${total}"
47
- fi
48
-
49
- # 轮次统计(从 handoff)
50
- local round_info="?"
51
- if grep -q '<第[0-9]轮>' "$handoff" 2>/dev/null; then
52
- local ck=$(grep -c '\[x\]' "$handoff" 2>/dev/null || true); ck=${ck:-0}
53
- local total=$(grep -c '<第[0-9]轮>' "$handoff" 2>/dev/null || true); total=${total:-0}
54
- [ "$total" -gt 0 ] && round_info="${ck}/${total}"
55
- else
56
- round_info="1/1"
57
- fi
58
-
59
- echo "${plan_kw}::${step_info}::${round_info}::${handoff}::${add_route:-none}"
60
- }
61
-
62
- # 标记 dev action
63
- mark_dev_action() {
64
- touch "$DEV_FLAG" 2>/dev/null || true
65
- }
66
-
67
- # 检测 dev action
68
- has_dev_action() {
69
- [ -f "$DEV_FLAG" ]
70
- }
71
-
72
- # 清理 dev action 标记(验收闭环后调用)
73
- clear_dev_action() {
74
- rm -f "$DEV_FLAG" 2>/dev/null || true
75
- }
76
-
77
- # 检查验收完整度,返回 issues 文本
78
- check_add_completeness() {
79
- local handoff="$1" add_route="$2"
80
- local issues=""
81
-
82
- # devlog(内容已回流至 handoff,检查 handoff 是否含验收结果)
83
- if [ -f "$handoff" ] && ! grep -qE '验收|收敛|闭环|本轮改了什么|devlog' "$handoff" 2>/dev/null; then
84
- issues="${issues} [ ] devlog 缺失(handoff 无验收记录)\n"
85
- fi
86
-
87
- # handoff 验证标准
88
- if [ -f "$handoff" ]; then
89
- local uc=$(grep -c '\[ \]' "$handoff" 2>/dev/null || echo "0")
90
- [ "$uc" -gt 0 ] && issues="${issues} [ ] handoff ${uc} 项未勾选\n"
91
- fi
92
-
93
- # add-route Step
94
- if [ -f "$add_route" ]; then
95
- local uc=$(grep -c '\[ \]' "$add_route" 2>/dev/null || echo "0")
96
- [ "$uc" -gt 0 ] && issues="${issues} [ ] add-route ${uc} Step 未闭环\n"
97
- fi
98
-
99
- echo -e "$issues"
100
- }
101
-
102
- # 检查是否已验收(幂等保护)
103
- # 返回 0 = 未验收,1 = 已验收
104
- is_already_accepted() {
105
- local add_route="$1" handoff="$2"
106
- # add-route Step 8 是否已 [x]
107
- if [ -f "$add_route" ]; then
108
- # 检查 Step 8 产出项是否勾选
109
- if grep -A 10 'Step 8' "$add_route" 2>/dev/null | grep -q '\[x\].*验证并更新项目状态'; then
110
- # handoff 是否有验收记录
111
- if [ -f "$handoff" ] && grep -qE '✅.*验收|收敛|全部闭环|全部.*完成' "$handoff" 2>/dev/null; then
112
- return 0
113
- fi
114
- fi
115
- fi
116
- return 1
117
- }
@@ -1,14 +1,9 @@
1
1
  #!/bin/bash
2
2
  # vocabulary.sh — 从 vocabulary markdown 表格加载触发词
3
- # 单一数据源: .qoder/vocabulary/add-governance-vocabulary.md §类别 A-F 表格
3
+ # 单一数据源: 当前 adapter 的 vocabulary/add-governance-vocabulary.md §类别 A-F 表格
4
4
 
5
- # 动态探测 MAGIC_DIR
6
- if [ -z "${MAGIC_DIR:-}" ]; then
7
- for m in ".claude" ".qoder" ".vscode" ".add"; do
8
- [ -d "${PROJECT_DIR:-$PWD}/$m" ] && { MAGIC_DIR="$m"; break; }
9
- done
10
- MAGIC_DIR="${MAGIC_DIR:-.add}"
11
- fi
5
+ # Codex 真源固定读取 `.codex`,禁止遍历或回退其他 magicDir。
6
+ MAGIC_DIR=".codex"
12
7
  VOCABULARY_FILE="${PROJECT_DIR:-$PWD}/$MAGIC_DIR/vocabulary/add-governance-vocabulary.md"
13
8
 
14
9
  # 输出格式: 优先级::触发词正则::响应文本(:: 避免与触发词内的 | 冲突)
@@ -1,5 +1,5 @@
1
1
  #!/bin/bash
2
- # Notification — Review 提醒 + Token 预警(Claude Code 适配)
2
+ # Notification — Review 提醒 + Token 预警(Codex 适配)
3
3
  # 治理卡位 #12: 开发提醒/Token 预警
4
4
  set -euo pipefail
5
5
 
@@ -11,7 +11,8 @@ if [ "$ntype" != "result" ]; then
11
11
  fi
12
12
 
13
13
  HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
14
- export CURRENT_MAGIC=$(basename "$(dirname "$HOOK_DIR")")
14
+ export CURRENT_MAGIC=".codex"
15
+ export MAGIC_DIR=".codex"
15
16
  COMMON_LIB="$HOOK_DIR/lib/common.sh"
16
17
  [ -f "$COMMON_LIB" ] && source "$COMMON_LIB"
17
18
 
@@ -22,24 +23,8 @@ state=$(detect_active_add 2>/dev/null || true)
22
23
 
23
24
  IFS='::' read -r plan _ _ _ _ <<< "$state"
24
25
 
25
- # 动态探测
26
- if [ -z "${MAGIC_DIR:-}" ]; then
27
- for m in ".claude" ".qoder" ".vscode" ".add"; do
28
- [ -d "${PROJECT_DIR:-$PWD}/$m" ] && { MAGIC_DIR="$m"; break; }
29
- done
30
- MAGIC_DIR="${MAGIC_DIR:-.add}"
31
- fi
32
26
  reviews_dir="${PROJECT_DIR}/$MAGIC_DIR/reviews"
33
27
  if ls "$reviews_dir"/*.md >/dev/null 2>&1; then
34
28
  echo "[ADD Notification] Plan: ${plan} — 请检查 Review 文档: ${reviews_dir}"
35
29
  fi
36
30
  exit 0
37
- #!/bin/bash
38
- # Notification — 通知事件处理(Claude Code 适配)
39
- set -euo pipefail
40
-
41
- HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
42
- SHARED_LIB="$HOOK_DIR/../../shared/hooks-lib/common.sh"
43
- [ -f "$SHARED_LIB" ] && source "$SHARED_LIB"
44
-
45
- exit 0
@@ -1,138 +1,43 @@
1
1
  #!/bin/bash
2
- # post-tool-use.sh — PostToolUse:格式化 + 文档守卫 + 审计提醒 + DPS 自动化
3
- # 治理卡位 #5: 格式化 + ADD文档守卫 + 审计落库 + 结果增强 + 哨兵自动化
2
+ # post-tool-use.sh — Codex PostToolUse:ADD 文档提示与开发操作审计提醒
4
3
  set -euo pipefail
5
4
 
6
5
  HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
6
+ export CURRENT_MAGIC=".codex"
7
+ export MAGIC_DIR=".codex"
8
+ export PROJECT_DIR="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
7
9
  COMMON_LIB="$HOOK_DIR/lib/common.sh"
8
10
  [ -f "$COMMON_LIB" ] && source "$COMMON_LIB"
9
11
 
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 "")
12
+ input=$(cat)
13
+ tool_name=$(echo "$input" | jq -r '.tool_name // empty')
13
14
 
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
15
+ _report_file() {
16
+ local file_path="$1"
17
+ [ -n "$file_path" ] || return 0
18
+ if echo "$file_path" | grep -qE '(^|/)\.codex/(plans|specs|reviews)/'; then
19
+ echo "[ADD PostToolUse] ADD 文档已写入: $file_path;请检查双向链接与 Plan/Spec 状态。" >&2
65
20
  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
21
+ echo "[ADD PostToolUse] 文件已写入: $file_path;请执行 record_dev_operation 落库审计。" >&2
22
+ }
23
+
24
+ if [ "$tool_name" = "apply_patch" ]; then
25
+ patch_command=$(echo "$input" | jq -r '.tool_input.command // empty')
26
+ patch_paths=$(printf '%s\n' "$patch_command" | sed -nE 's/^\*\*\* (Add|Update|Delete) File: (.+)$/\2/p')
27
+ while IFS= read -r file_path; do
28
+ _report_file "$file_path"
29
+ done <<< "$patch_paths"
94
30
  exit 0
95
31
  fi
96
32
 
97
- # ═══════════════ §3: Bash matcher: 结果增强 ═══════════════
98
- if [ "$tool_name" = "Bash" ]; then
99
- echo "[ADD PostToolUse] 命令执行完成。如有 lint/tsc 错误请修复。" >&2
33
+ if [ "$tool_name" = "Write" ] || [ "$tool_name" = "Edit" ] || [ "$tool_name" = "SearchReplace" ]; then
34
+ file_path=$(echo "$input" | jq -r '.tool_input.file_path // .tool_input.path // empty')
35
+ _report_file "$file_path"
100
36
  exit 0
101
37
  fi
102
38
 
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
39
  if [ "$tool_name" = "Bash" ]; then
134
- echo "[ADD PostToolUse] 命令执行完成。如有 lint/tsc 错误请修复。" >&2
135
- exit 0
40
+ echo "[ADD PostToolUse] Bash 命令完成;若产生 lint/typecheck/test 错误,请在本轮闭环。" >&2
136
41
  fi
137
42
 
138
43
  exit 0