add-coder 0.3.11 → 0.3.13

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 (30) hide show
  1. package/README.md +38 -2
  2. package/dist/caijuehub/dps-scoring-rules.toml +66 -0
  3. package/dist/index.js +66 -35
  4. package/package.json +1 -1
  5. package/templates/.add-coder-src-hash.json +26 -26
  6. package/templates/adapters/claude/hooks/lib/common.sh +1 -1
  7. package/templates/adapters/claude/hooks/lib/context-inject.sh +1 -1
  8. package/templates/adapters/claude/hooks/prompt-submit.sh +14 -9
  9. package/templates/adapters/codex/hooks/lib/common.sh +1 -1
  10. package/templates/adapters/codex/hooks/lib/context-inject.sh +1 -1
  11. package/templates/adapters/codex/hooks/prompt-submit.sh +6 -10
  12. package/templates/adapters/qoder/hooks/lib/common.sh +1 -1
  13. package/templates/adapters/qoder/hooks/lib/context-inject.sh +1 -1
  14. package/templates/adapters/qoder/hooks/prompt-submit.sh +7 -11
  15. package/templates/adapters/trae/hooks/lib/common.sh +1 -1
  16. package/templates/adapters/trae/hooks/lib/context-inject.sh +1 -1
  17. package/templates/adapters/trae/hooks/prompt-submit.sh +6 -10
  18. package/templates/adapters/vscode/hooks/lib/common.sh +1 -1
  19. package/templates/adapters/vscode/hooks/lib/context-inject.sh +1 -1
  20. package/templates/adapters/vscode/hooks/prompt-submit.sh +14 -9
  21. package/templates/core/agents/add-flow-guardian.md +4 -4
  22. package/templates/core/hooks/lib/common.sh +1 -1
  23. package/templates/core/hooks/lib/context-inject.sh +1 -1
  24. package/templates/core/hooks/prompt-submit.sh +6 -10
  25. package/templates/core/rules/project_rules.md +1 -1
  26. package/templates/core/scripts/mcp-server/tools/context.ts +1 -1
  27. package/templates/core/scripts/mcp-server/tools/gateway/check_dps.ts +1 -1
  28. package/templates/core/skills/add-paradigm/SKILL.md +2 -2
  29. package/templates/core/templates/01-/346/236/266/346/236/204//343/200/212ADD/345/274/200/345/217/221/345/267/245/344/275/234/350/267/257/345/276/204/344/270/216/346/226/207/346/241/243/345/215/217/345/220/214/350/247/204/350/214/203/343/200/213.md +1 -1
  30. package/templates/core/vocabulary/add-governance-vocabulary.md +4 -4
package/README.md CHANGED
@@ -54,6 +54,42 @@ dist-tags:
54
54
  published 2 weeks ago by wujixmm <wujixmm@gmail.com>
55
55
  ```
56
56
 
57
+
58
+ ---
59
+
60
+ > ## ⚠️ 数据共享知情清单(Data-Sharing Disclosure)
61
+ >
62
+ > add-coder 无意于搞各家厂商的对抗叙事。以下内容仅为**基于各家官方公开条款原文的事实摘录**,目的是让开发者在选择 AI 编程 IDE 前知情。条款可能随时变更,请以官方最新版本为准。
63
+ >
64
+ > | 产品 | 运营主体 | 官方条款要点(原文摘录) | 产品实测(用户反馈) | 出处 | 核实日期 |
65
+ > |------|---------|------------------------|---------------------|------|----------|
66
+ > | **Qoder** | BRIGHT ZENITH PTE. LTD.(新加坡) | 用户内容(含聊天、编程及智能体会话的输入/输出,即含代码)默认用于"研究、开发和改进我们的服务",保留期最长 5 年;条款文本称可关闭"共享与改进"(Share & Improve)退出,**但关闭前已为上述目的处理的数据仍保留和使用**;数据跨境存储于美国/新加坡/日本 | 实测为强制隐私共享模式,界面无有效切换入口 | [Qoder 隐私政策](https://qoder.com/zh/privacy-policy) | 2026-05-12 / 2026-08-04 |
67
+ > | **Qoder CN** | 阿里云(通义灵码系列) | 官方 FAQ 称:仅在用户点赞/点踩后,针对聊天记录(不包含代码)脱敏去标识化处理,用于算法升级与迭代 | **实测(v1.10.0):强制隐私共享模式,无切换功能**;官方 CLI 配置(`~/.qoder-cn/settings.json`)中亦无共享/改进开关项 | [阿里云帮助中心 FAQ](https://help.aliyun.com/zh/lingma/qoder-cn/support/faq) | 2026-07-15 / 2026-08-04 |
68
+ > | **Trae CN** | 北京引力弹弓科技有限公司(字节跳动) | 服务所收集的数据经加密、严格去标识化且无法重新识别个人后,**可能用于模型训练**以优化模型效果与产品体验;可通过隐私模式"限制"该数据使用;代码文件不提供给其他第三方 | — | [Trae 隐私协议](https://www.trae.cn/privacy-policy) | 现行版 / 2026-08-04 |
69
+ >
70
+ > **要点**:三家官方条款均为"**默认开启共享、需用户主动退出**"(opt-out)模式。**但产品实测层面**:Qoder / Qoder CN 的退出开关在实际产品中不可用(Qoder CN v1.10.0 无切换功能,CLI 配置亦无对应开关),条款上的退出承诺在 CN 产品中无落地入口,实际效果即强制共享。Qoder 明确将用户内容(含代码)用于改进服务并保留 5 年;Trae 明确将数据用于模型训练(可通过隐私模式限制);Qoder CN 官方条款范围最窄(仅反馈后的聊天记录、不含代码)。
71
+ >
72
+ > **建议**:涉及商业机密或个人数据的项目,使用前请逐项核对官方条款,并主动检查产品设置:Qoder(国际版)尝试关闭"共享与改进";Qoder CN(v1.10.0 实测无开关)与 Trae CN 请结合隐私模式与最小化输入策略使用;必要时改用数据完全本地化的替代方案。
73
+
74
+ ---
75
+ > ### 🔮 下一步:add-coder IDE 插件(实施中)
76
+
77
+ > add-coder 当前是 **脚手架 + 治理层**:把 ADD 范式(裁决集中、审计即基础设施、门禁驱动)部署进你的项目。
78
+ > 下一阶段会以 **IDE 插件** 形式落地,让治理能力直接嵌在编辑与 Agent 生命周期里。
79
+ >
80
+ > **为什么值得期待:**
81
+ >
82
+ > | 维度 | 说明 |
83
+ > |------|------|
84
+ > | **范式优势** | 不是「更好用的补全」,而是把规则、证据、审批、回溯做成一等公民。改规则不改代码,跨轮不靠聊天记忆。 |
85
+ > | **与 LLM 低耦合** | 核心是结构与门禁,不是绑死某一家模型。换模型不换治理逻辑;模型只负责生成,裁决与审计由范式层承担。 |
86
+ > | **与 IDE 低耦合** | 治理逻辑统一,适配层分离。今天支持 Claude Code / Qoder / VS Code / Trae / Codex,明天换宿主只需加适配,不必重写规则与审计链。 |
87
+ > | **不收集用户隐私** | 不上传代码、对话与项目数据。审计与裁决默认留在本地 / 你自己的基础设施里,不做「默认共享、事后退出」。 |
88
+ >
89
+ > 目标不是再做一个「AI 编程 IDE」,而是让 **任意 IDE + 任意 LLM** 都能跑在同一套可审计、可收敛、且不拿你数据的 ADD 之上。
90
+
91
+ ---
92
+
57
93
  **AI 代码治理的落地方案** — [codein2027](https://github.com/xiaomingming92/codein2027) 快速构建 ADD 编程范式的完整脚手架。以「审计即基础设施」为核心,彻底打破编程过程黑盒与跨轮失忆,让编程范式进化为可审计、可追溯、可收敛的新时代。 [NPM](https://www.npmjs.com/package/add-coder) · [GitHub](https://github.com/xiaomingming92/add-coder)
58
94
 
59
95
 
@@ -124,7 +160,7 @@ ADD 范式 + Qoder: cache 命中率 99.31%, 每次请求 MISS 仅 2,426 toke
124
160
 
125
161
  ```
126
162
  DPS (Documentation Precision Score) — TF-IDF/Jaccard 语义 + 香农/Deng 熵 + CPM 关键路径 + 结构完整度
127
- → 四维复合评分 + FFT 自适应权重,≥ 85 进入 Step 1
163
+ → 四维复合评分 + FFT 自适应权重,≥ 阈值(以 dps-scoring-rules.toml 为准,当前 PASS=80)进入 Step 1
128
164
  RAHS (Runtime Architecture Health Score) — 运行时架构健康度
129
165
  → 五维判定:范围保真 + 类型安全 + 审计完整 + Spec 合规 + 阶段对称,≥ 90 通过
130
166
  ```
@@ -446,7 +482,7 @@ Traditional AI coding is "you say, I do" — quality depends entirely on the LLM
446
482
 
447
483
  ```
448
484
  DPS (Documentation Precision Score) — TF-IDF/Jaccard semantics + Shannon/Deng entropy + CPM critical path + structural completeness
449
- → 4D composite scoring + FFT adaptive weights, ≥ 85 to enter Step 1
485
+ → 4D composite scoring + FFT adaptive weights, ≥ threshold (per dps-scoring-rules.toml, currently PASS=80) to enter Step 1
450
486
  RAHS (Runtime Architecture Health Score) — runtime architecture health
451
487
  → 5D assessment: scope fidelity + type safety + audit completeness + spec compliance + phase symmetry, ≥ 90 to pass
