@dommaker/harness 0.16.6 → 0.16.8

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 (641) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +54 -14
  3. package/bin/harness.js +56 -96
  4. package/dist/architecture/constraint-engine.d.ts.map +1 -1
  5. package/dist/architecture/constraint-engine.js +0 -4
  6. package/dist/architecture/constraint-engine.js.map +1 -1
  7. package/dist/architecture/cross-project-checker.d.ts.map +1 -1
  8. package/dist/architecture/cross-project-checker.js +5 -25
  9. package/dist/architecture/cross-project-checker.js.map +1 -1
  10. package/dist/cli/commands/analyze-sessions.d.ts +2 -0
  11. package/dist/cli/commands/analyze-sessions.d.ts.map +1 -1
  12. package/dist/cli/commands/analyze-sessions.js +25 -181
  13. package/dist/cli/commands/analyze-sessions.js.map +1 -1
  14. package/dist/cli/commands/check.d.ts +1 -0
  15. package/dist/cli/commands/check.d.ts.map +1 -1
  16. package/dist/cli/commands/check.js +24 -216
  17. package/dist/cli/commands/check.js.map +1 -1
  18. package/dist/cli/commands/doc-freshness-check.d.ts.map +1 -1
  19. package/dist/cli/commands/doc-freshness-check.js +14 -28
  20. package/dist/cli/commands/doc-freshness-check.js.map +1 -1
  21. package/dist/cli/commands/flow.d.ts.map +1 -1
  22. package/dist/cli/commands/flow.js +2 -1
  23. package/dist/cli/commands/flow.js.map +1 -1
  24. package/dist/cli/commands/init.js +2 -2
  25. package/dist/cli/commands/init.js.map +1 -1
  26. package/dist/cli/commands/posteval-plan.d.ts.map +1 -1
  27. package/dist/cli/commands/posteval-plan.js +0 -1
  28. package/dist/cli/commands/posteval-plan.js.map +1 -1
  29. package/dist/cli/commands/release.js +1 -1
  30. package/dist/cli/commands/release.js.map +1 -1
  31. package/dist/cli/commands/report.d.ts.map +1 -1
  32. package/dist/cli/commands/report.js +2 -0
  33. package/dist/cli/commands/report.js.map +1 -1
  34. package/dist/cli/commands/spec-baseline-check.d.ts.map +1 -1
  35. package/dist/cli/commands/spec-baseline-check.js +12 -23
  36. package/dist/cli/commands/spec-baseline-check.js.map +1 -1
  37. package/dist/cli/commands/sync-docs/agents-syncer.d.ts +19 -0
  38. package/dist/cli/commands/sync-docs/agents-syncer.d.ts.map +1 -0
  39. package/dist/cli/commands/sync-docs/agents-syncer.js +288 -0
  40. package/dist/cli/commands/sync-docs/agents-syncer.js.map +1 -0
  41. package/dist/cli/commands/sync-docs/capabilities-syncer.d.ts +37 -0
  42. package/dist/cli/commands/sync-docs/capabilities-syncer.d.ts.map +1 -0
  43. package/dist/cli/commands/sync-docs/capabilities-syncer.js +235 -0
  44. package/dist/cli/commands/sync-docs/capabilities-syncer.js.map +1 -0
  45. package/dist/cli/commands/sync-docs/context-syncer.d.ts +17 -0
  46. package/dist/cli/commands/sync-docs/context-syncer.d.ts.map +1 -0
  47. package/dist/cli/commands/sync-docs/context-syncer.js +143 -0
  48. package/dist/cli/commands/sync-docs/context-syncer.js.map +1 -0
  49. package/dist/cli/commands/{sync-docs.d.ts → sync-docs/index.d.ts} +9 -2
  50. package/dist/cli/commands/sync-docs/index.d.ts.map +1 -0
  51. package/dist/cli/commands/sync-docs/index.js +338 -0
  52. package/dist/cli/commands/sync-docs/index.js.map +1 -0
  53. package/dist/cli/commands/sync-docs/preserve-block.d.ts +24 -0
  54. package/dist/cli/commands/sync-docs/preserve-block.d.ts.map +1 -0
  55. package/dist/cli/commands/sync-docs/preserve-block.js +55 -0
  56. package/dist/cli/commands/sync-docs/preserve-block.js.map +1 -0
  57. package/dist/cli/commands/sync-docs/project-reader.d.ts +41 -0
  58. package/dist/cli/commands/sync-docs/project-reader.d.ts.map +1 -0
  59. package/dist/cli/commands/sync-docs/project-reader.js +183 -0
  60. package/dist/cli/commands/sync-docs/project-reader.js.map +1 -0
  61. package/dist/cli/commands/update-user-model.d.ts +2 -0
  62. package/dist/cli/commands/update-user-model.d.ts.map +1 -1
  63. package/dist/cli/commands/update-user-model.js +19 -90
  64. package/dist/cli/commands/update-user-model.js.map +1 -1
  65. package/dist/cli/commands/validate.d.ts +3 -0
  66. package/dist/cli/commands/validate.d.ts.map +1 -1
  67. package/dist/cli/commands/validate.js +6 -39
  68. package/dist/cli/commands/validate.js.map +1 -1
  69. package/dist/cli/session-mining/corrections.d.ts +17 -0
  70. package/dist/cli/session-mining/corrections.d.ts.map +1 -0
  71. package/dist/cli/session-mining/corrections.js +58 -0
  72. package/dist/cli/session-mining/corrections.js.map +1 -0
  73. package/dist/cli/session-mining/index.d.ts +13 -0
  74. package/dist/cli/session-mining/index.d.ts.map +1 -0
  75. package/dist/{core/spec → cli/session-mining}/index.js +9 -3
  76. package/dist/cli/session-mining/index.js.map +1 -0
  77. package/dist/cli/session-mining/text.d.ts +31 -0
  78. package/dist/cli/session-mining/text.d.ts.map +1 -0
  79. package/dist/cli/session-mining/text.js +126 -0
  80. package/dist/cli/session-mining/text.js.map +1 -0
  81. package/dist/cli/session-mining/transcript.d.ts +28 -0
  82. package/dist/cli/session-mining/transcript.d.ts.map +1 -0
  83. package/dist/cli/session-mining/transcript.js +123 -0
  84. package/dist/cli/session-mining/transcript.js.map +1 -0
  85. package/dist/constraints/lifecycle-runner.d.ts +1 -1
  86. package/dist/constraints/lifecycle-runner.d.ts.map +1 -1
  87. package/dist/context/compaction.d.ts.map +1 -1
  88. package/dist/context/compaction.js +2 -3
  89. package/dist/context/compaction.js.map +1 -1
  90. package/dist/context/knowledge-injector.d.ts.map +1 -1
  91. package/dist/context/tool-output-budget.d.ts +1 -1
  92. package/dist/context/tool-output-budget.d.ts.map +1 -1
  93. package/dist/context/tool-output-budget.js +1 -1
  94. package/dist/context/tool-output-budget.js.map +1 -1
  95. package/dist/core/constraints/capabilities-parser.d.ts +24 -0
  96. package/dist/core/constraints/capabilities-parser.d.ts.map +1 -0
  97. package/dist/core/constraints/capabilities-parser.js +95 -0
  98. package/dist/core/constraints/capabilities-parser.js.map +1 -0
  99. package/dist/core/constraints/checker.d.ts +37 -100
  100. package/dist/core/constraints/checker.d.ts.map +1 -1
  101. package/dist/core/constraints/checker.js +150 -737
  102. package/dist/core/constraints/checker.js.map +1 -1
  103. package/dist/core/constraints/checkers/always-pass.d.ts +17 -0
  104. package/dist/core/constraints/checkers/always-pass.d.ts.map +1 -0
  105. package/dist/core/constraints/checkers/always-pass.js +23 -0
  106. package/dist/core/constraints/checkers/always-pass.js.map +1 -0
  107. package/dist/core/constraints/checkers/capability-sync.d.ts +10 -0
  108. package/dist/core/constraints/checkers/capability-sync.d.ts.map +1 -0
  109. package/dist/core/constraints/checkers/capability-sync.js +60 -0
  110. package/dist/core/constraints/checkers/capability-sync.js.map +1 -0
  111. package/dist/core/constraints/checkers/context-doc-sync.d.ts +6 -0
  112. package/dist/core/constraints/checkers/context-doc-sync.d.ts.map +1 -0
  113. package/dist/core/constraints/checkers/context-doc-sync.js +35 -0
  114. package/dist/core/constraints/checkers/context-doc-sync.js.map +1 -0
  115. package/dist/core/constraints/checkers/docs-freshness.d.ts +10 -0
  116. package/dist/core/constraints/checkers/docs-freshness.d.ts.map +1 -0
  117. package/dist/core/constraints/checkers/docs-freshness.js +111 -0
  118. package/dist/core/constraints/checkers/docs-freshness.js.map +1 -0
  119. package/dist/core/constraints/checkers/guideline-flags.d.ts +9 -0
  120. package/dist/core/constraints/checkers/guideline-flags.d.ts.map +1 -0
  121. package/dist/core/constraints/checkers/guideline-flags.js +13 -0
  122. package/dist/core/constraints/checkers/guideline-flags.js.map +1 -0
  123. package/dist/core/constraints/checkers/index.d.ts +17 -0
  124. package/dist/core/constraints/checkers/index.d.ts.map +1 -0
  125. package/dist/core/constraints/checkers/index.js +82 -0
  126. package/dist/core/constraints/checkers/index.js.map +1 -0
  127. package/dist/core/constraints/checkers/iron-flags.d.ts +14 -0
  128. package/dist/core/constraints/checkers/iron-flags.d.ts.map +1 -0
  129. package/dist/core/constraints/checkers/iron-flags.js +24 -0
  130. package/dist/core/constraints/checkers/iron-flags.js.map +1 -0
  131. package/dist/core/constraints/checkers/no-any-type.d.ts +6 -0
  132. package/dist/core/constraints/checkers/no-any-type.d.ts.map +1 -0
  133. package/dist/core/constraints/checkers/no-any-type.js +42 -0
  134. package/dist/core/constraints/checkers/no-any-type.js.map +1 -0
  135. package/dist/core/constraints/checkers/no-bypass-checkpoint.d.ts +6 -0
  136. package/dist/core/constraints/checkers/no-bypass-checkpoint.d.ts.map +1 -0
  137. package/dist/core/constraints/checkers/no-bypass-checkpoint.js +40 -0
  138. package/dist/core/constraints/checkers/no-bypass-checkpoint.js.map +1 -0
  139. package/dist/core/constraints/checkers/no-excuse-patterns.d.ts +6 -0
  140. package/dist/core/constraints/checkers/no-excuse-patterns.d.ts.map +1 -0
  141. package/dist/core/constraints/checkers/no-excuse-patterns.js +25 -0
  142. package/dist/core/constraints/checkers/no-excuse-patterns.js.map +1 -0
  143. package/dist/core/constraints/checkers/no-fuzzy-completion-claim.d.ts +6 -0
  144. package/dist/core/constraints/checkers/no-fuzzy-completion-claim.d.ts.map +1 -0
  145. package/dist/core/constraints/checkers/no-fuzzy-completion-claim.js +34 -0
  146. package/dist/core/constraints/checkers/no-fuzzy-completion-claim.js.map +1 -0
  147. package/dist/core/constraints/checkers/no-performative-agreement.d.ts +8 -0
  148. package/dist/core/constraints/checkers/no-performative-agreement.d.ts.map +1 -0
  149. package/dist/core/constraints/checkers/no-performative-agreement.js +23 -0
  150. package/dist/core/constraints/checkers/no-performative-agreement.js.map +1 -0
  151. package/dist/core/constraints/checkers/no-simplification-without-approval.d.ts +6 -0
  152. package/dist/core/constraints/checkers/no-simplification-without-approval.d.ts.map +1 -0
  153. package/dist/core/constraints/checkers/no-simplification-without-approval.js +30 -0
  154. package/dist/core/constraints/checkers/no-simplification-without-approval.js.map +1 -0
  155. package/dist/core/constraints/checkers/no-test-simplification.d.ts +6 -0
  156. package/dist/core/constraints/checkers/no-test-simplification.d.ts.map +1 -0
  157. package/dist/core/constraints/checkers/no-test-simplification.js +29 -0
  158. package/dist/core/constraints/checkers/no-test-simplification.js.map +1 -0
  159. package/dist/core/constraints/checkers/test-coverage.d.ts +6 -0
  160. package/dist/core/constraints/checkers/test-coverage.d.ts.map +1 -0
  161. package/dist/core/constraints/checkers/test-coverage.js +33 -0
  162. package/dist/core/constraints/checkers/test-coverage.js.map +1 -0
  163. package/dist/core/constraints/checkers/types.d.ts +43 -0
  164. package/dist/core/constraints/checkers/types.d.ts.map +1 -0
  165. package/dist/core/constraints/checkers/types.js +23 -0
  166. package/dist/core/constraints/checkers/types.js.map +1 -0
  167. package/dist/core/constraints/checkers/yagni.d.ts +8 -0
  168. package/dist/core/constraints/checkers/yagni.d.ts.map +1 -0
  169. package/dist/core/constraints/checkers/yagni.js +96 -0
  170. package/dist/core/constraints/checkers/yagni.js.map +1 -0
  171. package/dist/core/constraints/context-builder.d.ts +67 -0
  172. package/dist/core/constraints/context-builder.d.ts.map +1 -0
  173. package/dist/core/constraints/context-builder.js +294 -0
  174. package/dist/core/constraints/context-builder.js.map +1 -0
  175. package/dist/core/constraints/definitions/guidelines.d.ts +7 -0
  176. package/dist/core/constraints/definitions/guidelines.d.ts.map +1 -0
  177. package/dist/core/constraints/definitions/guidelines.js +641 -0
  178. package/dist/core/constraints/definitions/guidelines.js.map +1 -0
  179. package/dist/core/constraints/definitions/iron-laws.d.ts +7 -0
  180. package/dist/core/constraints/definitions/iron-laws.d.ts.map +1 -0
  181. package/dist/core/constraints/definitions/iron-laws.js +322 -0
  182. package/dist/core/constraints/definitions/iron-laws.js.map +1 -0
  183. package/dist/core/constraints/definitions/tips.d.ts +7 -0
  184. package/dist/core/constraints/definitions/tips.d.ts.map +1 -0
  185. package/dist/core/constraints/definitions/tips.js +62 -0
  186. package/dist/core/constraints/definitions/tips.js.map +1 -0
  187. package/dist/core/constraints/definitions.d.ts +8 -21
  188. package/dist/core/constraints/definitions.d.ts.map +1 -1
  189. package/dist/core/constraints/definitions.js +15 -1048
  190. package/dist/core/constraints/definitions.js.map +1 -1
  191. package/dist/core/constraints/doc-freshness/runner.d.ts.map +1 -1
  192. package/dist/core/constraints/doc-freshness/runner.js +0 -1
  193. package/dist/core/constraints/doc-freshness/runner.js.map +1 -1
  194. package/dist/core/constraints/index.d.ts +4 -5
  195. package/dist/core/constraints/index.d.ts.map +1 -1
  196. package/dist/core/constraints/index.js +1 -16
  197. package/dist/core/constraints/index.js.map +1 -1
  198. package/dist/core/constraints/interceptor.d.ts.map +1 -1
  199. package/dist/core/constraints/interceptor.js.map +1 -1
  200. package/dist/core/index.js +0 -1
  201. package/dist/core/index.js.map +1 -1
  202. package/dist/core/project-config-loader.d.ts +6 -4
  203. package/dist/core/project-config-loader.d.ts.map +1 -1
  204. package/dist/core/project-config-loader.js +46 -13
  205. package/dist/core/project-config-loader.js.map +1 -1
  206. package/dist/core/validators/check-handlers/command.d.ts +7 -0
  207. package/dist/core/validators/check-handlers/command.d.ts.map +1 -0
  208. package/dist/core/validators/check-handlers/command.js +58 -0
  209. package/dist/core/validators/check-handlers/command.js.map +1 -0
  210. package/dist/core/validators/check-handlers/file.d.ts +10 -0
  211. package/dist/core/validators/check-handlers/file.d.ts.map +1 -0
  212. package/dist/core/validators/check-handlers/file.js +128 -0
  213. package/dist/core/validators/check-handlers/file.js.map +1 -0
  214. package/dist/core/validators/check-handlers/http.d.ts +7 -0
  215. package/dist/core/validators/check-handlers/http.d.ts.map +1 -0
  216. package/dist/core/validators/check-handlers/http.js +88 -0
  217. package/dist/core/validators/check-handlers/http.js.map +1 -0
  218. package/dist/core/validators/check-handlers/output.d.ts +15 -0
  219. package/dist/core/validators/check-handlers/output.d.ts.map +1 -0
  220. package/dist/core/validators/check-handlers/output.js +152 -0
  221. package/dist/core/validators/check-handlers/output.js.map +1 -0
  222. package/dist/core/validators/checkpoint.d.ts +4 -72
  223. package/dist/core/validators/checkpoint.d.ts.map +1 -1
  224. package/dist/core/validators/checkpoint.js +21 -400
  225. package/dist/core/validators/checkpoint.js.map +1 -1
  226. package/dist/core/validators/cso.js +1 -1
  227. package/dist/core/validators/cso.js.map +1 -1
  228. package/dist/core/validators/passes-gate.js +2 -2
  229. package/dist/core/validators/passes-gate.js.map +1 -1
  230. package/dist/dashboard/stats.d.ts.map +1 -1
  231. package/dist/dashboard/types.d.ts.map +1 -1
  232. package/dist/evolution/auto-evolve.d.ts +1 -2
  233. package/dist/evolution/auto-evolve.d.ts.map +1 -1
  234. package/dist/evolution/auto-evolve.js +2 -1
  235. package/dist/evolution/auto-evolve.js.map +1 -1
  236. package/dist/failure/types.d.ts +5 -85
  237. package/dist/failure/types.d.ts.map +1 -1
  238. package/dist/failure/types.js +19 -115
  239. package/dist/failure/types.js.map +1 -1
  240. package/dist/gates/contract.d.ts.map +1 -1
  241. package/dist/gates/contract.js.map +1 -1
  242. package/dist/gates/index.d.ts.map +1 -1
  243. package/dist/gates/index.js.map +1 -1
  244. package/dist/gates/performance.js +1 -1
  245. package/dist/gates/performance.js.map +1 -1
  246. package/dist/gates/security.d.ts.map +1 -1
  247. package/dist/gates/security.js +1 -1
  248. package/dist/gates/security.js.map +1 -1
  249. package/dist/hooks/bootstrap.d.ts.map +1 -1
  250. package/dist/hooks/bootstrap.js +6 -48
  251. package/dist/hooks/bootstrap.js.map +1 -1
  252. package/dist/index.d.ts +0 -1
  253. package/dist/index.d.ts.map +1 -1
  254. package/dist/index.js +3 -1
  255. package/dist/index.js.map +1 -1
  256. package/dist/knowledge/audit.d.ts.map +1 -1
  257. package/dist/knowledge/doctor.d.ts.map +1 -1
  258. package/dist/knowledge/doctor.js.map +1 -1
  259. package/dist/knowledge/import.d.ts.map +1 -1
  260. package/dist/knowledge/import.js +1 -1
  261. package/dist/knowledge/import.js.map +1 -1
  262. package/dist/knowledge/index-generator.d.ts.map +1 -1
  263. package/dist/knowledge/index-generator.js +0 -1
  264. package/dist/knowledge/index-generator.js.map +1 -1
  265. package/dist/knowledge/ingest.d.ts.map +1 -1
  266. package/dist/knowledge/ingest.js +1 -1
  267. package/dist/knowledge/ingest.js.map +1 -1
  268. package/dist/knowledge/lint.d.ts +1 -1
  269. package/dist/knowledge/lint.d.ts.map +1 -1
  270. package/dist/knowledge/lint.js +2 -2
  271. package/dist/knowledge/lint.js.map +1 -1
  272. package/dist/knowledge/primitives/code-structure.d.ts.map +1 -1
  273. package/dist/knowledge/primitives/code-structure.js +29 -12
  274. package/dist/knowledge/primitives/code-structure.js.map +1 -1
  275. package/dist/knowledge/query.d.ts.map +1 -1
  276. package/dist/knowledge/query.js.map +1 -1
  277. package/dist/knowledge/store.d.ts.map +1 -1
  278. package/dist/llm/adapter.d.ts +3 -3
  279. package/dist/llm/adapter.d.ts.map +1 -1
  280. package/dist/llm/adapter.js +3 -3
  281. package/dist/llm/adapter.js.map +1 -1
  282. package/dist/monitoring/analyzer-base.d.ts +50 -0
  283. package/dist/monitoring/analyzer-base.d.ts.map +1 -0
  284. package/dist/monitoring/analyzer-base.js +146 -0
  285. package/dist/monitoring/analyzer-base.js.map +1 -0
  286. package/dist/monitoring/constraint-doctor.d.ts +3 -46
  287. package/dist/monitoring/constraint-doctor.d.ts.map +1 -1
  288. package/dist/monitoring/constraint-doctor.js +11 -113
  289. package/dist/monitoring/constraint-doctor.js.map +1 -1
  290. package/dist/monitoring/constraint-evolver.d.ts +9 -63
  291. package/dist/monitoring/constraint-evolver.d.ts.map +1 -1
  292. package/dist/monitoring/constraint-evolver.js +8 -10
  293. package/dist/monitoring/constraint-evolver.js.map +1 -1
  294. package/dist/monitoring/diagnosis-rules.d.ts +18 -0
  295. package/dist/monitoring/diagnosis-rules.d.ts.map +1 -0
  296. package/dist/monitoring/diagnosis-rules.js +119 -0
  297. package/dist/monitoring/diagnosis-rules.js.map +1 -0
  298. package/dist/monitoring/knowledge-doctor.d.ts.map +1 -1
  299. package/dist/monitoring/knowledge-doctor.js.map +1 -1
  300. package/dist/monitoring/performance-analyzer.d.ts +0 -12
  301. package/dist/monitoring/performance-analyzer.d.ts.map +1 -1
  302. package/dist/monitoring/performance-analyzer.js +13 -93
  303. package/dist/monitoring/performance-analyzer.js.map +1 -1
  304. package/dist/monitoring/performance-collector.d.ts +0 -8
  305. package/dist/monitoring/performance-collector.d.ts.map +1 -1
  306. package/dist/monitoring/performance-collector.js +0 -21
  307. package/dist/monitoring/performance-collector.js.map +1 -1
  308. package/dist/monitoring/trace-analyzer.d.ts +0 -8
  309. package/dist/monitoring/trace-analyzer.d.ts.map +1 -1
  310. package/dist/monitoring/trace-analyzer.js +9 -91
  311. package/dist/monitoring/trace-analyzer.js.map +1 -1
  312. package/dist/presets/index.d.ts +1 -1
  313. package/dist/presets/index.d.ts.map +1 -1
  314. package/dist/presets/index.js +1 -4
  315. package/dist/presets/index.js.map +1 -1
  316. package/dist/presets/standard.d.ts +0 -9
  317. package/dist/presets/standard.d.ts.map +1 -1
  318. package/dist/presets/standard.js +1 -16
  319. package/dist/presets/standard.js.map +1 -1
  320. package/dist/safety/output-guardrail.d.ts +0 -1
  321. package/dist/safety/output-guardrail.d.ts.map +1 -1
  322. package/dist/safety/output-guardrail.js +0 -3
  323. package/dist/safety/output-guardrail.js.map +1 -1
  324. package/dist/tools/registry.d.ts.map +1 -1
  325. package/dist/types/constraint.d.ts +5 -59
  326. package/dist/types/constraint.d.ts.map +1 -1
  327. package/dist/types/constraint.js +1 -39
  328. package/dist/types/constraint.js.map +1 -1
  329. package/dist/types/failure.d.ts +89 -0
  330. package/dist/types/failure.d.ts.map +1 -0
  331. package/dist/types/failure.js +121 -0
  332. package/dist/types/failure.js.map +1 -0
  333. package/dist/types/index.d.ts +2 -3
  334. package/dist/types/index.d.ts.map +1 -1
  335. package/dist/types/index.js +7 -6
  336. package/dist/types/index.js.map +1 -1
  337. package/dist/types/monitoring-types.d.ts +114 -0
  338. package/dist/types/monitoring-types.d.ts.map +1 -0
  339. package/dist/types/monitoring-types.js +10 -0
  340. package/dist/types/monitoring-types.js.map +1 -0
  341. package/dist/utils/detect-source-roots.js.map +1 -1
  342. package/dist/utils/file-walk.d.ts +33 -0
  343. package/dist/utils/file-walk.d.ts.map +1 -0
  344. package/dist/utils/file-walk.js +89 -0
  345. package/dist/utils/file-walk.js.map +1 -0
  346. package/dist/verification/rules-based.d.ts.map +1 -1
  347. package/dist/verification/rules-based.js.map +1 -1
  348. package/package.json +3 -7
  349. package/src/__tests__/checker-extra.test.ts +0 -30
  350. package/src/__tests__/checker.test.ts +0 -33
  351. package/src/__tests__/checkpoint.test.ts +46 -46
  352. package/src/__tests__/constraint-evolver.test.ts +22 -21
  353. package/src/__tests__/doctor-evolver.test.ts +3 -3
  354. package/src/__tests__/iron-laws.test.ts +0 -27
  355. package/src/__tests__/presets.test.ts +1 -40
  356. package/src/architecture/constraint-engine.ts +0 -5
  357. package/src/architecture/cross-project-checker.ts +6 -24
  358. package/src/cli/commands/__tests__/check.test.ts +3 -1
  359. package/src/cli/commands/__tests__/sync-docs.test.ts +77 -0
  360. package/src/cli/commands/__tests__/validate.test.ts +5 -0
  361. package/src/cli/commands/analyze-sessions.ts +31 -185
  362. package/src/cli/commands/check.ts +26 -225
  363. package/src/cli/commands/doc-freshness-check.ts +14 -25
  364. package/src/cli/commands/flow.ts +5 -3
  365. package/src/cli/commands/init.ts +3 -3
  366. package/src/cli/commands/posteval-plan.ts +0 -1
  367. package/src/cli/commands/release.ts +1 -1
  368. package/src/cli/commands/report.ts +2 -0
  369. package/src/cli/commands/spec-baseline-check.ts +12 -19
  370. package/src/cli/commands/sync-docs/agents-syncer.ts +280 -0
  371. package/src/cli/commands/sync-docs/capabilities-syncer.ts +229 -0
  372. package/src/cli/commands/sync-docs/context-syncer.ts +108 -0
  373. package/src/cli/commands/sync-docs/index.ts +355 -0
  374. package/src/cli/commands/sync-docs/preserve-block.ts +59 -0
  375. package/src/cli/commands/sync-docs/project-reader.ts +163 -0
  376. package/src/cli/commands/update-user-model.ts +23 -87
  377. package/src/cli/commands/validate.ts +6 -40
  378. package/src/cli/session-mining/corrections.ts +56 -0
  379. package/src/cli/session-mining/index.ts +13 -0
  380. package/src/cli/session-mining/text.ts +117 -0
  381. package/src/cli/session-mining/transcript.ts +107 -0
  382. package/src/constraints/__tests__/lifecycle-runner.test.ts +1 -1
  383. package/src/constraints/lifecycle-runner.ts +1 -1
  384. package/src/context/compaction.ts +2 -3
  385. package/src/context/knowledge-injector.ts +1 -1
  386. package/src/context/tool-output-budget.ts +1 -1
  387. package/src/core/constraints/capabilities-parser.ts +70 -0
  388. package/src/core/constraints/checker.ts +170 -779
  389. package/src/core/constraints/checkers/always-pass.ts +22 -0
  390. package/src/core/constraints/checkers/capability-sync.ts +71 -0
  391. package/src/core/constraints/checkers/context-doc-sync.ts +36 -0
  392. package/src/core/constraints/checkers/docs-freshness.ts +116 -0
  393. package/src/core/constraints/checkers/guideline-flags.ts +30 -0
  394. package/src/core/constraints/checkers/index.ts +114 -0
  395. package/src/core/constraints/checkers/iron-flags.ts +62 -0
  396. package/src/core/constraints/checkers/no-any-type.ts +42 -0
  397. package/src/core/constraints/checkers/no-bypass-checkpoint.ts +40 -0
  398. package/src/core/constraints/checkers/no-excuse-patterns.ts +24 -0
  399. package/src/core/constraints/checkers/no-fuzzy-completion-claim.ts +33 -0
  400. package/src/core/constraints/checkers/no-performative-agreement.ts +22 -0
  401. package/src/core/constraints/checkers/no-simplification-without-approval.ts +29 -0
  402. package/src/core/constraints/checkers/no-test-simplification.ts +28 -0
  403. package/src/core/constraints/checkers/test-coverage.ts +35 -0
  404. package/src/core/constraints/checkers/types.ts +54 -0
  405. package/src/core/constraints/checkers/yagni.ts +65 -0
  406. package/src/core/constraints/context-builder.ts +262 -0
  407. package/src/core/constraints/definitions/guidelines.ts +668 -0
  408. package/src/core/constraints/definitions/iron-laws.ts +333 -0
  409. package/src/core/constraints/definitions/tips.ts +63 -0
  410. package/src/core/constraints/definitions.ts +9 -1086
  411. package/src/core/constraints/doc-freshness/runner.ts +2 -3
  412. package/src/core/constraints/index.ts +1 -27
  413. package/src/core/constraints/interceptor.ts +0 -2
  414. package/src/core/index.ts +1 -1
  415. package/src/core/project-config-loader.ts +49 -13
  416. package/src/core/validators/check-handlers/command.ts +58 -0
  417. package/src/core/validators/check-handlers/file.ts +104 -0
  418. package/src/core/validators/check-handlers/http.ts +88 -0
  419. package/src/core/validators/check-handlers/output.ts +165 -0
  420. package/src/core/validators/checkpoint.ts +32 -407
  421. package/src/core/validators/cso.ts +1 -1
  422. package/src/core/validators/passes-gate.ts +2 -2
  423. package/src/dashboard/stats.ts +1 -1
  424. package/src/dashboard/types.ts +1 -1
  425. package/src/evolution/__tests__/auto-evolve.test.ts +1 -2
  426. package/src/evolution/auto-evolve.ts +3 -3
  427. package/src/failure/types.ts +5 -161
  428. package/src/gates/contract.ts +0 -1
  429. package/src/gates/index.ts +0 -2
  430. package/src/gates/performance.ts +1 -1
  431. package/src/gates/security.ts +1 -3
  432. package/src/hooks/bootstrap.ts +6 -16
  433. package/src/index.ts +4 -1
  434. package/src/knowledge/__tests__/lifecycle.test.ts +4 -1
  435. package/src/knowledge/audit.ts +1 -1
  436. package/src/knowledge/doctor.ts +0 -1
  437. package/src/knowledge/import.ts +2 -2
  438. package/src/knowledge/index-generator.ts +0 -1
  439. package/src/knowledge/ingest.ts +1 -2
  440. package/src/knowledge/lint.ts +2 -2
  441. package/src/knowledge/primitives/__tests__/code-structure-degrade.test.ts +24 -0
  442. package/src/knowledge/primitives/code-structure.ts +36 -12
  443. package/src/knowledge/query.ts +0 -3
  444. package/src/knowledge/store.ts +1 -1
  445. package/src/llm/adapter.ts +3 -3
  446. package/src/monitoring/analyzer-base.ts +112 -0
  447. package/src/monitoring/constraint-doctor.ts +14 -175
  448. package/src/monitoring/constraint-evolver.ts +20 -92
  449. package/src/monitoring/diagnosis-rules.ts +132 -0
  450. package/src/monitoring/knowledge-doctor.ts +0 -1
  451. package/src/monitoring/performance-analyzer.ts +22 -72
  452. package/src/monitoring/performance-collector.ts +0 -22
  453. package/src/monitoring/trace-analyzer.ts +17 -73
  454. package/src/presets/__tests__/standard.test.ts +2 -17
  455. package/src/presets/index.ts +1 -3
  456. package/src/presets/standard.ts +1 -26
  457. package/src/safety/output-guardrail.ts +0 -4
  458. package/src/tools/registry.ts +1 -1
  459. package/src/types/__tests__/types.test.ts +1 -33
  460. package/src/types/constraint.ts +6 -75
  461. package/src/types/failure.ts +165 -0
  462. package/src/types/index.ts +7 -5
  463. package/src/types/monitoring-types.ts +150 -0
  464. package/src/utils/detect-source-roots.ts +1 -1
  465. package/src/utils/file-walk.ts +78 -0
  466. package/src/verification/rules-based.ts +0 -1
  467. package/bin/harness-knowledge-capture.js +0 -99
  468. package/bin/harness-knowledge-check.js +0 -164
  469. package/bin/harness-knowledge-track.js +0 -118
  470. package/dist/cli/commands/sync-docs.d.ts.map +0 -1
  471. package/dist/cli/commands/sync-docs.js +0 -1074
  472. package/dist/cli/commands/sync-docs.js.map +0 -1
  473. package/dist/constraints/index.d.ts +0 -4
  474. package/dist/constraints/index.d.ts.map +0 -1
  475. package/dist/constraints/index.js +0 -20
  476. package/dist/constraints/index.js.map +0 -1
  477. package/dist/core/constraints/doc-freshness/auto-fix.d.ts +0 -23
  478. package/dist/core/constraints/doc-freshness/auto-fix.d.ts.map +0 -1
  479. package/dist/core/constraints/doc-freshness/auto-fix.js +0 -59
  480. package/dist/core/constraints/doc-freshness/auto-fix.js.map +0 -1
  481. package/dist/core/constraints/prompt-injection.d.ts +0 -16
  482. package/dist/core/constraints/prompt-injection.d.ts.map +0 -1
  483. package/dist/core/constraints/prompt-injection.js +0 -69
  484. package/dist/core/constraints/prompt-injection.js.map +0 -1
  485. package/dist/core/spec/index.d.ts +0 -7
  486. package/dist/core/spec/index.d.ts.map +0 -1
  487. package/dist/core/spec/index.js.map +0 -1
  488. package/dist/governance/executor.d.ts +0 -45
  489. package/dist/governance/executor.d.ts.map +0 -1
  490. package/dist/governance/executor.js +0 -243
  491. package/dist/governance/executor.js.map +0 -1
  492. package/dist/governance/index.d.ts +0 -9
  493. package/dist/governance/index.d.ts.map +0 -1
  494. package/dist/governance/index.js +0 -13
  495. package/dist/governance/index.js.map +0 -1
  496. package/dist/governance/types.d.ts +0 -46
  497. package/dist/governance/types.d.ts.map +0 -1
  498. package/dist/governance/types.js +0 -9
  499. package/dist/governance/types.js.map +0 -1
  500. package/dist/tools/definitions/definitions/core/code/fingerprint.sh +0 -273
  501. package/dist/tools/definitions/definitions/core/code/fingerprint.yml +0 -72
  502. package/dist/tools/definitions/definitions/core/code/parse.yml +0 -68
  503. package/dist/tools/definitions/definitions/core/code/register-language.sh +0 -475
  504. package/dist/tools/definitions/definitions/core/code/register-language.yml +0 -74
  505. package/dist/tools/definitions/definitions/core/docker/build.yml +0 -73
  506. package/dist/tools/definitions/definitions/core/docker/run.yml +0 -81
  507. package/dist/tools/definitions/definitions/core/file/copy.yml +0 -88
  508. package/dist/tools/definitions/definitions/core/file/read.yml +0 -69
  509. package/dist/tools/definitions/definitions/core/file/write.yml +0 -75
  510. package/dist/tools/definitions/definitions/core/git/branch.yml +0 -61
  511. package/dist/tools/definitions/definitions/core/git/cleanup-worktree.yml +0 -50
  512. package/dist/tools/definitions/definitions/core/git/clone.yml +0 -69
  513. package/dist/tools/definitions/definitions/core/git/commit.yml +0 -65
  514. package/dist/tools/definitions/definitions/core/git/push.yml +0 -79
  515. package/dist/tools/definitions/definitions/core/git/worktree.yml +0 -96
  516. package/dist/tools/definitions/definitions/core/notification/notify.sh +0 -152
  517. package/dist/tools/definitions/definitions/core/notification/notify.yml +0 -60
  518. package/dist/tools/definitions/definitions/core/npm/build.yml +0 -75
  519. package/dist/tools/definitions/definitions/core/npm/install.yml +0 -58
  520. package/dist/tools/definitions/definitions/core/npm/test.yml +0 -75
  521. package/dist/tools/definitions/definitions/core/validation/check-reuse.yml +0 -170
  522. package/dist/tools/definitions/definitions/core/validation/validate-handlers.yml +0 -118
  523. package/dist/tools/definitions/definitions/core/validation/validate-readme-stats.yml +0 -155
  524. package/dist/tools/definitions/definitions/core/validation/validate-yaml-syntax.yml +0 -134
  525. package/dist/tools/definitions/definitions/ext/browser/browser-automate.sh +0 -255
  526. package/dist/tools/definitions/definitions/ext/browser/browser-automate.yml +0 -166
  527. package/dist/tools/definitions/definitions/ext/browser/browser-close.sh +0 -104
  528. package/dist/tools/definitions/definitions/ext/browser/browser-close.yml +0 -55
  529. package/dist/tools/definitions/definitions/ext/browser/browser-mcp-debug.sh +0 -682
  530. package/dist/tools/definitions/definitions/ext/browser/browser-mcp-debug.yml +0 -167
  531. package/dist/tools/definitions/definitions/ext/browser/browser-start.sh +0 -101
  532. package/dist/tools/definitions/definitions/ext/browser/browser-start.yml +0 -62
  533. package/dist/tools/definitions/definitions/registry.json +0 -795
  534. package/dist/tools/definitions/definitions/std/README.md +0 -350
  535. package/dist/tools/definitions/definitions/std/analysis/analyze-codebase.yml +0 -72
  536. package/dist/tools/definitions/definitions/std/analysis/analyze-diff.yml +0 -182
  537. package/dist/tools/definitions/definitions/std/analysis/analyze-git-diff.yml +0 -70
  538. package/dist/tools/definitions/definitions/std/analysis/analyze-impact.yml +0 -78
  539. package/dist/tools/definitions/definitions/std/analysis/analyze-requirements.yml +0 -105
  540. package/dist/tools/definitions/definitions/std/analysis/brainstorm-options.yml +0 -106
  541. package/dist/tools/definitions/definitions/std/analysis/build-graph.yml +0 -154
  542. package/dist/tools/definitions/definitions/std/analysis/clarify-requirements.yml +0 -90
  543. package/dist/tools/definitions/definitions/std/analysis/detect-context.yml +0 -109
  544. package/dist/tools/definitions/definitions/std/analysis/detect-layers.yml +0 -125
  545. package/dist/tools/definitions/definitions/std/analysis/generate-tour.yml +0 -102
  546. package/dist/tools/definitions/definitions/std/analysis/search-enhance.yml +0 -105
  547. package/dist/tools/definitions/definitions/std/backlog/add.yml +0 -51
  548. package/dist/tools/definitions/definitions/std/backlog/decide.yml +0 -39
  549. package/dist/tools/definitions/definitions/std/backlog/github-sync.yml +0 -161
  550. package/dist/tools/definitions/definitions/std/backlog/list.yml +0 -53
  551. package/dist/tools/definitions/definitions/std/backlog/load.yml +0 -46
  552. package/dist/tools/definitions/definitions/std/backlog/resolve.yml +0 -37
  553. package/dist/tools/definitions/definitions/std/backlog/update.yml +0 -42
  554. package/dist/tools/definitions/definitions/std/bugfix/diagnose.yml +0 -68
  555. package/dist/tools/definitions/definitions/std/bugfix/fix.yml +0 -66
  556. package/dist/tools/definitions/definitions/std/bugfix/verify.yml +0 -69
  557. package/dist/tools/definitions/definitions/std/constraint/check-decomposition.yml +0 -103
  558. package/dist/tools/definitions/definitions/std/constraint/check-feature-list.yml +0 -77
  559. package/dist/tools/definitions/definitions/std/constraint/check-progress.yml +0 -97
  560. package/dist/tools/definitions/definitions/std/constraint/generate-report.yml +0 -147
  561. package/dist/tools/definitions/definitions/std/deploy/commit-push.yml +0 -33
  562. package/dist/tools/definitions/definitions/std/deploy/deploy-backend.yml +0 -37
  563. package/dist/tools/definitions/definitions/std/deploy/deploy-frontend.yml +0 -37
  564. package/dist/tools/definitions/definitions/std/deploy/rollback.yml +0 -148
  565. package/dist/tools/definitions/definitions/std/design/analyze-architecture-impact.yml +0 -113
  566. package/dist/tools/definitions/definitions/std/design/design-api.yml +0 -55
  567. package/dist/tools/definitions/definitions/std/design/design-architecture.yml +0 -97
  568. package/dist/tools/definitions/definitions/std/design/design-db.yml +0 -81
  569. package/dist/tools/definitions/definitions/std/design/generate-spec.yml +0 -182
  570. package/dist/tools/definitions/definitions/std/development/develop-api.yml +0 -85
  571. package/dist/tools/definitions/definitions/std/development/develop-backend.yml +0 -88
  572. package/dist/tools/definitions/definitions/std/development/develop-frontend.yml +0 -87
  573. package/dist/tools/definitions/definitions/std/development/develop-shared-types.yml +0 -74
  574. package/dist/tools/definitions/definitions/std/development/develop-task.yml +0 -122
  575. package/dist/tools/definitions/definitions/std/development/develop-tests.yml +0 -76
  576. package/dist/tools/definitions/definitions/std/development/execute-batch.yml +0 -152
  577. package/dist/tools/definitions/definitions/std/development/fix-issues.yml +0 -100
  578. package/dist/tools/definitions/definitions/std/development/implement-task.yml +0 -124
  579. package/dist/tools/definitions/definitions/std/development/review-fix-cycle.yml +0 -232
  580. package/dist/tools/definitions/definitions/std/evolution/implement.yml +0 -125
  581. package/dist/tools/definitions/definitions/std/evolution/prioritize.yml +0 -112
  582. package/dist/tools/definitions/definitions/std/evolution/report-gap.yml +0 -166
  583. package/dist/tools/definitions/definitions/std/file/read.yml +0 -21
  584. package/dist/tools/definitions/definitions/std/governance/aggregate-opinions.sh +0 -201
  585. package/dist/tools/definitions/definitions/std/governance/aggregate-opinions.yml +0 -79
  586. package/dist/tools/definitions/definitions/std/governance/audit-task.yml +0 -178
  587. package/dist/tools/definitions/definitions/std/governance/cast-vote.yml +0 -129
  588. package/dist/tools/definitions/definitions/std/governance/collect-issues.yml +0 -16
  589. package/dist/tools/definitions/definitions/std/governance/create-signed-document.yml +0 -23
  590. package/dist/tools/definitions/definitions/std/governance/create-voting-session.yml +0 -101
  591. package/dist/tools/definitions/definitions/std/governance/define-stance.sh +0 -243
  592. package/dist/tools/definitions/definitions/std/governance/define-stance.yml +0 -82
  593. package/dist/tools/definitions/definitions/std/governance/generate-review-report.yml +0 -23
  594. package/dist/tools/definitions/definitions/std/governance/impeach.yml +0 -179
  595. package/dist/tools/definitions/definitions/std/governance/multi-stance-review.yml +0 -154
  596. package/dist/tools/definitions/definitions/std/governance/prepare-artifact.yml +0 -20
  597. package/dist/tools/definitions/definitions/std/governance/review-spec-approval.yml +0 -262
  598. package/dist/tools/definitions/definitions/std/governance/rollback.yml +0 -186
  599. package/dist/tools/definitions/definitions/std/governance/stance-review.yml +0 -149
  600. package/dist/tools/definitions/definitions/std/governance/track-effect.yml +0 -199
  601. package/dist/tools/definitions/definitions/std/governance/vote-tally.yml +0 -144
  602. package/dist/tools/definitions/definitions/std/patch/execute.yml +0 -51
  603. package/dist/tools/definitions/definitions/std/planning/generate-tasks.yml +0 -36
  604. package/dist/tools/definitions/definitions/std/planning/load-tasks.yml +0 -44
  605. package/dist/tools/definitions/definitions/std/planning/split-batch.yml +0 -481
  606. package/dist/tools/definitions/definitions/std/planning/split-tasks.yml +0 -359
  607. package/dist/tools/definitions/definitions/std/planning/update-tasks.yml +0 -51
  608. package/dist/tools/definitions/definitions/std/planning/validate-tasks.yml +0 -46
  609. package/dist/tools/definitions/definitions/std/project/decide-next-workflow.yml +0 -38
  610. package/dist/tools/definitions/definitions/std/project/load-state.yml +0 -31
  611. package/dist/tools/definitions/definitions/std/project/save-state.yml +0 -32
  612. package/dist/tools/definitions/definitions/std/quality/check-quality.yml +0 -241
  613. package/dist/tools/definitions/definitions/std/quality/debug-systematic.yml +0 -163
  614. package/dist/tools/definitions/definitions/std/quality/handle-feedback.yml +0 -108
  615. package/dist/tools/definitions/definitions/std/quality/review-code.yml +0 -128
  616. package/dist/tools/definitions/definitions/std/quality/review-spec.yml +0 -140
  617. package/dist/tools/definitions/definitions/std/quality/review-task.yml +0 -190
  618. package/dist/tools/definitions/definitions/std/quality/run-tests.yml +0 -80
  619. package/dist/tools/definitions/definitions/std/quick/analyze.yml +0 -56
  620. package/dist/tools/definitions/definitions/std/quick/implement.yml +0 -67
  621. package/dist/tools/definitions/definitions/std/quick/verify.yml +0 -71
  622. package/dist/tools/definitions/definitions/std/verification/verify_completion.yml +0 -113
  623. package/dist/tools/definitions/definitions/std/verification/wait-condition.yml +0 -107
  624. package/dist/types/iron-law.d.ts +0 -25
  625. package/dist/types/iron-law.d.ts.map +0 -1
  626. package/dist/types/iron-law.js +0 -16
  627. package/dist/types/iron-law.js.map +0 -1
  628. package/src/cli/commands/sync-docs.ts +0 -1175
  629. package/src/constraints/index.ts +0 -3
  630. package/src/core/constraints/__tests__/prompt-injection.test.ts +0 -89
  631. package/src/core/constraints/doc-freshness/auto-fix.ts +0 -69
  632. package/src/core/constraints/prompt-injection.ts +0 -73
  633. package/src/core/spec/index.ts +0 -7
  634. package/src/governance/CONTEXT.md +0 -22
  635. package/src/governance/__tests__/executor.test.ts +0 -249
  636. package/src/governance/executor.ts +0 -229
  637. package/src/governance/index.ts +0 -13
  638. package/src/governance/types.ts +0 -53
  639. package/src/tools/core/package.json +0 -7
  640. package/src/tools/core/pnpm-lock.yaml +0 -232
  641. package/src/types/iron-law.ts +0 -50
