add-coder 0.3.34 → 0.3.37

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 (98) hide show
  1. package/README.en.md +101 -42
  2. package/README.md +63 -18
  3. package/dist/index.js +24 -6
  4. package/package.json +2 -2
  5. package/templates/.add-coder-src-hash.json +94 -39
  6. package/templates/adapters/claude/hooks/doc-format-guard.mjs +172 -84
  7. package/templates/adapters/claude/hooks/post-tool-use.mjs +59 -1
  8. package/templates/adapters/claude/hooks/prompt-submit.mjs +72 -0
  9. package/templates/adapters/claude/hooks/session-start.mjs +65 -1
  10. package/templates/adapters/codex/hooks/doc-format-guard.mjs +172 -84
  11. package/templates/adapters/codex/hooks/post-tool-use.mjs +59 -1
  12. package/templates/adapters/codex/hooks/prompt-submit.mjs +72 -0
  13. package/templates/adapters/codex/hooks/session-start.mjs +65 -1
  14. package/templates/adapters/qoder/hooks/doc-format-guard.mjs +172 -84
  15. package/templates/adapters/qoder/hooks/post-tool-use.mjs +59 -1
  16. package/templates/adapters/qoder/hooks/prompt-submit.mjs +72 -0
  17. package/templates/adapters/qoder/hooks/session-start.mjs +67 -1
  18. package/templates/adapters/trae/hooks/doc-format-guard.mjs +172 -84
  19. package/templates/adapters/trae/hooks/post-tool-use.mjs +59 -1
  20. package/templates/adapters/trae/hooks/prompt-submit.mjs +72 -0
  21. package/templates/adapters/trae/hooks/session-start.mjs +65 -1
  22. package/templates/adapters/vscode/hooks/doc-format-guard.mjs +172 -84
  23. package/templates/adapters/vscode/hooks/post-tool-use.mjs +59 -1
  24. package/templates/adapters/vscode/hooks/prompt-submit.mjs +72 -0
  25. package/templates/adapters/vscode/hooks/session-start.mjs +65 -1
  26. package/templates/core/governance/doc-format-guard.ts +29 -112
  27. package/templates/core/governance/post-tool-router.ts +33 -1
  28. package/templates/core/governance/prompt-router.ts +47 -0
  29. package/templates/core/governance/session-start-guard.ts +48 -1
  30. package/templates/core/prisma/add.prisma +203 -0
  31. package/templates/core/scripts/db-ensure.sh +92 -2
  32. package/templates/core/scripts/mcp-server/shared/db-types.ts +119 -0
  33. package/templates/core/scripts/mcp-server/shared/hitl-create-policy.ts +27 -0
  34. package/templates/core/scripts/mcp-server/shared/hitl-proposal-content.ts +110 -0
  35. package/templates/core/scripts/mcp-server/shared/hitl-widget-instance.ts +85 -0
  36. package/templates/core/scripts/mcp-server/shared/memory/calibration/batch-fit.ts +250 -0
  37. package/templates/core/scripts/mcp-server/shared/memory/calibration/feedback-stats.ts +101 -0
  38. package/templates/core/scripts/mcp-server/shared/memory/calibration/unit-state.ts +224 -0
  39. package/templates/core/scripts/mcp-server/shared/memory/domain/conflicts.ts +59 -0
  40. package/templates/core/scripts/mcp-server/shared/memory/domain/dedup.ts +45 -0
  41. package/templates/core/scripts/mcp-server/shared/memory/domain/errors.ts +33 -0
  42. package/templates/core/scripts/mcp-server/shared/memory/domain/handoff-digest.ts +92 -0
  43. package/templates/core/scripts/mcp-server/shared/memory/domain/metric-candidate.ts +79 -0
  44. package/templates/core/scripts/mcp-server/shared/memory/domain/scope.ts +94 -0
  45. package/templates/core/scripts/mcp-server/shared/memory/domain/secrets.ts +50 -0
  46. package/templates/core/scripts/mcp-server/shared/memory/domain/state-machine.ts +90 -0
  47. package/templates/core/scripts/mcp-server/shared/memory/embedding/index.ts +117 -0
  48. package/templates/core/scripts/mcp-server/shared/memory/embedding/local-onnx.ts +105 -0
  49. package/templates/core/scripts/mcp-server/shared/memory/embedding/openai-compatible.ts +87 -0
  50. package/templates/core/scripts/mcp-server/shared/memory/jobs/consolidation.ts +226 -0
  51. package/templates/core/scripts/mcp-server/shared/memory/jobs/evidence-collector.ts +153 -0
  52. package/templates/core/scripts/mcp-server/shared/memory/jobs/snapshot.ts +114 -0
  53. package/templates/core/scripts/mcp-server/shared/memory/metrics/gate-recall.ts +134 -0
  54. package/templates/core/scripts/mcp-server/shared/memory/metrics/gate-writer.ts +217 -0
  55. package/templates/core/scripts/mcp-server/shared/memory/metrics/stage-words.ts +69 -0
  56. package/templates/core/scripts/mcp-server/shared/memory/retrieval/context-builder.ts +89 -0
  57. package/templates/core/scripts/mcp-server/shared/memory/retrieval/fts/pg.ts +139 -0
  58. package/templates/core/scripts/mcp-server/shared/memory/retrieval/fts/sqlite-fts5.sql +29 -0
  59. package/templates/core/scripts/mcp-server/shared/memory/retrieval/fts/sqlite.ts +106 -0
  60. package/templates/core/scripts/mcp-server/shared/memory/retrieval/fusion.ts +43 -0
  61. package/templates/core/scripts/mcp-server/shared/memory/retrieval/pipeline.ts +285 -0
  62. package/templates/core/scripts/mcp-server/shared/memory/retrieval/query-terms.ts +31 -0
  63. package/templates/core/scripts/mcp-server/shared/memory/retrieval/recall-writer.ts +87 -0
  64. package/templates/core/scripts/mcp-server/shared/memory/retrieval/reranker.ts +116 -0
  65. package/templates/core/scripts/mcp-server/shared/memory/retrieval/types.ts +52 -0
  66. package/templates/core/scripts/mcp-server/shared/memory/retrieval/vector/pgvector.ts +143 -0
  67. package/templates/core/scripts/mcp-server/shared/memory/retrieval/vector/sqlite-vec.ts +118 -0
  68. package/templates/core/scripts/mcp-server/shared/memory/switches.ts +39 -0
  69. package/templates/core/scripts/mcp-server/shared/review-files.ts +22 -0
  70. package/templates/core/scripts/mcp-server/shared/runtime-freshness.ts +235 -0
  71. package/templates/core/scripts/mcp-server/tools/gateway/check_dps.ts +37 -0
  72. package/templates/core/scripts/mcp-server/tools/gateway/check_rahs.ts +40 -1
  73. package/templates/core/scripts/mcp-server/tools/hitl.ts +108 -42
  74. package/templates/core/scripts/mcp-server/tools/index.ts +7 -1
  75. package/templates/core/scripts/mcp-server/tools/memory-compat.ts +258 -0
  76. package/templates/core/scripts/mcp-server/tools/memory.ts +654 -0
  77. package/templates/core/scripts/mcp-server/tools/plan.ts +8 -3
  78. package/templates/core/scripts/mcp-server/tools/review.ts +10 -7
  79. package/templates/core/scripts/mcp-server.ts +36 -0
  80. package/templates/core/templates/checklist-template.md +13 -0
  81. package/templates/core/templates/review-implementation-template.md +24 -0
  82. package/templates/core/templates/review-template.md +16 -0
  83. package/templates/core/validation/index.ts +136 -0
  84. package/templates/core/validation/policy.ts +91 -0
  85. package/templates/core/validation/registry.ts +61 -0
  86. package/templates/core/validation/schema-validator.ts +277 -0
  87. package/templates/core/validation/validators/add-route.ts +32 -0
  88. package/templates/core/validation/validators/checklist.ts +48 -0
  89. package/templates/core/validation/validators/handoff.ts +46 -0
  90. package/templates/core/validation/validators/hitl.ts +22 -0
  91. package/templates/core/validation/validators/index.ts +52 -0
  92. package/templates/core/validation/validators/plan.ts +20 -0
  93. package/templates/core/validation/validators/report.ts +16 -0
  94. package/templates/core/validation/validators/review.ts +30 -0
  95. package/templates/core/validation/validators/spec.ts +25 -0
  96. package/templates/core/validation/validators/tasks.ts +40 -0
  97. package/templates/core/validation/validators/types.ts +32 -0
  98. package/templates/core/vocabulary/add-governance-vocabulary.md +18 -0