452
488
  ```
@@ -0,0 +1,66 @@
1
+ # DPS 评分全参数 —— caijuehub 驱动,后续调优只需改此 TOML
2
+
3
+ # ═══════════════ 维度一:语义相关性 ═══════════════
4
+ [semantic]
5
+ # 子权重:Jaccard Plan↔Specs / Cosine Plan↔Specs / Jaccard Plan↔Review / Cosine Plan↔Review
6
+ weights = [0.35, 0.45, 0.08, 0.12]
7
+ # Review 缺失时的惩罚系数(0.0=不惩罚,0.4=打六折,即得分×0.6)
8
+ missing_review_penalty = 0.0
9
+
10
+ # ═══════════════ 维度二:信息熵匹配 ═══════════════
11
+ [entropy]
12
+ # 熵差距乘数(entropyGap × multiplier,越小越不敏感)
13
+ gap_multiplier = 10
14
+ # Deng 不确定性惩罚:每个标记扣分,上限
15
+ deng_per_marker = 0.05
16
+ deng_max_penalty = 0.3
17
+ # Specs 缺失时的熵差距(无 Specs 时 gap 设为此值)
18
+ missing_specs_gap = 10
19
+
20
+ # ═══════════════ 维度三:CPM 关键路径 ═══════════════
21
+ [cpm]
22
+ # 子权重:原子化 / 注意力匹配 / 依赖完整性
23
+ sub_weights = [0.4, 0.35, 0.25]
24
+ # 业务原子化:Jaccard 重叠乘数(overlap × multiplier → penalty)
25
+ overlap_multiplier = 2
26
+ # Task 数超过此阈值时随机采样配对(避免 O(N²) 爆炸,0 = 不限制)
27
+ max_task_pairs = 200
28
+ # 注意力匹配:文件/Task 阈值
29
+ file_per_task_low = 3 # ≤3 → 100
30
+ file_per_task_mid = 5 # 3~5 → 70,>5 → 40
31
+ # 注意力匹配:描述熵阈值(bits)
32
+ entropy_low = 6 # <6 → 100
33
+ entropy_mid = 8 # 6~8 → 75,>8 → 50
34
+ # 注意力匹配:子权重(文件耦合 / 描述熵)
35
+ attention_weights = [0.5, 0.5]
36
+ # 依赖完整性:子权重(覆盖率 / Task Dependencies 章节存在)
37
+ dep_weights = [0.6, 0.4]
38
+
39
+ # ═══════════════ 维度四:结构完整度 ═══════════════
40
+ [structure]
41
+ # 扣分项
42
+ placeholder_penalty = 15
43
+ missing_specs_penalty = 30
44
+ missing_tasks_penalty = 15
45
+ missing_checklist_penalty = 15
46
+ # 子权重:结构分 / 回流分
47
+ sub_weights = [0.6, 0.4]
48
+
49
+ # ═══════════════ FFT 自适应权重 ═══════════════
50
+ [fft]
51
+ cold_start_threshold = 5
52
+ history_limit = 50
53
+ default_weights = [0.25, 0.25, 0.25, 0.25]
54
+
55
+ # ═══════════════ DPS 阈值 ═══════════════
56
+ [thresholds]
57
+ pass = 80
58
+ warn = 65
59
+
60
+ # ═══════════════ Embedding 模型(@xenova/transformers ONNX)═══════════════
61
+ [embedding]
62
+ # 首次 DPS 调用自动下载并缓存到本地 ~/.cache/huggingface/hub/
63
+ # 可选值(注释掉的前两个是备选方案):
64
+ # "Xenova/all-MiniLM-L6-v2" 英文为主,80MB,速度快
65
+ # "Xenova/multilingual-e5-small" 多语言,118MB,平衡选择
66
+ model = "Xenova/bge-small-zh-v1.5"
package/dist/index.js CHANGED
@@ -400,9 +400,10 @@ function diffPrisma(basePath, targetPath) {
400
400
  }
401
401
 
402
402
  // src/core/renderer.ts
403
- import { readFileSync as readFileSync4, readdirSync, statSync } from "fs";
403
+ import { readFileSync as readFileSync4, readdirSync, statSync, existsSync as existsSync5 } from "fs";
404
404
  import { join as join4, relative, dirname as dirname2 } from "path";
405
405
  import { fileURLToPath } from "url";
406
+ import { parse } from "smol-toml";
406
407
  var __filename = fileURLToPath(import.meta.url);
407
408
  var __dirname = dirname2(__filename);
408
409
  var PLACEHOLDERS = {
@@ -417,12 +418,43 @@ var PLACEHOLDERS = {
417
418
  "{{mcpServerCommand}}": "mcpServerCommand",
418
419
  "{{agentAuditImport}}": "agentAuditImport"
419
420
  };
421
+ function loadDpsThresholds() {
422
+ try {
423
+ const candidates = [
424
+ join4(__dirname, "../caijuehub/dps-scoring-rules.toml"),
425
+ join4(__dirname, "caijuehub/dps-scoring-rules.toml"),
426
+ join4(__dirname, "../../caijuehub/dps-scoring-rules.toml")
427
+ ];
428
+ const tomlPath = candidates.find(existsSync5);
429
+ if (!tomlPath) {
430
+ throw new Error(`\u5019\u9009\u8DEF\u5F84\u5747\u4E0D\u5B58\u5728: ${candidates.join(" | ")}`);
431
+ }
432
+ const doc = parse(readFileSync4(tomlPath, "utf-8"));
433
+ if (doc.thresholds && typeof doc.thresholds.pass === "number") {
434
+ return {
435
+ pass: String(doc.thresholds.pass),
436
+ warn: String(doc.thresholds.warn ?? doc.thresholds.pass)
437
+ };
438
+ }
439
+ } catch (e) {
440
+ const errorMessage = e instanceof Error ? e.message : String(e);
441
+ console.warn(
442
+ `[renderer] DPS \u9608\u503C TOML \u8BFB\u53D6\u5931\u8D25\uFF0C\u4FDD\u7559 dpsPass/dpsWarn \u5360\u4F4D\u7B26: ${errorMessage}`
443
+ );
444
+ }
445
+ return null;
446
+ }
420
447
  function render(content, config) {
421
448
  let result = content;
422
449
  for (const [placeholder, key] of Object.entries(PLACEHOLDERS)) {
423
450
  const value = config[key];
424
451
  result = result.replaceAll(placeholder, value);
425
452
  }
453
+ const thresholds = loadDpsThresholds();
454
+ if (thresholds) {
455
+ result = result.replaceAll("{{dpsPass}}", thresholds.pass);
456
+ result = result.replaceAll("{{dpsWarn}}", thresholds.warn);
457
+ }
426
458
  return result;
427
459
  }
428
460
  var TEMPLATES_ROOT = join4(__dirname, "../templates");
@@ -512,7 +544,7 @@ function renderAdapter5(config, targetDir, dryRun, magicDir) {
512
544
 
513
545
  // src/lib/utils.ts
514
546
  import { createInterface as createInterface2 } from "readline";
515
- import { existsSync as existsSync5 } from "fs";
547
+ import { existsSync as existsSync6 } from "fs";
516
548
  import { resolve as resolve2 } from "path";
517
549
  function ask(q) {
518
550
  const rl = createInterface2({ input: process.stdin, output: process.stdout });
@@ -524,7 +556,7 @@ function ask(q) {
524
556
  });
525
557
  }
526
558
  function detectPm(projectRoot) {
527
- return existsSync5(resolve2(projectRoot, "pnpm-lock.yaml")) ? "pnpm" : "npm";
559
+ return existsSync6(resolve2(projectRoot, "pnpm-lock.yaml")) ? "pnpm" : "npm";
528
560
  }
529
561
 
530
562
  // src/cli/prisma-injector.ts
@@ -533,7 +565,7 @@ import { fileURLToPath as fileURLToPath2 } from "url";
533
565
 
534
566
  // src/caijuehub/strategies/prisma.strategy.ts
535
567
  import { spawnSync } from "child_process";
536
- import { copyFileSync, existsSync as existsSync6, readFileSync as readFileSync5, unlinkSync, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
568
+ import { copyFileSync, existsSync as existsSync7, readFileSync as readFileSync5, unlinkSync, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
537
569
  import { resolve as resolve3 } from "path";
538
570
  var PRISMA_CONFIG = {
539
571
  onMissing: "ask",
@@ -586,10 +618,10 @@ function runPrismaInit(projectRoot, provider, schemaPath) {
586
618
  stdio: "inherit",
587
619
  shell: false
588
620
  });
589
- if (initResult.status !== 0 || !existsSync6(schemaPath)) {
621
+ if (initResult.status !== 0 || !existsSync7(schemaPath)) {
590
622
  console.log("prisma init \u5931\u8D25\uFF0C\u624B\u52A8\u521B\u5EFA schema.prisma ...");
591
623
  const prismaDir = resolve3(projectRoot, "prisma");
592
- if (!existsSync6(prismaDir)) mkdirSync2(prismaDir, { recursive: true });
624
+ if (!existsSync7(prismaDir)) mkdirSync2(prismaDir, { recursive: true });
593
625
  const content = `generator client {
594
626
  provider = "prisma-client-js"
595
627
  }
