add-coder 0.3.31 → 0.3.32

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 (74) hide show
  1. package/package.json +1 -1
  2. package/templates/.add-coder-src-hash.json +73 -1
  3. package/templates/adapters/claude/hooks/doc-format-guard.mjs +850 -0
  4. package/templates/adapters/claude/hooks/notification.mjs +256 -0
  5. package/templates/adapters/claude/hooks/permission-denied.mjs +167 -0
  6. package/templates/adapters/claude/hooks/permission-gate.mjs +150 -0
  7. package/templates/adapters/claude/hooks/post-tool-failure.mjs +3 -0
  8. package/templates/adapters/claude/hooks/post-tool-use.mjs +413 -0
  9. package/templates/adapters/claude/hooks/pre-compact.mjs +226 -0
  10. package/templates/adapters/claude/hooks/pre-tool-use.mjs +914 -0
  11. package/templates/adapters/claude/hooks/prompt-submit.mjs +847 -0
  12. package/templates/adapters/claude/hooks/review-checklist.mjs +3 -0
  13. package/templates/adapters/claude/hooks/session-end.mjs +287 -0
  14. package/templates/adapters/claude/hooks/session-start.mjs +566 -0
  15. package/templates/adapters/claude/hooks/stop-check.mjs +505 -0
  16. package/templates/adapters/claude/hooks/stop-failure.mjs +222 -0
  17. package/templates/adapters/claude/hooks/subagent-guard.mjs +224 -0
  18. package/templates/adapters/claude/hooks/subagent-stop.mjs +277 -0
  19. package/templates/adapters/codex/hooks/doc-format-guard.mjs +849 -0
  20. package/templates/adapters/codex/hooks/notification.mjs +254 -0
  21. package/templates/adapters/codex/hooks/permission-gate.mjs +169 -0
  22. package/templates/adapters/codex/hooks/post-tool-failure.mjs +176 -0
  23. package/templates/adapters/codex/hooks/post-tool-use.mjs +575 -0
  24. package/templates/adapters/codex/hooks/pre-compact.mjs +328 -0
  25. package/templates/adapters/codex/hooks/pre-tool-use.mjs +963 -0
  26. package/templates/adapters/codex/hooks/prompt-submit.mjs +623 -0
  27. package/templates/adapters/codex/hooks/review-checklist.mjs +3 -0
  28. package/templates/adapters/codex/hooks/session-end.mjs +389 -0
  29. package/templates/adapters/codex/hooks/session-start.mjs +583 -0
  30. package/templates/adapters/codex/hooks/stop-check.mjs +539 -0
  31. package/templates/adapters/codex/hooks/subagent-guard.mjs +218 -0
  32. package/templates/adapters/codex/hooks/subagent-stop.mjs +381 -0
  33. package/templates/adapters/qoder/hooks/doc-format-guard.mjs +858 -0
  34. package/templates/adapters/qoder/hooks/notification.mjs +269 -0
  35. package/templates/adapters/qoder/hooks/permission-gate.mjs +284 -0
  36. package/templates/adapters/qoder/hooks/post-tool-failure.mjs +294 -0
  37. package/templates/adapters/qoder/hooks/post-tool-use.mjs +535 -0
  38. package/templates/adapters/qoder/hooks/pre-compact.mjs +234 -0
  39. package/templates/adapters/qoder/hooks/pre-tool-use.mjs +948 -0
  40. package/templates/adapters/qoder/hooks/prompt-submit.mjs +789 -0
  41. package/templates/adapters/qoder/hooks/review-checklist.mjs +409 -0
  42. package/templates/adapters/qoder/hooks/session-end.mjs +301 -0
  43. package/templates/adapters/qoder/hooks/session-start.mjs +619 -0
  44. package/templates/adapters/qoder/hooks/stop-check.mjs +567 -0
  45. package/templates/adapters/qoder/hooks/subagent-guard.mjs +219 -0
  46. package/templates/adapters/qoder/hooks/subagent-stop.mjs +298 -0
  47. package/templates/adapters/trae/hooks/doc-format-guard.mjs +849 -0
  48. package/templates/adapters/trae/hooks/notification.mjs +251 -0
  49. package/templates/adapters/trae/hooks/permission-gate.mjs +169 -0
  50. package/templates/adapters/trae/hooks/post-tool-failure.mjs +176 -0
  51. package/templates/adapters/trae/hooks/post-tool-use.mjs +415 -0
  52. package/templates/adapters/trae/hooks/pre-compact.mjs +224 -0
  53. package/templates/adapters/trae/hooks/pre-tool-use.mjs +873 -0
  54. package/templates/adapters/trae/hooks/prompt-submit.mjs +614 -0
  55. package/templates/adapters/trae/hooks/review-checklist.mjs +3 -0
  56. package/templates/adapters/trae/hooks/session-end.mjs +285 -0
  57. package/templates/adapters/trae/hooks/session-start.mjs +555 -0
  58. package/templates/adapters/trae/hooks/stop-check.mjs +502 -0
  59. package/templates/adapters/trae/hooks/subagent-guard.mjs +218 -0
  60. package/templates/adapters/trae/hooks/subagent-stop.mjs +274 -0
  61. package/templates/adapters/vscode/hooks/doc-format-guard.mjs +847 -0
  62. package/templates/adapters/vscode/hooks/notification.mjs +251 -0
  63. package/templates/adapters/vscode/hooks/permission-gate.mjs +169 -0
  64. package/templates/adapters/vscode/hooks/post-tool-failure.mjs +192 -0
  65. package/templates/adapters/vscode/hooks/post-tool-use.mjs +415 -0
  66. package/templates/adapters/vscode/hooks/pre-compact.mjs +224 -0
  67. package/templates/adapters/vscode/hooks/pre-tool-use.mjs +906 -0
  68. package/templates/adapters/vscode/hooks/prompt-submit.mjs +838 -0
  69. package/templates/adapters/vscode/hooks/review-checklist.mjs +3 -0
  70. package/templates/adapters/vscode/hooks/session-end.mjs +285 -0
  71. package/templates/adapters/vscode/hooks/session-start.mjs +560 -0
  72. package/templates/adapters/vscode/hooks/stop-check.mjs +502 -0
  73. package/templates/adapters/vscode/hooks/subagent-guard.mjs +218 -0
  74. package/templates/adapters/vscode/hooks/subagent-stop.mjs +274 -0
