add-coder 0.3.27 → 0.3.29

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 (262) hide show
  1. package/README.md +252 -150
  2. package/package.json +2 -1
  3. package/templates/.add-coder-src-hash.json +126 -148
  4. package/templates/adapters/claude/hooks/doc-format-guard.ts +32 -0
  5. package/templates/adapters/claude/hooks/lib/claude-env.ts +7 -0
  6. package/templates/adapters/claude/hooks/notification.ts +24 -0
  7. package/templates/adapters/claude/hooks/permission-denied.ts +33 -0
  8. package/templates/adapters/claude/hooks/permission-gate.ts +12 -0
  9. package/templates/adapters/claude/hooks/post-tool-failure.ts +4 -0
  10. package/templates/adapters/claude/hooks/post-tool-use.ts +17 -0
  11. package/templates/adapters/claude/hooks/pre-compact.ts +10 -0
  12. package/templates/adapters/claude/hooks/pre-tool-use.ts +81 -0
  13. package/templates/adapters/claude/hooks/prompt-submit.ts +82 -0
  14. package/templates/adapters/claude/hooks/review-checklist.ts +4 -0
  15. package/templates/adapters/claude/hooks/session-end.ts +10 -0
  16. package/templates/adapters/claude/hooks/session-start.ts +24 -0
  17. package/templates/adapters/claude/hooks/stop-check.ts +15 -0
  18. package/templates/adapters/claude/hooks/stop-failure.ts +34 -0
  19. package/templates/adapters/claude/hooks/subagent-guard.ts +25 -0
  20. package/templates/adapters/claude/hooks/subagent-stop.ts +12 -0
  21. package/templates/adapters/claude/settings.json +13 -13
  22. package/templates/adapters/codex/hooks/doc-format-guard.ts +30 -0
  23. package/templates/adapters/codex/hooks/notification.ts +26 -0
  24. package/templates/adapters/codex/hooks/permission-gate.ts +15 -0
  25. package/templates/adapters/codex/hooks/post-tool-failure.ts +14 -0
  26. package/templates/adapters/codex/hooks/post-tool-use.ts +85 -0
  27. package/templates/adapters/codex/hooks/pre-compact.ts +20 -0
  28. package/templates/adapters/codex/hooks/pre-tool-use.ts +141 -0
  29. package/templates/adapters/codex/hooks/prompt-submit.ts +38 -0
  30. package/templates/adapters/codex/hooks/review-checklist.ts +5 -0
  31. package/templates/adapters/codex/hooks/session-end.ts +19 -0
  32. package/templates/adapters/codex/hooks/session-start.ts +45 -0
  33. package/templates/adapters/codex/hooks/stop-check.ts +59 -0
  34. package/templates/adapters/codex/hooks/subagent-guard.ts +22 -0
  35. package/templates/adapters/codex/hooks/subagent-stop.ts +20 -0
  36. package/templates/adapters/codex/hooks.json +5 -5
  37. package/templates/adapters/qoder/hooks/doc-format-guard.ts +34 -0
  38. package/templates/adapters/qoder/hooks/lib/context-inject.ts +61 -0
  39. package/templates/adapters/qoder/hooks/lib/qoder-env.ts +23 -0
  40. package/templates/adapters/qoder/hooks/lib/review-checklist.ts +5 -0
  41. package/templates/adapters/qoder/hooks/notification.ts +34 -0
  42. package/templates/adapters/qoder/hooks/permission-gate.ts +26 -0
  43. package/templates/adapters/qoder/hooks/post-tool-failure.ts +30 -0
  44. package/templates/adapters/qoder/hooks/post-tool-use.ts +32 -0
  45. package/templates/adapters/qoder/hooks/pre-compact.ts +16 -0
  46. package/templates/adapters/qoder/hooks/pre-tool-use.ts +112 -0
  47. package/templates/adapters/qoder/hooks/prompt-submit.ts +66 -0
  48. package/templates/adapters/qoder/hooks/review-checklist.ts +24 -0
  49. package/templates/adapters/qoder/hooks/session-end.ts +27 -0
  50. package/templates/adapters/qoder/hooks/session-start.ts +83 -0
  51. package/templates/adapters/qoder/hooks/stop-check.ts +69 -0
  52. package/templates/adapters/qoder/hooks/subagent-guard.ts +16 -0
  53. package/templates/adapters/qoder/hooks/subagent-stop.ts +33 -0
  54. package/templates/adapters/qoder/settings.json +13 -13
  55. package/templates/adapters/trae/hooks/doc-format-guard.ts +30 -0
  56. package/templates/adapters/trae/hooks/notification.ts +22 -0
  57. package/templates/adapters/trae/hooks/permission-gate.ts +15 -0
  58. package/templates/adapters/trae/hooks/post-tool-failure.ts +14 -0
  59. package/templates/adapters/trae/hooks/post-tool-use.ts +24 -0
  60. package/templates/adapters/trae/hooks/pre-compact.ts +15 -0
  61. package/templates/adapters/trae/hooks/pre-tool-use.ts +40 -0
  62. package/templates/adapters/trae/hooks/prompt-submit.ts +29 -0
  63. package/templates/adapters/trae/hooks/review-checklist.ts +5 -0
  64. package/templates/adapters/trae/hooks/session-end.ts +16 -0
  65. package/templates/adapters/trae/hooks/session-start.ts +15 -0
  66. package/templates/adapters/trae/hooks/stop-check.ts +20 -0
  67. package/templates/adapters/trae/hooks/subagent-guard.ts +22 -0
  68. package/templates/adapters/trae/hooks/subagent-stop.ts +15 -0
  69. package/templates/adapters/trae/hooks.json +1 -1
  70. package/templates/adapters/vscode/hooks/doc-format-guard.ts +27 -0
  71. package/templates/adapters/vscode/hooks/notification.ts +22 -0
  72. package/templates/adapters/vscode/hooks/permission-gate.ts +15 -0
  73. package/templates/adapters/vscode/hooks/post-tool-failure.ts +32 -0
  74. package/templates/adapters/vscode/hooks/post-tool-use.ts +25 -0
  75. package/templates/adapters/vscode/hooks/pre-compact.ts +15 -0
  76. package/templates/adapters/vscode/hooks/pre-tool-use.ts +78 -0
  77. package/templates/adapters/vscode/hooks/prompt-submit.ts +74 -0
  78. package/templates/adapters/vscode/hooks/review-checklist.ts +5 -0
  79. package/templates/adapters/vscode/hooks/session-end.ts +16 -0
  80. package/templates/adapters/vscode/hooks/session-start.ts +24 -0
  81. package/templates/adapters/vscode/hooks/stop-check.ts +21 -0
  82. package/templates/adapters/vscode/hooks/subagent-guard.ts +21 -0
  83. package/templates/adapters/vscode/hooks/subagent-stop.ts +15 -0
  84. package/templates/core/docs/ADD-governance-claude-code.md +3 -3
  85. package/templates/core/docs/ADD-governance-codex.md +5 -5
  86. package/templates/core/docs/ADD-governance-qoder-cn.md +4 -4
  87. package/templates/core/docs/ADD-governance-trae.md +2 -2
  88. package/templates/core/docs/ADD-governance-vscode-copilot.md +21 -22
  89. package/templates/core/governance/audit-bridge.ts +47 -0
  90. package/templates/core/governance/common.ts +299 -0
  91. package/templates/core/governance/context-inject.ts +53 -0
  92. package/templates/core/governance/doc-format-guard.ts +440 -0
  93. package/templates/core/governance/notification-router.ts +62 -0
  94. package/templates/core/governance/notify.ts +66 -0
  95. package/templates/core/governance/permission-gate-router.ts +42 -0
  96. package/templates/core/governance/post-tool-failure-router.ts +56 -0
  97. package/templates/core/governance/post-tool-router.ts +212 -0
  98. package/templates/core/governance/pre-compact-guard.ts +41 -0
  99. package/templates/core/governance/pre-tool-guard.ts +309 -0
  100. package/templates/core/governance/preload-templates.ts +241 -0
  101. package/templates/core/governance/prompt-router.ts +222 -0
  102. package/templates/core/governance/review-checklist-guard.ts +186 -0
  103. package/templates/core/governance/rules.ts +720 -0
  104. package/templates/core/governance/session-end.ts +88 -0
  105. package/templates/core/governance/session-start-guard.ts +99 -0
  106. package/templates/core/governance/state-detect.ts +6 -0
  107. package/templates/core/governance/stop-router.ts +140 -0
  108. package/templates/core/governance/subagent-guard-router.ts +35 -0
  109. package/templates/core/governance/subagent-stop-router.ts +93 -0
  110. package/templates/core/governance/subagent-stop.ts +75 -0
  111. package/templates/core/governance/vocabulary.ts +109 -0
  112. package/templates/core/hooks/doc-format-guard.ts +21 -0
  113. package/templates/core/hooks/notification.ts +11 -0
  114. package/templates/core/hooks/permission-gate.ts +7 -0
  115. package/templates/core/hooks/post-tool-failure.ts +7 -0
  116. package/templates/core/hooks/post-tool-use.ts +23 -0
  117. package/templates/core/hooks/pre-compact.ts +9 -0
  118. package/templates/core/hooks/pre-tool-use.ts +30 -0
  119. package/templates/core/hooks/prompt-submit.ts +11 -0
  120. package/templates/core/hooks/review-checklist.ts +4 -0
  121. package/templates/core/hooks/session-end.ts +10 -0
  122. package/templates/core/hooks/session-start.ts +9 -0
  123. package/templates/core/hooks/stop-check.ts +14 -0
  124. package/templates/core/hooks/subagent-guard.ts +8 -0
  125. package/templates/core/hooks/subagent-stop.ts +9 -0
  126. package/templates/core/scripts/mcp-server/tools/gateway/check_rahs.ts +12 -1
  127. package/templates/core/scripts/mcp-server/tools/plan.ts +12 -2
  128. package/templates/adapters/claude/hooks/doc-format-guard.sh +0 -283
  129. package/templates/adapters/claude/hooks/lib/common.sh +0 -220
  130. package/templates/adapters/claude/hooks/lib/context-inject.sh +0 -96
  131. package/templates/adapters/claude/hooks/lib/notify.sh +0 -36
  132. package/templates/adapters/claude/hooks/lib/preload-templates.sh +0 -212
  133. package/templates/adapters/claude/hooks/lib/session-end.sh +0 -76
  134. package/templates/adapters/claude/hooks/lib/state-detect.sh +0 -13
  135. package/templates/adapters/claude/hooks/lib/subagent-stop.sh +0 -90
  136. package/templates/adapters/claude/hooks/lib/vocabulary.sh +0 -62
  137. package/templates/adapters/claude/hooks/notification.sh +0 -45
  138. package/templates/adapters/claude/hooks/permission-denied.sh +0 -42
  139. package/templates/adapters/claude/hooks/permission-gate.sh +0 -18
  140. package/templates/adapters/claude/hooks/post-tool-failure.sh +0 -10
  141. package/templates/adapters/claude/hooks/post-tool-use.sh +0 -35
  142. package/templates/adapters/claude/hooks/pre-compact.sh +0 -37
  143. package/templates/adapters/claude/hooks/pre-tool-use.sh +0 -153
  144. package/templates/adapters/claude/hooks/prompt-submit.sh +0 -99
  145. package/templates/adapters/claude/hooks/review-checklist.sh +0 -10
  146. package/templates/adapters/claude/hooks/session-end.sh +0 -21
  147. package/templates/adapters/claude/hooks/session-start.sh +0 -36
  148. package/templates/adapters/claude/hooks/stop-check.sh +0 -54
  149. package/templates/adapters/claude/hooks/stop-failure.sh +0 -44
  150. package/templates/adapters/claude/hooks/subagent-guard.sh +0 -36
  151. package/templates/adapters/claude/hooks/subagent-stop.sh +0 -20
  152. package/templates/adapters/codex/hooks/doc-format-guard.sh +0 -343
  153. package/templates/adapters/codex/hooks/lib/common.sh +0 -209
  154. package/templates/adapters/codex/hooks/lib/context-inject.sh +0 -96
  155. package/templates/adapters/codex/hooks/lib/notify.sh +0 -36
  156. package/templates/adapters/codex/hooks/lib/preload-templates.sh +0 -208
  157. package/templates/adapters/codex/hooks/lib/session-end.sh +0 -76
  158. package/templates/adapters/codex/hooks/lib/state-detect.sh +0 -8
  159. package/templates/adapters/codex/hooks/lib/subagent-stop.sh +0 -90
  160. package/templates/adapters/codex/hooks/lib/vocabulary.sh +0 -51
  161. package/templates/adapters/codex/hooks/notification.sh +0 -30
  162. package/templates/adapters/codex/hooks/permission-gate.sh +0 -18
  163. package/templates/adapters/codex/hooks/post-tool-failure.sh +0 -10
  164. package/templates/adapters/codex/hooks/post-tool-use.sh +0 -43
  165. package/templates/adapters/codex/hooks/pre-compact.sh +0 -37
  166. package/templates/adapters/codex/hooks/pre-tool-use.sh +0 -130
  167. package/templates/adapters/codex/hooks/prompt-submit.sh +0 -92
  168. package/templates/adapters/codex/hooks/review-checklist.sh +0 -10
  169. package/templates/adapters/codex/hooks/session-end.sh +0 -38
  170. package/templates/adapters/codex/hooks/session-start.sh +0 -63
  171. package/templates/adapters/codex/hooks/stop-check.sh +0 -71
  172. package/templates/adapters/codex/hooks/subagent-guard.sh +0 -15
  173. package/templates/adapters/codex/hooks/subagent-stop.sh +0 -47
  174. package/templates/adapters/qoder/hooks/doc-format-guard.sh +0 -341
  175. package/templates/adapters/qoder/hooks/lib/common.sh +0 -223
  176. package/templates/adapters/qoder/hooks/lib/context-inject.sh +0 -96
  177. package/templates/adapters/qoder/hooks/lib/notify.sh +0 -36
  178. package/templates/adapters/qoder/hooks/lib/preload-templates.sh +0 -212
  179. package/templates/adapters/qoder/hooks/lib/session-end.sh +0 -76
  180. package/templates/adapters/qoder/hooks/lib/state-detect.sh +0 -13
  181. package/templates/adapters/qoder/hooks/lib/subagent-stop.sh +0 -90
  182. package/templates/adapters/qoder/hooks/lib/vocabulary.sh +0 -62
  183. package/templates/adapters/qoder/hooks/notification.sh +0 -25
  184. package/templates/adapters/qoder/hooks/permission-gate.sh +0 -8
  185. package/templates/adapters/qoder/hooks/post-tool-failure.sh +0 -8
  186. package/templates/adapters/qoder/hooks/post-tool-use.sh +0 -121
  187. package/templates/adapters/qoder/hooks/pre-compact.sh +0 -37
  188. package/templates/adapters/qoder/hooks/pre-tool-use.sh +0 -154
  189. package/templates/adapters/qoder/hooks/prompt-submit.sh +0 -96
  190. package/templates/adapters/qoder/hooks/review-checklist.sh +0 -157
  191. package/templates/adapters/qoder/hooks/session-end.sh +0 -24
  192. package/templates/adapters/qoder/hooks/session-start.sh +0 -45
  193. package/templates/adapters/qoder/hooks/stop-check.sh +0 -59
  194. package/templates/adapters/qoder/hooks/subagent-guard.sh +0 -27
  195. package/templates/adapters/qoder/hooks/subagent-stop.sh +0 -26
  196. package/templates/adapters/trae/hooks/doc-format-guard.sh +0 -343
  197. package/templates/adapters/trae/hooks/lib/common.sh +0 -220
  198. package/templates/adapters/trae/hooks/lib/context-inject.sh +0 -96
  199. package/templates/adapters/trae/hooks/lib/notify.sh +0 -36
  200. package/templates/adapters/trae/hooks/lib/preload-templates.sh +0 -212
  201. package/templates/adapters/trae/hooks/lib/session-end.sh +0 -76
  202. package/templates/adapters/trae/hooks/lib/state-detect.sh +0 -10
  203. package/templates/adapters/trae/hooks/lib/subagent-stop.sh +0 -90
  204. package/templates/adapters/trae/hooks/lib/vocabulary.sh +0 -62
  205. package/templates/adapters/trae/hooks/notification.sh +0 -45
  206. package/templates/adapters/trae/hooks/permission-gate.sh +0 -18
  207. package/templates/adapters/trae/hooks/post-tool-failure.sh +0 -10
  208. package/templates/adapters/trae/hooks/post-tool-use.sh +0 -138
  209. package/templates/adapters/trae/hooks/pre-compact.sh +0 -37
  210. package/templates/adapters/trae/hooks/pre-tool-use.sh +0 -223
  211. package/templates/adapters/trae/hooks/prompt-submit.sh +0 -87
  212. package/templates/adapters/trae/hooks/review-checklist.sh +0 -10
  213. package/templates/adapters/trae/hooks/session-end.sh +0 -38
  214. package/templates/adapters/trae/hooks/session-start.sh +0 -53
  215. package/templates/adapters/trae/hooks/stop-check.sh +0 -54
  216. package/templates/adapters/trae/hooks/subagent-guard.sh +0 -15
  217. package/templates/adapters/trae/hooks/subagent-stop.sh +0 -47
  218. package/templates/adapters/vscode/hooks/doc-format-guard.sh +0 -282
  219. package/templates/adapters/vscode/hooks/lib/common.sh +0 -220
  220. package/templates/adapters/vscode/hooks/lib/context-inject.sh +0 -96
  221. package/templates/adapters/vscode/hooks/lib/notify.sh +0 -36
  222. package/templates/adapters/vscode/hooks/lib/preload-templates.sh +0 -212
  223. package/templates/adapters/vscode/hooks/lib/session-end.sh +0 -76
  224. package/templates/adapters/vscode/hooks/lib/state-detect.sh +0 -13
  225. package/templates/adapters/vscode/hooks/lib/subagent-stop.sh +0 -90
  226. package/templates/adapters/vscode/hooks/lib/vocabulary.sh +0 -62
  227. package/templates/adapters/vscode/hooks/notification.sh +0 -43
  228. package/templates/adapters/vscode/hooks/permission-gate.sh +0 -18
  229. package/templates/adapters/vscode/hooks/post-tool-failure.sh +0 -28
  230. package/templates/adapters/vscode/hooks/post-tool-use.sh +0 -35
  231. package/templates/adapters/vscode/hooks/pre-compact.sh +0 -37
  232. package/templates/adapters/vscode/hooks/pre-tool-use.sh +0 -153
  233. package/templates/adapters/vscode/hooks/prompt-submit.sh +0 -99
  234. package/templates/adapters/vscode/hooks/review-checklist.sh +0 -10
  235. package/templates/adapters/vscode/hooks/session-end.sh +0 -13
  236. package/templates/adapters/vscode/hooks/session-start.sh +0 -35
  237. package/templates/adapters/vscode/hooks/stop-check.sh +0 -62
  238. package/templates/adapters/vscode/hooks/subagent-guard.sh +0 -37
  239. package/templates/adapters/vscode/hooks/subagent-stop.sh +0 -12
  240. package/templates/core/hooks/doc-format-guard.sh +0 -343
  241. package/templates/core/hooks/lib/common.sh +0 -220
  242. package/templates/core/hooks/lib/context-inject.sh +0 -96
  243. package/templates/core/hooks/lib/notify.sh +0 -36
  244. package/templates/core/hooks/lib/preload-templates.sh +0 -212
  245. package/templates/core/hooks/lib/session-end.sh +0 -76
  246. package/templates/core/hooks/lib/state-detect.sh +0 -10
  247. package/templates/core/hooks/lib/subagent-stop.sh +0 -90
  248. package/templates/core/hooks/lib/vocabulary.sh +0 -62
  249. package/templates/core/hooks/notification.sh +0 -45
  250. package/templates/core/hooks/permission-gate.sh +0 -18
  251. package/templates/core/hooks/post-tool-failure.sh +0 -10
  252. package/templates/core/hooks/post-tool-use.sh +0 -138
  253. package/templates/core/hooks/pre-compact.sh +0 -37
  254. package/templates/core/hooks/pre-tool-use.sh +0 -223
  255. package/templates/core/hooks/prompt-submit.sh +0 -87
  256. package/templates/core/hooks/review-checklist.sh +0 -10
  257. package/templates/core/hooks/session-end.sh +0 -38
  258. package/templates/core/hooks/session-start.sh +0 -53
  259. package/templates/core/hooks/stop-check.sh +0 -54
  260. package/templates/core/hooks/subagent-guard.sh +0 -15
  261. package/templates/core/hooks/subagent-stop.sh +0 -47
  262. package/templates/shared/hooks-lib/common.sh +0 -22