@@ -1,6 +1,6 @@
1
1
  {
2
- "_version": "0.3.34",
3
- "adapters/claude/hooks/doc-format-guard.mjs": "eff9d727",
2
+ "_version": "0.3.37",
3
+ "adapters/claude/hooks/doc-format-guard.mjs": "b21350a0",
4
4
  "adapters/claude/hooks/doc-format-guard.ts": "2abf8013",
5
5
  "adapters/claude/hooks/lib/claude-env.ts": "170b40ca",
6
6
  "adapters/claude/hooks/notification.mjs": "7c532eef",
@@ -11,19 +11,19 @@
11
11
  "adapters/claude/hooks/permission-gate.ts": "858f2dc6",
12
12
  "adapters/claude/hooks/post-tool-failure.mjs": "c1490184",
13
13
  "adapters/claude/hooks/post-tool-failure.ts": "8c53fdd4",
14
- "adapters/claude/hooks/post-tool-use.mjs": "83d05985",
14
+ "adapters/claude/hooks/post-tool-use.mjs": "bb8f197e",
15
15
  "adapters/claude/hooks/post-tool-use.ts": "54c1840a",
16
16
  "adapters/claude/hooks/pre-compact.mjs": "3eb17466",
17
17
  "adapters/claude/hooks/pre-compact.ts": "fdb49e54",
18
18
  "adapters/claude/hooks/pre-tool-use.mjs": "9301fbd9",
19
19
  "adapters/claude/hooks/pre-tool-use.ts": "c47cc5d5",
20
- "adapters/claude/hooks/prompt-submit.mjs": "89895adb",
20
+ "adapters/claude/hooks/prompt-submit.mjs": "ab4994c4",
21
21
  "adapters/claude/hooks/prompt-submit.ts": "c3847e2a",
22
22
  "adapters/claude/hooks/review-checklist.mjs": "421384d5",
23
23
  "adapters/claude/hooks/review-checklist.ts": "94695330",
24
24
  "adapters/claude/hooks/session-end.mjs": "1cf8ea80",
25
25
  "adapters/claude/hooks/session-end.ts": "3c963eae",
26
- "adapters/claude/hooks/session-start.mjs": "9a526492",
26
+ "adapters/claude/hooks/session-start.mjs": "37240cdf",
27
27
  "adapters/claude/hooks/session-start.ts": "3f762d49",
28
28
  "adapters/claude/hooks/stop-check.mjs": "ad933373",
29
29
  "adapters/claude/hooks/stop-check.ts": "967fd318",
@@ -36,7 +36,7 @@
36
36
  "adapters/claude/mcp.json": "4ddc5120",
37
37
  "adapters/claude/settings.json": "9cf9603a",
38
38
  "adapters/codex/config.toml.example": "62c03d71",
39
- "adapters/codex/hooks/doc-format-guard.mjs": "d68873ab",
39
+ "adapters/codex/hooks/doc-format-guard.mjs": "6d3583ae",
40
40
  "adapters/codex/hooks/doc-format-guard.ts": "566b835f",
41
41
  "adapters/codex/hooks/notification.mjs": "bf95cd4c",
42
42
  "adapters/codex/hooks/notification.ts": "a4fd2749",
@@ -44,19 +44,19 @@
44
44
  "adapters/codex/hooks/permission-gate.ts": "15af671c",
45
45
  "adapters/codex/hooks/post-tool-failure.mjs": "a8e100b4",
46
46
  "adapters/codex/hooks/post-tool-failure.ts": "bddd1f4e",
47
- "adapters/codex/hooks/post-tool-use.mjs": "b73c1201",
47
+ "adapters/codex/hooks/post-tool-use.mjs": "c9b92bad",
48
48
  "adapters/codex/hooks/post-tool-use.ts": "a7a2fc6c",
49
49
  "adapters/codex/hooks/pre-compact.mjs": "2c16761f",
50
50
  "adapters/codex/hooks/pre-compact.ts": "c0671f9b",
51
51
  "adapters/codex/hooks/pre-tool-use.mjs": "d7499d78",
52
52
  "adapters/codex/hooks/pre-tool-use.ts": "3750e60b",
53
- "adapters/codex/hooks/prompt-submit.mjs": "e2df7fbc",
53
+ "adapters/codex/hooks/prompt-submit.mjs": "71078015",
54
54
  "adapters/codex/hooks/prompt-submit.ts": "625cdc5e",
55
55
  "adapters/codex/hooks/review-checklist.mjs": "f20c9bd7",
56
56
  "adapters/codex/hooks/review-checklist.ts": "9a664173",
57
57
  "adapters/codex/hooks/session-end.mjs": "e876065c",
58
58
  "adapters/codex/hooks/session-end.ts": "7fcb6f86",
59
- "adapters/codex/hooks/session-start.mjs": "e528f769",
59
+ "adapters/codex/hooks/session-start.mjs": "7eccb61e",
60
60
  "adapters/codex/hooks/session-start.ts": "4eacd44f",
61
61
  "adapters/codex/hooks/stop-check.mjs": "c8866935",
62
62
  "adapters/codex/hooks/stop-check.ts": "ee1801dd",
@@ -66,7 +66,7 @@
66
66
  "adapters/codex/hooks/subagent-stop.ts": "a27e6a9e",
67
67
  "adapters/codex/hooks.json": "3c78fb72",
68
68
  "adapters/codex/settings.json": "44136fa3",
69
- "adapters/qoder/hooks/doc-format-guard.mjs": "aface90b",
69
+ "adapters/qoder/hooks/doc-format-guard.mjs": "5ee30711",
70
70
  "adapters/qoder/hooks/doc-format-guard.ts": "12e360db",
71
71
  "adapters/qoder/hooks/lib/context-inject.ts": "aaee941a",
72
72
  "adapters/qoder/hooks/lib/qoder-env.ts": "ec8c3243",
@@ -77,19 +77,19 @@
77
77
  "adapters/qoder/hooks/permission-gate.ts": "8478e48e",
78
78
  "adapters/qoder/hooks/post-tool-failure.mjs": "e8b486b6",
79
79
  "adapters/qoder/hooks/post-tool-failure.ts": "b9439d5c",
80
- "adapters/qoder/hooks/post-tool-use.mjs": "2af854fd",
80
+ "adapters/qoder/hooks/post-tool-use.mjs": "42f88112",
81
81
  "adapters/qoder/hooks/post-tool-use.ts": "c7e9ce26",
82
82
  "adapters/qoder/hooks/pre-compact.mjs": "3f8a1fa7",
83
83
  "adapters/qoder/hooks/pre-compact.ts": "70a8e8f8",
84
84
  "adapters/qoder/hooks/pre-tool-use.mjs": "ab662bcf",
85
85
  "adapters/qoder/hooks/pre-tool-use.ts": "2f0cab18",
86
- "adapters/qoder/hooks/prompt-submit.mjs": "c9eee559",
86
+ "adapters/qoder/hooks/prompt-submit.mjs": "8c6567f7",
87
87
  "adapters/qoder/hooks/prompt-submit.ts": "9050e0cb",
88
88
  "adapters/qoder/hooks/review-checklist.mjs": "04b300e4",
89
89
  "adapters/qoder/hooks/review-checklist.ts": "cf4ac191",
90
90
  "adapters/qoder/hooks/session-end.mjs": "eee2e434",
91
91
  "adapters/qoder/hooks/session-end.ts": "e9bf7cd4",
92
- "adapters/qoder/hooks/session-start.mjs": "21b88d24",
92
+ "adapters/qoder/hooks/session-start.mjs": "8d4453db",
93
93
  "adapters/qoder/hooks/session-start.ts": "eeb089e0",
94
94
  "adapters/qoder/hooks/stop-check.mjs": "b010c028",
95
95
  "adapters/qoder/hooks/stop-check.ts": "53447287",
@@ -100,7 +100,7 @@
100
100
  "adapters/qoder/mcp.json": "b2075957",
101
101
  "adapters/qoder/settings.json": "31799ee7",
102
102
  "adapters/qoder/sync-policy.json": "9cb6ff90",
103
- "adapters/trae/hooks/doc-format-guard.mjs": "f1cb0b3b",
103
+ "adapters/trae/hooks/doc-format-guard.mjs": "6cf78bae",
104
104
  "adapters/trae/hooks/doc-format-guard.ts": "14968f12",
105
105
  "adapters/trae/hooks/notification.mjs": "495c8c2d",
106
106
  "adapters/trae/hooks/notification.ts": "f0b4b606",
@@ -108,19 +108,19 @@
108
108
  "adapters/trae/hooks/permission-gate.ts": "c53aedc7",
109
109
  "adapters/trae/hooks/post-tool-failure.mjs": "834b0545",
110
110
  "adapters/trae/hooks/post-tool-failure.ts": "4cd97dac",
111
- "adapters/trae/hooks/post-tool-use.mjs": "631d84c8",
111
+ "adapters/trae/hooks/post-tool-use.mjs": "e9d50cb9",
112
112
  "adapters/trae/hooks/post-tool-use.ts": "7b1e2f4f",
113
113
  "adapters/trae/hooks/pre-compact.mjs": "6c0c3e68",
114
114
  "adapters/trae/hooks/pre-compact.ts": "5de3b0fe",
115
115
  "adapters/trae/hooks/pre-tool-use.mjs": "8075f74e",
116
116
  "adapters/trae/hooks/pre-tool-use.ts": "a7486c97",
117
- "adapters/trae/hooks/prompt-submit.mjs": "9e47de7e",
117
+ "adapters/trae/hooks/prompt-submit.mjs": "6385a3d2",
118
118
  "adapters/trae/hooks/prompt-submit.ts": "95ebd771",
119
119
  "adapters/trae/hooks/review-checklist.mjs": "491dd85e",
120
120
  "adapters/trae/hooks/review-checklist.ts": "343bd699",
121
121
  "adapters/trae/hooks/session-end.mjs": "5d68ad3f",
122
122
  "adapters/trae/hooks/session-end.ts": "64ce383f",
123
- "adapters/trae/hooks/session-start.mjs": "d582fe06",
123
+ "adapters/trae/hooks/session-start.mjs": "59c49651",
124
124
  "adapters/trae/hooks/session-start.ts": "d6b4fdc7",
125
125
  "adapters/trae/hooks/stop-check.mjs": "a4335a46",
126
126
  "adapters/trae/hooks/stop-check.ts": "b33ad5e4",
@@ -141,7 +141,7 @@
141
141
  "adapters/vscode/.github/hooks/subagent-stop.json": "47dbdd8d",
142
142
  "adapters/vscode/.github/hooks/user-prompt-submit.json": "3a608d62",
143
143
  "adapters/vscode/extensions.json": "0f4024c1",
144
- "adapters/vscode/hooks/doc-format-guard.mjs": "f8882228",
144
+ "adapters/vscode/hooks/doc-format-guard.mjs": "af61a673",
145
145
  "adapters/vscode/hooks/doc-format-guard.ts": "38e71c50",
146
146
  "adapters/vscode/hooks/notification.mjs": "96883766",
147
147
  "adapters/vscode/hooks/notification.ts": "5eed547d",
@@ -149,19 +149,19 @@
149
149
  "adapters/vscode/hooks/permission-gate.ts": "ad096bc1",
150
150
  "adapters/vscode/hooks/post-tool-failure.mjs": "14faa5a1",
151
151
  "adapters/vscode/hooks/post-tool-failure.ts": "f7bc81b3",
152
- "adapters/vscode/hooks/post-tool-use.mjs": "03cfdbee",
152
+ "adapters/vscode/hooks/post-tool-use.mjs": "a083ed52",
153
153
  "adapters/vscode/hooks/post-tool-use.ts": "42146851",
154
154
  "adapters/vscode/hooks/pre-compact.mjs": "494dfd18",
155
155
  "adapters/vscode/hooks/pre-compact.ts": "15e4a043",
156
156
  "adapters/vscode/hooks/pre-tool-use.mjs": "4887a38f",
157
157
  "adapters/vscode/hooks/pre-tool-use.ts": "8e8e588d",
158
- "adapters/vscode/hooks/prompt-submit.mjs": "4cbc9d27",
158
+ "adapters/vscode/hooks/prompt-submit.mjs": "3618a565",
159
159
  "adapters/vscode/hooks/prompt-submit.ts": "767b13d2",
160
160
  "adapters/vscode/hooks/review-checklist.mjs": "6061e7fb",
161
161
  "adapters/vscode/hooks/review-checklist.ts": "f5fb4557",
162
162
  "adapters/vscode/hooks/session-end.mjs": "dc805cd7",
163
163
  "adapters/vscode/hooks/session-end.ts": "acdd9f42",
164
- "adapters/vscode/hooks/session-start.mjs": "a803d6e5",
164
+ "adapters/vscode/hooks/session-start.mjs": "7deea287",
165
165
  "adapters/vscode/hooks/session-start.ts": "54b262b0",
166
166
  "adapters/vscode/hooks/stop-check.mjs": "b7d81215",
167
167
  "adapters/vscode/hooks/stop-check.ts": "7a69b075",
@@ -181,20 +181,20 @@
181
181
  "core/governance/audit-bridge.ts": "1a0d5ccd",
182
182
  "core/governance/common.ts": "37570397",
183
183
  "core/governance/context-inject.ts": "8ded8188",
184
- "core/governance/doc-format-guard.ts": "70978fc9",
184
+ "core/governance/doc-format-guard.ts": "90bcc306",
185
185
  "core/governance/notification-router.ts": "526ee71c",
186
186
  "core/governance/notify.ts": "b7e8543f",
187
187
  "core/governance/permission-gate-router.ts": "e4fa8376",
188
188
  "core/governance/post-tool-failure-router.ts": "7542b2a0",
189
- "core/governance/post-tool-router.ts": "556f9200",
189
+ "core/governance/post-tool-router.ts": "6dc1b65c",
190
190
  "core/governance/pre-compact-guard.ts": "e1c2b2e7",
191
191
  "core/governance/pre-tool-guard.ts": "c64b7382",
192
192
  "core/governance/preload-templates.ts": "cfd6d3ca",
193
- "core/governance/prompt-router.ts": "15ca2987",
193
+ "core/governance/prompt-router.ts": "4b2f55a3",
194
194
  "core/governance/review-checklist-guard.ts": "b24568b1",
195
195
  "core/governance/rules.ts": "e6b261b7",
196
196
  "core/governance/session-end.ts": "108fc3f6",
197
- "core/governance/session-start-guard.ts": "96666e11",
197
+ "core/governance/session-start-guard.ts": "8a91218e",
198
198
  "core/governance/state-detect.ts": "55afc935",
199
199
  "core/governance/stop-router.ts": "af93ae1c",
200
200
  "core/governance/subagent-guard-router.ts": "398fb80e",
@@ -215,7 +215,7 @@
215
215
  "core/hooks/stop-check.ts": "0c3fc40a",
216
216
  "core/hooks/subagent-guard.ts": "37019300",
217
217
  "core/hooks/subagent-stop.ts": "9eebd61f",
218
- "core/prisma/add.prisma": "a543cd84",
218
+ "core/prisma/add.prisma": "a3365acc",
219
219
  "core/reports/REPORT-WORKFLOW.md": "03d39b21",
220
220
  "core/reports/boundary-runtime-report.md": "6fd8053f",
221
221
  "core/reports/code-review-combined-report.md": "195d52aa",
@@ -229,7 +229,7 @@
229
229
  "core/rules/profiles/webapp-profile.md": "e493ae7b",
230
230
  "core/rules/project_rules.md": "094821ad",
231
231
  "core/rules/theory-practice-map.toml": "b1db99fd",
232
- "core/scripts/db-ensure.sh": "94a5ff92",
232
+ "core/scripts/db-ensure.sh": "8f7ba569",
233
233
  "core/scripts/gen-plan-index.sh": "47836bec",
234
234
  "core/scripts/mcp-server/elicitation/confirm.ts": "924857b8",
235
235
  "core/scripts/mcp-server/elicitation/index.ts": "44c5dc3f",
@@ -246,15 +246,51 @@
246
246
  "core/scripts/mcp-server/sampling/index.ts": "7ee26d92",
247
247
  "core/scripts/mcp-server/sampling/review.ts": "dd6e22ff",
248
248
  "core/scripts/mcp-server/shared/anchor.ts": "ab15ff22",
249
- "core/scripts/mcp-server/shared/db-types.ts": "bd97e8b6",
249
+ "core/scripts/mcp-server/shared/db-types.ts": "2d54cc72",
250
250
  "core/scripts/mcp-server/shared/dps-scoring.strategy.ts": "92ecf32b",
251
251
  "core/scripts/mcp-server/shared/dps-spec-ref.ts": "c2257e3a",
252
252
  "core/scripts/mcp-server/shared/env.ts": "f79ab09c",
253
253
  "core/scripts/mcp-server/shared/fs.ts": "be216ce3",
254
+ "core/scripts/mcp-server/shared/hitl-create-policy.ts": "654affef",
254
255
  "core/scripts/mcp-server/shared/hitl-interaction.strategy.ts": "dcfe946f",
255
256
  "core/scripts/mcp-server/shared/hitl-lifecycle-mutation.ts": "06952c62",
257
+ "core/scripts/mcp-server/shared/hitl-proposal-content.ts": "a7609204",
256
258
  "core/scripts/mcp-server/shared/hitl-proposal-mutation.ts": "87a7a372",
257
259
  "core/scripts/mcp-server/shared/hitl-ui.ts": "51d574f2",
260
+ "core/scripts/mcp-server/shared/hitl-widget-instance.ts": "fa750c56",
261
+ "core/scripts/mcp-server/shared/memory/calibration/batch-fit.ts": "d93af367",
262
+ "core/scripts/mcp-server/shared/memory/calibration/feedback-stats.ts": "525d18cb",
263
+ "core/scripts/mcp-server/shared/memory/calibration/unit-state.ts": "42f92007",
264
+ "core/scripts/mcp-server/shared/memory/domain/conflicts.ts": "3069087b",
265
+ "core/scripts/mcp-server/shared/memory/domain/dedup.ts": "4102da3d",
266
+ "core/scripts/mcp-server/shared/memory/domain/errors.ts": "23a907df",
267
+ "core/scripts/mcp-server/shared/memory/domain/handoff-digest.ts": "0f2b906a",
268
+ "core/scripts/mcp-server/shared/memory/domain/metric-candidate.ts": "5450fa45",
269
+ "core/scripts/mcp-server/shared/memory/domain/scope.ts": "137c23eb",
270
+ "core/scripts/mcp-server/shared/memory/domain/secrets.ts": "fd5376b3",
271
+ "core/scripts/mcp-server/shared/memory/domain/state-machine.ts": "e37e877a",
272
+ "core/scripts/mcp-server/shared/memory/embedding/index.ts": "ec6d09b8",
273
+ "core/scripts/mcp-server/shared/memory/embedding/local-onnx.ts": "21fbd890",
274
+ "core/scripts/mcp-server/shared/memory/embedding/openai-compatible.ts": "7a6a7429",
275
+ "core/scripts/mcp-server/shared/memory/jobs/consolidation.ts": "d724ec0d",
276
+ "core/scripts/mcp-server/shared/memory/jobs/evidence-collector.ts": "b44b4d62",
277
+ "core/scripts/mcp-server/shared/memory/jobs/snapshot.ts": "7c7923eb",
278
+ "core/scripts/mcp-server/shared/memory/metrics/gate-recall.ts": "dc41a0fc",
279
+ "core/scripts/mcp-server/shared/memory/metrics/gate-writer.ts": "47cd35b0",
280
+ "core/scripts/mcp-server/shared/memory/metrics/stage-words.ts": "a81db64b",
281
+ "core/scripts/mcp-server/shared/memory/retrieval/context-builder.ts": "ea83c131",
282
+ "core/scripts/mcp-server/shared/memory/retrieval/fts/pg.ts": "1275eef4",
283
+ "core/scripts/mcp-server/shared/memory/retrieval/fts/sqlite-fts5.sql": "8fade96f",
284
+ "core/scripts/mcp-server/shared/memory/retrieval/fts/sqlite.ts": "09a6cf59",
285
+ "core/scripts/mcp-server/shared/memory/retrieval/fusion.ts": "c3aa6a4f",
286
+ "core/scripts/mcp-server/shared/memory/retrieval/pipeline.ts": "dbe4a472",
287
+ "core/scripts/mcp-server/shared/memory/retrieval/query-terms.ts": "423a0054",
288
+ "core/scripts/mcp-server/shared/memory/retrieval/recall-writer.ts": "ed9cba51",
289
+ "core/scripts/mcp-server/shared/memory/retrieval/reranker.ts": "659ed2e8",
290
+ "core/scripts/mcp-server/shared/memory/retrieval/types.ts": "f9f9f8ad",
291
+ "core/scripts/mcp-server/shared/memory/retrieval/vector/pgvector.ts": "732e70c1",
292
+ "core/scripts/mcp-server/shared/memory/retrieval/vector/sqlite-vec.ts": "d6ad13ff",
293
+ "core/scripts/mcp-server/shared/memory/switches.ts": "b1561bef",
258
294
  "core/scripts/mcp-server/shared/package.json": "e3d5a4a2",
259
295
  "core/scripts/mcp-server/shared/plan-lifecycle-events.ts": "ae99b9a0",
260
296
  "core/scripts/mcp-server/shared/plan-lifecycle-mutation.ts": "303d9674",
@@ -271,8 +307,10 @@
271
307
  "core/scripts/mcp-server/shared/quant-recheck.strategy.ts": "12211d20",
272
308
  "core/scripts/mcp-server/shared/redact.ts": "22e008aa",
273
309
  "core/scripts/mcp-server/shared/response.ts": "0d1539a8",
310
+ "core/scripts/mcp-server/shared/review-files.ts": "863e9074",
274
311
  "core/scripts/mcp-server/shared/run-command.ts": "42caf972",
275
312
  "core/scripts/mcp-server/shared/runtime-context.ts": "51d0b45f",
313
+ "core/scripts/mcp-server/shared/runtime-freshness.ts": "de5f0fb9",
276
314
  "core/scripts/mcp-server/shared/schema-topology.ts": "a680b738",
277
315
  "core/scripts/mcp-server/tasks/index.ts": "c040eb75",
278
316
  "core/scripts/mcp-server/tasks/runner.ts": "d84bd35d",
@@ -284,21 +322,23 @@
284
322
  "core/scripts/mcp-server/tools/gateway/check_add_route_completeness.ts": "b58e76ee",
285
323
  "core/scripts/mcp-server/tools/gateway/check_add_route_status.ts": "4caf552c",
286
324
  "core/scripts/mcp-server/tools/gateway/check_doc_similarity.ts": "2cba51c5",
287
- "core/scripts/mcp-server/tools/gateway/check_dps.ts": "eb0fd12d",
288
- "core/scripts/mcp-server/tools/gateway/check_rahs.ts": "7091a262",
325
+ "core/scripts/mcp-server/tools/gateway/check_dps.ts": "f52ef32c",
326
+ "core/scripts/mcp-server/tools/gateway/check_rahs.ts": "88d2c549",
289
327
  "core/scripts/mcp-server/tools/gateway/check_spec_sync.ts": "75c0d1e3",
290
328
  "core/scripts/mcp-server/tools/gateway/helpers.ts": "f8794a92",
291
329
  "core/scripts/mcp-server/tools/gateway/index.ts": "cffe9783",
292
330
  "core/scripts/mcp-server/tools/gateway.backup": "65eae393",
293
- "core/scripts/mcp-server/tools/hitl.ts": "04b6b807",
331
+ "core/scripts/mcp-server/tools/hitl.ts": "4488c338",
294
332
  "core/scripts/mcp-server/tools/hook-event-report.ts": "1d825b3f",
295
- "core/scripts/mcp-server/tools/index.ts": "443128c8",
296
- "core/scripts/mcp-server/tools/plan.ts": "d20b300c",
333
+ "core/scripts/mcp-server/tools/index.ts": "fcebff02",
334
+ "core/scripts/mcp-server/tools/memory-compat.ts": "8812c5b7",
335
+ "core/scripts/mcp-server/tools/memory.ts": "cf6a576d",
336
+ "core/scripts/mcp-server/tools/plan.ts": "edae2597",
297
337
  "core/scripts/mcp-server/tools/quality.ts": "c4634453",
298
338
  "core/scripts/mcp-server/tools/registrar.ts": "efd81b3a",
299
- "core/scripts/mcp-server/tools/review.ts": "65c35e31",
339
+ "core/scripts/mcp-server/tools/review.ts": "d114e522",
300
340
  "core/scripts/mcp-server/types.ts": "6c5e60bc",
301
- "core/scripts/mcp-server.ts": "0c9b0666",
341
+ "core/scripts/mcp-server.ts": "bcaead3c",
302
342
  "core/scripts/package.json": "5a065fe7",
303
343
  "core/scripts/plan-status-bridge.ts": "70c5d8b7",
304
344
  "core/skills/add-paradigm/SKILL.md": "55df369a",
@@ -311,7 +351,7 @@
311
351
  "core/templates/add-route-template-heavyweight.md": "0e107ac0",
312
352
  "core/templates/add-route-template.md": "da7022df",
313
353
  "core/templates/add-route-template.schema.json": "cca77a6e",
314
- "core/templates/checklist-template.md": "d6b73a5c",
354
+ "core/templates/checklist-template.md": "c1ea7aaf",
315
355
  "core/templates/checklist-template.schema.json": "fb3a73e8",
316
356
  "core/templates/collab-contract-template.md": "b8a52503",
317
357
  "core/templates/collab-contract-template.schema.json": "ae0f482c",
@@ -334,11 +374,11 @@
334
374
  "core/templates/prd-standard-template.schema.json": "2b76a919",
335
375
  "core/templates/report-template.md": "bc4602ac",
336
376
  "core/templates/report-template.schema.json": "44dd2bd0",
337
- "core/templates/review-implementation-template.md": "a8f8c748",
377
+ "core/templates/review-implementation-template.md": "6d7a46cb",
338
378
  "core/templates/review-implementation-template.schema.json": "d97b9eb6",
339
379
  "core/templates/review-runtime-template.md": "c5960af1",
340
380
  "core/templates/review-runtime-template.schema.json": "c346ea7d",
341
- "core/templates/review-template.md": "d5fd3323",
381
+ "core/templates/review-template.md": "644d2772",
342
382
  "core/templates/review-template.schema.json": "abc2ece6",
343
383
  "core/templates/runtime-report-template.md": "7b35208a",
344
384
  "core/templates/runtime-report-template.schema.json": "6c1143e6",
@@ -351,5 +391,20 @@
351
391
  "core/templates/tasks-template.md": "2b9d0d52",
352
392
  "core/templates/tasks-template.schema.json": "2e691c8a",
353
393
  "core/tools/README.md": "26a63460",
354
- "core/vocabulary/add-governance-vocabulary.md": "ee9e2bd2"
394
+ "core/validation/index.ts": "0a91bf6c",
395
+ "core/validation/policy.ts": "ff60b1ef",
396
+ "core/validation/registry.ts": "7d5c094a",
397
+ "core/validation/schema-validator.ts": "5f7cd2a8",
398
+ "core/validation/validators/add-route.ts": "241ff346",
399
+ "core/validation/validators/checklist.ts": "5adb68b2",
400
+ "core/validation/validators/handoff.ts": "5f7a3611",
401
+ "core/validation/validators/hitl.ts": "9f654cf3",
402
+ "core/validation/validators/index.ts": "a280de23",
403
+ "core/validation/validators/plan.ts": "ec69ae0b",
404
+ "core/validation/validators/report.ts": "ee1f4273",
405
+ "core/validation/validators/review.ts": "2da71463",
406
+ "core/validation/validators/spec.ts": "a7ad1d24",
407
+ "core/validation/validators/tasks.ts": "cae46ddc",
408
+ "core/validation/validators/types.ts": "dafcdbdc",
409
+ "core/vocabulary/add-governance-vocabulary.md": "37f2c301"
355
410
  }