@@ -17,17 +17,14 @@ import {
17
17
  ConstraintViolationError,
18
18
  } from '../../types/constraint';
19
19
  import type { ExecutionTrace } from '../../types/trace';
20
- import { getTraceCollector } from '../../monitoring/traces';
21
20
  import { IRON_LAWS, GUIDELINES, TIPS } from './definitions';
22
- import type { MergedConstraintsConfig, DocFreshnessConfig, DocFreshnessCheck } from '../../types/project-config';
23
- import { FreshnessRunner, type FreshnessCheckResult } from './doc-freshness/runner';
21
+ import type { MergedConstraintsConfig } from '../../types/project-config';
24
22
  import { normalizeTriggers } from '../../utils/exec';
25
23
  import { runCommand } from '../../utils/exec';
26
- import { existsSync, readFileSync, readdirSync, statSync } from 'fs';
27
24
  import { join, relative } from 'path';
28
- import * as yaml from 'js-yaml';
29
25
  import { CheckCache } from './check-cache';
30
- import { detectSourceRoots } from '../../utils/detect-source-roots';
26
+ import { findTsSourceFiles } from '../../utils/file-walk';
27
+ import { getConstraintCheck, type CheckEnv } from './checkers';
31
28
 
32
29
  /**
33
30
  * 例外名称 → ConstraintContext 中布尔字段的映射
@@ -59,6 +56,18 @@ const EXCEPTION_FIELD_MAP: Record<string, keyof ConstraintContext> = {
59
56
  existing_design: 'isExistingDesign',
60
57
  };
61
58
 
59
+ /**
60
+ * trace 记录器最小接口(工单 15:core→monitoring 循环消除)
61
+ *
62
+ * checker 不再值导入 monitoring/traces 的单例;生产调用方经
63
+ * setTraceRecorder 注入真实收集器,默认 no-op。
64
+ */
65
+ export interface TraceRecorder {
66
+ record(trace: ExecutionTrace): void;
67
+ }
68
+
69
+ const NOOP_TRACE_RECORDER: TraceRecorder = { record: () => undefined };
70
+
62
71
  /**
63
72
  * 约束检查器
64
73
  */