@@ -0,0 +1,38 @@
1
+ // prompt-submit.ts — UserPromptSubmit 入口(Codex 版,Task 7.1 继承体系)
2
+ // 继承 core PromptRouter(L1/L2/L3 模板方法);仅 override 协议差异(bash 原文逐字对照):
3
+ // ① extractPrompt = 基类默认(jsonGet 与 bash jq 同语义)
4
+ // ② acceptedText = 基类默认(codex bash 原文 6 行含 ★ 同步检查,与 core 逐字一致)
5
+ // ③ onAccepted: 输出 review-checklist 占位文本(codex bash 调占位脚本;core 是子进程 stdio ignore)
6
+ // ④ layer2ToStderr = 基类默认 true(codex bash 原文 Layer2 走 stderr)
7
+ // ⑤ layer3Text/日报 = 基类默认(codex bash 原文与 core 逐字一致)
8
+ // 入口差异: PROJECT_DIR=git toplevel + cd 统一 cwd(codex 大文件协议)+ MAGIC_DIR 注入
9
+
10
+ import { execSync } from "node:child_process"
11
+ import { readHookInput, tryResolveMagicDir } from "../../../core/governance/common.js"
12
+ import { PromptRouter } from "../../../core/governance/prompt-router.js"
13
+
14
+ class CodexPromptRouter extends PromptRouter {
15
+ /** ③ 验收后置: 输出 review-checklist 占位文本(codex bash 调占位脚本逐字) */
16
+ protected override onAccepted(_handoff: string, _addRoute: string): void {
17
+ process.stdout.write("[ADD ReviewChecklist] 请在提交前确认 checklist.md 全部项已勾选。\n")
18
+ }
19
+
20
+ // 其余(extractPrompt/acceptedText/layer2ToStderr/layer3Text/dailyWarnText)与 core 基线一致
21
+ }
22
+
23
+ // 对齐 bash: git rev-parse --show-toplevel || pwd + cd
24
+ function resolveProjectDir(): string {
25
+ try {
26
+ return execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim()
27
+ } catch {
28
+ return process.cwd()
29
+ }
30
+ }
31
+ const PROJECT_DIR = resolveProjectDir()
32
+ process.env.PROJECT_DIR = PROJECT_DIR
33
+ // 对齐 bash export MAGIC_DIR=".codex":唯一解析链(注入优先 → 物理推导),推导失败回退 .codex
34
+ process.env.MAGIC_DIR = tryResolveMagicDir() || ".codex"
35
+ process.chdir(PROJECT_DIR) // 对齐 bash cd "$PROJECT_DIR"
36
+
37
+ const input = readHookInput()
38
+ process.exit(new CodexPromptRouter(process.env.MAGIC_DIR).run(input))
@@ -0,0 +1,5 @@
1
+ // review-checklist.ts — Review 检查清单校验(Codex 版)
2
+ // bash 版缺陷修复: SHARED_LIB 路径断裂,TS 版 import core common.js(内联)。
3
+
4
+ process.stdout.write("[ADD ReviewChecklist] 请在提交前确认 checklist.md 全部项已勾选。\n")
5
+ process.exit(0)
@@ -0,0 +1,19 @@
1
+ // session-end.ts — SessionEnd 入口(Codex 版,Task 7.1 继承体系)
2
+ // 继承 core SessionEndGuard,命名子类 CodexSessionEndGuard:
3
+ // ① 清理标记(tpl + dev)+ ② 审计结算(stderr)+ ③ Stop 兜底 = 基类
4
+ // (2026-08-14 实态核验: codex 手写版与 core SessionEndGuard 逐字同构,收敛为子类)
5
+ // 协议差异仅剩: PROJECT_DIR = $PWD(codex 小文件无 git toplevel)+ MAGIC_DIR 注入
6
+
7
+ import { tryResolveMagicDir } from "../../../core/governance/common.js"
8
+ import { SessionEndGuard } from "../../../core/governance/session-end.js"
9
+
10
+ class CodexSessionEndGuard extends SessionEndGuard {
11
+ // 当前无 override(清理/结算/兜底与 core 基线一致);命名子类承载端身份 + 未来演进位
12
+ }
13
+
14
+ process.env.PROJECT_DIR = process.env.PROJECT_DIR || process.cwd()
15
+ // 对齐 bash export MAGIC_DIR=".codex":唯一解析链(注入优先 → 物理推导),推导失败回退 .codex
16
+ const inferred = tryResolveMagicDir()
17
+ if (inferred && !process.env.MAGIC_DIR) process.env.MAGIC_DIR = inferred
18
+
19
+ process.exit(new CodexSessionEndGuard(process.env.PROJECT_DIR).run())
@@ -0,0 +1,45 @@
1
+ // session-start.ts — SessionStart 入口(Codex 版,Task 7.1 继承体系)
2
+ // 继承 core SessionStartGuard,命名子类 CodexSessionStartGuard:
3
+ // ① emitState/emitTodoReminder/emitHitlPending = 基类默认(bash 原文逐字一致)
4
+ // ② emitIndex override: 自定义列表格式(codex bash 原文——`## ADD 可用模板清单` + `- f` 简单列出,
5
+ // 非 PreloadTemplates 表格格式)
6
+ // 入口差异: PROJECT_DIR=git toplevel(codex 大文件协议)+ MAGIC_DIR 注入(.codex 兜底)
7
+
8
+ import { existsSync, readdirSync } from "node:fs"
9
+ import { join } from "node:path"
10
+ import { execSync } from "node:child_process"
11
+ import { tryResolveMagicDir } from "../../../core/governance/common.js"
12
+ import { SessionStartGuard } from "../../../core/governance/session-start-guard.js"
13
+
14
+ class CodexSessionStartGuard extends SessionStartGuard {
15
+ /** ② 模板索引: 自定义列表格式(codex bash 原文逐字,非表格) */
16
+ protected override emitIndex(): void {
17
+ const TEMPLATES_DIR = join(this.projectDir, this.magicDir, "templates")
18
+ if (existsSync(TEMPLATES_DIR)) {
19
+ process.stdout.write("## ADD 可用模板清单\n")
20
+ try {
21
+ for (const f of readdirSync(TEMPLATES_DIR)) {
22
+ if (f.endsWith(".md")) process.stdout.write(`- ${f}\n`)
23
+ }
24
+ } catch {
25
+ /* ignore(对齐 bash 读取失败跳过) */
26
+ }
27
+ }
28
+ }
29
+ }
30
+
31
+ // 对齐 bash: git rev-parse --show-toplevel || pwd
32
+ function resolveProjectDir(): string {
33
+ try {
34
+ return execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim()
35
+ } catch {
36
+ return process.cwd()
37
+ }
38
+ }
39
+ const PROJECT_DIR = resolveProjectDir()
40
+ process.env.PROJECT_DIR = PROJECT_DIR
41
+ // 对齐 bash export MAGIC_DIR=".codex":唯一解析链(注入优先 → 物理推导),推导失败回退 .codex
42
+ const MAGIC_DIR = tryResolveMagicDir() || ".codex"
43
+ process.env.MAGIC_DIR = MAGIC_DIR
44
+
45
+ process.exit(new CodexSessionStartGuard(PROJECT_DIR).run())
@@ -0,0 +1,59 @@
1
+ // stop-check.ts — Stop 入口(Codex 版,Task 7.1 继承体系)
2
+ // 继承 core StopRouter,命名子类 CodexStopRouter:
3
+ // ① Q0/Q1/Q2 = 基类默认(stderr + exit 语义,与 codex bash 原文逐字一致)
4
+ // ② emitQ3 override: {systemMessage} JSON(codex 私有协议——plan/approval/tasks 字段)
5
+ // ③ emitQ4Pass override: {systemMessage} JSON(codex stdout 契约——Q4 通过形态;
6
+ // ~~q4Check override~~ → 2026-08-14 Task 9.4.4④ 删除,回归 core 双维度组合(DB 进度 + checklist 质量))
7
+ // 入口差异: PROJECT_DIR=git toplevel(codex 大文件协议)+ stopHookActive 续跑保护 + MAGIC_DIR 注入
8
+
9
+ import { execSync } from "node:child_process"
10
+ import { readHookInput, tryResolveMagicDir } from "../../../core/governance/common.js"
11
+ import { StopRouter } from "../../../core/governance/stop-router.js"
12
+
13
+ /** 对齐 bash jq -nc --arg message '{systemMessage: $message}'(codex 私有协议) */
14
+ function systemMessage(message: string): string {
15
+ return JSON.stringify({ systemMessage: message })
16
+ }
17
+
18
+ class CodexStopRouter extends StopRouter {
19
+ /** ② Q3: systemMessage JSON(codex 协议——approval/tasks 字段,bash 原文逐字) */
20
+ protected override emitQ3(plan: string, approval: string, tasks: string): number {
21
+ process.stdout.write(systemMessage(`[ADD Stop] Plan: ${plan};approval: ${approval};tasks: ${tasks}。本次无代码改动。`) + "\n")
22
+ return 0
23
+ }
24
+
25
+ /** ③ Q4 通过: systemMessage JSON(codex stdout 契约——Task 9.4.4④ 新增,
26
+ * 原 q4Check 完成分支的 systemMessage 语义保留到协议层) */
27
+ protected override emitQ4Pass(): number {
28
+ process.stdout.write(systemMessage("[ADD Stop] ✅ 验收通过——checklist 全部勾选,devlog 已记录。DB Plan tasks 已完成;可进入 Review/closure。") + "\n")
29
+ return 0
30
+ }
31
+ }
32
+
33
+ // 对齐 bash: git rev-parse --show-toplevel || pwd
34
+ function resolveProjectDir(): string {
35
+ try {
36
+ return execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim()
37
+ } catch {
38
+ return process.cwd()
39
+ }
40
+ }
41
+ const PROJECT_DIR = resolveProjectDir()
42
+ process.env.PROJECT_DIR = PROJECT_DIR
43
+ // 对齐 bash export MAGIC_DIR=".codex":唯一解析链(注入优先 → 物理推导),推导失败回退 .codex
44
+ process.env.MAGIC_DIR = tryResolveMagicDir() || ".codex"
45
+
46
+ const input = readHookInput()
47
+ let stopHookActive = false
48
+ if (input.trim() !== "") {
49
+ try {
50
+ const parsed = JSON.parse(input) as { stop_hook_active?: unknown }
51
+ stopHookActive = parsed.stop_hook_active === true
52
+ } catch {
53
+ stopHookActive = false
54
+ }
55
+ }
56
+ // codex 续跑保护: 内部 Stop 触发时跳过(bash 原文逐字)
57
+ if (stopHookActive) process.exit(0)
58
+
59
+ process.exit(new CodexStopRouter().run())
@@ -0,0 +1,22 @@
1
+ // subagent-guard.ts — SubagentStart 入口(Codex 版,Task 3.1 继承体系)
2
+ // 继承 core SubagentGuardRouter(状态注入模板方法——能力对齐):
3
+ // 能力对齐注: 原 codex 为弱版(事件提示空话),已对齐强版(状态注入)
4
+ // ① 输出形态: 纯文本状态块(core/qoder 是 hookSpecificOutput JSON)
5
+
6
+ import { SubagentGuardRouter } from "../../../core/governance/subagent-guard-router.js"
7
+
8
+ class CodexSubagentGuardRouter extends SubagentGuardRouter {
9
+ /** ① 纯文本状态块(codex 协议,与 claude 同构) */
10
+ protected override emit(state: string): void {
11
+ const [plan, step, rounds, handoff] = state.split("::")
12
+ process.stdout.write(`[ADD SubagentStart] 子代理上下文注入:
13
+ Plan: ${plan}
14
+ Step: ${step}
15
+ 轮次: ${rounds}
16
+ handoff: ${handoff}
17
+ 遵循 ADD 规范,完成后请检查 checklist 对应项
18
+ `)
19
+ }
20
+ }
21
+
22
+ process.exit(new CodexSubagentGuardRouter().run())
@@ -0,0 +1,20 @@
1
+ // subagent-stop.ts — SubagentStop 入口(Codex 版,Task 7.1 继承体系)
2
+ // 继承 core SubagentStopRouter,命名子类 CodexSubagentStopRouter:
3
+ // ① 边界校验 + deliverables 越界检查 + 审计聚合 = 基类(与 codex bash 原文逐字同构,
4
+ // 2026-08-14 实态核验——手写版逻辑与 core 基类完全一致,收敛为子类)
5
+ // 协议差异仅剩: PROJECT_DIR = $PWD(codex 小文件无 git toplevel)+ MAGIC_DIR 注入
6
+
7
+ import { readHookInput, tryResolveMagicDir } from "../../../core/governance/common.js"
8
+ import { SubagentStopRouter } from "../../../core/governance/subagent-stop-router.js"
9
+
10
+ class CodexSubagentStopRouter extends SubagentStopRouter {
11
+ // 当前无 override(边界校验 + 审计聚合与 core 基线一致);命名子类承载端身份 + 未来演进位
12
+ }
13
+
14
+ process.env.PROJECT_DIR = process.env.PROJECT_DIR || process.cwd()
15
+ // 对齐 bash export MAGIC_DIR=".codex":唯一解析链(注入优先 → 物理推导),推导失败回退 .codex
16
+ const inferred = tryResolveMagicDir()
17
+ if (inferred && !process.env.MAGIC_DIR) process.env.MAGIC_DIR = inferred
18
+
19
+ const input = readHookInput()
20
+ process.exit(new CodexSubagentStopRouter().run(input))
@@ -7,7 +7,7 @@
7
7
  "hooks": [
8
8
  {
9
9
  "type": "command",
10
- "command": "bash \"$(git rev-parse --show-toplevel)/.codex/hooks/session-start.sh\"",
10
+ "command": "node \"$(git rev-parse --show-toplevel)/.codex/hooks/session-start.mjs\"",
11
11
  "statusMessage": "Loading ADD state",
12
12
  "additionalContextLimit": 5000
13
13
  }
@@ -19,7 +19,7 @@
19
19
  "hooks": [
20
20
  {
21
21
  "type": "command",
22
- "command": "bash \"$(git rev-parse --show-toplevel)/.codex/hooks/prompt-submit.sh\"",
22
+ "command": "node \"$(git rev-parse --show-toplevel)/.codex/hooks/prompt-submit.mjs\"",
23
23
  "statusMessage": "Routing ADD workflow"
24
24
  }
25
25
  ]
@@ -31,7 +31,7 @@
31
31
  "hooks": [
32
32
  {
33
33
  "type": "command",
34
- "command": "bash \"$(git rev-parse --show-toplevel)/.codex/hooks/pre-tool-use.sh\"",
34
+ "command": "node \"$(git rev-parse --show-toplevel)/.codex/hooks/pre-tool-use.mjs\"",
35
35
  "statusMessage": "Checking ADD policy",
36
36
  "timeout": 30
37
37
  }
@@ -44,7 +44,7 @@
44
44
  "hooks": [
45
45
  {
46
46
  "type": "command",
47
- "command": "bash \"$(git rev-parse --show-toplevel)/.codex/hooks/post-tool-use.sh\"",
47
+ "command": "node \"$(git rev-parse --show-toplevel)/.codex/hooks/post-tool-use.mjs\"",
48
48
  "statusMessage": "Recording ADD result",
49
49
  "timeout": 30
50
50
  }
@@ -56,7 +56,7 @@
56
56
  "hooks": [
57
57
  {
58
58
  "type": "command",
59
- "command": "bash \"$(git rev-parse --show-toplevel)/.codex/hooks/stop-check.sh\"",
59
+ "command": "node \"$(git rev-parse --show-toplevel)/.codex/hooks/stop-check.mjs\"",
60
60
  "statusMessage": "Checking ADD closure",
61
61
  "timeout": 30
62
62
  }
@@ -0,0 +1,34 @@
1
+ // doc-format-guard.ts — schema.json 驱动的 ADD 文档格式守卫(Qoder CN 版,Task 4.1 继承体系)
2
+ // 继承 core DocFormatGuard,命名子类 QoderDocFormatGuard——六端实态核验(2026-08-14):
3
+ // 探测链与 core 数据驱动同语义(PLAN 元信息 → 一、Plan 概述 → 四、Handoff → simple-plan,
4
+ // 无 claude 的 Handoff 前置差异)→ 当前无 override(空子类承载端身份 + 未来演进位);
5
+ // 文本漂移(「doc-format-guard.sh」残留)已在 core 修正(TS 时代无 .sh)。
6
+ // 协议差异仅剩: PROJECT_DIR 注入链(qoder-env)
7
+
8
+ import { readFileSync } from "node:fs"
9
+ import { DocFormatGuard } from "../../../core/governance/doc-format-guard.js"
10
+ import { injectProjectDir } from "./lib/qoder-env.js"
11
+
12
+ /**
13
+ * Qoder DocFormatGuard(命名子类):
14
+ * 当前无 override(探测链同 core);未来 qoder 协议演进(如 hookSpecificOutput 新字段)
15
+ * 在此扩展,不改 core 基类。
16
+ */
17
+ class QoderDocFormatGuard extends DocFormatGuard {
18
+ constructor(projectDir: string, magicDir: string) {
19
+ super(projectDir, magicDir)
20
+ }
21
+ }
22
+
23
+ injectProjectDir()
24
+ const PROJECT_DIR = process.env.PROJECT_DIR || process.cwd()
25
+ const MAGIC_DIR = process.env.MAGIC_DIR || ".qoder"
26
+
27
+ const guard = new QoderDocFormatGuard(PROJECT_DIR, MAGIC_DIR)
28
+ let raw = ""
29
+ try {
30
+ raw = readFileSync(0, "utf-8")
31
+ } catch {
32
+ raw = ""
33
+ }
34
+ process.exitCode = guard.run(raw)
@@ -0,0 +1,61 @@
1
+ // lib/context-inject.ts — 上下文注入模板(Qoder CN 版,Task 4.1 diff 合并 core)
2
+ // R2 回流: context-inject diff 已合并——7 象限文本真源 = hook-context-rules.toml
3
+ // ([context.quadrants] core 基线 + [context.adapter_quadrants] qoder 差异)
4
+ // 差异保留(行为等价红线):
5
+ // has_add_dev_unclosed: qoder 版含「(不要等下次会话)」文本差异
6
+ // ~~{{info}} 字面量不插值~~ → 2026-08-14 Task 9.4.1 修复: 回归统一 replaceAll 插值语义
7
+ // (bash <<'EOF' 单引号 heredoc 缺陷照搬——issues 参数实际不生效,已修复)
8
+
9
+ import { context } from "../../../../core/governance/rules.js"
10
+
11
+ /** 象限条目(rules.context.quadrants / adapter_quadrants 结构) */
12
+ interface Quadrant {
13
+ adapter?: string
14
+ id: string
15
+ consumed: boolean
16
+ text: string
17
+ }
18
+
19
+ /** 结构化 SessionStart JSON 注入(与 core buildSessionStartJson 逐字一致) */
20
+ export function buildSessionStartJson(
21
+ plan: string,
22
+ step: string,
23
+ round: string,
24
+ handoff: string
25
+ ): string {
26
+ return `{
27
+ "continue": true,
28
+ "hookSpecificOutput": {
29
+ "hookEventName": "SessionStart",
30
+ "additionalContext": "上次 ADD 流程未完成:\\n Plan: ${plan}\\n 轮次: ${round}\\n 当前 Step: ${step} (add-route)\\n 恢复命令: query_audit_logs({ planKeyword: '${plan}' })\\n handoff: ${handoff}"
31
+ }
32
+ }
33
+ `
34
+ }
35
+
36
+ /** 象限文本索引(adapter 差异优先,回退 core 基线) */
37
+ const QUADRANTS: Map<string, Quadrant> = new Map()
38
+ for (const q of ((context.adapter_quadrants as unknown as Quadrant[]) ?? []).filter((x) => x.adapter === "qoder")) {
39
+ QUADRANTS.set(q.id, q)
40
+ }
41
+ for (const q of ((context.quadrants as unknown as Quadrant[]) ?? [])) {
42
+ if (!QUADRANTS.has(q.id)) QUADRANTS.set(q.id, q)
43
+ }
44
+
45
+ /**
46
+ * Stop 七象限分流 few-shot 上下文(Qoder CN 版)。
47
+ * Task 9.4.1 修复: has_add_dev_unclosed 的 {{info}} 正常插值(原 bash <<'EOF' 缺陷照搬——不 replace)
48
+ */
49
+ export function buildStopContext(quadrant: string, info: string): string {
50
+ const q = QUADRANTS.get(quadrant)
51
+ if (!q) return ""
52
+ return q.text.replaceAll("{{info}}", info)
53
+ }
54
+
55
+ /** 写操作前置守卫上下文(与 core buildPretoolContext 逐字对齐) */
56
+ export function buildPretoolContext(plan: string, round: string): string {
57
+ return `[ADD PreToolUse] 当前 Plan: ${plan},轮次: ${round}。
58
+ 本次写入应属于 ADD Step 3 代码实现阶段。
59
+ 完成后执行 record_dev_operation 记录审计。
60
+ `
61
+ }
@@ -0,0 +1,23 @@
1
+ // lib/qoder-env.ts — Qoder CN 私有环境解析(PROJECT_DIR 注入链)
2
+ // 契约: qoder 端所有 hook 的 PROJECT_DIR 来源 = ${CLAUDE_PROJECT_DIR:-${QODER_PROJECT_DIR:-${QODERCN_PROJECT_DIR:-$PWD}}}
3
+ // (对齐 qoder state-detect.sh 宿主注入链,与 claude-env.ts 同构)
4
+
5
+ /** 解析项目根目录(对齐 bash ${CLAUDE_PROJECT_DIR:-${QODER_PROJECT_DIR:-${QODERCN_PROJECT_DIR:-$PWD}}}) */
6
+ export function resolveQoderProjectDir(): string {
7
+ return (
8
+ process.env.CLAUDE_PROJECT_DIR ||
9
+ process.env.QODER_PROJECT_DIR ||
10
+ process.env.QODERCN_PROJECT_DIR ||
11
+ process.cwd()
12
+ )
13
+ }
14
+
15
+ /**
16
+ * 注入 PROJECT_DIR 到 process.env(对齐 bash export PROJECT_DIR)。
17
+ * 入口统一调用;后续 hash/路径计算均消费该值。
18
+ */
19
+ export function injectProjectDir(): string {
20
+ const dir = resolveQoderProjectDir()
21
+ process.env.PROJECT_DIR = dir
22
+ return dir
23
+ }
@@ -0,0 +1,5 @@
1
+ // lib/review-checklist.ts — 验收 Review 模式(Qoder CN 版,Task 4.1 收敛)
2
+ // R2 回流: review-checklist 逻辑已收敛 core governance/review-checklist-guard.ts
3
+ // (checkReviewQuality 逐字迁移 + specRoot 参数化);本文件仅 re-export 保持 import 兼容。
4
+
5
+ export { checkReviewQuality } from "../../../../core/governance/review-checklist-guard.js"
@@ -0,0 +1,34 @@
1
+ // notification.ts — Notification 入口(Qoder CN 版,Task 4.1 继承体系补全)
2
+ // 继承 core NotificationRouter,命名子类 QoderNotificationRouter:
3
+ // ① 兜底 magicDir = ".qoder"(构造参数注入——替代 bash 硬编码 ${PROJECT_DIR}/.qoder/reviews)
4
+ // ② emitReminder override: 无 Plan 前缀(qoder bash 原文逐字「[ADD Notification] 请检查 Review 文档」,
5
+ // 与 core 的 Plan 前缀文本差异保留——非能力漂移,qoder bash 原文如此)
6
+ // ③ 输出通道: stdout(qoder bash 原文 echo 无 >&2 重定向——违反 qoder JSON 规范但缺陷照搬,
7
+ // 归 Task 9.4 缺陷修复专项)
8
+ // 协议差异仅剩: PROJECT_DIR 注入链(qoder-env)
9
+
10
+ import { readHookInput } from "../../../core/governance/common.js"
11
+ import { NotificationRouter } from "../../../core/governance/notification-router.js"
12
+ import { injectProjectDir } from "./lib/qoder-env.js"
13
+
14
+ class QoderNotificationRouter extends NotificationRouter {
15
+ /** 协议差异封装: fallbackMagicDir = ".qoder"(qoder 端兜底,bash 原文硬编码语义) */
16
+ constructor(projectDir: string) {
17
+ super(projectDir, ".qoder")
18
+ }
19
+
20
+ /** ① qoder bash 原文硬编码 ${PROJECT_DIR}/.qoder/reviews——无跨端探测循环(协议差异,不做探测) */
21
+ protected override resolveMagicDir(): string {
22
+ return process.env.MAGIC_DIR ?? ".qoder"
23
+ }
24
+
25
+ /** ② qoder 提醒文本: 无 Plan 前缀(bash 原文逐字) */
26
+ protected override emitReminder(_plan: string, reviewsDir: string): void {
27
+ process.stdout.write(`[ADD Notification] 请检查 Review 文档: ${reviewsDir}\n`)
28
+ }
29
+ }
30
+
31
+ const input = readHookInput()
32
+ const PROJECT_DIR = injectProjectDir()
33
+
34
+ process.exit(new QoderNotificationRouter(PROJECT_DIR).run(input))
@@ -0,0 +1,26 @@
1
+ // permission-gate.ts — PermissionRequest 入口(Qoder CN 版,Task 4.1 继承体系补全)
2
+ // 继承 core PermissionGateRouter,命名子类 QoderPermissionGateRouter:
3
+ // ① emit override: 全量工具 stderr 日志(qoder bash 原文无条件输出——
4
+ // qoder 权限弹窗自行处理 Review 卡位;core 是仅高风险工具 stdout 提示)
5
+
6
+ import { readHookInput, tryResolveMagicDir } from "../../../core/governance/common.js"
7
+ import { PermissionGateRouter } from "../../../core/governance/permission-gate-router.js"
8
+
9
+ class QoderPermissionGateRouter extends PermissionGateRouter {
10
+ /** ① tool_name 缺失回退 "unknown"(bash jq `// \"unknown\"` 语义) */
11
+ protected override fallbackToolName(): string {
12
+ return "unknown"
13
+ }
14
+
15
+ /** ② qoder 协议: 全量工具 stderr 日志(bash 原文逐字) */
16
+ protected override emit(toolName: string): void {
17
+ process.stderr.write(`[ADD PermissionRequest] 工具 ${toolName} 请求权限。如有 Review 文档待确认,请先检查。\n`)
18
+ }
19
+ }
20
+
21
+ // 对齐 bash: MAGIC_DIR 由物理位置推导注入(替代 HOOK_DIR 局部变量 source 传递)
22
+ const inferred = tryResolveMagicDir()
23
+ if (inferred && !process.env.MAGIC_DIR) process.env.MAGIC_DIR = inferred
24
+
25
+ const input = readHookInput()
26
+ process.exit(new QoderPermissionGateRouter().run(input))
@@ -0,0 +1,30 @@
1
+ // post-tool-failure.ts — PostToolUseFailure 入口(Qoder CN 版,Task 4.1 继承体系补全)
2
+ // 继承 core PostToolFailureRouter,命名子类 QoderPostToolFailureRouter:
3
+ // ① emit override: stderr 回退建议(qoder bash 原文逐字——
4
+ // 「检查是否需要回退到上一 ADD Step 重新执行」;core 是 stdout 固定提示)
5
+
6
+ import { readHookInput, tryResolveMagicDir } from "../../../core/governance/common.js"
7
+ import { PostToolFailureRouter } from "../../../core/governance/post-tool-failure-router.js"
8
+
9
+ class QoderPostToolFailureRouter extends PostToolFailureRouter {
10
+ /** ① tool_name/error 缺失回退 "unknown"(bash jq `// \"unknown\"` 语义) */
11
+ protected override fallbackToolName(): string {
12
+ return "unknown"
13
+ }
14
+
15
+ protected override fallbackError(): string {
16
+ return "unknown"
17
+ }
18
+
19
+ /** ② qoder 协议: stderr 回退建议(bash 原文逐字) */
20
+ protected override emit(toolName: string, error: string): void {
21
+ process.stderr.write(`[ADD PostToolUseFailure] 工具 ${toolName} 失败: ${error}。检查是否需要回退到上一 ADD Step 重新执行。\n`)
22
+ }
23
+ }
24
+
25
+ // 对齐 bash: MAGIC_DIR 由物理位置推导注入
26
+ const inferred = tryResolveMagicDir()
27
+ if (inferred && !process.env.MAGIC_DIR) process.env.MAGIC_DIR = inferred
28
+
29
+ const input = readHookInput()
30
+ process.exit(new QoderPostToolFailureRouter().run(input))
@@ -0,0 +1,32 @@
1
+ // post-tool-use.ts — PostToolUse 入口(Qoder CN 版,Task 4.1 能力演进)
2
+ // 继承 core PostToolRouter;协议能力实证(2026-08-14 Qoder 官方文档):
3
+ // Qoder PostToolUse 事件支持 stdout JSON,专属字段 hookSpecificOutput.feedback
4
+ // (「反馈信息,会展示给用户」)——qoder 输出通道用 feedback JSON(能力演进,
5
+ // 非收敛降级);段落能力(§1 DPS + §2a-e + §3)对齐 core 全段(此前 qoder §1
6
+ // 缺分支为 bash 时代漂移,已补齐)。
7
+ // 协议差异: 输出通道 collectJson=true(feedback JSON)+ PROJECT_DIR 注入链
8
+
9
+ import { jsonGet, readHookInput, tryResolveMagicDir } from "../../../core/governance/common.js"
10
+ import { PostToolRouter } from "../../../core/governance/post-tool-router.js"
11
+ import { injectProjectDir } from "./lib/qoder-env.js"
12
+
13
+ injectProjectDir()
14
+ const inferred = tryResolveMagicDir()
15
+ if (inferred && !process.env.MAGIC_DIR) process.env.MAGIC_DIR = inferred
16
+ const PROJECT_DIR = process.env.PROJECT_DIR || process.cwd()
17
+ const MAGIC_DIR = process.env.MAGIC_DIR || ".qoder"
18
+
19
+ class QoderPostToolRouter extends PostToolRouter {
20
+ /** 输出通道: feedback JSON(Qoder 文档实证 PostToolUse 专属字段) */
21
+ protected override collectJson(): boolean {
22
+ return true
23
+ }
24
+ }
25
+
26
+ const input = readHookInput()
27
+ let toolName = jsonGet(input, "tool_name")
28
+ if (toolName === "") {
29
+ toolName = input.match(/"tool_name"\s*:\s*"([^"]*)"/)?.[1] ?? ""
30
+ }
31
+
32
+ process.exit(new QoderPostToolRouter(PROJECT_DIR, MAGIC_DIR).run(input, toolName))
@@ -0,0 +1,16 @@
1
+ // pre-compact.ts — 上下文压缩前 ADD 状态保存(Qoder CN 版,Task 4.1 继承体系补全)
2
+ // 继承 core PreCompactGuard,命名子类 QoderPreCompactGuard:
3
+ // ① 状态保存到恢复标记 + ② tpl 标记清理 = 基类(与 qoder bash 原文逐字同构,
4
+ // 2026-08-14 实态核验——手写版逻辑与 core 基类完全一致,收敛为子类)
5
+ // 协议差异仅剩: PROJECT_DIR 注入链(qoder-env)
6
+
7
+ import { PreCompactGuard } from "../../../core/governance/pre-compact-guard.js"
8
+ import { injectProjectDir } from "./lib/qoder-env.js"
9
+
10
+ class QoderPreCompactGuard extends PreCompactGuard {
11
+ // 当前无 override(状态保存/恢复清单/tpl 清理与 core 基线一致);命名子类承载端身份 + 未来演进位
12
+ }
13
+
14
+ injectProjectDir()
15
+
16
+ process.exit(new QoderPreCompactGuard().run())
@@ -0,0 +1,112 @@
1
+ // pre-tool-use.ts — PreToolUse 入口(Qoder CN 版,Task 4.1 继承体系)
2
+ // 继承 core PreToolUseGuard(模板方法固化治理流程);仅 override 协议差异(bash 原文逐字对照):
3
+ // ① 检测链: 构造传 adapterName="qoder" → 加载 [guard.adapter_detectors] qoder 独立链
4
+ // (与 claude 同构四段链,2026-08-14 实态核验)
5
+ // ② onBlock: stderr + stdout JSON deny(permissionDecision: deny)+ 事件 + exit 2(无 logBlock)
6
+ // ③ onSensitiveDeny: stderr + JSON deny + 事件 + exit 2(core 无事件上报)
7
+ // ④ onSectionAPass: Bash 放行 markDevAction(同 claude)
8
+ // ⑤ largeFileText: 「Qoder 40500」错误码提示(qoder IDE 特有)
9
+ // ⑥ onHitlDeny: JSON deny + additionalContext + exit 2 + event "ask"(core exit 0 + event "deny")
10
+ // ⑦ onOtherTool: ③ Read matcher 模板提示(同 claude)
11
+
12
+ import { jsonGet, readHookInput, tryResolveMagicDir } from "../../../core/governance/common.js"
13
+ import { writeHookEvent } from "../../../core/governance/notify.js"
14
+ import { PreToolUseGuard } from "../../../core/governance/pre-tool-guard.js"
15
+ import { markDevAction } from "../../../core/governance/common.js"
16
+ import { injectProjectDir } from "./lib/qoder-env.js"
17
+
18
+ injectProjectDir()
19
+ const inferred = tryResolveMagicDir()
20
+ if (inferred && !process.env.MAGIC_DIR) process.env.MAGIC_DIR = inferred
21
+ const PROJECT_DIR = process.env.PROJECT_DIR || process.cwd()
22
+ const MAGIC_DIR = process.env.MAGIC_DIR || ".qoder"
23
+
24
+ /** JSON deny 输出(Qoder PreToolUse 协议: permissionDecision deny) */
25
+ function denyJsonOut(reason: string): string {
26
+ return JSON.stringify({
27
+ hookSpecificOutput: {
28
+ hookEventName: "PreToolUse",
29
+ permissionDecision: "deny",
30
+ permissionDecisionReason: reason,
31
+ },
32
+ }) + "\n"
33
+ }
34
+
35
+ class QoderPreToolUseGuard extends PreToolUseGuard {
36
+ constructor(projectDir: string, magicDir: string) {
37
+ super(projectDir, magicDir, "qoder")
38
+ }
39
+
40
+ /** ② §A 阻断: stderr + JSON deny + 事件 + exit 2(无 logBlock) */
41
+ protected override onBlock(blocked: { reason: string; stderr: string }, command: string): number {
42
+ process.stderr.write(blocked.stderr.replaceAll("{{cmd}}", command))
43
+ process.stdout.write(denyJsonOut(blocked.reason))
44
+ writeHookEvent("pre-tool-use", "deny", command, blocked.reason, this.planKeyword, this.planStatus)
45
+ return 2
46
+ }
47
+
48
+ /** ③ §B 敏感文件: stderr + JSON deny + 事件 + exit 2 */
49
+ protected override onSensitiveDeny(filePath: string): number {
50
+ process.stderr.write(`⛔ 敏感文件受保护,禁止写入: ${filePath}\n`)
51
+ process.stdout.write(denyJsonOut("敏感文件受保护"))
52
+ writeHookEvent("pre-tool-use", "deny", filePath, "敏感文件受保护", this.planKeyword, this.planStatus)
53
+ return 2
54
+ }
55
+
56
+ /** ④ §A 放行后处理: bash 原文 mark_dev_action */
57
+ protected override onSectionAPass(_command: string): void {
58
+ markDevAction()
59
+ }
60
+
61
+ /** ⑤ 大文件提示: Qoder 40500 错误码(qoder IDE 特有) */
62
+ protected override largeFileText(fsize: number): string {
63
+ return `⚠️ [ADD PreToolUse] 文件已有 ${fsize} 字节,Write 全量覆盖可能触发 Qoder 40500。建议用 SearchReplace 分块追加。\n`
64
+ }
65
+
66
+ /** ⑥ HITL 未 tongyi: JSON deny + additionalContext + exit 2 + event "ask" */
67
+ protected override onHitlDeny(toolName: string, filePath: string, tongyiMarker: string): number {
68
+ process.stderr.write(`⛔ [ADD PreToolUse §C] HITL 未 tongyi: ${filePath}\n`)
69
+ process.stderr.write(` 原因: 哨兵文件 ${tongyiMarker} 不存在\n`)
70
+ process.stderr.write(` 操作: 请先调用 create_hitl 创建审批,再 update_hitl({ status: "TONGYI" })\n`)
71
+ const msg = `⛔ HITL 未 tongyi: 哨兵 ${tongyiMarker} 不存在。请先 create_hitl → 人工 tongyi → update_hitl 后再写入`
72
+ process.stdout.write(
73
+ JSON.stringify({
74
+ hookSpecificOutput: {
75
+ hookEventName: "PreToolUse",
76
+ permissionDecision: "deny",
77
+ permissionDecisionReason: msg,
78
+ additionalContext: msg,
79
+ },
80
+ }) + "\n"
81
+ )
82
+ writeHookEvent("pre-tool-use", "ask", `${toolName} ${filePath}`, `HITL 未 tongyi: ${tongyiMarker}`, this.planKeyword, this.planStatus)
83
+ return 2
84
+ }
85
+
86
+ /** ⑦ ③ Read matcher: 模板路径兜底提示 */
87
+ protected override onOtherTool(input: string, toolName: string): number {
88
+ if (toolName === "Read") {
89
+ const filePath = jsonGet(input, "file_path")
90
+ if (/templates\//.test(filePath)) {
91
+ process.stderr.write("[ADD PreToolUse] 提示: 模板文件已通过 hook 预读到上下文,可跳过重复读取\n")
92
+ }
93
+ }
94
+ return 0
95
+ }
96
+ }
97
+
98
+ const input = readHookInput()
99
+ let toolName = jsonGet(input, "tool_name")
100
+ if (toolName === "") {
101
+ toolName = input.match(/"tool_name"\s*:\s*"([^"]*)"/)?.[1] ?? ""
102
+ }
103
+
104
+ const guard = new QoderPreToolUseGuard(PROJECT_DIR, MAGIC_DIR)
105
+
106
+ if (toolName === "Bash") {
107
+ process.exit(guard.runSectionA(input))
108
+ } else if (toolName === "Write" || toolName === "Edit" || toolName === "SearchReplace") {
109
+ process.exit(guard.runSectionB(input, toolName))
110
+ } else {
111
+ process.exit(guard.runSectionC(input, toolName))
112
+ }