@@ -600,7 +632,7 @@ datasource db {
600
632
  `;
601
633
  writeFileSync2(schemaPath, content, "utf-8");
602
634
  const devEnvPath = resolve3(projectRoot, ".env.development");
603
- if (!existsSync6(devEnvPath)) {
635
+ if (!existsSync7(devEnvPath)) {
604
636
  const defaultUrl = provider === "sqlite" ? 'DATABASE_URL="file:./data/dev.db"' : '# \u8BF7\u7F16\u8F91\u4E3A\u4F60\u7684\u6570\u636E\u5E93\u8FDE\u63A5\u4FE1\u606F\nDATABASE_URL="postgresql://USER:PASSWORD@HOST:PORT/DB?schema=public"';
605
637
  writeFileSync2(devEnvPath, defaultUrl + "\n", "utf-8");
606
638
  console.log("\u5DF2\u521B\u5EFA .env.development");
@@ -612,16 +644,16 @@ datasource db {
612
644
  function postInitSetup(projectRoot, schemaPath, addPrismaTemplate, destPath) {
613
645
  const envPath = resolve3(projectRoot, ".env");
614
646
  const devEnvPath = resolve3(projectRoot, ".env.development");
615
- if (existsSync6(envPath)) {
647
+ if (existsSync7(envPath)) {
616
648
  const envContent = readFileSync5(envPath, "utf-8");
617
649
  const dbUrl = envContent.match(/DATABASE_URL=.*/);
618
650
  if (dbUrl) {
619
- const existing = existsSync6(devEnvPath) ? readFileSync5(devEnvPath, "utf-8") : "";
651
+ const existing = existsSync7(devEnvPath) ? readFileSync5(devEnvPath, "utf-8") : "";
620
652
  if (!existing.includes("DATABASE_URL=")) {
621
653
  writeFileSync2(devEnvPath, `${existing}${existing ? "\n" : ""}${dbUrl[0]}
622
654
  `, "utf-8");
623
655
  }
624
- if (existsSync6(envPath)) unlinkSync(envPath);
656
+ if (existsSync7(envPath)) unlinkSync(envPath);
625
657
  console.log("\u5DF2\u5C06 DATABASE_URL \u8FC1\u79FB\u5230 .env.development");
626
658
  }
627
659
  }
@@ -634,7 +666,7 @@ async function injectPrisma(projectRoot, addPrismaTemplate, options = {}) {
634
666
  const schemaPath = resolve3(prismaDir, "schema.prisma");
635
667
  const destPath = resolve3(prismaDir, "add.prisma");
636
668
  let justInited = false;
637
- if (!existsSync6(prismaDir) || !existsSync6(schemaPath)) {
669
+ if (!existsSync7(prismaDir) || !existsSync7(schemaPath)) {
638
670
  if (C.onMissing === "skip") {
639
671
  console.log("\u8DF3\u8FC7\uFF1A\u7F3A\u5C11 Prisma");
640
672
  return true;
@@ -653,7 +685,7 @@ async function injectPrisma(projectRoot, addPrismaTemplate, options = {}) {
653
685
  postInitSetup(projectRoot, schemaPath, addPrismaTemplate, destPath);
654
686
  justInited = true;
655
687
  }
656
- if (existsSync6(destPath) && !justInited) {
688
+ if (existsSync7(destPath) && !justInited) {
657
689
  if (options.dryRun) {
658
690
  console.log("[dry-run] \u5DF2\u6709 add.prisma");
659
691
  return true;
@@ -726,7 +758,7 @@ async function injectPrisma2(projectRoot, options = {}) {
726
758
  }
727
759
 
728
760
  // src/cli/commands/init.ts
729
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync3, existsSync as existsSync7, mkdirSync as mkdirSync3, copyFileSync as copyFileSync2, readdirSync as readdirSync2 } from "fs";
761
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync3, existsSync as existsSync8, mkdirSync as mkdirSync3, copyFileSync as copyFileSync2, readdirSync as readdirSync2 } from "fs";
730
762
  import { createHash } from "crypto";
731
763
  import { resolve as resolve5 } from "path";
732
764
  import { spawnSync as spawnSync2 } from "child_process";
@@ -906,13 +938,13 @@ main().catch((e) => { console.error(e); process.exit(1); });
906
938
  console.log(`[dry-run] \u5C06\u5199\u5165 ${scriptPath}`);
907
939
  return;
908
940
  }
909
- if (!existsSync7(scriptsDir)) mkdirSync3(scriptsDir, { recursive: true });
941
+ if (!existsSync8(scriptsDir)) mkdirSync3(scriptsDir, { recursive: true });
910
942
  writeFileSync3(scriptPath, content, "utf-8");
911
943
  console.log("\u5DF2\u751F\u6210 scripts/export-db.ts");
912
944
  }
913
945
  function injectDbExportScript(projectRoot, dryRun) {
914
946
  const pkgPath = resolve5(projectRoot, "package.json");
915
- if (!existsSync7(pkgPath)) return;
947
+ if (!existsSync8(pkgPath)) return;
916
948
  if (dryRun) {
917
949
  console.log("[dry-run] \u5C06\u6CE8\u5165 db:export");
918
950
  return;
@@ -947,13 +979,13 @@ function writeComposeEnv(ctx) {
947
979
  if (!db.reuseExisting) {
948
980
  const composeName = db.container === "podman" ? "podman-compose.add.yml" : "docker-compose.add.yml";
949
981
  const composePath = resolve5(projectRoot, composeName);
950
- if (!options.dryRun && (!existsSync7(composePath) || options.force)) {
982
+ if (!options.dryRun && (!existsSync8(composePath) || options.force)) {
951
983
  writeFileSync3(composePath, composeContent(config.projectName || "add-project"), "utf-8");
952
984
  console.log(`\u5DF2\u521B\u5EFA ${composeName}`);
953
985
  }
954
986
  }
955
987
  const devEnvPath = resolve5(projectRoot, ".env.development");
956
- if (!options.dryRun && existsSync7(devEnvPath)) {
988
+ if (!options.dryRun && existsSync8(devEnvPath)) {
957
989
  const existing = readFileSync6(devEnvPath, "utf-8");
958
990
  if (!/^DATABASE_USER=/m.test(existing)) {
959
991
  writeFileSync3(devEnvPath, existing + `
@@ -994,7 +1026,7 @@ async function renderAndWrite(ctx) {
994
1026
  }
995
1027
  for (const d of [".add", magicDir]) {
996
1028
  const reviewsDir = resolve5(projectRoot, d, "reviews");
997
- if (!existsSync7(reviewsDir)) {
1029
+ if (!existsSync8(reviewsDir)) {
998
1030
  if (dry) {
999
1031
  console.log(`[dry-run] \u5C06\u521B\u5EFA ${reviewsDir}/`);
1000
1032
  } else {
@@ -1038,7 +1070,7 @@ async function deployDatabase(ctx) {
1038
1070
  }
1039
1071
  if (db.engine === "postgresql" && db.container === "manual") {
1040
1072
  const dbScript = resolve5(projectRoot, magicDir, "scripts", "db-ensure.sh");
1041
- if (existsSync7(dbScript)) spawnSync2("bash", [dbScript, "postgresql", "manual"], { cwd: projectRoot, stdio: "inherit" });
1073
+ if (existsSync8(dbScript)) spawnSync2("bash", [dbScript, "postgresql", "manual"], { cwd: projectRoot, stdio: "inherit" });
1042
1074
  console.log([
1043
1075
  "",
1044
1076
  "\u2501".repeat(30),
@@ -1079,12 +1111,12 @@ function deployDocs(ctx) {
1079
1111
  for (const d of ["00-\u9700\u6C42", "01-\u67B6\u6784", "02-\u89C4\u8303"]) {
1080
1112
  const srcDir = resolve5(groundingSrc, d);
1081
1113
  const destDir = resolve5(docsBase, d);
1082
- if (!existsSync7(destDir)) mkdirSync3(destDir, { recursive: true });
1083
- if (!existsSync7(srcDir)) continue;
1114
+ if (!existsSync8(destDir)) mkdirSync3(destDir, { recursive: true });
1115
+ if (!existsSync8(srcDir)) continue;
1084
1116
  for (const f of readdirSync2(srcDir)) {
1085
1117
  const src = resolve5(srcDir, f);
1086
1118
  const dest = resolve5(destDir, f);
1087
- if (existsSync7(dest)) continue;
1119
+ if (existsSync8(dest)) continue;
1088
1120
  try {
1089
1121
  copyFileSync2(src, dest);
1090
1122
  } catch {
@@ -1112,7 +1144,7 @@ function finalize(ctx, result) {
1112
1144
  }
1113
1145
 
1114
1146
  // src/cli/commands/sync.ts
1115
- import { existsSync as existsSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4 } from "fs";
1147
+ import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4 } from "fs";
1116
1148
  import { resolve as resolve6, dirname as dirname4 } from "path";
1117
1149
  import { createHash as createHash2 } from "crypto";
1118
1150
 
@@ -1250,7 +1282,7 @@ async function syncCommand(options = {}) {
1250
1282
  let sameCount = 0;
1251
1283
  for (const [relPath, content] of candidates) {
1252
1284
  const absPath = resolve6(projectRoot, relPath);
1253
- if (!existsSync8(absPath)) {
1285
+ if (!existsSync9(absPath)) {
1254
1286
  missingFiles.set(relPath, content);
1255
1287
  } else if (establishBaseline) {
1256
1288
  missingFiles.set(relPath, content);
@@ -1288,7 +1320,7 @@ async function syncCommand(options = {}) {
1288
1320
  }
1289
1321
  const missing = /* @__PURE__ */ new Map();
1290
1322
  for (const [relPath, content] of allFiles) {
1291
- if (!existsSync8(resolve6(projectRoot, relPath))) {
1323
+ if (!existsSync9(resolve6(projectRoot, relPath))) {
1292
1324
  missing.set(relPath, content);
1293
1325
  }
1294
1326
  }
@@ -1310,7 +1342,7 @@ async function syncCommand(options = {}) {
1310
1342
  }
1311
1343
  function printMigrateGuidance(targetPath, changed) {
1312
1344
  const g = SYNC_PRISMA_CONFIG.POST_SYNC;
1313
- const isManaged = existsSync8(resolve6(dirname4(targetPath), "migrations"));
1345
+ const isManaged = existsSync9(resolve6(dirname4(targetPath), "migrations"));
1314
1346
  const actions = isManaged ? g.MANAGED_ACTIONS : g.UNMANAGED_ACTIONS;
1315
1347
  console.log(` \u25B6 \u5DF2\u5199\u5165 ${changed} \u5904\u53D8\u66F4\uFF0C${g.HEADER}`);
1316
1348
  for (const a of actions) {
@@ -1334,7 +1366,7 @@ async function checkPrismaDiff(projectRoot, options) {
1334
1366
  if (!options.patch) return;
1335
1367
  const basePath = resolve6(projectRoot, SYNC_PRISMA_CONFIG.BASE_SCHEMA);
1336
1368
  const targetPath = resolve6(projectRoot, SYNC_PRISMA_CONFIG.TARGET_PATTERN);
1337
- if (!existsSync8(basePath)) {
1369
+ if (!existsSync9(basePath)) {
1338
1370
  console.log(`
1339
1371
  \u26A0\uFE0F \u57FA\u51C6 schema \u4E0D\u5B58\u5728: ${basePath}`);
1340
1372
  console.log(` \u8BF7\u786E\u4FDD add-coder \u5DF2\u6B63\u786E\u5B89\u88C5\u3002`);
@@ -1346,7 +1378,7 @@ async function checkPrismaDiff(projectRoot, options) {
1346
1378
  \u2705 Prisma schema \u4E0E add-coder \u6807\u51C6\u4E00\u81F4\uFF0C\u65E0\u9700\u540C\u6B65\u3002`);
1347
1379
  return;
1348
1380
  }
1349
- const targetExists = existsSync8(targetPath);
1381
+ const targetExists = existsSync9(targetPath);
1350
1382
  let modifiedCount = 0;
1351
1383
  console.log(`
1352
1384
  \u26A0\uFE0F Prisma schema \u5DEE\u5F02\u68C0\u6D4B:`);
@@ -1533,13 +1565,12 @@ function injectFieldLines(targetPath, basePath, modelName, fieldKeys) {
1533
1565
  const fieldName = key.split(":")[0];
1534
1566
  const fieldLine = baseFields[fieldName];
1535
1567
  if (!fieldLine) continue;
1536
- if (new RegExp(`^\\s*${fieldName}\\s+`, "m").test(content)) continue;
1537
- const modelRegex = new RegExp(`(model\\s+${modelName}\\s*\\{[^}]*?)\\n(\\s*\\})`, "m");
1568
+ const modelRegex = new RegExp(`(model\\s+${modelName}\\s*\\{)([^}]*?)(\\n\\s*\\})`, "m");
1538
1569
  const m = content.match(modelRegex);
1539
1570
  if (!m) continue;
1540
- content = content.replace(modelRegex, `$1
1541
- ${fieldLine}
1542
- $2`);
1571
+ if (new RegExp(`^\\s*${fieldName}\\s+`, "m").test(m[2])) continue;
1572
+ content = content.replace(modelRegex, `$1$2
1573
+ ${fieldLine}$3`);
1543
1574
  count++;
1544
1575
  }
1545
1576
  if (count > 0) writeFileSync4(targetPath, content, "utf-8");
@@ -1564,7 +1595,7 @@ function overwriteFieldLines(targetPath, basePath, modelName, conflicts) {
1564
1595
  }
1565
1596
 
1566
1597
  // src/cli/commands/status.ts
1567
- import { existsSync as existsSync9 } from "fs";
1598
+ import { existsSync as existsSync10 } from "fs";
1568
1599
  import { resolve as resolve7 } from "path";
1569
1600
  async function statusCommand() {
1570
1601
  const projectRoot = process.cwd();
@@ -1574,7 +1605,7 @@ async function statusCommand() {
1574
1605
  const missing = [];
1575
1606
  const present = [];
1576
1607
  for (const [relPath] of coreFiles) {
1577
- if (existsSync9(resolve7(projectRoot, relPath))) {
1608
+ if (existsSync10(resolve7(projectRoot, relPath))) {
1578
1609
  present.push(relPath);
1579
1610
  } else {
1580
1611
  missing.push(relPath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "add-coder",
3
- "version": "0.3.11",
3
+ "version": "0.3.13",
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": {
@@ -1,8 +1,8 @@
1
1
  {
2
- "_version": "0.3.11",
2
+ "_version": "0.3.13",
3
3
  "adapters/claude/hooks/doc-format-guard.sh": "ec59ad3f",
4
- "adapters/claude/hooks/lib/common.sh": "db321ef6",
5
- "adapters/claude/hooks/lib/context-inject.sh": "4132f203",
4
+ "adapters/claude/hooks/lib/common.sh": "4f3e64ad",
5
+ "adapters/claude/hooks/lib/context-inject.sh": "cfc8c65e",
6
6
  "adapters/claude/hooks/lib/notify.sh": "e0033e53",
7
7
  "adapters/claude/hooks/lib/preload-templates.sh": "96dd67fe",
8
8
  "adapters/claude/hooks/lib/session-end.sh": "29813cbc",
@@ -16,7 +16,7 @@
16
16
  "adapters/claude/hooks/post-tool-use.sh": "f54dd009",
17
17
  "adapters/claude/hooks/pre-compact.sh": "4248f84f",
18
18
  "adapters/claude/hooks/pre-tool-use.sh": "ecbdc628",
19
- "adapters/claude/hooks/prompt-submit.sh": "680b41f4",
19
+ "adapters/claude/hooks/prompt-submit.sh": "2fe9e42c",
20
20
  "adapters/claude/hooks/review-checklist.sh": "b383a983",
21
21
  "adapters/claude/hooks/session-end.sh": "777ae808",
22
22
  "adapters/claude/hooks/session-start.sh": "fd1d5e4f",
@@ -27,8 +27,8 @@
27
27
  "adapters/claude/mcp.json": "4ddc5120",
28
28
  "adapters/claude/settings.json": "067ccc45",
29
29
  "adapters/codex/hooks/doc-format-guard.sh": "8e134e78",
30
- "adapters/codex/hooks/lib/common.sh": "db321ef6",
31
- "adapters/codex/hooks/lib/context-inject.sh": "4132f203",
30
+ "adapters/codex/hooks/lib/common.sh": "4f3e64ad",
31
+ "adapters/codex/hooks/lib/context-inject.sh": "cfc8c65e",
32
32
  "adapters/codex/hooks/lib/notify.sh": "e0033e53",
33
33
  "adapters/codex/hooks/lib/preload-templates.sh": "96dd67fe",
34
34
  "adapters/codex/hooks/lib/session-end.sh": "29813cbc",
@@ -41,7 +41,7 @@
41
41
  "adapters/codex/hooks/post-tool-use.sh": "27123aee",
42
42
  "adapters/codex/hooks/pre-compact.sh": "6164c007",
43
43
  "adapters/codex/hooks/pre-tool-use.sh": "ffa7936b",
44
- "adapters/codex/hooks/prompt-submit.sh": "bea6f381",
44
+ "adapters/codex/hooks/prompt-submit.sh": "a41371ea",
45
45
  "adapters/codex/hooks/review-checklist.sh": "b383a983",
46
46
  "adapters/codex/hooks/session-end.sh": "3cc8c346",
47
47
  "adapters/codex/hooks/session-start.sh": "aa8faa0f",
@@ -51,8 +51,8 @@
51
51
  "adapters/codex/hooks.json": "d9c99f6b",
52
52
  "adapters/codex/settings.json": "44136fa3",
53
53
  "adapters/qoder/hooks/doc-format-guard.sh": "bd4ffffb",
54
- "adapters/qoder/hooks/lib/common.sh": "db321ef6",
55
- "adapters/qoder/hooks/lib/context-inject.sh": "4132f203",
54
+ "adapters/qoder/hooks/lib/common.sh": "4f3e64ad",
55
+ "adapters/qoder/hooks/lib/context-inject.sh": "cfc8c65e",
56
56
  "adapters/qoder/hooks/lib/notify.sh": "e0033e53",
57
57
  "adapters/qoder/hooks/lib/preload-templates.sh": "96dd67fe",
58
58
  "adapters/qoder/hooks/lib/session-end.sh": "29813cbc",
@@ -65,7 +65,7 @@
65
65
  "adapters/qoder/hooks/post-tool-use.sh": "051cb6ed",
66
66
  "adapters/qoder/hooks/pre-compact.sh": "092fa6cf",
67
67
  "adapters/qoder/hooks/pre-tool-use.sh": "5ba6d9ae",
68
- "adapters/qoder/hooks/prompt-submit.sh": "f36e6ae8",
68
+ "adapters/qoder/hooks/prompt-submit.sh": "336f262e",
69
69
  "adapters/qoder/hooks/review-checklist.sh": "666831c8",
70
70
  "adapters/qoder/hooks/session-end.sh": "c50339df",
71
71
  "adapters/qoder/hooks/session-start.sh": "a4307a78",
@@ -76,8 +76,8 @@
76
76
  "adapters/qoder/settings.json": "4bae3c9a",
77
77
  "adapters/qoder/sync-policy.json": "a4bcbbaf",
78
78
  "adapters/trae/hooks/doc-format-guard.sh": "9b99f253",
79
- "adapters/trae/hooks/lib/common.sh": "db321ef6",
80
- "adapters/trae/hooks/lib/context-inject.sh": "4132f203",
79
+ "adapters/trae/hooks/lib/common.sh": "4f3e64ad",
80
+ "adapters/trae/hooks/lib/context-inject.sh": "cfc8c65e",
81
81
  "adapters/trae/hooks/lib/notify.sh": "e0033e53",
82
82
  "adapters/trae/hooks/lib/preload-templates.sh": "96dd67fe",
83
83
  "adapters/trae/hooks/lib/session-end.sh": "29813cbc",
@@ -90,7 +90,7 @@
90
90
  "adapters/trae/hooks/post-tool-use.sh": "27123aee",
91
91
  "adapters/trae/hooks/pre-compact.sh": "6164c007",
92
92
  "adapters/trae/hooks/pre-tool-use.sh": "8e57d1fa",
93
- "adapters/trae/hooks/prompt-submit.sh": "bea6f381",
93
+ "adapters/trae/hooks/prompt-submit.sh": "a41371ea",
94
94
  "adapters/trae/hooks/review-checklist.sh": "b383a983",
95
95
  "adapters/trae/hooks/session-end.sh": "3cc8c346",
96
96
  "adapters/trae/hooks/session-start.sh": "aa8faa0f",
@@ -111,8 +111,8 @@
111
111
  "adapters/vscode/.github/hooks/user-prompt-submit.json": "3a608d62",
112
112
  "adapters/vscode/extensions.json": "0f4024c1",
113
113
  "adapters/vscode/hooks/doc-format-guard.sh": "0db27261",
114
- "adapters/vscode/hooks/lib/common.sh": "db321ef6",
115
- "adapters/vscode/hooks/lib/context-inject.sh": "4132f203",
114
+ "adapters/vscode/hooks/lib/common.sh": "4f3e64ad",
115
+ "adapters/vscode/hooks/lib/context-inject.sh": "cfc8c65e",
116
116
  "adapters/vscode/hooks/lib/notify.sh": "e0033e53",
117
117
  "adapters/vscode/hooks/lib/preload-templates.sh": "96dd67fe",
118
118
  "adapters/vscode/hooks/lib/session-end.sh": "29813cbc",
@@ -125,7 +125,7 @@
125
125
  "adapters/vscode/hooks/post-tool-use.sh": "5f188718",
126
126
  "adapters/vscode/hooks/pre-compact.sh": "a0908f0e",
127
127
  "adapters/vscode/hooks/pre-tool-use.sh": "6232624b",
128
- "adapters/vscode/hooks/prompt-submit.sh": "4529a394",
128
+ "adapters/vscode/hooks/prompt-submit.sh": "3e56d1a9",
129
129
  "adapters/vscode/hooks/review-checklist.sh": "b383a983",
130
130
  "adapters/vscode/hooks/session-end.sh": "7b407b9f",
131
131
  "adapters/vscode/hooks/session-start.sh": "ad724a3e",
@@ -135,15 +135,15 @@
135
135
  "adapters/vscode/launch.json": "f2b79855",
136
136
  "adapters/vscode/settings.json": "7cabd00e",
137
137
  "adapters/vscode/tasks.json": "654d7fbd",
138
- "core/agents/add-flow-guardian.md": "a23f50cf",
138
+ "core/agents/add-flow-guardian.md": "c3e650d2",
139
139
  "core/docs/ADD-governance-claude-code.md": "0f582a7e",
140
140
  "core/docs/ADD-governance-codex.md": "289e8b71",
141
141
  "core/docs/ADD-governance-qoder-cn.md": "332a7253",
142
142
  "core/docs/ADD-governance-trae.md": "ffb29a0e",
143
143
  "core/docs/ADD-governance-vscode-copilot.md": "74062e88",
144
144
  "core/hooks/doc-format-guard.sh": "5cd6d1f2",
145
- "core/hooks/lib/common.sh": "db321ef6",
146
- "core/hooks/lib/context-inject.sh": "4132f203",
145
+ "core/hooks/lib/common.sh": "4f3e64ad",
146
+ "core/hooks/lib/context-inject.sh": "cfc8c65e",
147
147
  "core/hooks/lib/notify.sh": "e0033e53",
148
148
  "core/hooks/lib/preload-templates.sh": "96dd67fe",
149
149
  "core/hooks/lib/session-end.sh": "29813cbc",
@@ -156,7 +156,7 @@
156
156
  "core/hooks/post-tool-use.sh": "27123aee",
157
157
  "core/hooks/pre-compact.sh": "6164c007",
158
158
  "core/hooks/pre-tool-use.sh": "fa73df98",
159
- "core/hooks/prompt-submit.sh": "bea6f381",
159
+ "core/hooks/prompt-submit.sh": "a41371ea",
160
160
  "core/hooks/review-checklist.sh": "b383a983",
161
161
  "core/hooks/session-end.sh": "3cc8c346",
162
162
  "core/hooks/session-start.sh": "aa8faa0f",
@@ -175,7 +175,7 @@
175
175
  "core/reports/index.md": "6348c374",
176
176
  "core/reports/runtime-report/gateway.md": "a5751665",
177
177
  "core/reviews/.gitkeep": "e3b0c442",
178
- "core/rules/project_rules.md": "b2680762",
178
+ "core/rules/project_rules.md": "fea8bfaa",
179
179
  "core/rules/theory-practice-map.toml": "b1db99fd",
180
180
  "core/scripts/db-ensure.sh": "faeb6b92",
181
181
  "core/scripts/gen-plan-index.sh": "bfc6ad3e",
@@ -204,11 +204,11 @@
204
204
  "core/scripts/mcp-server/tasks/runner.ts": "d84bd35d",
205
205
  "core/scripts/mcp-server/tasks/store.ts": "2fce1a92",
206
206
  "core/scripts/mcp-server/tools/audit.ts": "3c23458b",
207
- "core/scripts/mcp-server/tools/context.ts": "463df4f4",
207
+ "core/scripts/mcp-server/tools/context.ts": "5a00457b",
208
208
  "core/scripts/mcp-server/tools/docs.ts": "a3937aec",
209
209
  "core/scripts/mcp-server/tools/gateway/check_add_route_completeness.ts": "c205989d",
210
210
  "core/scripts/mcp-server/tools/gateway/check_add_route_status.ts": "3662b6dc",
211
- "core/scripts/mcp-server/tools/gateway/check_dps.ts": "12f3b375",
211
+ "core/scripts/mcp-server/tools/gateway/check_dps.ts": "cea4cb8b",
212
212
  "core/scripts/mcp-server/tools/gateway/check_rahs.ts": "c37f6810",
213
213
  "core/scripts/mcp-server/tools/gateway/check_spec_sync.ts": "a683697f",
214
214
  "core/scripts/mcp-server/tools/gateway/helpers.ts": "5ed11a3b",
@@ -222,12 +222,12 @@
222
222
  "core/scripts/mcp-server/tools/review.ts": "c2d464ed",
223
223
  "core/scripts/mcp-server/types.ts": "6c5e60bc",
224
224
  "core/scripts/mcp-server.ts": "99cc6833",
225
- "core/skills/add-paradigm/SKILL.md": "b74ef053",
225
+ "core/skills/add-paradigm/SKILL.md": "5d4fa389",
226
226
  "core/skills/session-init/SKILL.md": "bb1205b0",
227
227
  "core/specs/add-coder-npm-package/checklist.md": "ed92032c",
228
228
  "core/specs/add-coder-npm-package/spec.md": "c7d0f235",
229
229
  "core/specs/add-coder-npm-package/tasks.md": "c34301e5",
230
- "core/templates/01-架构/《ADD开发工作路径与文档协同规范》.md": "4a566775",
230
+ "core/templates/01-架构/《ADD开发工作路径与文档协同规范》.md": "c86814d0",
231
231
  "core/templates/TERMINOLOGY.md": "e9f4f781",
232
232
  "core/templates/add-route-template-heavyweight.md": "0e107ac0",
233
233
  "core/templates/add-route-template.md": "da7022df",
@@ -267,6 +267,6 @@
267
267
  "core/templates/tasks-template.md": "2b9d0d52",
268
268
  "core/templates/tasks-template.schema.json": "fff6eb47",
269
269
  "core/tools/README.md": "26a63460",
270
- "core/vocabulary/add-governance-vocabulary.md": "0bd9f725",
270
+ "core/vocabulary/add-governance-vocabulary.md": "62d71481",
271
271
  "shared/hooks-lib/common.sh": "441eee52"
272
272
  }
@@ -214,7 +214,7 @@ Plan 不是"文档开销"——它是代码治理的基础设施。跳过 Plan
214
214
 
215
215
  方案 A — 补 ADD 流程(招安):
216
216
  Step 0: 读 .qoder/templates/plan-template.md → 生成 Plan
217
- 生成 add-route → check_dps ≥ 85
217
+ 生成 add-route → check_dps ≥ {{dpsPass}}
218
218
  Step 1: 扩展 AgentAuditPhase(如需要)
219
219
  Step 2: 确认 agentAudit() 通道
220
220
  Step 3: 将已写代码关联到 tasks.md
@@ -36,7 +36,7 @@ Plan 不是"文档开销"——它是代码治理的基础设斻。跳过 Plan
36
36
 
37
37
  方案 A — 补 ADD 流程(招安):
38
38
  Step 0: 读 .qoder/templates/plan-template.md → 生成 Plan → .qoder/plans/{today}/{keyword}-plan-v1.md
39
- 生成 add-route → check_dps ≥ 85
39
+ 生成 add-route → check_dps ≥ {{dpsPass}}
40
40
  Step 1: 扩展 AgentAuditPhase(如需要)
41
41
  Step 2: 确认 agentAudit() 通道
42
42
  Step 3: 将已写代码关联到 tasks.md
@@ -9,6 +9,7 @@ export CURRENT_MAGIC=$(basename "$(dirname "$HOOK_DIR")")
9
9
  COMMON_LIB="$HOOK_DIR/lib/common.sh"
10
10
  [ -f "$COMMON_LIB" ] && source "$COMMON_LIB"
11
11
  [ -f "$HOOK_DIR/lib/notify.sh" ] && source "$HOOK_DIR/lib/notify.sh" 2>/dev/null || true
12
+ [ -f "$HOOK_DIR/lib/vocabulary.sh" ] && source "$HOOK_DIR/lib/vocabulary.sh" 2>/dev/null || true
12
13
 
13
14
  export PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$PWD}"
14
15
 
@@ -40,25 +41,29 @@ EOF
40
41
  exit 0
41
42
  fi
42
43
 
43
- # ─── 开发关键词检测 ───
44
- if ! echo "$prompt" | grep -qiE '开发|改功能|修.?bug|加需求|新增|重构|实施|验收|继续|生成plan|生成计划'; then
44
+ # ─── 开发关键词检测(从词汇表动态加载) ───
45
+ dev_kw=$(load_dev_keywords 2>/dev/null || true)
46
+ if [ -z "$dev_kw" ]; then
47
+ exit 0
48
+ fi
49
+
50
+ if ! echo "$prompt" | grep -qiE "$dev_kw"; then
45
51
  exit 0
46
52
  fi
47
53
 
48
54
  echo "[ADD PromptSubmit] 检测到开发关键词" >&2
49
55
 
50
- # ─── Layer 2: 无活跃 ADD → 阻断 ───
56
+ # ─── Layer 2: 无活跃 ADD → 提示(不阻断) ───
51
57
  state=$(detect_active_add 2>/dev/null || true)
52
58
  if [ -z "$state" ]; then
53
59
  cat <<'EOF'
54
- [ADD 强制规则] 检测到开发任务。你必须先执行 add-paradigm SKILL 完成 ADD 工作流:
60
+ [ADD 提示] 检测到开发任务,但无活跃 ADD Plan。建议先执行 add-paradigm SKILL:
55
61
  Step 0: 文档先行 (Plan → Review → Specs)
56
62
  Step 3: 代码实现 + 审计植入
57
63
  Step 8: 收敛判断
58
- 如果 add-paradigm SKILL 尚未激活,请先调用它。
59
64
  EOF
60
- write_hook_event "prompt-submit" "deny" "$prompt" "无活跃 ADD Plan 下检测到开发任务" "no-active-plan" "none" 2>/dev/null || true
61
- exit 2
65
+ write_hook_event "prompt-submit" "info" "$prompt" "无活跃 ADD Plan 下检测到开发任务" "no-active-plan" "none" 2>/dev/null || true
66
+ exit 0
62
67
  fi
63
68
 
64
69
  # ─── Layer 3: 有活跃 ADD → 注入状态 + 模板全文 ───
@@ -78,9 +83,9 @@ if [ -f "$HOOK_JSONL" ]; then
78
83
  TOTAL=$(grep -c "\"ts\":\"${TODAY}" "$HOOK_JSONL" 2>/dev/null || echo 0)
79
84
  NO_PLAN=$(grep "\"ts\":\"${TODAY}" "$HOOK_JSONL" 2>/dev/null | grep -c '"planKeyword":"no-active-plan"' || echo 0)
80
85
  if [ "$TOTAL" -gt 0 ] 2>/dev/null; then
81
- echo "[Hook 治理] 今日拦截: ${TOTAL} 次 | 无 Plan 违规: ${NO_PLAN} 次"
86
+ echo "[Hook 治理] 今日提示: ${TOTAL} 次 | 无 Plan 提示: ${NO_PLAN} 次"
82
87
  if [ "$NO_PLAN" -ge 10 ] 2>/dev/null; then
83
- echo "[Hook ⚠️] 无 Plan 违规已达 ${NO_PLAN} 次(≥10),建议创建 Plan"
88
+ echo "[Hook ⚠️] 无 Plan 提示已达 ${NO_PLAN} 次(≥10),建议创建 Plan"
84
89
  fi
85
90
  fi
86
91
  fi
@@ -214,7 +214,7 @@ Plan 不是"文档开销"——它是代码治理的基础设施。跳过 Plan
214
214
 
215
215
  方案 A — 补 ADD 流程(招安):
216
216
  Step 0: 读 .qoder/templates/plan-template.md → 生成 Plan
217
- 生成 add-route → check_dps ≥ 85
217
+ 生成 add-route → check_dps ≥ {{dpsPass}}
218
218
  Step 1: 扩展 AgentAuditPhase(如需要)
219
219
  Step 2: 确认 agentAudit() 通道
220
220
  Step 3: 将已写代码关联到 tasks.md
@@ -36,7 +36,7 @@ Plan 不是"文档开销"——它是代码治理的基础设斻。跳过 Plan
36
36
 
37
37
  方案 A — 补 ADD 流程(招安):
38
38
  Step 0: 读 .qoder/templates/plan-template.md → 生成 Plan → .qoder/plans/{today}/{keyword}-plan-v1.md
39
- 生成 add-route → check_dps ≥ 85
39
+ 生成 add-route → check_dps ≥ {{dpsPass}}
40
40
  Step 1: 扩展 AgentAuditPhase(如需要)
41
41
  Step 2: 确认 agentAudit() 通道
42
42
  Step 3: 将已写代码关联到 tasks.md
@@ -53,19 +53,15 @@ fi
53
53
  # ─── Layer 2/3: 按活跃 ADD 分流 ───
54
54
  state=$(detect_active_add 2>/dev/null || true)
55
55
  if [ -z "$state" ]; then
56
- # Layer 2: 无活跃 ADD → 强制启动
56
+ # Layer 2: 无活跃 ADD → 提示启动(不阻断)
57
57
  cat >&2 <<'EOF'
58
- [ADD 强制规则] 检测到开发任务。你必须先执行 add-paradigm SKILL 完成 ADD 工作流:
58
+ [ADD 提示] 检测到开发任务,但无活跃 ADD Plan。建议先执行 add-paradigm SKILL:
59
59
  Step 0: 文档先行 (Plan → Review → Specs)
60
- Step 1: 扩展 AgentAuditPhase
61
- Step 2: 确认 agentAudit() 通道
62
60
  Step 3: 代码实现 + 审计植入
63
- ...
64
61
  Step 8: 收敛判断
65
- 如果 add-paradigm SKILL 尚未激活,请先调用它。
66
62
  EOF
67
- write_hook_event "prompt-submit" "deny" "$prompt" "无活跃 ADD Plan 下检测到开发任务" "no-active-plan" "none" 2>/dev/null || true
68
- exit 2
63
+ write_hook_event "prompt-submit" "info" "$prompt" "无活跃 ADD Plan 下检测到开发任务" "no-active-plan" "none" 2>/dev/null || true
64
+ exit 0
69
65
  fi
70
66
 
71
67
  # Layer 3: 有活跃 ADD → 注入状态
@@ -82,9 +78,9 @@ if [ -f "$HOOK_JSONL" ]; then
82
78
  TOTAL=$(grep -c "\"ts\":\"${TODAY}" "$HOOK_JSONL" 2>/dev/null || echo 0)
83
79
  NO_PLAN=$(grep "\"ts\":\"${TODAY}" "$HOOK_JSONL" 2>/dev/null | grep -c '"planKeyword":"no-active-plan"' || echo 0)
84
80
  if [ "$TOTAL" -gt 0 ] 2>/dev/null; then
85
- echo "[Hook 治理] 今日拦截: ${TOTAL} 次 | 无 Plan 违规: ${NO_PLAN} 次"
81
+ echo "[Hook 治理] 今日提示: ${TOTAL} 次 | 无 Plan 提示: ${NO_PLAN} 次"
86
82
  if [ "$NO_PLAN" -ge 10 ] 2>/dev/null; then
87
- echo "[Hook ⚠️] 无 Plan 违规已达 ${NO_PLAN} 次(≥10),建议创建 Plan 或检查 hooks 误报"
83
+ echo "[Hook ⚠️] 无 Plan 提示已达 ${NO_PLAN} 次(≥10),建议创建 Plan 或检查 hooks 误报"
88
84
  fi
89
85
  fi
90
86
  fi
@@ -214,7 +214,7 @@ Plan 不是"文档开销"——它是代码治理的基础设施。跳过 Plan
214
214
 
215
215
  方案 A — 补 ADD 流程(招安):
216
216
  Step 0: 读 .qoder/templates/plan-template.md → 生成 Plan
217
- 生成 add-route → check_dps ≥ 85
217
+ 生成 add-route → check_dps ≥ {{dpsPass}}
218
218
  Step 1: 扩展 AgentAuditPhase(如需要)
219
219
  Step 2: 确认 agentAudit() 通道
220
220
  Step 3: 将已写代码关联到 tasks.md
@@ -36,7 +36,7 @@ Plan 不是"文档开销"——它是代码治理的基础设斻。跳过 Plan
36
36
 
37
37
  方案 A — 补 ADD 流程(招安):
38
38
  Step 0: 读 .qoder/templates/plan-template.md → 生成 Plan → .qoder/plans/{today}/{keyword}-plan-v1.md
39
- 生成 add-route → check_dps ≥ 85
39
+ 生成 add-route → check_dps ≥ {{dpsPass}}
40
40
  Step 1: 扩展 AgentAuditPhase(如需要)
41
41
  Step 2: 确认 agentAudit() 通道
42
42
  Step 3: 将已写代码关联到 tasks.md
@@ -55,22 +55,18 @@ if ! echo "$prompt" | grep -qiE "$dev_kw"; then
55
55
  exit 0
56
56
  fi
57
57
 
58
- # ─── Layer 2/3: 按活跃 ADD 分流(原 Layer 2/3,不修改) ───
58
+ # ─── Layer 2/3: 按活跃 ADD 分流 ───
59
59
  state=$(detect_active_add 2>/dev/null || true)
60
60
  if [ -z "$state" ]; then
61
- # Layer 2: 无活跃 ADD → 强制启动
61
+ # Layer 2: 无活跃 ADD → 提示启动(不阻断)
62
62
  cat >&2 <<'EOF'
63
- [ADD 强制规则] 检测到开发任务。你必须先执行 add-paradigm SKILL 完成 ADD 工作流:
63
+ [ADD 提示] 检测到开发任务,但无活跃 ADD Plan。建议先执行 add-paradigm SKILL:
64
64
  Step 0: 文档先行 (Plan → Review → Specs)
65
- Step 1: 扩展 AgentAuditPhase
66
- Step 2: 确认 agentAudit() 通道
67
65
  Step 3: 代码实现 + 审计植入
68
- ...
69
66
  Step 8: 收敛判断
70
- 如果 add-paradigm SKILL 尚未激活,请先调用它。
71
67
  EOF
72
- write_hook_event "prompt-submit" "deny" "$prompt" "无活跃 ADD Plan 下检测到开发任务" "no-active-plan" "none" 2>/dev/null || true
73
- exit 2
68
+ write_hook_event "prompt-submit" "info" "$prompt" "无活跃 ADD Plan 下检测到开发任务" "no-active-plan" "none" 2>/dev/null || true
69
+ exit 0
74
70
  fi
75
71
 
76
72
  # Layer 3: 有活跃 ADD → 注入状态
@@ -88,9 +84,9 @@ if [ -f "$HOOK_JSONL" ]; then
88
84
  TOTAL=$(grep -c "\"ts\":\"${TODAY}" "$HOOK_JSONL" 2>/dev/null || echo 0)
89
85
  NO_PLAN=$(grep "\"ts\":\"${TODAY}" "$HOOK_JSONL" 2>/dev/null | grep -c '"planKeyword":"no-active-plan"' || echo 0)
90
86
  if [ "$TOTAL" -gt 0 ] 2>/dev/null; then
91
- add_ctx="${add_ctx}\n[Hook 治理] 今日拦截: ${TOTAL} 次 | 无 Plan 违规: ${NO_PLAN} 次"
87
+ add_ctx="${add_ctx}\n[Hook 治理] 今日提示: ${TOTAL} 次 | 无 Plan 提示: ${NO_PLAN} 次"
92
88
  if [ "$NO_PLAN" -ge 10 ] 2>/dev/null; then
93
- add_ctx="${add_ctx}\n[Hook ⚠️] 无 Plan 违规已达 ${NO_PLAN} 次(≥10),建议创建 Plan"
89
+ add_ctx="${add_ctx}\n[Hook ⚠️] 无 Plan 提示已达 ${NO_PLAN} 次(≥10),建议创建 Plan"
94
90
  fi
95
91
  fi
96
92
  fi
@@ -214,7 +214,7 @@ Plan 不是"文档开销"——它是代码治理的基础设施。跳过 Plan
214
214
 
215
215
  方案 A — 补 ADD 流程(招安):
216
216
  Step 0: 读 .qoder/templates/plan-template.md → 生成 Plan
217
- 生成 add-route → check_dps ≥ 85
217
+ 生成 add-route → check_dps ≥ {{dpsPass}}
218
218
  Step 1: 扩展 AgentAuditPhase(如需要)
219
219
  Step 2: 确认 agentAudit() 通道
220
220
  Step 3: 将已写代码关联到 tasks.md
@@ -36,7 +36,7 @@ Plan 不是"文档开销"——它是代码治理的基础设斻。跳过 Plan
36
36
 
37
37
  方案 A — 补 ADD 流程(招安):
38
38
  Step 0: 读 .qoder/templates/plan-template.md → 生成 Plan → .qoder/plans/{today}/{keyword}-plan-v1.md
39
- 生成 add-route → check_dps ≥ 85
39
+ 生成 add-route → check_dps ≥ {{dpsPass}}
40
40
  Step 1: 扩展 AgentAuditPhase(如需要)
41
41
  Step 2: 确认 agentAudit() 通道
42
42
  Step 3: 将已写代码关联到 tasks.md
@@ -53,19 +53,15 @@ fi
53
53
  # ─── Layer 2/3: 按活跃 ADD 分流 ───
54
54
  state=$(detect_active_add 2>/dev/null || true)
55
55
  if [ -z "$state" ]; then
56
- # Layer 2: 无活跃 ADD → 强制启动
56
+ # Layer 2: 无活跃 ADD → 提示启动(不阻断)
57
57
  cat >&2 <<'EOF'
58
- [ADD 强制规则] 检测到开发任务。你必须先执行 add-paradigm SKILL 完成 ADD 工作流:
58
+ [ADD 提示] 检测到开发任务,但无活跃 ADD Plan。建议先执行 add-paradigm SKILL:
59
59
  Step 0: 文档先行 (Plan → Review → Specs)
60
- Step 1: 扩展 AgentAuditPhase
61
- Step 2: 确认 agentAudit() 通道
62
60
  Step 3: 代码实现 + 审计植入
63
- ...
64
61
  Step 8: 收敛判断
65
- 如果 add-paradigm SKILL 尚未激活,请先调用它。
66
62
  EOF
67
- write_hook_event "prompt-submit" "deny" "$prompt" "无活跃 ADD Plan 下检测到开发任务" "no-active-plan" "none" 2>/dev/null || true
68
- exit 2
63
+ write_hook_event "prompt-submit" "info" "$prompt" "无活跃 ADD Plan 下检测到开发任务" "no-active-plan" "none" 2>/dev/null || true
64
+ exit 0
69
65
  fi
70
66
 
71
67
  # Layer 3: 有活跃 ADD → 注入状态
@@ -82,9 +78,9 @@ if [ -f "$HOOK_JSONL" ]; then
82
78
  TOTAL=$(grep -c "\"ts\":\"${TODAY}" "$HOOK_JSONL" 2>/dev/null || echo 0)
83
79
  NO_PLAN=$(grep "\"ts\":\"${TODAY}" "$HOOK_JSONL" 2>/dev/null | grep -c '"planKeyword":"no-active-plan"' || echo 0)
84
80
  if [ "$TOTAL" -gt 0 ] 2>/dev/null; then
85
- echo "[Hook 治理] 今日拦截: ${TOTAL} 次 | 无 Plan 违规: ${NO_PLAN} 次"
81
+ echo "[Hook 治理] 今日提示: ${TOTAL} 次 | 无 Plan 提示: ${NO_PLAN} 次"
86
82
  if [ "$NO_PLAN" -ge 10 ] 2>/dev/null; then
87
- echo "[Hook ⚠️] 无 Plan 违规已达 ${NO_PLAN} 次(≥10),建议创建 Plan 或检查 hooks 误报"
83
+ echo "[Hook ⚠️] 无 Plan 提示已达 ${NO_PLAN} 次(≥10),建议创建 Plan 或检查 hooks 误报"
88
84
  fi
89
85
  fi
90
86
  fi
@@ -214,7 +214,7 @@ Plan 不是"文档开销"——它是代码治理的基础设施。跳过 Plan
214
214
 
215
215
  方案 A — 补 ADD 流程(招安):
216
216
  Step 0: 读 .qoder/templates/plan-template.md → 生成 Plan
217
- 生成 add-route → check_dps ≥ 85
217
+ 生成 add-route → check_dps ≥ {{dpsPass}}
218
218
  Step 1: 扩展 AgentAuditPhase(如需要)
219
219
  Step 2: 确认 agentAudit() 通道
220
220
  Step 3: 将已写代码关联到 tasks.md
@@ -36,7 +36,7 @@ Plan 不是"文档开销"——它是代码治理的基础设斻。跳过 Plan
36
36
 
37
37
  方案 A — 补 ADD 流程(招安):
38
38
  Step 0: 读 .qoder/templates/plan-template.md → 生成 Plan → .qoder/plans/{today}/{keyword}-plan-v1.md
39
- 生成 add-route → check_dps ≥ 85
39
+ 生成 add-route → check_dps ≥ {{dpsPass}}
40
40
  Step 1: 扩展 AgentAuditPhase(如需要)
41
41
  Step 2: 确认 agentAudit() 通道
42
42
  Step 3: 将已写代码关联到 tasks.md
@@ -9,6 +9,7 @@ export CURRENT_MAGIC=$(basename "$(dirname "$HOOK_DIR")")
9
9
  COMMON_LIB="$HOOK_DIR/lib/common.sh"
10
10
  [ -f "$COMMON_LIB" ] && source "$COMMON_LIB"
11
11
  [ -f "$HOOK_DIR/lib/notify.sh" ] && source "$HOOK_DIR/lib/notify.sh" 2>/dev/null || true
12
+ [ -f "$HOOK_DIR/lib/vocabulary.sh" ] && source "$HOOK_DIR/lib/vocabulary.sh" 2>/dev/null || true
12
13
 
13
14
  export PROJECT_DIR="$PWD"
14
15
 
@@ -40,25 +41,29 @@ EOF
40
41
  exit 0
41
42
  fi
42
43
 
43
- # ─── 开发关键词检测 ───
44
- if ! echo "$prompt" | grep -qiE '开发|改功能|修.?bug|加需求|新增|重构|实施|验收|继续|生成plan|生成计划'; then
44
+ # ─── 开发关键词检测(从词汇表动态加载) ───
45
+ dev_kw=$(load_dev_keywords 2>/dev/null || true)
46
+ if [ -z "$dev_kw" ]; then
47
+ exit 0
48
+ fi
49
+
50
+ if ! echo "$prompt" | grep -qiE "$dev_kw"; then
45
51
  exit 0
46
52
  fi
47
53
 
48
54
  echo "[ADD PromptSubmit] 检测到开发关键词" >&2
49
55
 
50
- # ─── Layer 2: 无活跃 ADD → 阻断 ───
56
+ # ─── Layer 2: 无活跃 ADD → 提示(不阻断) ───
51
57
  state=$(detect_active_add 2>/dev/null || true)
52
58
  if [ -z "$state" ]; then
53
59
  cat <<'EOF'
54
- [ADD 强制规则] 检测到开发任务。你必须先执行 add-paradigm SKILL 完成 ADD 工作流:
60
+ [ADD 提示] 检测到开发任务,但无活跃 ADD Plan。建议先执行 add-paradigm SKILL:
55
61
  Step 0: 文档先行 (Plan → Review → Specs)
56
62
  Step 3: 代码实现 + 审计植入
57
63
  Step 8: 收敛判断
58
- 如果 add-paradigm SKILL 尚未激活,请先调用它。
59
64
  EOF
60
- write_hook_event "prompt-submit" "deny" "$prompt" "无活跃 ADD Plan 下检测到开发任务" "no-active-plan" "none" 2>/dev/null || true
61
- exit 2
65
+ write_hook_event "prompt-submit" "info" "$prompt" "无活跃 ADD Plan 下检测到开发任务" "no-active-plan" "none" 2>/dev/null || true
66
+ exit 0
62
67
  fi
63
68
 
64
69
  # ─── Layer 3: 有活跃 ADD → 注入状态 + 模板全文 ───
@@ -78,9 +83,9 @@ if [ -f "$HOOK_JSONL" ]; then
78
83
  TOTAL=$(grep -c "\"ts\":\"${TODAY}" "$HOOK_JSONL" 2>/dev/null || echo 0)
79
84
  NO_PLAN=$(grep "\"ts\":\"${TODAY}" "$HOOK_JSONL" 2>/dev/null | grep -c '"planKeyword":"no-active-plan"' || echo 0)
80
85
  if [ "$TOTAL" -gt 0 ] 2>/dev/null; then
81
- echo "[Hook 治理] 今日拦截: ${TOTAL} 次 | 无 Plan 违规: ${NO_PLAN} 次"
86
+ echo "[Hook 治理] 今日提示: ${TOTAL} 次 | 无 Plan 提示: ${NO_PLAN} 次"
82
87
  if [ "$NO_PLAN" -ge 10 ] 2>/dev/null; then
83
- echo "[Hook ⚠️] 无 Plan 违规已达 ${NO_PLAN} 次(≥10),建议创建 Plan"
88
+ echo "[Hook ⚠️] 无 Plan 提示已达 ${NO_PLAN} 次(≥10),建议创建 Plan"
84
89
  fi
85
90
  fi
86
91
  fi
@@ -67,7 +67,7 @@ Step N-1 出口 ──→ Guardian 出口检查 ──→ BLOCKED? 回退
67
67
  #### Step 1 入口(功能分析)
68
68
  | 检查项 | 方法 | 不通过 |
69
69
  |--------|------|--------|
70
- | DPS 闸门 ≥ 85 | 读取 add-route §0.8 的最新 `check_dps` 结果(如无记录则提醒主 agent 先调用) | **BLOCKED** — 回退 Step 0 补齐文档 |
70
+ | DPS 闸门 ≥ {{dpsPass}} | 读取 add-route §0.8 的最新 `check_dps` 结果(如无记录则提醒主 agent 先调用) | **BLOCKED** — 回退 Step 0 补齐文档 |
71
71
  | 0.6.5 Review 回流 | 检查 add-route Step 0 产出中是否已勾选 Review 回流项;如 add-route 无此勾选项但 reviews/ 下有 review 文件 → 提醒主 agent 先执行回流 | **BLOCKED** |
72
72
  | 原子闭包判定 | 检查 add-route 是否包含"原子闭包三可性判定"章节 | **BLOCKED** — 回退 Step 0.7 |
73
73
 
@@ -126,9 +126,9 @@ Step N-1 出口 ──→ Guardian 出口检查 ──→ BLOCKED? 回退
126
126
  | Review 文件存在 | 确认 `{{magicDir}}/reviews/` 下有对应的 review 文件 | 缺失 → **BLOCKED** |
127
127
  | add-route 已生成 | 确认 `{{magicDir}}/plans/` 下(含日期子目录)有 `*add-route*.md` | 缺失 → **BLOCKED** |
128
128
  | 项目文档已更新 | 检查 add-route Step 0 产出中是否勾选了"项目文档已更新"或"无需更新声明已记录" | 未勾选 → **FAIL** |
129
- | 0.6.5 回流完成 | 检查 add-route §0.8 是否记录了 DPS ≥ 85(或有 DPS 待通过标记) | 无记录 → **FAIL** |
129
+ | 0.6.5 回流完成 | 检查 add-route §0.8 是否记录了 DPS ≥ {{dpsPass}}(或有 DPS 待通过标记) | 无记录 → **FAIL** |
130
130
  | 原子闭包判定已执行 | add-route 含"原子闭包三可性判定"章节且有结论 | 缺失 → **BLOCKED** |
131
- | **DPS 闸门 ≥ 85** | **此为主 agent 在出口前必须调用的 MCP 闸门。Guardian 检查 add-route §0.8 中是否已记录 DPS 结果** | **DPS < 85 或无记录 → BLOCKED** |
131
+ | **DPS 闸门 ≥ {{dpsPass}}** | **此为主 agent 在出口前必须调用的 MCP 闸门。Guardian 检查 add-route §0.8 中是否已记录 DPS 结果** | **DPS < {{dpsPass}} 或无记录 → BLOCKED** |
132
132
  | TypeScript 编译 | 检查 add-route 中是否记录了主 agent 的 tsc 编译结果(主 agent 应先执行 `npx tsc --noEmit`) | 无记录 → **FAIL** |
133
133
  | eslint 检查 | 检查 add-route 中是否记录了主 agent 的 eslint 结果(主 agent 应先执行 `npx eslint`) | 无记录 → **FAIL** |
134
134
 
@@ -224,7 +224,7 @@ Plan: {✅ 存在 | ❌ 缺失}
224
224
  add-route: {文件路径 | ❌ 缺失 → BLOCKED}
225
225
  Specs 三元组: {spec/tasks/checklist 各状态}
226
226
  Review: {文件路径 | ❌ 缺失}
227
- DPS 记录: {已通过 ≥85 | 未通过 | 无记录}
227
+ DPS 记录: {已通过 ≥{{dpsPass}} | 未通过 | 无记录}
228
228
  RAHS 记录: {已通过 ≥90 | 未通过 | 无记录}
229
229
 
230
230
  【add-route 勾选状态】
@@ -214,7 +214,7 @@ Plan 不是"文档开销"——它是代码治理的基础设施。跳过 Plan
214
214
 
215
215
  方案 A — 补 ADD 流程(招安):
216
216
  Step 0: 读 .qoder/templates/plan-template.md → 生成 Plan
217
- 生成 add-route → check_dps ≥ 85
217
+ 生成 add-route → check_dps ≥ {{dpsPass}}
218
218
  Step 1: 扩展 AgentAuditPhase(如需要)
219
219
  Step 2: 确认 agentAudit() 通道
220
220
  Step 3: 将已写代码关联到 tasks.md
@@ -36,7 +36,7 @@ Plan 不是"文档开销"——它是代码治理的基础设斻。跳过 Plan
36
36
 
37
37
  方案 A — 补 ADD 流程(招安):
38
38
  Step 0: 读 .qoder/templates/plan-template.md → 生成 Plan → .qoder/plans/{today}/{keyword}-plan-v1.md
39
- 生成 add-route → check_dps ≥ 85
39
+ 生成 add-route → check_dps ≥ {{dpsPass}}
40
40
  Step 1: 扩展 AgentAuditPhase(如需要)
41
41
  Step 2: 确认 agentAudit() 通道
42
42
  Step 3: 将已写代码关联到 tasks.md
@@ -53,19 +53,15 @@ fi
53
53
  # ─── Layer 2/3: 按活跃 ADD 分流 ───
54
54
  state=$(detect_active_add 2>/dev/null || true)
55
55
  if [ -z "$state" ]; then
56
- # Layer 2: 无活跃 ADD → 强制启动
56
+ # Layer 2: 无活跃 ADD → 提示启动(不阻断)
57
57
  cat >&2 <<'EOF'
58
- [ADD 强制规则] 检测到开发任务。你必须先执行 add-paradigm SKILL 完成 ADD 工作流:
58
+ [ADD 提示] 检测到开发任务,但无活跃 ADD Plan。建议先执行 add-paradigm SKILL:
59
59
  Step 0: 文档先行 (Plan → Review → Specs)
60
- Step 1: 扩展 AgentAuditPhase
61
- Step 2: 确认 agentAudit() 通道
62
60
  Step 3: 代码实现 + 审计植入
63
- ...
64
61
  Step 8: 收敛判断
65
- 如果 add-paradigm SKILL 尚未激活,请先调用它。
66
62
  EOF
67
- write_hook_event "prompt-submit" "deny" "$prompt" "无活跃 ADD Plan 下检测到开发任务" "no-active-plan" "none" 2>/dev/null || true
68
- exit 2
63
+ write_hook_event "prompt-submit" "info" "$prompt" "无活跃 ADD Plan 下检测到开发任务" "no-active-plan" "none" 2>/dev/null || true
64
+ exit 0
69
65
  fi
70
66
 
71
67
  # Layer 3: 有活跃 ADD → 注入状态
@@ -82,9 +78,9 @@ if [ -f "$HOOK_JSONL" ]; then
82
78
  TOTAL=$(grep -c "\"ts\":\"${TODAY}" "$HOOK_JSONL" 2>/dev/null || echo 0)
83
79
  NO_PLAN=$(grep "\"ts\":\"${TODAY}" "$HOOK_JSONL" 2>/dev/null | grep -c '"planKeyword":"no-active-plan"' || echo 0)
84
80
  if [ "$TOTAL" -gt 0 ] 2>/dev/null; then
85
- echo "[Hook 治理] 今日拦截: ${TOTAL} 次 | 无 Plan 违规: ${NO_PLAN} 次"
81
+ echo "[Hook 治理] 今日提示: ${TOTAL} 次 | 无 Plan 提示: ${NO_PLAN} 次"
86
82
  if [ "$NO_PLAN" -ge 10 ] 2>/dev/null; then
87
- echo "[Hook ⚠️] 无 Plan 违规已达 ${NO_PLAN} 次(≥10),建议创建 Plan 或检查 hooks 误报"
83
+ echo "[Hook ⚠️] 无 Plan 提示已达 ${NO_PLAN} 次(≥10),建议创建 Plan 或检查 hooks 误报"
88
84
  fi
89
85
  fi
90
86
  fi
@@ -23,7 +23,7 @@
23
23
  | P2 | ADD-10 意图与实现的语义鸿沟 | 意图与实现是两层抽象,对齐只能靠显式对照 | ✅ 已实现 | |
24
24
  | P2 | ADD-11 证据的不可再生性 | 运行时上下文不可再生,证据必须优先持久化 | 🔶 待实现 | 需 runtime hook + predev 脚本 |
25
25
  | P2 | ADD-12 双源头漂移的必然性 | 代码与文档无同步必漂移,漂移代价由下一个接手者承担 | ✅ 已实现 | |
26
- | P2 | ADD-13 DPS 上游文档质量闸门 | Plan 概括度 → Review 注意力稀释 → Specs 遗漏 → 实现偏差。`check_dps`(DPS ≥ 85)在 Step 0 末尾量化阻断 | ✅ 已实现 | 2026-06-11 引入 |
26
+ | P2 | ADD-13 DPS 上游文档质量闸门 | Plan 概括度 → Review 注意力稀释 → Specs 遗漏 → 实现偏差。`check_dps`(DPS ≥ {{dpsPass}})在 Step 0 末尾量化阻断 | ✅ 已实现 | 2026-06-11 引入 |
27
27
  | P2 | ADD-14 RAHS 下游执行健康度闸门 | 范围保真度 + 类型安全 + 审计完整度 + Spec 合规 + 阶段对称性。`check_rahs`(RAHS ≥ 90)在 Step 4/8 量化阻断 | ✅ 已实现 | 2026-06-11 引入 |
28
28
  | P2 | ADD-15 add-route 闭环自检 | Step 3 代码完成后必须调用 `check_add_route_completeness` 扫描 add-route Step 完成度,防止执行遗漏。返回 complete 方可进入 Step 3.5 | ✅ 已实现 | 2026-06-11 引入 |
29
29
  | P2 | ADD-17 HITL 磋商临时文件机制 | doc-format-guard 要求 Plan/Review 文件包含完整章节才放行,HITL 第一步只写总览表会被 guard 阻断。用 `{name}.temporary.md` 做磋商(不受 guard 检查),人类拍板后再写正式文件并删除 temporary.md | ✅ 已实现 | 2026-07-23 引入 |
@@ -161,7 +161,7 @@ export function registerContextTools(server: McpServer) {
161
161
  const planKw = activePlan.replace(/-plan-v\d+\.md$/, "")
162
162
  const sd = existsSync(specsDir) ? await readdir(specsDir) : []
163
163
  if (!sd.some(d => d.toLowerCase().includes(planKw.toLowerCase())) && reviewBackflowRate >= 70) { todoItems.push("3. [Step 0] 生成 Specs 三元组") }
164
- if (todoItems.length === 0) { todoItems.push("✅ ADD 就绪 — check_dps ≥ 85 后可进入 Step 1") }
164
+ if (todoItems.length === 0) { todoItems.push("✅ ADD 就绪 — check_dps ≥ {{dpsPass}} 后可进入 Step 1") }
165
165
  }
166
166
  for (const item of todoItems) parts.push(item)
167
167
  parts.push(""); parts.push("快速指令: 说「执行 add-paradigm Step 0」进入文档先行流程")
@@ -34,7 +34,7 @@ export function registerCheckDps(server: McpServer) {
34
34
  "check_dps",
35
35
  {
36
36
  description:
37
- "DPS 闸门。四维复合评分: 语义相关性(TF-IDF/Jaccard) + 信息熵匹配(香农/Deng) + CPM关键路径 + 结构完整度 + FFT自适应权重。DPS >= 85 可进入 Step 1。",
37
+ `DPS 闸门。四维复合评分: 语义相关性(TF-IDF/Jaccard) + 信息熵匹配(香农/Deng) + CPM关键路径 + 结构完整度 + FFT自适应权重。DPS >= ${CFG.THRESHOLD_PASS} 可进入 Step 1。`,
38
38
  inputSchema: z.object({
39
39
  planKeyword: z.string().describe("Plan 文件的关键词"),
40
40
  }),
@@ -280,7 +280,7 @@ find_related_docs({ query: "功能关键词" })
280
280
 
281
281
  5. **验证回流完整性**:
282
282
  - 对 Review 中每个 P0/P1 问题,确认能在 Plan/Specs 中找到对应的"已修正后的文字"
283
- - 调用 `check_dps({ planKeyword: "..." })` 确认 DPS ≥ 85——如果回流后 DPS 仍然不达标,说明 Review 本身覆盖度不足或回流遗漏
283
+ - 调用 `check_dps({ planKeyword: "..." })` 确认 DPS ≥ {{dpsPass}}——如果回流后 DPS 仍然不达标,说明 Review 本身覆盖度不足或回流遗漏
284
284
 
285
285
  6. **记录审计**:调用 `record_dev_operation`(`targetType: "PLAN"`,`action: "DOC_UPDATED"`,`beforeState`: Review 问题编号列表,`afterState`: 每个问题的回流位置)
286
286
 
@@ -399,7 +399,7 @@ Plan 级闭包: {业务功能描述}
399
399
  - [ ] 文档合约一致性已确认
400
400
  - [ ] **[0.6.5] Review 结论已回流至 Plan 与 Specs**——Review 中每个 P0/P1 问题在 Plan/Specs 中有对应的修正后文字
401
401
  - [ ] 原子闭包判定已执行(Plan 级:确认单一业务功能;轮次级:确认文件边界独立、无跨轮修改、每轮可独立验证),轮次拆分方案已写入 add-route
402
- - [ ] **DPS 上游文档质量闸门已通过**——调用 `check_dps({ planKeyword: "<Plan 核心关键词>" })`,DPS ≥ 85 方可进入 Step 1。未通过时回退补齐短板(Plan 粒度不足 / Review 覆盖维度缺失 / Specs Requirements 遗漏)。详见 [ADD 协同规范 §八]({{projectRoot}}/{{docsDir}}/knowledge/01-架构/《ADD开发工作路径与文档协同规范》.md#八双质量闸门dps-与-rahs)
402
+ - [ ] **DPS 上游文档质量闸门已通过**——调用 `check_dps({ planKeyword: "<Plan 核心关键词>" })`,DPS ≥ {{dpsPass}} 方可进入 Step 1。未通过时回退补齐短板(Plan 粒度不足 / Review 覆盖维度缺失 / Specs Requirements 遗漏)。详见 [ADD 协同规范 §八]({{projectRoot}}/{{docsDir}}/knowledge/01-架构/《ADD开发工作路径与文档协同规范》.md#八双质量闸门dps-与-rahs)
403
403
 
404
404
  ---
405
405
 
@@ -24,7 +24,7 @@ ADD 不是"写代码时顺便打日志",而是一套覆盖全开发周期的
24
24
  │ │ 产物:{{magicDir}}/plans/{需求域名}-plan-v{n}.md │
25
25
  │ │ {{magicDir}}/plans/{需求域名}-add-route-v{n}.md │
26
26
  │ │ {{magicDir}}/reviews/{需求域名}-review-v{n}.md │
27
- │ │ 阈值:check_dps(DPS ≥ 85 方可进入 Step 1) │
27
+ │ │ 阈值:check_dps(DPS ≥ {{dpsPass}} 方可进入 Step 1) │
28
28
  ├────────────┼─────────────────────────────────────────────────────────────────┤
29
29
  │ Step 1 │ 功能分析与审计阶段定义 │
30
30
  │ 审计定义 │ 分析业务阶段 → 扩展 AgentAuditPhase 联合类型 → 确认审计通道 │
@@ -56,7 +56,7 @@
56
56
 
57
57
  | 触发词 | LLM 默认操作 | 优先级 |
58
58
  |--------|-------------|--------|
59
- | `DPS` / `DPS闸门` | 调 `check_dps({ planKeyword: "..." })`,DPS ≥ 85 通过 | 🔴 P0 |
59
+ | `DPS` / `DPS闸门` | 调 `check_dps({ planKeyword: "..." })`,DPS ≥ {{dpsPass}} 通过 | 🔴 P0 |
60
60
  | `RAHS` / `RAHS闸门` | 调 `check_rahs({ planKeyword: "..." })`,RAHS ≥ 90 通过 | 🔴 P0 |
61
61
  | `Guardian` / `门禁` / `add-flow-guardian` | 调 `add-flow-guardian` Subagent(入口或出口模式) | 🔴 P0 |
62
62
  | `add-route 闭环` / `闭环自检` | 调 `check_add_route_completeness({ planKeyword: "..." })` | 🟡 P1 |
@@ -197,7 +197,7 @@ LLM: "DPS 偏低,但不影响代码,继续 Step 1..." [忽略阻断]
197
197
  **正确输出**:
198
198
  ```
199
199
  LLM: "⛔ BLOCKED → 不得继续。修正 P0 阻断项后重新跑 DPS 门禁。"
200
- [回退到 Step 0,修复问题,重新 DPS,直到 ≥ 85]
200
+ [回退到 Step 0,修复问题,重新 DPS,直到 ≥ {{dpsPass}}]
201
201
  ```
202
202
 
203
203
  ### 场景 6: "继续" 被误解为跳到代码
@@ -278,7 +278,7 @@ LLM: "验收通过 → 自动写 devlog日志(走mcp)(无需用户提醒)→
278
278
 
279
279
  | 优先级 | 触发词 | LLM 默认操作 |
280
280
  |:--:|------|-------------|
281
- | P0 | `开发` / `改功能` / `修.?bug` / `fix.?bug` / `加需求` / `新增` / `重构` / `实现` / `接入` / `改造` / `升级` / `加个` / `添加功能` / `新建` / `改一下` / `修改.*逻辑` / `优化.*代码` / `对接` / `迁移` / `重写` / `implement` / `refactor` / `feature` | 开发任务检测——无活跃 ADD 时强制退出并提示启动 add-paradigm SKILL;有活跃 Plan 时注入当前 Step/轮次/handoff 上下文 |
281
+ | P0 | `开发` / `改功能` / `修.?bug` / `fix.?bug` / `加需求` / `新增` / `重构` / `实现` / `接入` / `改造` / `升级` / `加个` / `添加功能` / `新建` / `改一下` / `修改.*逻辑` / `优化.*代码` / `对接` / `迁移` / `重写` / `implement` / `refactor` / `feature` | 开发任务检测——无活跃 ADD 时提示启动 add-paradigm SKILL |
282
282
  | P0 | `实施` / `开始实施` / `进入实施` | Plan 就绪后 → 进入 add-paradigm SKILL → 从当前 Step 开始执行代码实现。如无活跃 add-route 先回 Step 0.5 生成 |
283
283
  | P0 | `继续` | **上下文锁定**:沿用上一条 AI 消息中明确提出的 Step/操作(如 "继续 Step 0.5 生成 add-route?" → "继续" = 执行 Step 0.5)。**禁止**将 "继续" 理解为"跳到代码编写(Step 3)"。**禁止**在 AI 刚提出 Step N 但用户说"继续"时跳过 Step N 做别的事 |
284
284
  | P1 | `Step 0` / `文档先行` | 进入 add-paradigm Step 0:分析变更 → 更新文档 → 生成 add-route → DPS 门禁 |
@@ -306,7 +306,7 @@ LLM: "验收通过 → 自动写 devlog日志(走mcp)(无需用户提醒)→
306
306
 
307
307
  | 优先级 | 触发词 | LLM 默认操作 |
308
308
  |:--:|------|-------------|
309
- | P0 | `DPS` / `DPS闸门` | 调 `check_dps({ planKeyword: "..." })`,DPS ≥ 85 通过 |
309
+ | P0 | `DPS` / `DPS闸门` | 调 `check_dps({ planKeyword: "..." })`,DPS ≥ {{dpsPass}} 通过 |
310
310
  | P0 | `RAHS` / `RAHS闸门` | 调 `check_rahs({ planKeyword: "..." })`,RAHS ≥ 90 通过 |
311
311
  | P0 | `Guardian` / `门禁` / `add-flow-guardian` | 调 `add-flow-guardian` Subagent(入口或出口模式) |
312
312
  | P1 | `add-route 闭环` / `闭环自检` | 调 `check_add_route_completeness({ planKeyword: "..." })` |