@@ -68,11 +77,51 @@ export class ConstraintChecker {
68
77
  /** 自定义约束配置(项目级) */
69
78
  private customConfig: MergedConstraintsConfig | null = null;
70
79
 
71
- /** 检查结果缓存(S7:减少重复 git diff / src scan I/O,TTL=1s 防跨测试污染) */
80
+ /** 检查结果缓存(S7src 扫描等重复 I/O,TTL=1s 防跨测试污染) */
72
81
  private cache: CheckCache = new CheckCache({ ttlMs: 1000 });
73
82
 
83
+ /**
84
+ * run 级 memo(工单 18):一次 checkConstraints/checkConstraintsSafe 内
85
+ * git diff 等命令只执行一次;run 外直接调用私有检查方法时不 memo(恒新鲜)。
86
+ */
87
+ private runCache: Map<string, Promise<string>> | null = null;
88
+
89
+ /** trace 记录器(注入式,默认 no-op;生产入口经 setTraceRecorder 接入真实收集器) */
90
+ private traceRecorder: TraceRecorder = NOOP_TRACE_RECORDER;
91
+
74
92
  private constructor() {}
75
93
 
94
+ /**
95
+ * run 内 memoize;无活动 run 时直接执行(工单 18)
96
+ */
97
+ private memoRun(key: string, fn: () => Promise<string>): Promise<string> {
98
+ if (!this.runCache) return fn();
99
+ let pending = this.runCache.get(key);
100
+ if (!pending) {
101
+ pending = fn();
102
+ this.runCache.set(key, pending);
103
+ }
104
+ return pending;
105
+ }
106
+
107
+ /**
108
+ * staged 全量 diff(同一次 run 内只执行一次 git 命令,工单 18)
109
+ */
110
+ private getStagedDiff(projectPath: string): Promise<string> {
111
+ return this.memoRun(`git_diff_staged:${projectPath}`, () =>
112
+ runCommand('git diff --cached', projectPath)
113
+ );
114
+ }
115
+
116
+ /**
117
+ * staged 变更文件名列表(同一次 run 内只执行一次 git 命令,工单 18)
118
+ */
119
+ private getStagedDiffNames(projectPath: string): Promise<string> {
120
+ return this.memoRun(`git_diff_staged_names:${projectPath}`, () =>
121
+ runCommand('git diff --cached --name-only', projectPath)
122
+ );
123
+ }
124
+
76
125
  /**
77
126
  * 获取单例实例
78
127
  */
@@ -83,6 +132,13 @@ export class ConstraintChecker {
83
132
  return ConstraintChecker.instance;
84
133
  }
85
134
 
135
+ /**
136
+ * 注入 trace 记录器(工单 15:解耦 core 对 monitoring 的值依赖)
137
+ */
138
+ setTraceRecorder(recorder: TraceRecorder): void {
139
+ this.traceRecorder = recorder;
140
+ }
141
+
86
142
  /**
87
143
  * 设置项目级约束配置
88
144
  *
@@ -191,7 +247,7 @@ export class ConstraintChecker {
191
247
  * 记录约束检查的 trace
192
248
  */
193
249
  private recordTrace(
194
- collector: ReturnType<typeof getTraceCollector>,
250
+ collector: TraceRecorder,
195
251
  constraint: Constraint,
196
252
  checkResult: ConstraintResult,
197
253
  context: ConstraintContext
@@ -212,679 +268,32 @@ export class ConstraintChecker {
212
268
  }
213
269
 
214
270
  /**
215
- * 检查约束前置条件
271
+ * 检查约束前置条件(工单 21:分发至 checkers/ 注册表)
272
+ *
273
+ * 未注册的约束默认通过(保持历史 default 分支语义)。
216
274
  */
217
275
  private async checkPrecondition(
218
276
  constraint: Constraint,
219
277
  context: ConstraintContext
220
278
  ): Promise<boolean> {
221
- const projectPath = context.projectPath || process.cwd();
222
-
223
- switch (constraint.id) {
224
- // Iron Laws
225
- case 'no_bypass_checkpoint':
226
- // 检查代码中是否有 skip/bypass 关键词
227
- return await this.checkNoBypassCheckpoint(context);
228
-
229
- case 'no_self_approval':
230
- // 检查是否有测试证据
231
- return context.hasTest === true;
232
-
233
- case 'no_completion_without_verification':
234
- // 检查是否有验证证据
235
- return context.hasVerificationEvidence === true;
236
-
237
- case 'no_test_simplification':
238
- // 检查是否删除了测试
239
- return await this.checkNoTestSimplification(projectPath);
240
-
241
- case 'incremental_progress':
242
- // 检查是否一次做多个任务(需要 context 提供信息)
243
- // undefined = 未验证 → Iron Law 必须显式确认
244
- return context.hasSingleTask === true;
245
-
246
- case 'verify_external_capability':
247
- // 检查是否已验证外部能力
248
- // undefined = 未验证 → Iron Law 必须显式确认
249
- return context.hasExternalCapabilityVerification === true;
250
-
251
- case 'no_implementation_without_requirement_review':
252
- // 检查实现后是否对比需求验证
253
- return context.hasRequirementReview === true;
254
-
255
- case 'no_implementation_without_requirement':
256
- // 检查是否有需求文档
257
- return context.hasRequirement === true;
258
-
259
- case 'prefer_worktree':
260
- // 检查是否在 worktree 中执行
261
- return context.hasWorktree === true;
262
-
263
- case 'no_fuzzy_completion_claim':
264
- // 检查完成声明是否包含模糊词(含"我记得""之前说""大部分"等无验证模式)
265
- return this.checkNoFuzzyWords(context.completionClaimText || '');
266
-
267
- case 'no_claim_without_evidence':
268
- // 检查是否提供了验证证据(test output / file check / spec AC matrix)
269
- return context.hasVerificationEvidence === true ||
270
- (context.taskDescription || '').includes('test') ||
271
- context.hasTest === true;
272
-
273
- case 'no_delete_without_context':
274
- // 检查删除前是否审查了设计文档
275
- return context.hasRequirementReview === true ||
276
- context.hasRequirement === true ||
277
- context.isExistingDesign === true;
278
-
279
- case 'no_performative_agreement':
280
- // 检查是否有表演性同意(主要由 promptInjection 驱动,这里做辅助检查)
281
- return this.checkNoPerformativePatterns(context.taskDescription || '');
282
-
283
- case 'two_stage_review_required':
284
- // 检查是否完成两阶段审查
285
- return context.hasTwoStageReview === true;
286
-
287
- // Guidelines
288
- case 'no_fix_without_root_cause':
289
- // 检查是否有根本原因调查
290
- return context.hasRootCauseInvestigation === true;
291
-
292
- case 'no_code_without_test':
293
- // 检查是否有失败的测试
294
- return context.hasFailingTest === true;
295
-
296
- case 'no_any_type':
297
- // 检查代码中是否有 any 类型
298
- return await this.checkNoAnyType(projectPath, context.changedFiles);
299
-
300
- case 'simplest_solution_first':
301
- // 检查是否已检查本地数据源
302
- return context.hasReuseCheck === true;
303
-
304
- case 'no_creation_without_reuse_check':
305
- // 检查是否已进行复用检查
306
- return context.hasReuseCheck === true;
307
-
308
- case 'capability_sync':
309
- // 检查 CAPABILITIES.md 是否更新
310
- return await this.checkCapabilitySync(projectPath);
311
-
312
- case 'no_simplification_without_approval':
313
- // 检查是否简化了逻辑
314
- return await this.checkNoSimplificationWithoutApproval(projectPath);
315
-
316
- case 'no_skill_without_test':
317
- // 检查是否有测试
318
- return context.hasTest === true;
319
-
320
- case 'test_coverage_required':
321
- // 检查测试覆盖率
322
- return await this.checkTestCoverage(projectPath);
323
-
324
- case 'context_doc_sync':
325
- return await this.checkContextDocSync(projectPath);
326
-
327
- case 'docs_freshness':
328
- return await this.checkDocsFreshness(projectPath);
329
-
330
- case 'no_excuse_patterns':
331
- // 检查是否使用了借口模式
332
- return this.checkNoExcusePatterns(context.completionClaimText || context.taskDescription || '');
333
-
334
- case 'yagni_check':
335
- // 检查是否有过度设计(主要由 promptInjection 驱动)
336
- return this.checkYagni(projectPath, context.changedFiles);
337
-
338
- // Mnilax guidelines + first-principles (injectPrompt=true, behavior-level, always pass — post-checked)
339
- case 'surgical_changes_only':
340
- case 'no_model_for_deterministic':
341
- case 'no_conflict_blending':
342
- case 'read_before_write':
343
- case 'follow_conventions':
344
- case 'first_principles_first':
345
- case 'fix_the_problem_not_the_gate':
346
- case 'diagnosis_to_fix_gate':
347
- // Guideline: behavior constraints, enforced via promptInjection + post-check
348
- return true;
349
-
350
- // Tips - 总是返回 true(仅提示)
351
- case 'readme_required':
352
- return true;
353
-
354
- case 'doc_required_for_public_api':
355
- return true;
356
-
357
- default:
358
- // 未知约束,默认通过
359
- return true;
360
- }
361
- }
362
-
363
- /**
364
- * 检查文本中是否包含模糊词
365
- */
366
- private checkNoFuzzyWords(text: string): boolean {
367
- if (!text) return true; // 没有文本时默认通过(由其他检查覆盖)
368
- const fuzzyPatterns = [
369
- /应该没问题/,
370
- /应该可以/,
371
- /大概/,
372
- /可能/,
373
- /好像/,
374
- /似乎/,
375
- /差不多/,
376
- /基本完成/,
377
- /大部分/,
378
- // audit-learned (2026-05-18): unverified completion claims
379
- /我记得删[过掉]了/,
380
- /之前说删了/,
381
- /已删除.*但/,
382
- /大部分实现/,
383
- /大部分完成/,
384
- /已修复.*但/,
385
- ];
386
- return !fuzzyPatterns.some(p => p.test(text));
387
- }
388
-
389
- /**
390
- * 检查文本中是否包含表演性同意模式
391
- */
392
- private checkNoPerformativePatterns(text: string): boolean {
393
- if (!text) return true;
394
- // 检查是否只有"好的/明白了"等同意词,没有后续分析
395
- const performativeStart = /^(好的[,,]*\s*我[来去]做|明白了[,,]*|没问题[,,]*|ok[,,]*\s*i.?ll)/i;
396
- // 如果以表演性模式开头,且总长度很短(< 50 字符),视为表演性同意
397
- if (performativeStart.test(text) && text.length < 100) {
398
- return false;
399
- }
400
- return true;
401
- }
402
-
403
- /**
404
- * 检查文本中是否包含借口模式
405
- */
406
- private checkNoExcusePatterns(text: string): boolean {
407
- if (!text) return true;
408
- const excusePatterns = [
409
- /稍后修复/,
410
- /小问题/,
411
- /不影响功能/,
412
- /以后再说/,
413
- /先这样/,
414
- /临时方案/,
415
- /暂时这样/,
416
- ];
417
- return !excusePatterns.some(p => p.test(text));
418
- }
419
-
420
- /**
421
- * 检查 YAGNI:过度设计信号
422
- *
423
- * 检查是否存在只有一个实现的 interface/abstract class。
424
- * 主要由 promptInjection 驱动,这里是辅助检查。
425
- */
426
- private async checkYagni(
427
- projectPath?: string,
428
- changedFiles?: string[]
429
- ): Promise<boolean> {
430
- // 无上下文时默认通过(主要由 promptInjection 驱动)
431
- if (!projectPath || !changedFiles || changedFiles.length === 0) return true;
432
-
433
- try {
434
- const path = await import('path');
435
- const fs = await import('fs');
436
-
437
- for (const file of changedFiles) {
438
- if (!file.endsWith('.ts') && !file.endsWith('.tsx')) continue;
439
-
440
- const filePath = path.join(projectPath, file);
441
- if (!fs.existsSync(filePath)) continue;
442
-
443
- const content = fs.readFileSync(filePath, 'utf-8');
444
-
445
- // 检查是否有 export interface/abstract class
446
- const hasInterface = /export\s+(?:default\s+)?interface\s+(\w+)/g;
447
- const hasAbstract = /export\s+(?:default\s+)?abstract\s+class\s+(\w+)/g;
448
-
449
- const interfaces = [...content.matchAll(hasInterface)].map(m => m[1]);
450
- const abstracts = [...content.matchAll(hasAbstract)].map(m => m[1]);
451
-
452
- const exportedTypes = [...interfaces, ...abstracts];
453
-
454
- for (const typeName of exportedTypes) {
455
- // 检查同一个 typeName 的 implements/extends 出现次数
456
- const implPattern = new RegExp(`(?:implements|extends)\\s+${typeName}\\b`, 'g');
457
- // 在整个项目中搜索(简化版:只在 changedFiles 中搜索)
458
- let implCount = 0;
459
- for (const f of changedFiles) {
460
- if (!f.endsWith('.ts') && !f.endsWith('.tsx')) continue;
461
- const fp = path.join(projectPath, f);
462
- if (!fs.existsSync(fp)) continue;
463
- const fc = fs.readFileSync(fp, 'utf-8');
464
- const matches = fc.match(implPattern);
465
- if (matches) implCount += matches.length;
466
- }
467
-
468
- // 只有一个实现者 → YAGNI 违规
469
- if (implCount <= 1) {
470
- return false;
471
- }
472
- }
473
- }
474
- } catch {
475
- // 文件读取失败,默认通过
476
- return true;
477
- }
478
-
479
- return true;
480
- }
481
-
482
- /**
483
- * 检查 no_bypass_checkpoint:检查代码中是否有 skip/bypass 关键词
484
- */
485
- private async checkNoBypassCheckpoint(context: ConstraintContext): Promise<boolean> {
486
- const changedFiles = context.changedFiles || [];
487
-
488
- if (changedFiles.length === 0) {
489
- return true; // 无变更文件,默认通过
490
- }
491
-
492
- // 检查文件内容是否有 skip/bypass 关键词
493
- const bypassPatterns = [
494
- /\.skip\(/, // Jest/Vitest skip
495
- /\.bypass\s*=/, // bypass flag
496
- /skip:\s*true/, // skip option
497
- /bypass\s*checkpoint/, // explicit bypass
498
- /\/\/\s*skip/, // comment skip
499
- ];
500
-
501
- for (const file of changedFiles) {
502
- if (!existsSync(file)) continue;
503
- try {
504
- const content = readFileSync(file, 'utf-8');
505
- for (const pattern of bypassPatterns) {
506
- if (pattern.test(content)) {
507
- return false; // 发现 bypass 关键词
508
- }
509
- }
510
- } catch {
511
- // 文件读取失败,忽略
512
- }
513
- }
514
-
515
- return true;
516
- }
517
-
518
- /**
519
- * 检查 no_test_simplification:检查 git diff 是否删除了测试
520
- */
521
- private async checkNoTestSimplification(projectPath: string): Promise<boolean> {
522
- try {
523
- // 检查是否有删除测试的 diff
524
- const diff = await runCommand('git diff --cached', projectPath);
525
-
526
- // 检查是否删除了测试行
527
- const deletedTestPatterns = [
528
- /^-\s*(test|it|describe)\s*\(/, // 删除 test/it/describe
529
- /^-\s*expect\s*\(/, // 删除 expect
530
- /^-\s*\/\/\s*test/, // 删除注释的 test
531
- ];
532
-
533
- for (const pattern of deletedTestPatterns) {
534
- if (pattern.test(diff)) {
535
- return false; // 发现删除测试
536
- }
537
- }
538
-
539
- return true;
540
- } catch {
541
- return true; // git 命令失败,默认通过
542
- }
543
- }
544
-
545
- /**
546
- * 检查 no_any_type:grep any 类型
547
- */
548
- private async checkNoAnyType(projectPath: string, changedFiles?: string[]): Promise<boolean> {
549
- try {
550
- const filesToCheck = changedFiles && changedFiles.length > 0
551
- ? changedFiles.filter(f => f.endsWith('.ts') || f.endsWith('.tsx'))
552
- : [];
553
-
554
- if (filesToCheck.length === 0) {
555
- return true; // 无 TS 文件变更
556
- }
557
-
558
- // 检查是否有 : any 类型
559
- for (const file of filesToCheck) {
560
- if (!existsSync(file)) continue;
561
- try {
562
- const content = readFileSync(file, 'utf-8');
563
- // 检查 : any(排除注释和字符串)
564
- const lines = content.split('\n');
565
- for (const line of lines) {
566
- // 跳过注释和字符串
567
- if (line.trim().startsWith('//') || line.trim().startsWith('*')) continue;
568
- if (line.includes(': any') && !line.includes('// ') && !line.includes('/*')) {
569
- return false; // 发现 any 类型
570
- }
571
- }
572
- } catch {
573
- // 文件读取失败,忽略
574
- }
575
- }
576
-
577
- return true;
578
- } catch {
579
- return true; // 检查失败,默认通过
580
- }
581
- }
582
-
583
- /**
584
- * 检查 capability_sync:检查 CAPABILITIES.md 是否与代码同步
585
- *
586
- * 两步验证:
587
- * 1. Git diff 检查 — 当前变更的非测试文件是否在文档中有记录(增量检查)
588
- * 2. 全量扫描 — src/ 下的所有源文件是否都在 CAPABILITIES.md 中(完整性检查)
589
- */
590
- private async checkCapabilitySync(projectPath: string): Promise<boolean> {
591
- try {
592
- const capabilitiesPath = join(projectPath, 'CAPABILITIES.md');
593
- if (!existsSync(capabilitiesPath)) {
594
- // 检查是否有代码变更,无变更则跳过
595
- const diff = await runCommand('git diff --cached --name-only', projectPath);
596
- const changedCodeFiles = diff.split('\n').filter(
597
- (f: string) => f.endsWith('.ts') || f.endsWith('.tsx') || f.endsWith('.js')
598
- );
599
- return changedCodeFiles.length === 0;
600
- }
601
-
602
- const listedFiles = this.parseCapabilitiesFiles(capabilitiesPath);
603
-
604
- // ── Step 1: Git diff 增量检查 ──
605
- const diff = await runCommand('git diff --cached --name-only', projectPath);
606
- const changedCodeFiles = diff.split('\n').filter(
607
- (f: string) => f.endsWith('.ts') || f.endsWith('.tsx') || f.endsWith('.js')
608
- );
609
-
610
- if (changedCodeFiles.length > 0 && listedFiles.length > 0) {
611
- const significantChanges = changedCodeFiles.filter(
612
- (f: string) => !f.includes('__tests__') && !f.includes('.test.') && !f.includes('.spec.')
613
- );
614
-
615
- if (significantChanges.length > 0) {
616
- const covered = significantChanges.some((changed: string) =>
617
- listedFiles.some((listed: string) => changed.endsWith(listed) || changed.includes(listed))
618
- );
619
- if (!covered) return false;
620
- }
621
- }
279
+ const impl = getConstraintCheck(constraint.id);
280
+ if (!impl) return true;
622
281
 
623
- // ── Step 2: 全量 src/ 扫描(T-058 修复核心)──
624
- // 检查是否有 src/ 下的源文件未在 CAPABILITIES.md 中记录
625
- if (listedFiles.length > 0) {
626
- const sourceRoots = detectSourceRoots(projectPath);
627
- for (const root of sourceRoots) {
628
- const srcDir = join(projectPath, root);
629
- if (existsSync(srcDir)) {
630
- const actualFiles = this.cache.getSync(`src_scan_${root}`, projectPath, () =>
631
- this.findSourceFiles(srcDir, projectPath)
632
- );
633
- for (const file of actualFiles) {
634
- if (!listedFiles.includes(file)) {
635
- return false;
636
- }
637
- }
638
- }
639
- }
640
- }
641
-
642
- return true;
643
- } catch {
644
- return true; // 检查失败,默认通过
645
- }
646
- }
647
-
648
- /**
649
- * 解析 CAPABILITIES.md 中表格的文件路径列
650
- */
651
- private parseCapabilitiesFiles(capabilitiesPath: string): string[] {
652
- try {
653
- const content = readFileSync(capabilitiesPath, 'utf-8');
654
- const files: string[] = [];
655
-
656
- // 匹配 markdown 表格行中的 .ts/.tsx/.js/.jsx 文件路径(第二列)
657
- const tableRowRegex = /^\|[^|]+\|\s*([^|]+?\.(?:ts|tsx|js|jsx))\s*\|/gm;
658
- let match;
659
- while ((match = tableRowRegex.exec(content)) !== null) {
660
- files.push(match[1].trim());
661
- }
662
-
663
- return files;
664
- } catch {
665
- return [];
666
- }
667
- }
668
-
669
- /**
670
- * 检查 no_simplification_without_approval:检查简化关键词
671
- */
672
- private async checkNoSimplificationWithoutApproval(projectPath: string): Promise<boolean> {
673
- try {
674
- const diff = await runCommand('git diff --cached', projectPath);
675
-
676
- // 检查是否有简化关键词
677
- const simplificationPatterns = [
678
- /removed\s*test/i,
679
- /simplified\s*logic/i,
680
- /removed\s*validation/i,
681
- /skip\s*check/i,
682
- ];
683
-
684
- for (const pattern of simplificationPatterns) {
685
- if (pattern.test(diff)) {
686
- return false; // 发现简化关键词
687
- }
688
- }
689
-
690
- return true;
691
- } catch {
692
- return true; // 检查失败,默认通过
693
- }
694
- }
695
-
696
- /**
697
- * 检查 test_coverage_required:读取 coverage 报告
698
- */
699
- private async checkTestCoverage(projectPath: string): Promise<boolean> {
700
- try {
701
- // 检查 coverage 报告文件
702
- const coverageJsonPath = join(projectPath, 'coverage', 'coverage-final.json');
703
- const coverageSummaryPath = join(projectPath, 'coverage', 'coverage-summary.json');
704
-
705
- if (!existsSync(coverageJsonPath) && !existsSync(coverageSummaryPath)) {
706
- return true; // 无 coverage 报告,默认通过
707
- }
708
-
709
- // 尝试读取 coverage-summary.json
710
- if (existsSync(coverageSummaryPath)) {
711
- const summary = JSON.parse(readFileSync(coverageSummaryPath, 'utf-8'));
712
- const total = summary.total || {};
713
- const linesCoverage = total.lines?.pct || 0;
714
-
715
- // 默认要求 50% 覆盖率(可配置)
716
- return linesCoverage >= 50;
717
- }
718
-
719
- return true;
720
- } catch {
721
- return true; // 检查失败,默认通过
722
- }
723
- }
724
-
725
- /**
726
- * 检查 context_doc_sync:关键目录是否有 CONTEXT.md
727
- */
728
- private async checkContextDocSync(projectPath: string): Promise<boolean> {
729
- try {
730
- const configPath = join(projectPath, '.harness', 'config.yml');
731
- const configContent = readFileSync(configPath, 'utf-8');
732
- const config = yaml.load(configContent) as Record<string, unknown>;
733
- const governance = config.governance as Record<string, unknown> | undefined;
734
- const contextFiles = governance?.context_files as Record<string, unknown> | undefined;
735
-
736
- if (!contextFiles?.enabled || !Array.isArray(contextFiles.required_dirs)) {
737
- return true; // 未配置,跳过
738
- }
739
-
740
- const requiredDirs = contextFiles.required_dirs as string[];
741
- for (const dir of requiredDirs) {
742
- const contextPath = join(projectPath, dir, 'CONTEXT.md');
743
- if (!existsSync(contextPath)) {
744
- return false;
745
- }
746
- }
747
-
748
- return true;
749
- } catch {
750
- return true; // 配置不存在或解析失败,跳过
751
- }
752
- }
753
-
754
- /**
755
- * 检查 docs_freshness:CAPABILITIES.md 文件表 + 能力清单格式 + CLAUDE.md + CHANGELOG
756
- *
757
- * 1. 文件表格式:检查 CAPABILITIES.md 中列出的文件是否存在(防过期引用)
758
- * 2. 能力清单格式:通过 FreshnessRunner 配置驱动检查计数/目录
759
- * 3. 无配置时注入内置默认配置(等价旧硬编码行为)
760
- */
761
- private async checkDocsFreshness(projectPath: string): Promise<boolean> {
762
- // Step 1: 文件表格式 — 检查列出的文件是否还存在
763
- const fileTableResult = await this.checkCapabilitiesFreshness(projectPath);
764
- if (!fileTableResult) return false;
765
-
766
- // Step 2: 能力清单格式 + CLAUDE.md + CHANGELOG — 通过 FreshnessRunner
767
- try {
768
- const configPath = join(projectPath, '.harness', 'config.yml');
769
- let freshnessConfig: DocFreshnessConfig | undefined;
770
- let requiredDirs: string[] | undefined;
771
-
772
- if (existsSync(configPath)) {
773
- try {
774
- const raw = yaml.load(readFileSync(configPath, 'utf-8')) as Record<string, unknown>;
775
- const governance = raw.governance as Record<string, unknown> | undefined;
776
- freshnessConfig = governance?.doc_freshness as DocFreshnessConfig | undefined;
777
-
778
- const contextFiles = governance?.context_files as Record<string, unknown> | undefined;
779
- if (contextFiles?.enabled && Array.isArray(contextFiles.required_dirs)) {
780
- requiredDirs = contextFiles.required_dirs as string[];
781
- }
782
- } catch {
783
- // 配置解析失败,使用默认
784
- }
785
- }
786
-
787
- const runner = new FreshnessRunner();
788
- let results: FreshnessCheckResult[];
789
-
790
- if (freshnessConfig?.checks && freshnessConfig.checks.length > 0) {
791
- results = runner.runAll(freshnessConfig, projectPath, { requiredDirs });
792
- } else {
793
- const builtIn = this.getBuiltInDocFreshnessConfig(requiredDirs);
794
- results = runner.runAll({ checks: builtIn }, projectPath, { requiredDirs });
795
- }
796
-
797
- if (!results.every(r => r.pass)) return false;
798
- } catch {
799
- // FreshnessRunner 失败不影响整体
800
- }
801
-
802
- return true;
803
- }
804
-
805
- /**
806
- * 获取内置默认文档新鲜度检查配置
807
- *
808
- * 等价旧硬编码的 checkCapabilitiesFreshness + checkClaudeMdFreshness 行为。
809
- * 仅当项目未提供 governance.doc_freshness 配置时使用。
810
- */
811
- private getBuiltInDocFreshnessConfig(_requiredDirs?: string[]): DocFreshnessCheck[] {
812
- return [
813
- // CONTEXT.md 存在性 — key directories must have CONTEXT.md
814
- { type: 'context_docs' },
815
- // CHANGELOG 版本 vs package.json 版本 — prevents version drift
816
- { type: 'changelog_version' },
817
- ];
818
- }
819
-
820
- /**
821
- * 检查 CAPABILITIES.md 是否与源码同步(文件表格式)
822
- *
823
- * 检查 CAPABILITIES.md 中列出的文件路径是否仍然存在于磁盘上(防过期引用)。
824
- * 多根查找:支持不同项目的源码根(harness=src/, studio=apps/api/src/ 等)。
825
- * 无表格行(能力清单格式)时跳过。
826
- */
827
- private async checkCapabilitiesFreshness(projectPath: string): Promise<boolean> {
828
- try {
829
- const capabilitiesPath = join(projectPath, 'CAPABILITIES.md');
830
- if (!existsSync(capabilitiesPath)) return true;
831
- const content = readFileSync(capabilitiesPath, 'utf-8');
832
-
833
- const listedFiles: string[] = [];
834
- const tableRowRegex = /^\|[^|]+\|\s*([^|]+?\.(?:ts|tsx|js|jsx))\s*\|/gm;
835
- let match;
836
- while ((match = tableRowRegex.exec(content)) !== null) {
837
- listedFiles.push(match[1].trim());
838
- }
839
-
840
- if (listedFiles.length === 0) return true;
841
-
842
- const sourceRoots = detectSourceRoots(projectPath);
843
- const fileExists = (file: string): boolean => {
844
- if (existsSync(join(projectPath, file))) return true;
845
- for (const root of sourceRoots) {
846
- if (existsSync(join(projectPath, root, file))) return true;
847
- }
848
- return false;
849
- };
850
-
851
- for (const file of listedFiles) {
852
- if (!fileExists(file)) return false;
853
- }
854
-
855
- return true;
856
- } catch {
857
- return true;
858
- }
859
- }
860
-
861
- /**
862
- * 查找 src/ 目录中的源文件
863
- */
864
- private findSourceFiles(dir: string, projectPath: string): string[] {
865
- const results: string[] = [];
866
- let entries: string[];
867
- try {
868
- entries = readdirSync(dir);
869
- } catch {
870
- return [];
871
- }
282
+ const projectPath = context.projectPath || process.cwd();
283
+ const env: CheckEnv = {
284
+ context,
285
+ projectPath,
286
+ stagedDiff: () => this.getStagedDiff(projectPath),
287
+ stagedDiffNames: () => this.getStagedDiffNames(projectPath),
288
+ srcScan: (root: string) =>
289
+ this.cache.getSync(`src_scan_${root}`, projectPath, () =>
290
+ findTsSourceFiles(join(projectPath, root), { skipIndex: true }).map((f) =>
291
+ relative(projectPath, f)
292
+ )
293
+ ),
294
+ };
872
295
 
873
- for (const entry of entries) {
874
- if (entry === 'node_modules' || entry === '__tests__' || entry === 'dist') continue;
875
- const entryPath = join(dir, entry);
876
- try {
877
- const stat = statSync(entryPath);
878
- if (stat.isDirectory()) {
879
- results.push(...this.findSourceFiles(entryPath, projectPath));
880
- } else if (entry.endsWith('.ts') && !entry.endsWith('.d.ts') && entry !== 'index.ts') {
881
- results.push(relative(projectPath, entryPath));
882
- }
883
- } catch {
884
- // ignore
885
- }
886
- }
887
- return results;
296
+ return await impl.evaluate(env);
888
297
  }
889
298
 
890
299
  /**
@@ -934,59 +343,67 @@ export class ConstraintChecker {
934
343
  context: ConstraintContext,
935
344
  customConfig?: MergedConstraintsConfig | null
936
345
  ): Promise<ConstraintCheckResult> {
937
- const result: ConstraintCheckResult = {
938
- ironLaws: [],
939
- guidelines: [],
940
- tips: [],
941
- passed: true,
942
- warningCount: 0,
943
- tipCount: 0,
944
- };
346
+ // run 起始:重置 run 级缓存;run 结束(含铁律提前抛出)清空(工单 18)
347
+ this.cache.invalidate();
348
+ this.runCache = new Map();
945
349
 
946
- const traceCollector = getTraceCollector();
947
- const constraints = this.getConstraints(customConfig);
350
+ try {
351
+ const result: ConstraintCheckResult = {
352
+ ironLaws: [],
353
+ guidelines: [],
354
+ tips: [],
355
+ passed: true,
356
+ warningCount: 0,
357
+ tipCount: 0,
358
+ };
948
359
 
949
- // 1. Iron Laws: 必须全部通过
950
- for (const constraint of Object.values(constraints.ironLaws)) {
951
- if (!this.matchesTrigger(constraint, context.operation)) continue;
360
+ const traceCollector = this.traceRecorder;
361
+ const constraints = this.getConstraints(customConfig);
952
362
 
953
- const checkResult = await this.check(constraint, context);
954
- result.ironLaws.push(checkResult);
955
- this.recordTrace(traceCollector, constraint, checkResult, context);
363
+ // 1. Iron Laws: 必须全部通过
364
+ for (const constraint of Object.values(constraints.ironLaws)) {
365
+ if (!this.matchesTrigger(constraint, context.operation)) continue;
956
366
 
957
- if (!checkResult.satisfied) {
958
- result.passed = false;
959
- throw new ConstraintViolationError(checkResult);
367
+ const checkResult = await this.check(constraint, context);
368
+ result.ironLaws.push(checkResult);
369
+ this.recordTrace(traceCollector, constraint, checkResult, context);
370
+
371
+ if (!checkResult.satisfied) {
372
+ result.passed = false;
373
+ throw new ConstraintViolationError(checkResult);
374
+ }
960
375
  }
961
- }
962
376
 
963
- // 2. Guidelines: 记录警告
964
- for (const constraint of Object.values(constraints.guidelines)) {
965
- if (!this.matchesTrigger(constraint, context.operation)) continue;
377
+ // 2. Guidelines: 记录警告
378
+ for (const constraint of Object.values(constraints.guidelines)) {
379
+ if (!this.matchesTrigger(constraint, context.operation)) continue;
966
380
 
967
- const checkResult = await this.check(constraint, context);
968
- result.guidelines.push(checkResult);
969
- this.recordTrace(traceCollector, constraint, checkResult, context);
381
+ const checkResult = await this.check(constraint, context);
382
+ result.guidelines.push(checkResult);
383
+ this.recordTrace(traceCollector, constraint, checkResult, context);
970
384
 
971
- if (!checkResult.satisfied) {
972
- result.warningCount++;
385
+ if (!checkResult.satisfied) {
386
+ result.warningCount++;
387
+ }
973
388
  }
974
- }
975
389
 
976
- // 3. Tips: 仅记录
977
- for (const constraint of Object.values(constraints.tips)) {
978
- if (!this.matchesTrigger(constraint, context.operation)) continue;
390
+ // 3. Tips: 仅记录
391
+ for (const constraint of Object.values(constraints.tips)) {
392
+ if (!this.matchesTrigger(constraint, context.operation)) continue;
979
393
 
980
- const checkResult = await this.check(constraint, context);
981
- result.tips.push(checkResult);
982
- this.recordTrace(traceCollector, constraint, checkResult, context);
394
+ const checkResult = await this.check(constraint, context);
395
+ result.tips.push(checkResult);
396
+ this.recordTrace(traceCollector, constraint, checkResult, context);
983
397
 
984
- if (!checkResult.satisfied) {
985
- result.tipCount++;
398
+ if (!checkResult.satisfied) {
399
+ result.tipCount++;
400
+ }
986
401
  }
987
- }
988
402
 
989
- return result;
403
+ return result;
404
+ } finally {
405
+ this.runCache = null;
406
+ }
990
407
  }
991
408
 
992
409
  /**
@@ -999,43 +416,51 @@ export class ConstraintChecker {
999
416
  context: ConstraintContext,
1000
417
  customConfig?: MergedConstraintsConfig | null
1001
418
  ): Promise<ConstraintCheckResult> {
1002
- const result: ConstraintCheckResult = {
1003
- ironLaws: [],
1004
- guidelines: [],
1005
- tips: [],
1006
- passed: true,
1007
- warningCount: 0,
1008
- tipCount: 0,
1009
- };
419
+ // run 起始:重置 run 级缓存(工单 18)
420
+ this.cache.invalidate();
421
+ this.runCache = new Map();
1010
422
 
1011
- const traceCollector = getTraceCollector();
1012
- const constraints = this.getConstraints(customConfig);
423
+ try {
424
+ const result: ConstraintCheckResult = {
425
+ ironLaws: [],
426
+ guidelines: [],
427
+ tips: [],
428
+ passed: true,
429
+ warningCount: 0,
430
+ tipCount: 0,
431
+ };
1013
432
 
1014
- for (const constraint of Object.values(constraints.ironLaws)) {
1015
- if (!this.matchesTrigger(constraint, context.operation)) continue;
1016
- const checkResult = await this.check(constraint, context);
1017
- result.ironLaws.push(checkResult);
1018
- this.recordTrace(traceCollector, constraint, checkResult, context);
1019
- if (!checkResult.satisfied) result.passed = false;
1020
- }
433
+ const traceCollector = this.traceRecorder;
434
+ const constraints = this.getConstraints(customConfig);
1021
435
 
1022
- for (const constraint of Object.values(constraints.guidelines)) {
1023
- if (!this.matchesTrigger(constraint, context.operation)) continue;
1024
- const checkResult = await this.check(constraint, context);
1025
- result.guidelines.push(checkResult);
1026
- this.recordTrace(traceCollector, constraint, checkResult, context);
1027
- if (!checkResult.satisfied) result.warningCount++;
1028
- }
436
+ for (const constraint of Object.values(constraints.ironLaws)) {
437
+ if (!this.matchesTrigger(constraint, context.operation)) continue;
438
+ const checkResult = await this.check(constraint, context);
439
+ result.ironLaws.push(checkResult);
440
+ this.recordTrace(traceCollector, constraint, checkResult, context);
441
+ if (!checkResult.satisfied) result.passed = false;
442
+ }
1029
443
 
1030
- for (const constraint of Object.values(constraints.tips)) {
1031
- if (!this.matchesTrigger(constraint, context.operation)) continue;
1032
- const checkResult = await this.check(constraint, context);
1033
- result.tips.push(checkResult);
1034
- this.recordTrace(traceCollector, constraint, checkResult, context);
1035
- if (!checkResult.satisfied) result.tipCount++;
1036
- }
444
+ for (const constraint of Object.values(constraints.guidelines)) {
445
+ if (!this.matchesTrigger(constraint, context.operation)) continue;
446
+ const checkResult = await this.check(constraint, context);
447
+ result.guidelines.push(checkResult);
448
+ this.recordTrace(traceCollector, constraint, checkResult, context);
449
+ if (!checkResult.satisfied) result.warningCount++;
450
+ }
451
+
452
+ for (const constraint of Object.values(constraints.tips)) {
453
+ if (!this.matchesTrigger(constraint, context.operation)) continue;
454
+ const checkResult = await this.check(constraint, context);
455
+ result.tips.push(checkResult);
456
+ this.recordTrace(traceCollector, constraint, checkResult, context);
457
+ if (!checkResult.satisfied) result.tipCount++;
458
+ }
1037
459
 
1038
- return result;
460
+ return result;
461
+ } finally {
462
+ this.runCache = null;
463
+ }
1039
464
  }
1040
465
 
1041
466
  /**
@@ -1133,37 +558,3 @@ export async function checkBeforeExecution(
1133
558
 
1134
559
  // 导出单例
1135
560
  export const constraintChecker = ConstraintChecker.getInstance();
1136
-
1137
- // ========================================
1138
- // 向后兼容的类和函数
1139
- // ========================================
1140
-
1141
- /**
1142
- * @deprecated 使用 ConstraintChecker 代替
1143
- */
1144
- export const IronLawChecker = ConstraintChecker;
1145
-
1146
- /**
1147
- * @deprecated 使用 checkConstraint 代替
1148
- */
1149
- export async function checkIronLaw(
1150
- lawId: string,
1151
- context: ConstraintContext
1152
- ): Promise<ConstraintResult> {
1153
- return checkConstraint(lawId, context);
1154
- }
1155
-
1156
- /**
1157
- * @deprecated 使用 checkConstraints 代替
1158
- */
1159
- export async function checkAllIronLaws(
1160
- context: ConstraintContext
1161
- ): Promise<ConstraintResult[]> {
1162
- const result = await checkConstraints(context);
1163
- return [...result.ironLaws, ...result.guidelines, ...result.tips];
1164
- }
1165
-
1166
- /**
1167
- * @deprecated 使用 constraintChecker 代替
1168
- */
1169
- export const ironLawChecker = constraintChecker;