@@ -0,0 +1,502 @@
1
+ // templates/core/governance/common.ts
2
+ import { existsSync, readFileSync, writeFileSync, unlinkSync } from "node:fs";
3
+ import { basename, dirname, join } from "node:path";
4
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
5
+ import { spawnSync } from "node:child_process";
6
+ import { createHash } from "node:crypto";
7
+
8
+ // templates/core/governance/rules.ts
9
+ var context = {
10
+ "quadrants": [
11
+ {
12
+ "id": "no_add_no_dev",
13
+ "consumed": false,
14
+ "text": "[ADD Stop] \u65E0\u6D3B\u8DC3 Plan\uFF0C\u65E0\u4EE3\u7801\u6539\u52A8\u3002\u6B63\u5E38\u7ED3\u675F\u3002"
15
+ },
16
+ {
17
+ "id": "no_add_has_dev",
18
+ "consumed": true,
19
+ "text": '[ADD Stop] \u26A0\uFE0F \u68C0\u6D4B\u5230\u4EE3\u7801\u4FEE\u6539\u4F46\u65E0\u6D3B\u8DC3 ADD Plan\u3002\n\nPlan \u4E0D\u662F"\u6587\u6863\u5F00\u9500"\u2014\u2014\u5B83\u662F\u4EE3\u7801\u6CBB\u7406\u7684\u57FA\u7840\u8BBE\u65BD\u3002\u8DF3\u8FC7 Plan \u7684\u540E\u679C:\n \xB7 \u6CA1\u6709 add-route \u2192 \u6BCF\u6B21\u6539\u52A8\u65E0\u6CD5\u8FFD\u6EAF\u5230\u5177\u4F53 Task\n \xB7 \u6CA1\u6709 tasks.md \u2192 \u540E\u7EED AI Session \u4E0D\u77E5\u9053\u6539\u4E86\u54EA\u4E9B\u6587\u4EF6\n \xB7 \u6CA1\u6709 handoff \u2192 \u4EA4\u63A5\u65F6\u4E0A\u4E0B\u6587\u5168\u4E22\uFF0C\u53EA\u80FD\u9760 git log \u731C\n\n\u4F60\u5FC5\u987B\u7ACB\u5373\u8865\u6551\uFF0C\u4E8C\u9009\u4E00:\n\n\u65B9\u6848 A \u2014 \u8865 ADD \u6D41\u7A0B\uFF08\u62DB\u5B89\uFF09:\n Step 0: \u8BFB .qoder/templates/plan-template.md \u2192 \u751F\u6210 Plan \u2192 .qoder/plans/{today}/{keyword}-plan-v1.md\n \u751F\u6210 add-route \u2192 check_dps \u2265 {{dpsPass}}\n Step 1: \u6269\u5C55 AgentAuditPhase\uFF08\u5982\u9700\u8981\uFF09\n Step 2: \u786E\u8BA4 agentAudit() \u901A\u9053\n Step 3: \u5C06\u5DF2\u5199\u4EE3\u7801\u5173\u8054\u5230 tasks.md\n \u5B8C\u6210\u540E\u53EF\u6B63\u5E38\u505C\u6B62\u3002\n\n\u65B9\u6848 B \u2014 \u8865\u4E0D\u4E0A\u5219\u56DE\u6EDA:\n \u5982\u679C\u6539\u52A8\u592A\u590D\u6742\u65E0\u6CD5\u8FFD\u6EAF\u751F\u6210 Plan\uFF0C\u5219:\n \u2460 git diff \u786E\u8BA4\u6539\u52A8\u8303\u56F4\n \u2461 \u4EC5\u5BF9\u5DF2\u786E\u8BA4\u5C5E\u4E8E\u672C\u8F6E\u7684\u6587\u4EF6\u751F\u6210\u53CD\u5411 apply_patch\n \u2462 \u65E0\u6CD5\u5B89\u5168\u786E\u8BA4\u6539\u52A8\u6240\u6709\u6743\u65F6\u505C\u6B62\uFF0C\u5E76\u8BF7\u6C42\u7528\u6237\u51B3\u5B9A\n\n\u65E0\u8BBA\u9009 A \u8FD8\u662F B\uFF0C\u5B8C\u6210\u540E\u544A\u8BC9\u7528\u6237\u4E0B\u6B21\u6267\u884C session-init \u6062\u590D\u4E0A\u4E0B\u6587\u3002\n'
20
+ },
21
+ {
22
+ "id": "has_add_no_dev",
23
+ "consumed": false,
24
+ "text": "[ADD Stop] ADD \u6D41\u7A0B\u8FDB\u884C\u4E2D ({{info}})\uFF0C\u672C\u6B21\u65E0\u4EE3\u7801\u6539\u52A8\u3002\u4E0B\u6B21\u7EE7\u7EED\u65F6\u6267\u884C session-init \u6062\u590D\u4E0A\u4E0B\u6587\u3002"
25
+ },
26
+ {
27
+ "id": "has_add_dev_step02",
28
+ "consumed": false,
29
+ "text": "[ADD Stop] ADD Step 0-2: \u6587\u6863\u5148\u884C/\u5BA1\u8BA1\u51C6\u5907\u9636\u6BB5\u3002\u65E0\u9700\u9A8C\u6536\u95ED\u73AF\u3002\u4E0B\u4E00\u6B65: \u8FDB\u5165 Step 3 \u4EE3\u7801\u5B9E\u73B0\u3002"
30
+ },
31
+ {
32
+ "id": "has_add_dev_step3",
33
+ "consumed": false,
34
+ "text": "[ADD Stop] ADD Step 3: \u4EE3\u7801\u5B9E\u73B0\u8FDB\u884C\u4E2D ({{info}})\u3002\u5B8C\u6210\u540E\u8FDB\u5165 Step 3.5 \u5B9E\u73B0\u5BA1\u67E5\u3002"
35
+ },
36
+ {
37
+ "id": "has_add_dev_unclosed",
38
+ "consumed": true,
39
+ "text": "[ADD Stop] \u26A0\uFE0F \u4EE3\u7801\u5DF2\u5B8C\u6210\u4F46\u9A8C\u6536\u672A\u95ED\u73AF:\n{{info}}\n\n\u8BF7\u4F9D\u6B21\u6267\u884C\uFF08\u4E0D\u8981\u7B49\u4E0B\u6B21\u4F1A\u8BDD\uFF09:\n \u2460 Write devlog \u2192 handoff \u540C\u76EE\u5F55 devlog-{plan}-v{n}.md\n \u683C\u5F0F: # Devlog: {plan}\\n \u65E5\u671F / Plan / \u8F6E\u6B21 / \u672C\u8F6E\u6539\u4E86\u4EC0\u4E48 / \u9A8C\u6536\u7ED3\u679C / \u9057\u7559\u9879 / \u67B6\u6784\u56DE\u770B\n \u2461 Edit handoff \u2192 \u66F4\u65B0 \xA7\u9A8C\u8BC1\u6807\u51C6 \u5168\u90E8 [x] + \u8865\u5145\u5BA1\u8BA1 ID\n \u2605 \u540C\u6B65: checklist \u6709\u65B0 cuid \u2192 handoff ADD-7 \u8868\u5FC5\u987B\u5BF9\u5E94\u65B0\u589E\u884C\n \u2605 Step 0 \u51C6\u5165: handoff + add-route + Specs \u4E09\u5143\u7EC4\u7F3A\u4E00\u4E0D\u53EF\uFF0C\u7F3A\u5219\u56DE\u9000 Step 0.5\n \u2462 Read docs/ \u2192 \u56DE\u770B\u67B6\u6784\u6587\u6863\u786E\u8BA4\u4E00\u81F4\u6027\n \u2463 Edit add-route \u2192 \u52FE\u9009\u5BF9\u5E94 Step [x]\n\n\u4EE5\u4E0A\u5168\u90E8\u5B8C\u6210\u540E Agent \u624D\u80FD\u505C\u6B62\u3002\n\n\u4E0B\u6B21\u6062\u590D: \u8BFB handoff \u2192 \u67E5\u540C\u76EE\u5F55 devlog-*.md \u2192 query_audit_logs\n"
40
+ },
41
+ {
42
+ "id": "has_add_dev_closed",
43
+ "consumed": false,
44
+ "text": "[ADD Stop] \u2705 \u9A8C\u6536\u95ED\u73AF: add-route\u5168\u90E8[x], devlog\u5DF2\u8BB0\u5F55, handoff\u5DF2\u66F4\u65B0\u3002\u9A8C\u6536\u5E42\u7B49\u2014\u2014\u91CD\u590D\u89E6\u53D1\u4E0D\u8986\u76D6\u5DF2\u6709\u7ED3\u8BBA\u3002"
45
+ }
46
+ ],
47
+ "adapter_quadrants": [
48
+ {
49
+ "adapter": "qoder",
50
+ "id": "has_add_dev_unclosed",
51
+ "text": "[ADD Stop] \u26A0\uFE0F \u4EE3\u7801\u5DF2\u5B8C\u6210\u4F46\u9A8C\u6536\u672A\u95ED\u73AF:\n{{info}}\n\n\u8BF7\u4F9D\u6B21\u6267\u884C\uFF08\u4E0D\u8981\u7B49\u4E0B\u6B21\u4F1A\u8BDD\uFF09:\n \u2460 Write devlog \u2192 handoff \u540C\u76EE\u5F55 devlog-{plan}-v{n}.md\n \u683C\u5F0F: # Devlog: {plan}\\n \u65E5\u671F / Plan / \u8F6E\u6B21 / \u672C\u8F6E\u6539\u4E86\u4EC0\u4E48 / \u9A8C\u6536\u7ED3\u679C / \u9057\u7559\u9879 / \u67B6\u6784\u56DE\u770B\n \u2461 Edit handoff \u2192 \u66F4\u65B0 \xA7\u9A8C\u8BC1\u6807\u51C6 \u5168\u90E8 [x] + \u8865\u5145\u5BA1\u8BA1 ID\n \u2605 \u540C\u6B65: checklist \u6709\u65B0 cuid \u2192 handoff ADD-7 \u8868\u5FC5\u987B\u5BF9\u5E94\u65B0\u589E\u884C\n \u2605 Step 0 \u51C6\u5165: handoff + add-route + Specs \u4E09\u5143\u7EC4\u7F3A\u4E00\u4E0D\u53EF\uFF0C\u7F3A\u5219\u56DE\u9000 Step 0.5\n \u2462 Read docs/ \u2192 \u56DE\u770B\u67B6\u6784\u6587\u6863\u786E\u8BA4\u4E00\u81F4\u6027\n \u2463 Edit add-route \u2192 \u52FE\u9009\u5BF9\u5E94 Step [x]\n\n\u4EE5\u4E0A\u5168\u90E8\u5B8C\u6210\u540E Agent \u624D\u80FD\u505C\u6B62\u3002\n\n\u4E0B\u6B21\u6062\u590D: \u8BFB handoff \u2192 \u67E5\u540C\u76EE\u5F55 devlog-*.md \u2192 query_audit_logs\n"
52
+ }
53
+ ],
54
+ "templates": {
55
+ "priority_order": [
56
+ "simple-plan-template.md",
57
+ "spec-template.md",
58
+ "tasks-template.md",
59
+ "checklist-template.md",
60
+ "review-template.md",
61
+ "standard-plan-template.md",
62
+ "add-route-template-heavyweight.md",
63
+ "add-route-template.md",
64
+ "handoff-single-round-template.md",
65
+ "handoff-multi-round-template.md"
66
+ ],
67
+ "descriptions": {
68
+ "simple-plan-template.md": "\u9700\u6C42\u65B9\u6848\uFF08\u7B80\u5355\u7248\uFF09\uFF1A\u516D\u8282\u7ED3\u6784\uFF0C\u5143\u4FE1\u606F+\u80CC\u666F+\u65B9\u6848+\u67B6\u6784+\u5B9E\u65BD+\u9A8C\u6536",
69
+ "spec-template.md": "\u529F\u80FD\u89C4\u683C\uFF1AWhy/What Changes/Impact/WHEN-THEN Requirements",
70
+ "tasks-template.md": "\u4EFB\u52A1\u62C6\u5206\uFF1APhase\u2192Task\u2192SubTask\u5C42\u7EA7",
71
+ "checklist-template.md": "\u9A8C\u6536\u6E05\u5355\uFF1A[T]\u7F16\u8BD1\u671F+[R]\u8FD0\u884C\u65F6+ADD\u89C4\u5219\u5408\u89C4",
72
+ "review-template.md": "\u65B9\u6848\u5BA1\u67E5\uFF08ADD-9\uFF09\uFF1A\u95EE\u9898\u590D\u73B0+\u65B9\u6848\u5BF9\u6BD4+\u51B3\u7B56\u7ED3\u8BBA+\u5F71\u54CD\u8BC4\u4F30",
73
+ "standard-plan-template.md": "\u9700\u6C42\u65B9\u6848\uFF08\u6807\u51C6\u7248\uFF09\uFF1APLAN\u5143\u4FE1\u606F+\u80CC\u666F+\u65B9\u6848+\u67B6\u6784+\u5B9E\u65BDTask+\u9A8C\u6536+\u5173\u8054\u6587\u6863",
74
+ "add-route-template-heavyweight.md": "ADD\u6267\u884C\u8DEF\u7EBF\u56FE\uFF08\u91CD\u578B\uFF09\uFF1A\u6BCFStep\u9A8C\u8BC1\u5E76\u66F4\u65B0\u72B6\u6001+spec_sync\u4EA4\u53C9\u6821\u9A8C",
75
+ "add-route-template.md": "ADD\u6267\u884C\u8DEF\u7EBF\u56FE\uFF08\u8F7B\u91CF\uFF09\uFF1A\u6807\u51C6Step\u4EA7\u51FA\u68C0\u67E5",
76
+ "handoff-single-round-template.md": "\u5355\u8F6E\u4EA4\u63A5\uFF1A9\u7AE0\u8282\uFF08\u542B\u6062\u590D\u4E0A\u4E0B\u6587\u5BA1\u8BA1\u67E5\u8BE2\uFF09",
77
+ "handoff-multi-round-template.md": "\u591A\u8F6E\u4EA4\u63A5\uFF1A\u5168\u5C40\u62D3\u6251+\u6BCF\u8F6E13\u5B50\u7AE0\u8282+\u6536\u655B\u89C4\u5219+\u542F\u52A8\u6A21\u677F"
78
+ }
79
+ },
80
+ "pretool": {
81
+ "text": "[ADD PreToolUse] \u5F53\u524D Plan: {{plan}}\uFF0C\u8F6E\u6B21: {{round}}\u3002\n\u672C\u6B21\u5199\u5165\u5E94\u5C5E\u4E8E ADD Step 3 \u4EE3\u7801\u5B9E\u73B0\u9636\u6BB5\u3002\n\u5B8C\u6210\u540E\u6267\u884C record_dev_operation \u8BB0\u5F55\u5BA1\u8BA1\u3002"
82
+ }
83
+ };
84
+ var protocol = {
85
+ "exit_codes": {
86
+ "pass": 0,
87
+ "block": 2,
88
+ "note": "\u5192\u70DF\u6821\u9A8C: \u4EA7\u7269\u9000\u51FA\u7801 \u2208 {0,2}\uFF08\u5176\u4F59\u4E3A\u975E\u9884\u671F\uFF0C\u9700\u4FEE\u590D\uFF09"
89
+ },
90
+ "output": {
91
+ "stdout_json_only": true,
92
+ "stderr_human_text": true,
93
+ "field_separator": "::",
94
+ "magic_dir_resolution": "\u6CE8\u5165\u4F18\u5148 \u2192 \u7269\u7406\u4F4D\u7F6E\u63A8\u5BFC \u2192 failClosed\uFF08\u7981\u6B62\u731C\u6D4B adapter \u540D\uFF09"
95
+ },
96
+ "adapters": {
97
+ "claude": {
98
+ "stdout_form": "plain-text",
99
+ "project_dir_env": "CLAUDE_PROJECT_DIR",
100
+ "magic_dir": ".claude",
101
+ "handlerTypes": [
102
+ "command",
103
+ "mcp_tool"
104
+ ]
105
+ },
106
+ "qoder": {
107
+ "stdout_form": "json",
108
+ "project_dir_env": "QODER_PROJECT_DIR",
109
+ "magic_dir": ".qoder",
110
+ "handlerTypes": [
111
+ "command",
112
+ "http"
113
+ ]
114
+ },
115
+ "codex": {
116
+ "stdout_form": "systemMessage",
117
+ "project_dir_env": "git-toplevel",
118
+ "magic_dir": ".codex",
119
+ "handlerTypes": [
120
+ "command"
121
+ ]
122
+ },
123
+ "vscode": {
124
+ "stdout_form": "plain-text",
125
+ "project_dir_env": "PWD",
126
+ "magic_dir": ".vscode",
127
+ "handlerTypes": [
128
+ "command"
129
+ ]
130
+ },
131
+ "trae": {
132
+ "stdout_form": "plain-text",
133
+ "project_dir_env": "PWD",
134
+ "magic_dir": ".trae",
135
+ "handlerTypes": [
136
+ "command"
137
+ ]
138
+ }
139
+ },
140
+ "event_outputs": {
141
+ "qoder": {
142
+ "SessionStart": "additionalContext",
143
+ "UserPromptSubmit": "additionalContext",
144
+ "PreToolUse": "permissionDecision",
145
+ "Stop": "additionalContext",
146
+ "PostToolUse": "feedback",
147
+ "SubagentStart": "additionalContext",
148
+ "SubagentStop": "additionalContext",
149
+ "PostToolUseFailure": "text",
150
+ "PermissionRequest": "text",
151
+ "SessionEnd": "text",
152
+ "PreCompact": "text",
153
+ "Notification": "text"
154
+ },
155
+ "claude": {
156
+ "SessionStart": "additionalContext",
157
+ "UserPromptSubmit": "additionalContext",
158
+ "PreToolUse": "permissionDecision",
159
+ "Stop": "text",
160
+ "PostToolUse": "feedback",
161
+ "SubagentStart": "text",
162
+ "SubagentStop": "text",
163
+ "PostToolUseFailure": "text",
164
+ "PermissionRequest": "text",
165
+ "SessionEnd": "text",
166
+ "PreCompact": "text",
167
+ "Notification": "text"
168
+ },
169
+ "codex": {
170
+ "Stop": "systemMessage",
171
+ "PostToolUse": "text"
172
+ },
173
+ "vscode": {
174
+ "PostToolUse": "text"
175
+ },
176
+ "trae": {
177
+ "PostToolUse": "text"
178
+ }
179
+ },
180
+ "core": {
181
+ "stdout_form": "json",
182
+ "magic_dir": ".add",
183
+ "note": "core \u5165\u53E3\u534F\u8BAE = qoder \u540C\u6784\u53C2\u8003\u5B9E\u73B0\uFF1Badapter \u4EC5\u4FDD\u7559\u672C\u8868\u58F0\u660E\u7684\u79C1\u6709\u5DEE\u5F02"
184
+ },
185
+ "adapter_defaults": {
186
+ "magic_dir_fallback": ".qoder",
187
+ "probe_magic_dirs": [
188
+ ".claude",
189
+ ".qoder",
190
+ ".vscode",
191
+ ".add",
192
+ ".trae",
193
+ ".codex"
194
+ ]
195
+ }
196
+ };
197
+
198
+ // node_modules/.pnpm/find-up@8.0.0/node_modules/find-up/index.js
199
+ import path2 from "node:path";
200
+
201
+ // node_modules/.pnpm/locate-path@8.0.0/node_modules/locate-path/index.js
202
+ import process2 from "node:process";
203
+ import path from "node:path";
204
+ import fs, { promises as fsPromises } from "node:fs";
205
+ import { fileURLToPath } from "node:url";
206
+ var typeMappings = {
207
+ directory: "isDirectory",
208
+ file: "isFile"
209
+ };
210
+ function checkType(type) {
211
+ if (type === "both" || Object.hasOwn(typeMappings, type)) {
212
+ return;
213
+ }
214
+ throw new Error(`Invalid type specified: ${type}`);
215
+ }
216
+ var matchType = (type, stat) => type === "both" ? stat.isFile() || stat.isDirectory() : stat[typeMappings[type]]();
217
+ var toPath = (urlOrPath) => urlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath;
218
+ function locatePathSync(paths, {
219
+ cwd = process2.cwd(),
220
+ type = "file",
221
+ allowSymlinks = true
222
+ } = {}) {
223
+ checkType(type);
224
+ cwd = toPath(cwd);
225
+ const statFunction = allowSymlinks ? fs.statSync : fs.lstatSync;
226
+ for (const path_ of paths) {
227
+ try {
228
+ const stat = statFunction(path.resolve(cwd, path_), {
229
+ throwIfNoEntry: false
230
+ });
231
+ if (!stat) {
232
+ continue;
233
+ }
234
+ if (matchType(type, stat)) {
235
+ return path_;
236
+ }
237
+ } catch {
238
+ }
239
+ }
240
+ }
241
+
242
+ // node_modules/.pnpm/unicorn-magic@0.3.0/node_modules/unicorn-magic/node.js
243
+ import { promisify } from "node:util";
244
+ import { execFile as execFileCallback, execFileSync as execFileSyncOriginal } from "node:child_process";
245
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
246
+ var execFileOriginal = promisify(execFileCallback);
247
+ function toPath2(urlOrPath) {
248
+ return urlOrPath instanceof URL ? fileURLToPath2(urlOrPath) : urlOrPath;
249
+ }
250
+ var TEN_MEGABYTES_IN_BYTES = 10 * 1024 * 1024;
251
+
252
+ // node_modules/.pnpm/find-up@8.0.0/node_modules/find-up/index.js
253
+ var findUpStop = /* @__PURE__ */ Symbol("findUpStop");
254
+ function findUpMultipleSync(name, options = {}) {
255
+ let directory = path2.resolve(toPath2(options.cwd) ?? "");
256
+ const { root } = path2.parse(directory);
257
+ const stopAt = path2.resolve(directory, toPath2(options.stopAt) ?? root);
258
+ const limit = options.limit ?? Number.POSITIVE_INFINITY;
259
+ const paths = [name].flat();
260
+ const runMatcher = (locateOptions) => {
261
+ if (typeof name !== "function") {
262
+ return locatePathSync(paths, locateOptions);
263
+ }
264
+ const foundPath = name(locateOptions.cwd);
265
+ if (typeof foundPath === "string") {
266
+ return locatePathSync([foundPath], locateOptions);
267
+ }
268
+ return foundPath;
269
+ };
270
+ const matches = [];
271
+ while (true) {
272
+ const foundPath = runMatcher({ ...options, cwd: directory });
273
+ if (foundPath === findUpStop) {
274
+ break;
275
+ }
276
+ if (foundPath) {
277
+ matches.push(path2.resolve(directory, foundPath));
278
+ }
279
+ if (directory === stopAt || matches.length >= limit) {
280
+ break;
281
+ }
282
+ directory = path2.dirname(directory);
283
+ }
284
+ return matches;
285
+ }
286
+ function findUpSync(name, options = {}) {
287
+ const matches = findUpMultipleSync(name, { ...options, limit: 1 });
288
+ return matches[0];
289
+ }
290
+
291
+ // templates/core/governance/common.ts
292
+ var EXIT_PASS = protocol.exit_codes.pass;
293
+ var EXIT_BLOCK = protocol.exit_codes.block;
294
+ var STATE_SEP = protocol.output.field_separator;
295
+ function tryResolveMagicDir() {
296
+ const injected = process.env.MAGIC_DIR;
297
+ if (injected) return injected;
298
+ const startDir = dirname(fileURLToPath3(import.meta.url));
299
+ const hit = findUpSync((dir) => basename(dir).startsWith(".") ? dir : void 0, {
300
+ cwd: startDir,
301
+ type: "directory"
302
+ });
303
+ return hit ? basename(hit) : "";
304
+ }
305
+ function queryPlanStatus() {
306
+ const magicDir = process.env.MAGIC_DIR;
307
+ if (!magicDir) {
308
+ return {
309
+ stdout: '{"availability":"STATUS_UNAVAILABLE","source":"database","reason":"magicDir \u672A\u6CE8\u5165\u4E14\u65E0\u6CD5\u4ECE\u7269\u7406\u4F4D\u7F6E\u63A8\u5BFC"}',
310
+ exitCode: 3
311
+ };
312
+ }
313
+ const bridge = join(
314
+ process.env.PROJECT_DIR || process.cwd(),
315
+ magicDir,
316
+ "scripts",
317
+ "plan-status-bridge.ts"
318
+ );
319
+ if (!existsSync(bridge)) {
320
+ return {
321
+ stdout: '{"availability":"STATUS_UNAVAILABLE","source":"database","reason":"plan-status bridge missing"}',
322
+ exitCode: 3
323
+ };
324
+ }
325
+ const r = spawnSync("node", ["--import", "tsx", bridge], {
326
+ encoding: "utf-8",
327
+ timeout: 1e4
328
+ });
329
+ return { stdout: r.stdout ?? "", exitCode: r.status ?? -1 };
330
+ }
331
+ function detectActiveAdd() {
332
+ const r = queryPlanStatus();
333
+ if (r.exitCode !== 0) {
334
+ let reason = "database status unavailable";
335
+ try {
336
+ const parsed = JSON.parse(r.stdout);
337
+ if (parsed.reason) reason = parsed.reason;
338
+ } catch {
339
+ }
340
+ return `__STATUS_UNAVAILABLE__::${reason}::database::none::none`;
341
+ }
342
+ let snapshot;
343
+ try {
344
+ snapshot = JSON.parse(r.stdout);
345
+ } catch {
346
+ return null;
347
+ }
348
+ if (!(snapshot.availability === "READY" && snapshot.isActive === true)) return null;
349
+ const done = snapshot.progress?.doneTasks ?? 0;
350
+ const total = snapshot.progress?.totalTasks ?? 0;
351
+ const approval = snapshot.approvalStatus ?? "none";
352
+ return `${snapshot.planName}::${done}/${total}::${approval}::none::none`;
353
+ }
354
+ function projectHash() {
355
+ try {
356
+ return createHash("md5").update(`${process.env.PROJECT_DIR || process.cwd()}
357
+ `).digest("hex").slice(0, 8);
358
+ } catch {
359
+ return "default";
360
+ }
361
+ }
362
+ var DEV_FLAG = `/tmp/add_dev_${projectHash()}`;
363
+ function hasDevAction() {
364
+ return existsSync(DEV_FLAG);
365
+ }
366
+ function clearDevAction() {
367
+ try {
368
+ unlinkSync(DEV_FLAG);
369
+ } catch {
370
+ }
371
+ }
372
+ function checkAddCompleteness(handoff, addRoute) {
373
+ const issues = [];
374
+ if (handoff && existsSync(handoff)) {
375
+ const content = readFileSync(handoff, "utf-8");
376
+ if (!/验收|收敛|闭环|本轮改了什么|devlog/.test(content)) {
377
+ issues.push(" [ ] devlog \u7F3A\u5931\uFF08handoff \u65E0\u9A8C\u6536\u8BB0\u5F55\uFF09");
378
+ }
379
+ const unchecked = (content.match(/\[ \]/g) || []).length;
380
+ if (unchecked > 0) {
381
+ issues.push(` [ ] handoff ${unchecked} \u9879\u672A\u52FE\u9009`);
382
+ }
383
+ }
384
+ if (addRoute && existsSync(addRoute)) {
385
+ const content = readFileSync(addRoute, "utf-8");
386
+ const unchecked = (content.match(/\[ \]/g) || []).length;
387
+ if (unchecked > 0) {
388
+ issues.push(` [ ] add-route ${unchecked} Step \u672A\u95ED\u73AF`);
389
+ }
390
+ }
391
+ return issues;
392
+ }
393
+
394
+ // templates/core/governance/context-inject.ts
395
+ var QUADRANTS = new Map(
396
+ (context.quadrants ?? []).filter((q) => q.consumed === true).map((q) => [q.id, q])
397
+ );
398
+ function buildStopContext(quadrant, info) {
399
+ const q = QUADRANTS.get(quadrant);
400
+ if (!q) return "";
401
+ return q.text.replaceAll("{{info}}", info);
402
+ }
403
+
404
+ // templates/core/governance/stop-router.ts
405
+ var StopRouter = class {
406
+ /** 主路由:返回 exit code(0 放行 / 2 阻断) */
407
+ run() {
408
+ const state = detectActiveAdd();
409
+ const hasDev = hasDevAction();
410
+ if (state !== null && state.startsWith("__STATUS_UNAVAILABLE__")) {
411
+ const reason = state.split("::")[1] ?? "";
412
+ return this.emitQ0(reason);
413
+ }
414
+ if (state === null && !hasDev) {
415
+ return 0;
416
+ }
417
+ if (state === null && hasDev) {
418
+ return this.emitQ2();
419
+ }
420
+ const fields = state.split("::");
421
+ const plan = fields[0] ?? "";
422
+ const step = fields[1] ?? "";
423
+ const rounds = fields[2] ?? "";
424
+ const handoff = fields[3] ?? "";
425
+ const addRoute = fields[4] ?? "";
426
+ if (!hasDev) {
427
+ return this.emitQ3(plan, rounds, step);
428
+ }
429
+ return this.q4Check(plan, rounds, step, handoff, addRoute);
430
+ }
431
+ // ─────────────────────────── 扩展点 ───────────────────────────
432
+ /**
433
+ * Q4 验收决策(双维度组合——2026-08-14 Task 9.4.4④ 上提,回流: I2):
434
+ * 维度 1(前置): DB 任务进度(step = done/total,数值且 done<total → 未完成阻断提示)
435
+ * 维度 2: checklist 质量(checkAddCompleteness 未闭环 → 阻断)
436
+ * 互补非替代——codex 原 DB 进度分流语义上提 core,core checklist 质量语义保留。
437
+ */
438
+ q4Check(plan, rounds, step, handoff, addRoute) {
439
+ void plan;
440
+ void rounds;
441
+ const [donePart, totalPart] = step.split("/");
442
+ if (/^\d+$/.test(donePart) && /^\d+$/.test(totalPart) && Number(donePart) < Number(totalPart)) {
443
+ return this.emitQ4Unclosed(
444
+ `DB Plan \u4EFB\u52A1\u8FDB\u5EA6 ${donePart}/${totalPart}\uFF0C\u5C1A\u6709\u672A\u5B8C\u6210 Task\u3002\u8BF7\u7EE7\u7EED\u6267\u884C\u5F53\u524D Plan \u7684\u672A\u5B8C\u6210 Task\uFF0C\u5E76\u4E3A\u672C\u8F6E\u6539\u52A8\u8865\u9F50 record_dev_operation \u5BA1\u8BA1\u3002`
445
+ );
446
+ }
447
+ const issues = checkAddCompleteness(
448
+ handoff && handoff !== "none" ? handoff : "",
449
+ addRoute && addRoute !== "none" ? addRoute : ""
450
+ );
451
+ if (issues.length > 0) {
452
+ return this.emitQ4Unclosed(issues.join("\n"));
453
+ }
454
+ clearDevAction();
455
+ return this.emitQ4Pass();
456
+ }
457
+ /** Q0: DB 不可用(core: stderr + 2) */
458
+ emitQ0(reason) {
459
+ process.stderr.write(
460
+ `[ADD Stop] \u26D4 Plan status \u6682\u4E0D\u53EF\u7528\uFF08${reason}\uFF09\u3002\u672A\u56DE\u9000 Handoff/add-route \u731C\u6D4B\uFF0C\u8BF7\u6062\u590D\u6570\u636E\u5E93\u6216 MCP resolver \u540E\u91CD\u8BD5\u3002
461
+ `
462
+ );
463
+ return EXIT_BLOCK;
464
+ }
465
+ /** Q2: 无 ADD + 有 dev(core: stderr few-shot + 2) */
466
+ emitQ2() {
467
+ process.stderr.write(buildStopContext("no_add_has_dev", "") + "\n");
468
+ return EXIT_BLOCK;
469
+ }
470
+ /** Q3: 有 ADD + 无 dev(core: 纯文本状态注入 + 0) */
471
+ emitQ3(plan, rounds, step) {
472
+ process.stdout.write(`[ADD Stop] Plan: ${plan}, \u8F6E\u6B21: ${rounds}, Step: ${step}
473
+ `);
474
+ process.stdout.write("\u672C\u6B21\u65E0\u4EE3\u7801\u6539\u52A8\u3002\u4E0B\u6B21\u7EE7\u7EED\u65F6\u6267\u884C session-init \u6062\u590D\u4E0A\u4E0B\u6587\u3002\n");
475
+ return 0;
476
+ }
477
+ /** Q4 验收未闭环(core: stderr + 2;unclosedInterpolate=true 插值) */
478
+ emitQ4Unclosed(info) {
479
+ const text = this.unclosedInterpolate() ? buildStopContext("has_add_dev_unclosed", info) : buildStopContext("has_add_dev_unclosed", "");
480
+ process.stderr.write(text + "\n");
481
+ return EXIT_BLOCK;
482
+ }
483
+ /** Q4 验收通过(core: 纯文本 + 0) */
484
+ emitQ4Pass() {
485
+ process.stdout.write("[ADD Stop] \u2705 \u9A8C\u6536\u901A\u8FC7\u2014\u2014checklist \u5168\u90E8\u52FE\u9009\uFF0Cdevlog \u5DF2\u8BB0\u5F55\u3002\n");
486
+ return 0;
487
+ }
488
+ /** has_add_dev_unclosed 是否插值(core: true;qoder: false 缺陷照搬) */
489
+ unclosedInterpolate() {
490
+ return true;
491
+ }
492
+ };
493
+
494
+ // templates/adapters/trae/hooks/stop-check.ts
495
+ var TraeStopRouter = class extends StopRouter {
496
+ // 当前无 override(Q0-Q4 分流与 core 基线一致);命名子类承载端身份 + 未来演进位
497
+ };
498
+ var inferredMagicDir = tryResolveMagicDir();
499
+ if (inferredMagicDir && !process.env.MAGIC_DIR) {
500
+ process.env.MAGIC_DIR = inferredMagicDir;
501
+ }
502
+ process.exit(new TraeStopRouter().run());