@@ -500,6 +500,156 @@ function writeHookEvent(hook, decision, cmd, reason, plan = "unknown", status =
500
500
  appendFileSync(file, line);
501
501
  }
502
502
 
503
+ // templates/core/validation/schema-validator.ts
504
+ function countOccurrences(haystack, needle) {
505
+ if (!needle) return 0;
506
+ const h = normalizeWidth(haystack);
507
+ const n = normalizeWidth(needle);
508
+ let count = 0;
509
+ let idx = h.indexOf(n);
510
+ while (idx !== -1) {
511
+ count++;
512
+ idx = h.indexOf(n, idx + n.length);
513
+ }
514
+ return count;
515
+ }
516
+ var FULLWIDTH_START = 65281;
517
+ var FULLWIDTH_END = 65374;
518
+ var FULLWIDTH_TO_HALF = 65248;
519
+ var WIDTH_FOLD_EXTRA = { "\u3000": " " };
520
+ function normalizeWidth(text) {
521
+ let out = "";
522
+ for (const ch of text) {
523
+ const code = ch.codePointAt(0);
524
+ if (code >= FULLWIDTH_START && code <= FULLWIDTH_END) {
525
+ out += String.fromCharCode(code - FULLWIDTH_TO_HALF);
526
+ } else {
527
+ out += WIDTH_FOLD_EXTRA[ch] ?? ch;
528
+ }
529
+ }
530
+ return out;
531
+ }
532
+ function stripFencedBlocks(content) {
533
+ return content.replace(/```[\s\S]*?```/g, "\n");
534
+ }
535
+ function structText(content, groupColumn) {
536
+ let text = (content.match(/^#{2,}\s.*$/gm) ?? []).join("\n");
537
+ const col = typeof groupColumn === "number" ? groupColumn : Number(groupColumn);
538
+ if (Number.isFinite(col) && col > 0) {
539
+ const cells = content.split("\n").map((line) => {
540
+ const cells2 = line.split("|");
541
+ return cells2.length > col ? (cells2[col + 1] ?? "").trim() : "";
542
+ }).filter(Boolean);
543
+ text += "\n" + cells.join("\n");
544
+ }
545
+ return text;
546
+ }
547
+ function validateAnchors(content, schema, templateContent) {
548
+ const issues = [];
549
+ const nContent = normalizeWidth(content);
550
+ for (const section of schema.sections) {
551
+ if (!section.anchor) continue;
552
+ const refAnchor = normalizeWidth(section.anchor);
553
+ const refLine = templateContent.split("\n").find((l) => normalizeWidth(l).includes(refAnchor));
554
+ if (!refLine) continue;
555
+ const tokens = [
556
+ ...new Set(
557
+ normalizeWidth(refLine).replace(/[#*`|(){]/g, " ").split(/\s+/).filter((t) => t !== "" && !t.includes("{"))
558
+ )
559
+ ];
560
+ if (tokens.length === 0) continue;
561
+ let scope = nContent;
562
+ if (section.within) {
563
+ const startIdx = nContent.indexOf(normalizeWidth(section.within));
564
+ if (startIdx < 0) continue;
565
+ const endIdx = nContent.indexOf("\n## ", startIdx + 1);
566
+ scope = nContent.slice(startIdx, endIdx === -1 ? void 0 : endIdx);
567
+ }
568
+ const missTokens = tokens.filter((tok) => !scope.includes(tok));
569
+ if (missTokens.length > 0) {
570
+ issues.push({
571
+ code: "ANCHOR_MISS",
572
+ detail: `\u7F3A\u951A\u70B9(${section.id}): ${missTokens.join(" ")}`,
573
+ expected: section.anchor
574
+ });
575
+ }
576
+ }
577
+ return issues;
578
+ }
579
+ function inferRoundHeading(schema) {
580
+ const round = schema.sections.find((s) => s.heading?.includes("<\u7B2CN\u8F6E>"));
581
+ return round?.heading ?? null;
582
+ }
583
+ function countRounds(content, roundHeading) {
584
+ const heading = normalizeWidth(roundHeading);
585
+ if (!heading.includes("<\u7B2CN\u8F6E>")) return 0;
586
+ const pattern = heading.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace("<\u7B2CN\u8F6E>", "\u7B2C\\s*\\d+\\s*\u8F6E");
587
+ const re = new RegExp(`^${pattern}`, "gm");
588
+ return (normalizeWidth(content).match(re) ?? []).length;
589
+ }
590
+ function validateAgainstSchema(content, schema, opts = {}) {
591
+ const issues = [];
592
+ const proseOnly = stripFencedBlocks(content);
593
+ const contentNormalized = normalizeWidth(content);
594
+ const roundHeading = opts.roundHeading ?? inferRoundHeading(schema);
595
+ for (const section of schema.sections) {
596
+ if (!section.heading) continue;
597
+ const isRoundSection = roundHeading !== null && section.heading === roundHeading;
598
+ if (isRoundSection) {
599
+ const need = opts.expectRounds ?? 1;
600
+ const found = countRounds(content, roundHeading);
601
+ if (found < need) {
602
+ issues.push({
603
+ code: "ROUND_COUNT_SHORT",
604
+ detail: `\u8F6E\u6B21\u7AE0\u8282\u4E0D\u8DB3\uFF1A\u671F\u671B ${need} \u8F6E\uFF0C\u5B9E\u9645 ${found} \u8F6E`,
605
+ expected: roundHeading
606
+ });
607
+ }
608
+ for (const sub of section.subsections ?? []) {
609
+ if (countOccurrences(content, sub.heading) < need) {
610
+ issues.push({
611
+ code: "MISSING_SUBSECTION",
612
+ detail: `\u8F6E\u6B21\u5B50\u7AE0\u8282\u7F3A\u5931\u6216\u4E0D\u8DB3\uFF08\u9700\u8981 ${need} \u4EFD\uFF09\uFF1A${sub.heading}`,
613
+ expected: sub.heading
614
+ });
615
+ }
616
+ }
617
+ continue;
618
+ }
619
+ if (section.required && countOccurrences(content, section.heading) === 0) {
620
+ issues.push({ code: "MISSING_SECTION", detail: `\u7F3A\u5C11\u5FC5\u9700\u7AE0\u8282\uFF1A${section.heading}`, expected: section.heading });
621
+ }
622
+ for (const sub of section.subsections ?? []) {
623
+ const need = isRoundSection ? opts.expectRounds ?? 1 : 1;
624
+ if (countOccurrences(content, sub.heading) < need) {
625
+ issues.push({
626
+ code: "MISSING_SUBSECTION",
627
+ detail: `\u5B50\u7AE0\u8282\u7F3A\u5931\u6216\u4E0D\u8DB3\uFF08\u9700\u8981 ${need} \u4EFD\uFF09\uFF1A${sub.heading}`,
628
+ expected: sub.heading
629
+ });
630
+ }
631
+ }
632
+ }
633
+ for (const ph of schema.placeholders ?? []) {
634
+ if (!ph) continue;
635
+ const nPh = normalizeWidth(ph);
636
+ const idx = contentNormalized.indexOf(nPh);
637
+ if (idx === -1) continue;
638
+ const hit = nPh === ph ? ph : `${content.slice(idx, idx + nPh.length)}\uFF08\u5BBD\u5EA6\u7B49\u4EF7\u4E8E ${ph}\uFF09`;
639
+ issues.push({ code: "PLACEHOLDER_LEFT", detail: `\u5360\u4F4D\u7B26\u672A\u66FF\u6362\uFF1A${hit}`, expected: ph });
640
+ }
641
+ const struct = normalizeWidth(structText(content, schema.groupColumn));
642
+ for (const term of schema.forbidden_terms ?? []) {
643
+ if (term && struct.includes(normalizeWidth(term))) {
644
+ issues.push({ code: "FORBIDDEN_TERM", detail: `\u7ED3\u6784\u4F4D\u7981\u8BCD\uFF1A${term}\uFF08\u4EC5\u6807\u9898\u884C\u4E0E\u6307\u5B9A\u5217\u5224\u5B9A\uFF09`, expected: term });
645
+ }
646
+ }
647
+ if (opts.templateContent) {
648
+ issues.push(...validateAnchors(content, schema, opts.templateContent));
649
+ }
650
+ return issues;
651
+ }
652
+
503
653
  // templates/core/governance/doc-format-guard.ts
504
654
  function extractContent(input) {
505
655
  const ti = input.tool_input;
@@ -595,90 +745,28 @@ var DocFormatGuard = class {
595
745
  }
596
746
  /** 章节/锚定/占位符/禁词校验,返回 struct 统计 */
597
747
  runSchemaChecks(schema, templateName, content, isSearchReplace) {
598
- const templatesDir = join3(this.projectDir, this.magicDir, "templates");
599
- let applied = 0;
600
- let missed = 0;
601
- let anchorHit = true;
602
- const headings = schema.sections.filter((s) => s.heading).map((s) => s.heading);
603
- const requiredHeadings = schema.sections.filter((s) => s.required === true && s.heading).map((s) => s.heading);
604
- const subs = schema.sections.flatMap((s) => s.subsections ?? []).filter((s) => s.heading).map((s) => s.heading);
605
- const placeholders = schema.placeholders ?? [];
606
- const terms = schema.forbidden_terms ?? [];
607
- if (!isSearchReplace) {
608
- for (const section of schema.sections) {
609
- if (!section.anchor) continue;
610
- applied++;
611
- const templateContent = existsSync3(join3(templatesDir, templateName)) ? readFileSync2(join3(templatesDir, templateName), "utf-8") : "";
612
- const refLine = templateContent.split("\n").find((l) => l.includes(section.anchor));
613
- if (!refLine) {
614
- process.stderr.write(`[doc-format-guard] anchor_miss: schema ${section.id} \u58F0\u660E\u7684 anchor '${section.anchor}' \u5728 ${templateName} \u4E2D\u672A\u5B9A\u4F4D\uFF0C\u8DF3\u8FC7\u8BE5\u89C4\u5219\uFF08\u5192\u70DF\u5DE1\u68C0\u5151\u5E95\uFF09
615
- `);
616
- applied--;
617
- continue;
618
- }
619
- const tokens = [...new Set(refLine.replace(/[#*`|(){]/g, " ").split(/\s+/).filter((t) => t !== "" && !t.includes("{")))];
620
- if (tokens.length === 0) {
621
- applied--;
622
- continue;
623
- }
624
- let scope = content;
625
- if (section.within) {
626
- if (content.includes(section.within)) {
627
- const startIdx = content.indexOf(section.within);
628
- const endIdx = content.indexOf("\n## ", startIdx + 1);
629
- scope = content.slice(startIdx, endIdx === -1 ? void 0 : endIdx);
630
- } else {
631
- process.stderr.write(`[doc-format-guard] within_miss: schema ${section.id} \u7684 within '${section.within}' \u5728\u6587\u6863\u4E2D\u672A\u5B9A\u4F4D\uFF0C\u8DF3\u8FC7\u8BE5\u89C4\u5219
632
- `);
633
- applied--;
634
- continue;
635
- }
636
- }
637
- const missTokens = tokens.filter((tok) => !scope.includes(tok));
638
- if (missTokens.length > 0) {
639
- this.issues.push(` \u7F3A\u951A\u70B9(${section.id}): ${missTokens.join(" ")}`);
640
- missed++;
641
- anchorHit = false;
642
- }
643
- }
644
- for (const heading of requiredHeadings) {
645
- applied++;
646
- if (!content.includes(heading)) {
647
- this.issues.push(` \u7F3A\u7AE0\u8282: ${heading}`);
648
- missed++;
649
- }
650
- }
651
- for (const sub of subs) {
652
- applied++;
653
- if (!content.includes(sub)) {
654
- this.issues.push(` \u7F3A\u5B50\u7AE0\u8282: ${sub}`);
655
- missed++;
656
- }
657
- }
658
- }
659
- for (const ph of placeholders) {
660
- if (content.includes(ph)) {
661
- this.issues.push(` \u672A\u66FF\u6362\u5360\u4F4D\u7B26: ${ph}`);
662
- missed++;
663
- }
664
- }
665
- let structText = (content.match(/^#{2,}\s.*$/gm) ?? []).join("\n");
666
- const col = typeof schema.groupColumn === "number" ? schema.groupColumn : Number(schema.groupColumn);
667
- if (!Number.isNaN(col) && col > 0) {
668
- const colLines = content.split("\n").map((l) => {
669
- const cells = l.split("|");
670
- return cells.length > col ? (cells[col + 1] ?? "").trim() : "";
671
- }).filter(Boolean);
672
- structText += "\n" + colLines.join("\n");
673
- }
674
- for (const term of terms) {
675
- applied++;
676
- if (structText.includes(term)) {
677
- this.issues.push(` \u7ED3\u6784\u4F4D\u7981\u8BCD: ${term}`);
678
- missed++;
679
- }
680
- }
681
- return { applied, missed, anchorHit };
748
+ const templatePath = join3(this.projectDir, this.magicDir, "templates", templateName);
749
+ const templateContent = existsSync3(templatePath) ? readFileSync2(templatePath, "utf-8") : "";
750
+ const all = validateAgainstSchema(content, schema, { templateContent });
751
+ const relevant = isSearchReplace ? all.filter((i) => i.code === "PLACEHOLDER_LEFT" || i.code === "FORBIDDEN_TERM") : all;
752
+ for (const i of relevant) this.issues.push(` ${i.detail}`);
753
+ const missed = relevant.length;
754
+ const declared = this.countDeclaredRules(schema, isSearchReplace);
755
+ return {
756
+ applied: Math.max(missed, declared),
757
+ missed,
758
+ anchorHit: !relevant.some((i) => i.code === "ANCHOR_MISS")
759
+ };
760
+ }
761
+ /** 已声明规则数(用于 struct_score 分母;口径与原内联实现一致:按规则条数计) */
762
+ countDeclaredRules(schema, isSearchReplace) {
763
+ const placeholders = (schema.placeholders ?? []).length;
764
+ const terms = (schema.forbidden_terms ?? []).length;
765
+ if (isSearchReplace) return placeholders + terms;
766
+ const anchors = schema.sections.filter((s) => s.anchor).length;
767
+ const required = schema.sections.filter((s) => s.required === true && s.heading).length;
768
+ const subs = schema.sections.flatMap((s) => s.subsections ?? []).filter((s) => s.heading).length;
769
+ return anchors + required + subs + placeholders + terms;
682
770
  }
683
771
  /** 算法化规则校验(真源: [doc.anti_cheat] + HITL 表非空 + handoff 冲突)
684
772
  * protected: adapter 子类可 override(如 claude 版无算法规则段) */