add-coder 0.2.7 → 0.2.10
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.en.md +23 -4
- package/README.md +77 -20
- package/dist/index.js +10 -0
- package/package.json +4 -11
- package/templates/adapters/claude/hooks/doc-format-guard.sh +17 -0
- package/templates/adapters/claude/hooks/lib/notify.sh +34 -0
- package/templates/adapters/claude/hooks/pre-tool-use.sh +26 -7
- package/templates/adapters/claude/hooks/prompt-submit.sh +16 -0
- package/templates/adapters/codex/hooks/doc-format-guard.sh +17 -0
- package/templates/adapters/codex/hooks/lib/notify.sh +34 -0
- package/templates/adapters/codex/hooks/pre-tool-use.sh +48 -18
- package/templates/adapters/codex/hooks/prompt-submit.sh +16 -0
- package/templates/adapters/qoder/hooks/doc-format-guard.sh +17 -0
- package/templates/adapters/qoder/hooks/lib/notify.sh +34 -0
- package/templates/adapters/qoder/hooks/pre-tool-use.sh +28 -9
- package/templates/adapters/qoder/hooks/prompt-submit.sh +18 -1
- package/templates/adapters/trae/hooks/doc-format-guard.sh +17 -0
- package/templates/adapters/trae/hooks/lib/notify.sh +34 -0
- package/templates/adapters/trae/hooks/pre-tool-use.sh +48 -18
- package/templates/adapters/trae/hooks/prompt-submit.sh +16 -0
- package/templates/adapters/vscode/hooks/doc-format-guard.sh +16 -0
- package/templates/adapters/vscode/hooks/lib/notify.sh +34 -0
- package/templates/adapters/vscode/hooks/pre-tool-use.sh +26 -7
- package/templates/adapters/vscode/hooks/prompt-submit.sh +16 -0
- package/templates/core/hooks/doc-format-guard.sh +17 -0
- package/templates/core/hooks/lib/notify.sh +34 -0
- package/templates/core/hooks/pre-tool-use.sh +48 -18
- package/templates/core/hooks/prompt-submit.sh +16 -0
- package/templates/core/reviews/.gitkeep +0 -0
- package/templates/core/scripts/mcp-server/elicitation/confirm.ts +30 -0
- package/templates/core/scripts/mcp-server/elicitation/index.ts +1 -0
- package/templates/core/scripts/mcp-server/index.ts +15 -0
- package/templates/core/scripts/mcp-server/notifications/hitl.ts +49 -0
- package/templates/core/scripts/mcp-server/notifications/hook.ts +268 -0
- package/templates/core/scripts/mcp-server/notifications/index.ts +8 -0
- package/templates/core/scripts/mcp-server/resources/add-coder-version.ts +25 -0
- package/templates/core/scripts/mcp-server/resources/add-state.ts +44 -0
- package/templates/core/scripts/mcp-server/resources/hook-events-report.ts +104 -0
- package/templates/core/scripts/mcp-server/resources/index.ts +12 -0
- package/templates/core/scripts/mcp-server/resources/round-task.ts +22 -0
- package/templates/core/scripts/mcp-server/sampling/index.ts +1 -0
- package/templates/core/scripts/mcp-server/sampling/review.ts +47 -0
- package/templates/core/scripts/mcp-server/shared/env.ts +26 -0
- package/templates/core/scripts/mcp-server/shared/fs.ts +40 -0
- package/templates/core/scripts/mcp-server/shared/prisma.ts +35 -0
- package/templates/core/scripts/mcp-server/shared/response.ts +9 -0
- package/templates/core/scripts/mcp-server/tasks/index.ts +2 -0
- package/templates/core/scripts/mcp-server/tasks/runner.ts +20 -0
- package/templates/core/scripts/mcp-server/tasks/store.ts +20 -0
- package/templates/core/scripts/mcp-server/tools/audit.ts +73 -0
- package/templates/core/scripts/mcp-server/tools/context.ts +337 -0
- package/templates/core/scripts/mcp-server/tools/docs.ts +42 -0
- package/templates/core/scripts/mcp-server/tools/gateway.ts +135 -0
- package/templates/core/scripts/mcp-server/tools/hook-event-report.ts +92 -0
- package/templates/core/scripts/mcp-server/tools/index.ts +17 -0
- package/templates/core/scripts/mcp-server/tools/quality.ts +93 -0
- package/templates/core/scripts/mcp-server/types.ts +7 -0
- package/templates/core/scripts/mcp-server.ts +8 -3455
package/README.en.md
CHANGED
|
@@ -27,7 +27,26 @@ Traditional AI development: Chat → Generate code → Dig through chat history
|
|
|
27
27
|
| Auditing relies on developer discipline | The **MCP audit toolchain** automatically records every operation; system gateways enforce checks |
|
|
28
28
|
| No traceability | Audit events are naturally linked: Plan → Spec → Task → Step → Tool Call, forming a complete evidence chain |
|
|
29
29
|
|
|
30
|
-
### ②
|
|
30
|
+
### ② Prompt Cache Native — ¥218/mo, 98% Savings
|
|
31
|
+
|
|
32
|
+
The ADD paradigm isn't just methodology — its structured Step workflow naturally aligns with DeepSeek's Prompt Cache prefix-matching mechanism, delivering extreme token cost efficiency. **Real-world billing validation**:
|
|
33
|
+
|
|
34
|
+
| Metric | Value |
|
|
35
|
+
|--------|-------|
|
|
36
|
+
| July actual DeepSeek bill | **¥218.35** |
|
|
37
|
+
| Theoretical cost without cache | ¥11,100 |
|
|
38
|
+
| Cache hit rate | **99.31%** |
|
|
39
|
+
| Cache hit vs miss price gap | **120x** (¥0.025/M vs ¥3/M) |
|
|
40
|
+
| Total cost savings | **98.1%** |
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Traditional IDE free chat: cache hit rate 85–91%, ~5,000 MISS tokens/req
|
|
44
|
+
ADD paradigm + Qoder: cache hit rate 99.31%, only 2,426 MISS tokens/req
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
> 📊 [Full analysis report](./docs/ADD范式缓存命中分析报告.md) — 4 Mermaid diagrams, 17-day daily data, cross-IDE comparison, and cost modeling.
|
|
48
|
+
|
|
49
|
+
### ③ Gateway-Driven, Not Free-Form Conversation
|
|
31
50
|
|
|
32
51
|
Traditional AI coding is "you say, I do" — quality depends entirely on the LLM's state that day. add-coder embeds **dual quality gateways** into the architecture:
|
|
33
52
|
|
|
@@ -38,7 +57,7 @@ RAHS (Runtime Architecture Health Score) — Runtime architecture health, < 90%
|
|
|
38
57
|
|
|
39
58
|
These are not "suggestions" — they are **architectural blocks**. A Step cannot advance without passing its gateway.
|
|
40
59
|
|
|
41
|
-
###
|
|
60
|
+
### ④ Cross-Session Memory, Not Per-Session Amnesia
|
|
42
61
|
|
|
43
62
|
The fatal flaw of AI conversations: architectural decisions from last session, bugs fixed, agreements reached — all forgotten in the next conversation. add-coder solves this at the architecture level:
|
|
44
63
|
|
|
@@ -46,7 +65,7 @@ The fatal flaw of AI conversations: architectural decisions from last session, b
|
|
|
46
65
|
- **Plan Index** — All Plans are centrally indexed via `index.md`, supporting fuzzy-match quick lookup
|
|
47
66
|
- **DevLog Timeline** — Every operation is written to the `{YYYY-MM}/{DD}/` timeline, enabling full historical state traceability
|
|
48
67
|
|
|
49
|
-
###
|
|
68
|
+
### ⑤ Policy-Update-Loop: Self-Evolving Governance (the scaffold itself does not include this architectural capability; a DEMO repo will be provided next to better illustrate the Policy-Update-Loop and Report system)
|
|
50
69
|
|
|
51
70
|
Not a static template, but a **closed-loop adaptive system**:
|
|
52
71
|
|
|
@@ -56,7 +75,7 @@ Execute → Audit → Boundary Report → Rule Adjustment → Next Execution
|
|
|
56
75
|
|
|
57
76
|
Runtime-generated Reports feed back into governance rules, enabling continuous evolution of governance strategies.
|
|
58
77
|
|
|
59
|
-
###
|
|
78
|
+
### ⑥ Multi-IDE Hooks as the Governance Layer
|
|
60
79
|
|
|
61
80
|
Hooks are not "notification push" — they are the **IDE runtime interception layer**:
|
|
62
81
|
|
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# add-coder
|
|
2
2
|
|
|
3
|
+
Make 0.75 into one.
|
|
4
|
+
|
|
3
5
|
> 🀄中文 | 🔤[English](#-english-readme)
|
|
4
6
|
|
|
5
7
|
**AI 代码治理的落地方案** — [codein2027](https://github.com/xiaomingming92/codein2027) 快速构建 ADD 编程范式的完整脚手架。以「审计即基础设施」为核心,彻底打破编程过程黑盒与跨轮失忆,让编程范式进化为可审计、可追溯、可收敛的新时代。 [NPM](https://www.npmjs.com/package/add-coder) · [GitHub](https://github.com/xiaomingming92/add-coder)
|
|
@@ -27,7 +29,26 @@ npx add-coder init
|
|
|
27
29
|
| 审计靠开发者自觉记录 | **MCP 审计工具链** 自动记录每次操作,系统闸门强制检查 |
|
|
28
30
|
| 无关联性 | 审计事件天然关联 Plan → Spec → Task → Step → Tool Call,形成完整证据链 |
|
|
29
31
|
|
|
30
|
-
### ②
|
|
32
|
+
### ② Prompt Cache 原生友好 — 月费 ¥218,节省 98%
|
|
33
|
+
|
|
34
|
+
ADD 范式不仅是方法论——它的结构化 Step 流程天然适配 DeepSeek Prompt Cache 的前缀匹配机制,带来极致的 Token 成本效率。**实测数据验证**:
|
|
35
|
+
|
|
36
|
+
| 指标 | 数值 |
|
|
37
|
+
|------|------|
|
|
38
|
+
| DeepSeek 7月实际账单 | **¥218.35** |
|
|
39
|
+
| 若无 Prompt Cache 理论费用 | ¥11,100 |
|
|
40
|
+
| Cache 命中率 | **99.31%** |
|
|
41
|
+
| 缓存命中 vs 未命中价差 | **120 倍**(¥0.025/M vs ¥3/M) |
|
|
42
|
+
| 总费用节省 | **98.1%** |
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
传统 IDE 自由对话: cache 命中率 85-91%, 每次请求 MISS 5,000 tokens
|
|
46
|
+
ADD 范式 + Qoder: cache 命中率 99.31%, 每次请求 MISS 仅 2,426 tokens
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
> 📊 [完整分析报告](./docs/ADD范式缓存命中分析报告.md) — 含 4 张 Mermaid 图表、17 天逐日数据、跨 IDE 对比与成本建模。
|
|
50
|
+
|
|
51
|
+
### ③ 门禁驱动,而非自由对话
|
|
31
52
|
|
|
32
53
|
传统 AI coding 是「你说我做」,质量完全依赖 LLM 当天状态。add-coder 在架构中嵌入了 **双质量闸门**:
|
|
33
54
|
|
|
@@ -38,7 +59,7 @@ RAHS (Runtime Architecture Health Score) — 运行时架构健康度,< 90% BL
|
|
|
38
59
|
|
|
39
60
|
这不是「建议」,是**架构阻断** — 不通过闸门的 Step 无法推进到下一步。
|
|
40
61
|
|
|
41
|
-
###
|
|
62
|
+
### ④ 跨轮记忆,而非每轮失忆
|
|
42
63
|
|
|
43
64
|
AI 对话的致命缺陷:上次讨论的架构决策、已修复的 Bug、达成的约定,下轮对话全部遗忘。add-coder 在架构层面解决:
|
|
44
65
|
|
|
@@ -46,7 +67,7 @@ AI 对话的致命缺陷:上次讨论的架构决策、已修复的 Bug、达
|
|
|
46
67
|
- **Plan 索引** — 所有 Plan 通过 `index.md` 集中索引,支持模糊匹配快速定位
|
|
47
68
|
- **DevLog 时序记录** — 每一步操作写入 `{YYYY-MM}/{DD}/` 时间轴,可回溯任意历史状态
|
|
48
69
|
|
|
49
|
-
###
|
|
70
|
+
### ⑤ Policy-Update-Loop:治理自我进化(脚手架不包含此架构能力,接下来会给到DEMO仓库让大家更好理解Policy-Update-Loop和Report体系)
|
|
50
71
|
|
|
51
72
|
不是静态模板,而是**闭环自适应系统**:
|
|
52
73
|
|
|
@@ -56,7 +77,7 @@ AI 对话的致命缺陷:上次讨论的架构决策、已修复的 Bug、达
|
|
|
56
77
|
|
|
57
78
|
运行时产生的 Report 会反过来更新 governance rules,实现治理策略的持续进化。
|
|
58
79
|
|
|
59
|
-
###
|
|
80
|
+
### ⑥ 多 IDE 的 Hook 即治理层
|
|
60
81
|
|
|
61
82
|
hook 不是「通知推送」,而是 **ADD 范式在 IDE agent 生命周期中的 17 个确定性治理卡位**。每个 IDE(Claude Code / Qoder CN / VS Code Copilot / Trae / Codex)有各自的 hook 机制,但治理逻辑统一——架构一致,适配层不同。
|
|
62
83
|
|
|
@@ -134,7 +155,21 @@ npx add-coder init
|
|
|
134
155
|
|
|
135
156
|
## MCP 审计工具链
|
|
136
157
|
|
|
137
|
-
`init` 自动部署 MCP 服务器 (`mcp-server.ts`) 到项目中,IDE 通过 `mcp.json`
|
|
158
|
+
`init` 自动部署 MCP 服务器 (`mcp-server.ts`) 到项目中,IDE 通过 `mcp.json` 加载。基于 **MCP 协议六大能力**(四大原语 + 两个横切):
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
MCP 能力 方向 当前状态 说明
|
|
162
|
+
─────────────────────────────────────────────────────────────
|
|
163
|
+
Tools Client→Server ✅ 已实现 18 个审计与治理工具(pull 模式)
|
|
164
|
+
Resources+Sub Client←Server ✅ 已实现 8 个端点 Plan/Review/Route/Task/Hook 状态推送
|
|
165
|
+
Notifications Server→Client ✅ 已实现 HITL 就绪 + Hook 拦截事件推送
|
|
166
|
+
Sampling Server→Client ✅ 已实现 服务端回调 AI 生成 Review (HITL 两步法)
|
|
167
|
+
── 横切 ──
|
|
168
|
+
Elicitation Server→Client ✅ 已实现 向用户请求 HITL 确认/风险输入
|
|
169
|
+
Tasks (实验性) 双向 ✅ 已实现 长任务持久化 + 状态追踪
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**当前已实现的 18 个 Tools**:
|
|
138
173
|
|
|
139
174
|
| 工具 | 用途 | 触发场景 |
|
|
140
175
|
|------|------|---------|
|
|
@@ -147,8 +182,9 @@ npx add-coder init
|
|
|
147
182
|
| `check_add_route_status` | add-route 文件存在性校验 | Step 3 前 |
|
|
148
183
|
| `check_spec_sync` | Spec 文档勾选状态与代码一致性 | Spec 执行后 |
|
|
149
184
|
| `find_related_docs` | 检索相关架构/规范文档 | 语境理解 |
|
|
185
|
+
| `get_hook_events` | 查询 Hook 拦截事件(planKeyword/hook/时间过滤+分组) | 治理审计、阈值告警 |
|
|
150
186
|
|
|
151
|
-
>
|
|
187
|
+
> 完整六能力架构设计见 [MCP 重构 Plan](.qoder/plans/2026-07/23/add-coder-mcp-restructure-plan-v1.md)。
|
|
152
188
|
|
|
153
189
|
## 架构全景
|
|
154
190
|
|
|
@@ -213,11 +249,12 @@ npx add-coder init
|
|
|
213
249
|
|
|
214
250
|
## 🎬 预告
|
|
215
251
|
|
|
216
|
-
| 计划 | 说明
|
|
217
|
-
|
|
218
|
-
| Demo 仓库演示 | 提供完整示例仓库,展示 Policy-Update-Loop 与 Report 体系的端到端闭环实践
|
|
219
|
-
| MCP 能力重构 | MCP 工具链架构升级,提升审计与门禁工具的可扩展性和独立部署能力 |
|
|
220
|
-
|
|
|
252
|
+
| 计划 | 说明 |备注|
|
|
253
|
+
|------|------|------|
|
|
254
|
+
| Demo 仓库演示 | 提供完整示例仓库,展示 Policy-Update-Loop 与 Report 体系的端到端闭环实践 |--|
|
|
255
|
+
| MCP 能力重构 | ✅ v0.2.9 MCP 工具链架构升级,提升审计与门禁工具的可扩展性和独立部署能力 | 2026-07/23/add-coder-mcp-restructure-plan-v1.md |
|
|
256
|
+
| Hook 通知升级 | ✅ v0.2.9 Hook 拦截事件 jsonl → fs.watch → record_dev_operation 落库 + Notification + 治理信号 | 2026-07/24/add-coder-hook-notify-upgrade-plan-v1.md |
|
|
257
|
+
| 对话记忆增强 | 长期项目知识记忆和plan级别的稀疏记忆 |--|
|
|
221
258
|
|
|
222
259
|
|
|
223
260
|
|
|
@@ -249,7 +286,26 @@ Traditional AI development: Chat → Generate code → Dig through chat history
|
|
|
249
286
|
| Auditing relies on developer discipline | The **MCP audit toolchain** automatically records every operation; system gateways enforce checks |
|
|
250
287
|
| No traceability | Audit events are naturally linked: Plan → Spec → Task → Step → Tool Call, forming a complete evidence chain |
|
|
251
288
|
|
|
252
|
-
### ②
|
|
289
|
+
### ② Prompt Cache Native — ¥218/mo, 98% Savings
|
|
290
|
+
|
|
291
|
+
The ADD paradigm isn't just methodology — its structured Step workflow naturally aligns with DeepSeek's Prompt Cache prefix-matching mechanism, delivering extreme token cost efficiency. **Real-world billing validation**:
|
|
292
|
+
|
|
293
|
+
| Metric | Value |
|
|
294
|
+
|--------|-------|
|
|
295
|
+
| July actual DeepSeek bill | **¥218.35** |
|
|
296
|
+
| Theoretical cost without cache | ¥11,100 |
|
|
297
|
+
| Cache hit rate | **99.31%** |
|
|
298
|
+
| Cache hit vs miss price gap | **120x** (¥0.025/M vs ¥3/M) |
|
|
299
|
+
| Total cost savings | **98.1%** |
|
|
300
|
+
|
|
301
|
+
```
|
|
302
|
+
Traditional IDE free chat: cache hit rate 85–91%, ~5,000 MISS tokens/req
|
|
303
|
+
ADD paradigm + Qoder: cache hit rate 99.31%, only 2,426 MISS tokens/req
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
> 📊 [Full analysis report](./docs/ADD范式缓存命中分析报告.md) — 4 Mermaid diagrams, 17-day daily data, cross-IDE comparison, and cost modeling.
|
|
307
|
+
|
|
308
|
+
### ③ Gateway-Driven, Not Free-Form Conversation
|
|
253
309
|
|
|
254
310
|
Traditional AI coding is "you say, I do" — quality depends entirely on the LLM's state that day. add-coder embeds **dual quality gateways** into the architecture:
|
|
255
311
|
|
|
@@ -260,7 +316,7 @@ RAHS (Runtime Architecture Health Score) — Runtime architecture health, < 90%
|
|
|
260
316
|
|
|
261
317
|
These are not "suggestions" — they are **architectural blocks**. A Step cannot advance without passing its gateway.
|
|
262
318
|
|
|
263
|
-
###
|
|
319
|
+
### ④ Cross-Session Memory, Not Per-Session Amnesia
|
|
264
320
|
|
|
265
321
|
The fatal flaw of AI conversations: architectural decisions from last session, bugs fixed, agreements reached — all forgotten in the next conversation. add-coder solves this at the architecture level:
|
|
266
322
|
|
|
@@ -268,7 +324,7 @@ The fatal flaw of AI conversations: architectural decisions from last session, b
|
|
|
268
324
|
- **Plan Index** — All Plans are centrally indexed via `index.md`, supporting fuzzy-match quick lookup
|
|
269
325
|
- **DevLog Timeline** — Every operation is written to the `{YYYY-MM}/{DD}/` timeline, enabling full historical state traceability
|
|
270
326
|
|
|
271
|
-
###
|
|
327
|
+
### ⑤ Policy-Update-Loop: Self-Evolving Governance (the scaffold itself does not include this architectural capability; a DEMO repo will be provided next to better illustrate the Policy-Update-Loop and Report system)
|
|
272
328
|
|
|
273
329
|
Not a static template, but a **closed-loop adaptive system**:
|
|
274
330
|
|
|
@@ -278,7 +334,7 @@ Execute → Audit → Boundary Report → Rule Adjustment → Next Execution
|
|
|
278
334
|
|
|
279
335
|
Runtime-generated Reports feed back into governance rules, enabling continuous evolution of governance strategies.
|
|
280
336
|
|
|
281
|
-
###
|
|
337
|
+
### ⑥ Multi-IDE Hooks as the Governance Layer
|
|
282
338
|
|
|
283
339
|
Hooks are not "notification push" — they are the **IDE runtime interception layer**:
|
|
284
340
|
|
|
@@ -445,10 +501,11 @@ npx add-coder init
|
|
|
445
501
|
|
|
446
502
|
## 🎬 Coming Soon
|
|
447
503
|
|
|
448
|
-
| Plan | Description |
|
|
449
|
-
|
|
450
|
-
| Demo Repo |
|
|
451
|
-
| MCP Restructure |
|
|
452
|
-
|
|
|
504
|
+
| Plan | Description | remark |
|
|
505
|
+
|------|-------------|:---:|
|
|
506
|
+
| Demo Repo | Full example repository showcasing Policy-Update-Loop with Report system end-to-end | 📋 |
|
|
507
|
+
| ~~MCP Restructure~~ | ✅ v0.2.9 3,467-line monolith → 27 modules covering all six MCP primitives | 2026-07/23/... |
|
|
508
|
+
| ~~Hook Notification Upgrade~~ | ✅ v0.2.9 ~36 files: hook intercept → jsonl → fs.watch → record_dev_operation | 2026-07/24/... |
|
|
509
|
+
| Memory Enhancement | Long-term project knowledge memory and plan-level sparse memory | 📋 |
|
|
453
510
|
|
|
454
511
|
---
|
package/dist/index.js
CHANGED
|
@@ -893,6 +893,16 @@ async function renderAndWrite(ctx) {
|
|
|
893
893
|
for (const [p, c] of claudeFiles) allFiles.set(p, c);
|
|
894
894
|
console.log(`claude adapter (via Agent Host): ${claudeFiles.size} \u6587\u4EF6`);
|
|
895
895
|
}
|
|
896
|
+
for (const d of [".add", magicDir]) {
|
|
897
|
+
const reviewsDir = resolve5(projectRoot, d, "reviews");
|
|
898
|
+
if (!existsSync6(reviewsDir)) {
|
|
899
|
+
if (dry) {
|
|
900
|
+
console.log(`[dry-run] \u5C06\u521B\u5EFA ${reviewsDir}/`);
|
|
901
|
+
} else {
|
|
902
|
+
mkdirSync3(reviewsDir, { recursive: true });
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
}
|
|
896
906
|
return await writeFiles2(projectRoot, allFiles, { force: options.force, dryRun: options.dryRun });
|
|
897
907
|
}
|
|
898
908
|
async function deployDatabase(ctx) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "add-coder",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "[codein2027](https://github.com/xiaomingming92/codein2027) - A complete scaffolding for building the ADD programming paradigm, the implementation layer for AI code governance. Core principle: Audit as Infrastructure. Breaks the black-box programming process and cross-session amnesia, evolving programming paradigms into an auditable, traceable, and convergent new era. npx-ready.\n\n[codein2027](https://github.com/xiaomingming92/codein2027) 快速构建 ADD 编程范式的完整脚手架——AI 代码治理的落地方案。以「审计即基础设施」为核心,彻底打破编程过程黑盒与跨轮失忆,让编程范式进化为可审计、可追溯、可收敛的新时代。npx 即用,人人可体验。",
|
|
6
6
|
"repository": {
|
|
@@ -38,19 +38,18 @@
|
|
|
38
38
|
"email": "wujixmm@gmail.com",
|
|
39
39
|
"license": "AGPL-3.0-only",
|
|
40
40
|
"dependencies": {
|
|
41
|
+
"@modelcontextprotocol/server": "2.0.0-beta.5",
|
|
41
42
|
"commander": "^13.1.0",
|
|
42
43
|
"smol-toml": "^1.7.0",
|
|
43
|
-
"zod": "^
|
|
44
|
+
"zod": "^4.4.3"
|
|
44
45
|
},
|
|
45
46
|
"peerDependencies": {
|
|
46
|
-
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
47
47
|
"@prisma/adapter-libsql": "^7.0.0",
|
|
48
48
|
"@prisma/adapter-pg": "^7.0.0",
|
|
49
49
|
"@prisma/client": "^7.0.0",
|
|
50
50
|
"dotenv": "*",
|
|
51
51
|
"prisma": "^7.0.0",
|
|
52
|
-
"tsx": "
|
|
53
|
-
"zod": "^3.24.0"
|
|
52
|
+
"tsx": ">=4"
|
|
54
53
|
},
|
|
55
54
|
"peerDependenciesMeta": {
|
|
56
55
|
"@prisma/client": {
|
|
@@ -59,12 +58,6 @@
|
|
|
59
58
|
"prisma": {
|
|
60
59
|
"optional": false
|
|
61
60
|
},
|
|
62
|
-
"@modelcontextprotocol/sdk": {
|
|
63
|
-
"optional": false
|
|
64
|
-
},
|
|
65
|
-
"zod": {
|
|
66
|
-
"optional": false
|
|
67
|
-
},
|
|
68
61
|
"dotenv": {
|
|
69
62
|
"optional": false
|
|
70
63
|
},
|
|
@@ -8,6 +8,18 @@ input=$(cat)
|
|
|
8
8
|
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
9
9
|
PARENT_DIR="$(dirname "$HOOK_DIR")"
|
|
10
10
|
MAGIC_DIR="$(basename "$PARENT_DIR")"
|
|
11
|
+
PROJECT_DIR="$PWD"
|
|
12
|
+
|
|
13
|
+
# ── Hook 通知: 拦截事件写入 jsonl(旁路,失败不阻断 exit 2)──
|
|
14
|
+
source "${HOOK_DIR}/lib/notify.sh" 2>/dev/null || true
|
|
15
|
+
ACTIVE_PLAN=$(detect_active_add 2>/dev/null || true)
|
|
16
|
+
if [ -n "$ACTIVE_PLAN" ]; then
|
|
17
|
+
PLAN_KEYWORD="${ACTIVE_PLAN%%::*}"
|
|
18
|
+
PLAN_STATUS="active"
|
|
19
|
+
else
|
|
20
|
+
PLAN_KEYWORD="no-active-plan"
|
|
21
|
+
PLAN_STATUS="none"
|
|
22
|
+
fi
|
|
11
23
|
|
|
12
24
|
# DEBUG: dump stdin for investigation
|
|
13
25
|
mkdir -p "$MAGIC_DIR/debug-dump"
|
|
@@ -44,6 +56,7 @@ CONTENT=$(echo "$input" | jq -r '
|
|
|
44
56
|
if [ -z "$CONTENT" ]; then
|
|
45
57
|
echo "⛔ 拒绝:Write 工具未传 file_content,无法校验手写文档格式" >&2
|
|
46
58
|
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"ask","permissionDecisionReason":"Write 工具未传 file_content,无法校验手写文档。请用 SearchReplace 改写已有文件,或用 Write 工具重试。"}}'
|
|
59
|
+
write_hook_event "doc-format-guard" "deny" "Write" "Write 工具未传 file_content" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
47
60
|
exit 2
|
|
48
61
|
fi
|
|
49
62
|
|
|
@@ -91,6 +104,7 @@ if [ -z "$TEMPLATE_NAME" ]; then
|
|
|
91
104
|
else
|
|
92
105
|
echo "⛔ handoff 文件内容无法识别模板类型(缺 '## 全局元信息' 或 '## 1. 交接前状态'),拒绝写入" >&2
|
|
93
106
|
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"ask","permissionDecisionReason":"handoff 内容不符合 single/multi 模板规范"}}'
|
|
107
|
+
write_hook_event "doc-format-guard" "deny" "$file_path" "handoff 模板类型无法识别" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
94
108
|
exit 2
|
|
95
109
|
fi
|
|
96
110
|
;;
|
|
@@ -111,6 +125,7 @@ if [ -z "$TEMPLATE_NAME" ]; then
|
|
|
111
125
|
fi
|
|
112
126
|
echo "⛔ 拒绝:无法识别文档类型 (file_path: $file_path),缺少模板匹配规则" >&2
|
|
113
127
|
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"ask","permissionDecisionReason":"无法识别 ADD 文档类型,请联系管理员更新 doc-format-guard.sh"}}'
|
|
128
|
+
write_hook_event "doc-format-guard" "deny" "$file_path" "无法识别文档类型" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
114
129
|
exit 2
|
|
115
130
|
;;
|
|
116
131
|
esac
|
|
@@ -122,6 +137,7 @@ SCHEMA_FILE="$TEMPLATES_DIR/${TEMPLATE_NAME%.md}.schema.json"
|
|
|
122
137
|
if [ ! -f "$SCHEMA_FILE" ]; then
|
|
123
138
|
echo "⛔ 阻断:模板 ${TEMPLATE_NAME} 缺少对应的 .schema.json 校验规则" >&2
|
|
124
139
|
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"ask","permissionDecisionReason":"缺少 .schema.json 校验规则文件,禁止无规则放行"}}'
|
|
140
|
+
write_hook_event "doc-format-guard" "deny" "$file_path" "缺少 .schema.json 校验规则" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
125
141
|
exit 2
|
|
126
142
|
fi
|
|
127
143
|
|
|
@@ -172,6 +188,7 @@ if [ -n "$ISSUES" ]; then
|
|
|
172
188
|
echo "⛔ $TEMPLATE_NAME 校验不通过:
|
|
173
189
|
$ISSUES" >&2
|
|
174
190
|
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"ask\",\"permissionDecisionReason\":\"文档格式校验不通过,请对照模板修正\"}}"
|
|
191
|
+
write_hook_event "doc-format-guard" "deny" "$file_path" "文档格式校验不通过" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
175
192
|
exit 2
|
|
176
193
|
fi
|
|
177
194
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# notify.sh — Hook 拦截事件写入 jsonl(零外部依赖,bash 原生)
|
|
3
|
+
# 用法: source 后在 exit 2 前调用 write_hook_event
|
|
4
|
+
#
|
|
5
|
+
# 写入格式(7 字段 jsonl):
|
|
6
|
+
# {"ts":"ISO8601","hook":"...","decision":"deny","cmd":"...","reason":"...","planKeyword":"...","planStatus":"..."}
|
|
7
|
+
#
|
|
8
|
+
# 磁盘管理:
|
|
9
|
+
# - 单文件 ≤256KB,超限轮转为 .old(覆盖,不累积多份)
|
|
10
|
+
# - 总量 ≤512KB(当前 + 一个 .old)
|
|
11
|
+
# - MCP Server 宕机不丢事件,重启后从文件恢复消费
|
|
12
|
+
|
|
13
|
+
write_hook_event() {
|
|
14
|
+
local hook="$1" decision="$2" cmd="$3" reason="$4" plan="${5:-unknown}" status="${6:-none}"
|
|
15
|
+
local dir="${MAGIC_DIR:-.qoder}/reports"
|
|
16
|
+
mkdir -p "$dir" 2>/dev/null || true
|
|
17
|
+
local file="$dir/hook-events.jsonl"
|
|
18
|
+
|
|
19
|
+
# 超过 256KB 自动轮转(262144 bytes)
|
|
20
|
+
if [ -f "$file" ]; then
|
|
21
|
+
local sz
|
|
22
|
+
sz=$(stat -c%s "$file" 2>/dev/null || echo 0)
|
|
23
|
+
[ "$sz" -gt 262144 ] && mv "$file" "${file}.old" 2>/dev/null || true
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
printf '{"ts":"%s","hook":"%s","decision":"%s","cmd":"%s","reason":"%s","planKeyword":"%s","planStatus":"%s"}\n' \
|
|
27
|
+
"$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
28
|
+
"$hook" \
|
|
29
|
+
"$decision" \
|
|
30
|
+
"$cmd" \
|
|
31
|
+
"$reason" \
|
|
32
|
+
"$plan" \
|
|
33
|
+
"$status" >> "$file"
|
|
34
|
+
}
|
|
@@ -7,6 +7,17 @@ HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
|
7
7
|
export CURRENT_MAGIC=$(basename "$(dirname "$HOOK_DIR")")
|
|
8
8
|
COMMON_LIB="$HOOK_DIR/lib/common.sh"
|
|
9
9
|
[ -f "$COMMON_LIB" ] && source "$COMMON_LIB"
|
|
10
|
+
[ -f "$HOOK_DIR/lib/notify.sh" ] && source "$HOOK_DIR/lib/notify.sh" 2>/dev/null || true
|
|
11
|
+
|
|
12
|
+
# ── Hook 通知: 提前计算 Plan 关联信息 ──
|
|
13
|
+
ACTIVE_PLAN=$(detect_active_add 2>/dev/null || true)
|
|
14
|
+
if [ -n "$ACTIVE_PLAN" ]; then
|
|
15
|
+
PLAN_KEYWORD="${ACTIVE_PLAN%%::*}"
|
|
16
|
+
PLAN_STATUS="active"
|
|
17
|
+
else
|
|
18
|
+
PLAN_KEYWORD="no-active-plan"
|
|
19
|
+
PLAN_STATUS="none"
|
|
20
|
+
fi
|
|
10
21
|
|
|
11
22
|
input=$(parse_input)
|
|
12
23
|
tool_name=$(json_get "$input" "tool_name")
|
|
@@ -20,21 +31,25 @@ if [ "$tool_name" = "Bash" ]; then
|
|
|
20
31
|
# 危险命令
|
|
21
32
|
if echo "$cmd" | grep -qiE 'rm[[:space:]]+-rf[[:space:]]+/|DROP[[:space:]]+TABLE|git[[:space:]]+push[[:space:]]+--force|mkfs\.|dd[[:space:]]+if='; then
|
|
22
33
|
echo "⛔ 危险命令已被阻止: $cmd" >&2
|
|
34
|
+
write_hook_event "pre-tool-use" "deny" "$cmd" "危险命令已被阻止" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
23
35
|
exit $EXIT_BLOCK
|
|
24
36
|
fi
|
|
25
37
|
# 终端写文件拦截(含 > / >> / << heredoc / mv / touch / python -c > file)
|
|
26
38
|
if echo "$cmd" | grep -qE '(cat|echo|tee|sed[[:space:]]+-i|awk|printf|cp|mv|dd|touch)[[:space:]]*.*([>]{1,2}|[|][[:space:]]*tee|<<)'; then
|
|
27
39
|
echo "⛔ 禁止通过终端命令直接写文件: $cmd。请使用 Write/Edit/SearchReplace 工具。" >&2
|
|
40
|
+
write_hook_event "pre-tool-use" "deny" "$cmd" "禁止通过终端直接写文件" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
28
41
|
exit $EXIT_BLOCK
|
|
29
42
|
fi
|
|
30
|
-
# mv
|
|
31
|
-
if echo "$cmd" | grep -qE '
|
|
32
|
-
echo "⛔ 禁止通过 mv
|
|
43
|
+
# cp / mv / touch — 可创建或覆盖文件,无重定向也拦(对齐 core §A 检测5)
|
|
44
|
+
if echo "$cmd" | grep -qE '(^|;|\|\||&&|\|)\s*(cp|mv|touch)\b'; then
|
|
45
|
+
echo "⛔ 禁止通过 cp/mv/touch 操作文件: $cmd。请使用 Write 或 SearchReplace 工具。" >&2
|
|
46
|
+
write_hook_event "pre-tool-use" "deny" "$cmd" "禁止通过 cp/mv/touch 操作文件" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
33
47
|
exit $EXIT_BLOCK
|
|
34
48
|
fi
|
|
35
|
-
# python/node
|
|
36
|
-
if echo "$cmd" | grep -qE '(python3|
|
|
37
|
-
echo "⛔
|
|
49
|
+
# python/node/ruby/perl/php 脚本解释器 — 可写任意文件
|
|
50
|
+
if echo "$cmd" | grep -qE '(^|;|\|\||&&|\|)\s*(python3?|node|ruby|perl|php)(\s|$)'; then
|
|
51
|
+
echo "⛔ 禁止通过脚本解释器直接写文件: $cmd。请使用 Write 或 SearchReplace 工具。" >&2
|
|
52
|
+
write_hook_event "pre-tool-use" "deny" "$cmd" "禁止通过脚本解释器直接修改文件" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
38
53
|
exit $EXIT_BLOCK
|
|
39
54
|
fi
|
|
40
55
|
mark_dev_action
|
|
@@ -51,7 +66,10 @@ if [ "$tool_name" = "Write" ] || [ "$tool_name" = "Edit" ]; then
|
|
|
51
66
|
if type detect_active_add >/dev/null 2>&1; then
|
|
52
67
|
state=$(detect_active_add 2>/dev/null || true)
|
|
53
68
|
if [ -z "$state" ]; then
|
|
54
|
-
echo "
|
|
69
|
+
echo "⛔ 正在写入 Plan/Spec/Review 文档但无活跃 ADD Plan——请先执行 add-paradigm" >&2
|
|
70
|
+
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"Plan/Spec/Review 写入需要活跃 ADD Plan,请先执行 add-paradigm\"}}"
|
|
71
|
+
write_hook_event "pre-tool-use" "deny" "$file_path" "Plan/Spec/Review 写入需活跃 ADD Plan" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
72
|
+
exit $EXIT_BLOCK
|
|
55
73
|
fi
|
|
56
74
|
fi
|
|
57
75
|
fi
|
|
@@ -59,6 +77,7 @@ if [ "$tool_name" = "Write" ] || [ "$tool_name" = "Edit" ]; then
|
|
|
59
77
|
# 敏感文件保护
|
|
60
78
|
if echo "$file_path" | grep -qE '\.env$|\.env\.production$|\.env\.local$|credentials|secrets'; then
|
|
61
79
|
echo "⛔ 敏感文件受保护,禁止写入: $file_path" >&2
|
|
80
|
+
write_hook_event "pre-tool-use" "deny" "$file_path" "敏感文件受保护" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
62
81
|
exit $EXIT_BLOCK
|
|
63
82
|
fi
|
|
64
83
|
|
|
@@ -8,6 +8,7 @@ export CURRENT_MAGIC=$(basename "$(dirname "$HOOK_DIR")")
|
|
|
8
8
|
|
|
9
9
|
COMMON_LIB="$HOOK_DIR/lib/common.sh"
|
|
10
10
|
[ -f "$COMMON_LIB" ] && source "$COMMON_LIB"
|
|
11
|
+
[ -f "$HOOK_DIR/lib/notify.sh" ] && source "$HOOK_DIR/lib/notify.sh" 2>/dev/null || true
|
|
11
12
|
|
|
12
13
|
export PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$PWD}"
|
|
13
14
|
|
|
@@ -56,6 +57,7 @@ if [ -z "$state" ]; then
|
|
|
56
57
|
Step 8: 收敛判断
|
|
57
58
|
如果 add-paradigm SKILL 尚未激活,请先调用它。
|
|
58
59
|
EOF
|
|
60
|
+
write_hook_event "prompt-submit" "deny" "$prompt" "无活跃 ADD Plan 下检测到开发任务" "no-active-plan" "none" 2>/dev/null || true
|
|
59
61
|
exit 2
|
|
60
62
|
fi
|
|
61
63
|
|
|
@@ -69,6 +71,20 @@ cat <<EOF
|
|
|
69
71
|
handoff: ${handoff}
|
|
70
72
|
EOF
|
|
71
73
|
|
|
74
|
+
# ─── Hook 治理日报(注入 AI 上下文)───
|
|
75
|
+
HOOK_JSONL="${MAGIC_DIR:-.qoder}/reports/hook-events.jsonl"
|
|
76
|
+
if [ -f "$HOOK_JSONL" ]; then
|
|
77
|
+
TODAY="$(date +%Y-%m-%d)"
|
|
78
|
+
TOTAL=$(grep -c "\"ts\":\"${TODAY}" "$HOOK_JSONL" 2>/dev/null || echo 0)
|
|
79
|
+
NO_PLAN=$(grep "\"ts\":\"${TODAY}" "$HOOK_JSONL" 2>/dev/null | grep -c '"planKeyword":"no-active-plan"' || echo 0)
|
|
80
|
+
if [ "$TOTAL" -gt 0 ] 2>/dev/null; then
|
|
81
|
+
echo "[Hook 治理] 今日拦截: ${TOTAL} 次 | 无 Plan 违规: ${NO_PLAN} 次"
|
|
82
|
+
if [ "$NO_PLAN" -ge 10 ] 2>/dev/null; then
|
|
83
|
+
echo "[Hook ⚠️] 无 Plan 违规已达 ${NO_PLAN} 次(≥10),建议创建 Plan"
|
|
84
|
+
fi
|
|
85
|
+
fi
|
|
86
|
+
fi
|
|
87
|
+
|
|
72
88
|
# 模板全文注入(tpl-injected 去重)
|
|
73
89
|
TPL_SCRIPT="$HOOK_DIR/lib/preload-templates.sh"
|
|
74
90
|
if [ -f "$TPL_SCRIPT" ]; then
|
|
@@ -5,6 +5,18 @@ set -euo pipefail
|
|
|
5
5
|
input=$(cat)
|
|
6
6
|
|
|
7
7
|
MAGIC_DIR=".codex"
|
|
8
|
+
PROJECT_DIR="$PWD"
|
|
9
|
+
|
|
10
|
+
# ── Hook 通知: 拦截事件写入 jsonl(旁路,失败不阻断 exit 2)──
|
|
11
|
+
source "${HOOK_DIR}/lib/notify.sh" 2>/dev/null || true
|
|
12
|
+
ACTIVE_PLAN=$(detect_active_add 2>/dev/null || true)
|
|
13
|
+
if [ -n "$ACTIVE_PLAN" ]; then
|
|
14
|
+
PLAN_KEYWORD="${ACTIVE_PLAN%%::*}"
|
|
15
|
+
PLAN_STATUS="active"
|
|
16
|
+
else
|
|
17
|
+
PLAN_KEYWORD="no-active-plan"
|
|
18
|
+
PLAN_STATUS="none"
|
|
19
|
+
fi
|
|
8
20
|
|
|
9
21
|
# DEBUG: dump stdin for investigation
|
|
10
22
|
mkdir -p "$MAGIC_DIR/debug-dump"
|
|
@@ -41,6 +53,7 @@ CONTENT=$(echo "$input" | jq -r '
|
|
|
41
53
|
if [ -z "$CONTENT" ]; then
|
|
42
54
|
echo "⛔ 拒绝:Write 工具未传 file_content,无法校验手写文档格式" >&2
|
|
43
55
|
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"ask","permissionDecisionReason":"Write 工具未传 file_content,无法校验手写文档。请用 SearchReplace 改写已有文件,或用 Write 工具重试。"}}'
|
|
56
|
+
write_hook_event "doc-format-guard" "deny" "Write" "Write 工具未传 file_content" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
44
57
|
exit 2
|
|
45
58
|
fi
|
|
46
59
|
|
|
@@ -90,6 +103,7 @@ if [ -z "$TEMPLATE_NAME" ]; then
|
|
|
90
103
|
else
|
|
91
104
|
echo "⛔ handoff 文件内容无法识别模板类型(缺 '## 全局元信息' 或 '## 1. 交接前状态'),拒绝写入" >&2
|
|
92
105
|
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"ask","permissionDecisionReason":"handoff 内容不符合 single/multi 模板规范"}}'
|
|
106
|
+
write_hook_event "doc-format-guard" "deny" "$file_path" "handoff 模板类型无法识别" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
93
107
|
exit 2
|
|
94
108
|
fi
|
|
95
109
|
;;
|
|
@@ -110,6 +124,7 @@ if [ -z "$TEMPLATE_NAME" ]; then
|
|
|
110
124
|
fi
|
|
111
125
|
echo "⛔ 拒绝:无法识别文档类型 (file_path: $file_path),缺少模板匹配规则" >&2
|
|
112
126
|
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"ask","permissionDecisionReason":"无法识别 ADD 文档类型,请联系管理员更新 doc-format-guard.sh"}}'
|
|
127
|
+
write_hook_event "doc-format-guard" "deny" "$file_path" "无法识别文档类型" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
113
128
|
exit 2
|
|
114
129
|
;;
|
|
115
130
|
esac
|
|
@@ -121,6 +136,7 @@ SCHEMA_FILE="$TEMPLATES_DIR/${TEMPLATE_NAME%.md}.schema.json"
|
|
|
121
136
|
if [ ! -f "$SCHEMA_FILE" ]; then
|
|
122
137
|
echo "⛔ 阻断:模板 ${TEMPLATE_NAME} 缺少对应的 .schema.json 校验规则" >&2
|
|
123
138
|
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"ask","permissionDecisionReason":"缺少 .schema.json 校验规则文件,禁止无规则放行"}}'
|
|
139
|
+
write_hook_event "doc-format-guard" "deny" "$file_path" "缺少 .schema.json 校验规则" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
124
140
|
exit 2
|
|
125
141
|
fi
|
|
126
142
|
|
|
@@ -227,6 +243,7 @@ if [ -n "$ISSUES" ]; then
|
|
|
227
243
|
echo "⛔ $TEMPLATE_NAME 校验不通过:
|
|
228
244
|
$ISSUES" >&2
|
|
229
245
|
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"ask\",\"permissionDecisionReason\":\"文档格式校验不通过,请对照模板修正\"}}"
|
|
246
|
+
write_hook_event "doc-format-guard" "deny" "$file_path" "文档格式校验不通过" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
230
247
|
exit 2
|
|
231
248
|
fi
|
|
232
249
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# notify.sh — Hook 拦截事件写入 jsonl(零外部依赖,bash 原生)
|
|
3
|
+
# 用法: source 后在 exit 2 前调用 write_hook_event
|
|
4
|
+
#
|
|
5
|
+
# 写入格式(7 字段 jsonl):
|
|
6
|
+
# {"ts":"ISO8601","hook":"...","decision":"deny","cmd":"...","reason":"...","planKeyword":"...","planStatus":"..."}
|
|
7
|
+
#
|
|
8
|
+
# 磁盘管理:
|
|
9
|
+
# - 单文件 ≤256KB,超限轮转为 .old(覆盖,不累积多份)
|
|
10
|
+
# - 总量 ≤512KB(当前 + 一个 .old)
|
|
11
|
+
# - MCP Server 宕机不丢事件,重启后从文件恢复消费
|
|
12
|
+
|
|
13
|
+
write_hook_event() {
|
|
14
|
+
local hook="$1" decision="$2" cmd="$3" reason="$4" plan="${5:-unknown}" status="${6:-none}"
|
|
15
|
+
local dir="${MAGIC_DIR:-.qoder}/reports"
|
|
16
|
+
mkdir -p "$dir" 2>/dev/null || true
|
|
17
|
+
local file="$dir/hook-events.jsonl"
|
|
18
|
+
|
|
19
|
+
# 超过 256KB 自动轮转(262144 bytes)
|
|
20
|
+
if [ -f "$file" ]; then
|
|
21
|
+
local sz
|
|
22
|
+
sz=$(stat -c%s "$file" 2>/dev/null || echo 0)
|
|
23
|
+
[ "$sz" -gt 262144 ] && mv "$file" "${file}.old" 2>/dev/null || true
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
printf '{"ts":"%s","hook":"%s","decision":"%s","cmd":"%s","reason":"%s","planKeyword":"%s","planStatus":"%s"}\n' \
|
|
27
|
+
"$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
28
|
+
"$hook" \
|
|
29
|
+
"$decision" \
|
|
30
|
+
"$cmd" \
|
|
31
|
+
"$reason" \
|
|
32
|
+
"$plan" \
|
|
33
|
+
"$status" >> "$file"
|
|
34
|
+
}
|