@dommaker/harness 0.16.9 → 0.17.1

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 (337) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +33 -32
  3. package/bin/harness.js +33 -20
  4. package/dist/cli/commands/check.d.ts +3 -2
  5. package/dist/cli/commands/check.d.ts.map +1 -1
  6. package/dist/cli/commands/check.js +69 -36
  7. package/dist/cli/commands/check.js.map +1 -1
  8. package/dist/cli/commands/constraints-report.d.ts +42 -0
  9. package/dist/cli/commands/constraints-report.d.ts.map +1 -0
  10. package/dist/cli/commands/constraints-report.js +233 -0
  11. package/dist/cli/commands/constraints-report.js.map +1 -0
  12. package/dist/cli/commands/constraints-retire.d.ts +71 -0
  13. package/dist/cli/commands/constraints-retire.d.ts.map +1 -0
  14. package/dist/cli/commands/constraints-retire.js +384 -0
  15. package/dist/cli/commands/constraints-retire.js.map +1 -0
  16. package/dist/cli/commands/constraints.d.ts +1 -1
  17. package/dist/cli/commands/constraints.d.ts.map +1 -1
  18. package/dist/cli/commands/constraints.js +4 -4
  19. package/dist/cli/commands/constraints.js.map +1 -1
  20. package/dist/cli/commands/index.d.ts +2 -1
  21. package/dist/cli/commands/index.d.ts.map +1 -1
  22. package/dist/cli/commands/index.js +10 -4
  23. package/dist/cli/commands/index.js.map +1 -1
  24. package/dist/cli/commands/init.d.ts +20 -0
  25. package/dist/cli/commands/init.d.ts.map +1 -1
  26. package/dist/cli/commands/init.js +81 -59
  27. package/dist/cli/commands/init.js.map +1 -1
  28. package/dist/cli/commands/report.js +4 -4
  29. package/dist/cli/commands/report.js.map +1 -1
  30. package/dist/cli/commands/status.d.ts.map +1 -1
  31. package/dist/cli/commands/status.js +3 -4
  32. package/dist/cli/commands/status.js.map +1 -1
  33. package/dist/cli/commands/sync-docs/capabilities-syncer.d.ts +5 -1
  34. package/dist/cli/commands/sync-docs/capabilities-syncer.d.ts.map +1 -1
  35. package/dist/cli/commands/sync-docs/capabilities-syncer.js +2 -10
  36. package/dist/cli/commands/sync-docs/capabilities-syncer.js.map +1 -1
  37. package/dist/cli/commands/validate.d.ts.map +1 -1
  38. package/dist/cli/commands/validate.js +1 -5
  39. package/dist/cli/commands/validate.js.map +1 -1
  40. package/dist/core/constraints/capabilities-parser.d.ts +7 -0
  41. package/dist/core/constraints/capabilities-parser.d.ts.map +1 -1
  42. package/dist/core/constraints/capabilities-parser.js +13 -0
  43. package/dist/core/constraints/capabilities-parser.js.map +1 -1
  44. package/dist/core/constraints/checker.d.ts +13 -5
  45. package/dist/core/constraints/checker.d.ts.map +1 -1
  46. package/dist/core/constraints/checker.js +62 -25
  47. package/dist/core/constraints/checker.js.map +1 -1
  48. package/dist/core/constraints/checkers/capability-sync.d.ts +9 -2
  49. package/dist/core/constraints/checkers/capability-sync.d.ts.map +1 -1
  50. package/dist/core/constraints/checkers/capability-sync.js +55 -22
  51. package/dist/core/constraints/checkers/capability-sync.js.map +1 -1
  52. package/dist/core/constraints/checkers/context-doc-sync.d.ts +3 -0
  53. package/dist/core/constraints/checkers/context-doc-sync.d.ts.map +1 -1
  54. package/dist/core/constraints/checkers/context-doc-sync.js +8 -2
  55. package/dist/core/constraints/checkers/context-doc-sync.js.map +1 -1
  56. package/dist/core/constraints/checkers/docs-freshness.d.ts +1 -0
  57. package/dist/core/constraints/checkers/docs-freshness.d.ts.map +1 -1
  58. package/dist/core/constraints/checkers/docs-freshness.js +39 -0
  59. package/dist/core/constraints/checkers/docs-freshness.js.map +1 -1
  60. package/dist/core/constraints/checkers/index.d.ts +8 -4
  61. package/dist/core/constraints/checkers/index.d.ts.map +1 -1
  62. package/dist/core/constraints/checkers/index.js +29 -46
  63. package/dist/core/constraints/checkers/index.js.map +1 -1
  64. package/dist/core/constraints/checkers/iron-flags.d.ts +6 -7
  65. package/dist/core/constraints/checkers/iron-flags.d.ts.map +1 -1
  66. package/dist/core/constraints/checkers/iron-flags.js +10 -17
  67. package/dist/core/constraints/checkers/iron-flags.js.map +1 -1
  68. package/dist/core/constraints/checkers/no-hardcoded-credentials.d.ts +13 -0
  69. package/dist/core/constraints/checkers/no-hardcoded-credentials.d.ts.map +1 -0
  70. package/dist/core/constraints/checkers/no-hardcoded-credentials.js +91 -0
  71. package/dist/core/constraints/checkers/no-hardcoded-credentials.js.map +1 -0
  72. package/dist/core/constraints/checkers/types.d.ts +15 -4
  73. package/dist/core/constraints/checkers/types.d.ts.map +1 -1
  74. package/dist/core/constraints/checkers/types.js +16 -4
  75. package/dist/core/constraints/checkers/types.js.map +1 -1
  76. package/dist/core/constraints/context-builder.d.ts +6 -3
  77. package/dist/core/constraints/context-builder.d.ts.map +1 -1
  78. package/dist/core/constraints/context-builder.js +29 -20
  79. package/dist/core/constraints/context-builder.js.map +1 -1
  80. package/dist/core/constraints/definitions/guidelines.d.ts +6 -2
  81. package/dist/core/constraints/definitions/guidelines.d.ts.map +1 -1
  82. package/dist/core/constraints/definitions/guidelines.js +29 -572
  83. package/dist/core/constraints/definitions/guidelines.js.map +1 -1
  84. package/dist/core/constraints/definitions/iron-laws.d.ts +6 -2
  85. package/dist/core/constraints/definitions/iron-laws.d.ts.map +1 -1
  86. package/dist/core/constraints/definitions/iron-laws.js +48 -231
  87. package/dist/core/constraints/definitions/iron-laws.js.map +1 -1
  88. package/dist/core/constraints/definitions/prompts.d.ts +12 -0
  89. package/dist/core/constraints/definitions/prompts.d.ts.map +1 -0
  90. package/dist/core/constraints/definitions/prompts.js +405 -0
  91. package/dist/core/constraints/definitions/prompts.js.map +1 -0
  92. package/dist/core/constraints/definitions.d.ts +15 -9
  93. package/dist/core/constraints/definitions.d.ts.map +1 -1
  94. package/dist/core/constraints/definitions.js +18 -12
  95. package/dist/core/constraints/definitions.js.map +1 -1
  96. package/dist/core/constraints/index.d.ts +3 -2
  97. package/dist/core/constraints/index.d.ts.map +1 -1
  98. package/dist/core/constraints/index.js +8 -2
  99. package/dist/core/constraints/index.js.map +1 -1
  100. package/dist/core/constraints/injection-drift.d.ts +48 -0
  101. package/dist/core/constraints/injection-drift.d.ts.map +1 -0
  102. package/dist/core/constraints/injection-drift.js +140 -0
  103. package/dist/core/constraints/injection-drift.js.map +1 -0
  104. package/dist/core/constraints/injection-renderer.d.ts +23 -0
  105. package/dist/core/constraints/injection-renderer.d.ts.map +1 -0
  106. package/dist/core/constraints/injection-renderer.js +44 -0
  107. package/dist/core/constraints/injection-renderer.js.map +1 -0
  108. package/dist/core/constraints/interceptor.d.ts.map +1 -1
  109. package/dist/core/constraints/interceptor.js +3 -2
  110. package/dist/core/constraints/interceptor.js.map +1 -1
  111. package/dist/core/constraints/usage-report.d.ts +95 -0
  112. package/dist/core/constraints/usage-report.d.ts.map +1 -0
  113. package/dist/core/constraints/usage-report.js +206 -0
  114. package/dist/core/constraints/usage-report.js.map +1 -0
  115. package/dist/core/effective-constraints.d.ts +47 -0
  116. package/dist/core/effective-constraints.d.ts.map +1 -0
  117. package/dist/core/effective-constraints.js +60 -0
  118. package/dist/core/effective-constraints.js.map +1 -0
  119. package/dist/core/index.d.ts +1 -0
  120. package/dist/core/index.d.ts.map +1 -1
  121. package/dist/core/index.js +2 -0
  122. package/dist/core/index.js.map +1 -1
  123. package/dist/core/project-config-loader.d.ts +17 -2
  124. package/dist/core/project-config-loader.d.ts.map +1 -1
  125. package/dist/core/project-config-loader.js +55 -8
  126. package/dist/core/project-config-loader.js.map +1 -1
  127. package/dist/dashboard/data.d.ts +1 -9
  128. package/dist/dashboard/data.d.ts.map +1 -1
  129. package/dist/dashboard/data.js +7 -15
  130. package/dist/dashboard/data.js.map +1 -1
  131. package/dist/dashboard/types.d.ts +13 -1
  132. package/dist/dashboard/types.d.ts.map +1 -1
  133. package/dist/index.d.ts +0 -4
  134. package/dist/index.d.ts.map +1 -1
  135. package/dist/index.js +1 -13
  136. package/dist/index.js.map +1 -1
  137. package/dist/monitoring/index.d.ts +0 -2
  138. package/dist/monitoring/index.d.ts.map +1 -1
  139. package/dist/monitoring/index.js +0 -2
  140. package/dist/monitoring/index.js.map +1 -1
  141. package/dist/monitoring/knowledge-evolver.d.ts +1 -1
  142. package/dist/monitoring/knowledge-evolver.js +1 -1
  143. package/dist/monitoring/trace-analyzer.d.ts +1 -1
  144. package/dist/monitoring/trace-analyzer.d.ts.map +1 -1
  145. package/dist/monitoring/trace-analyzer.js +16 -10
  146. package/dist/monitoring/trace-analyzer.js.map +1 -1
  147. package/dist/monitoring/traces.d.ts +2 -1
  148. package/dist/monitoring/traces.d.ts.map +1 -1
  149. package/dist/monitoring/traces.js +5 -3
  150. package/dist/monitoring/traces.js.map +1 -1
  151. package/dist/presets/standard.d.ts +3 -1
  152. package/dist/presets/standard.d.ts.map +1 -1
  153. package/dist/presets/standard.js +18 -8
  154. package/dist/presets/standard.js.map +1 -1
  155. package/dist/types/constraint.d.ts +51 -11
  156. package/dist/types/constraint.d.ts.map +1 -1
  157. package/dist/types/constraint.js +8 -4
  158. package/dist/types/constraint.js.map +1 -1
  159. package/dist/types/index.d.ts +1 -1
  160. package/dist/types/index.d.ts.map +1 -1
  161. package/dist/types/index.js.map +1 -1
  162. package/dist/types/monitoring-types.d.ts +2 -63
  163. package/dist/types/monitoring-types.d.ts.map +1 -1
  164. package/dist/types/monitoring-types.js +2 -2
  165. package/dist/types/project-config.d.ts +26 -1
  166. package/dist/types/project-config.d.ts.map +1 -1
  167. package/dist/types/trace.d.ts +16 -7
  168. package/dist/types/trace.d.ts.map +1 -1
  169. package/dist/types/trace.js +8 -0
  170. package/dist/types/trace.js.map +1 -1
  171. package/package.json +1 -1
  172. package/src/CONTEXT.md +2 -2
  173. package/src/__tests__/checker-extra.test.ts +228 -333
  174. package/src/__tests__/checker.test.ts +87 -724
  175. package/src/__tests__/constraint-doctor.test.ts +5 -5
  176. package/src/__tests__/doctor-extra.test.ts +164 -0
  177. package/src/__tests__/effective-constraints.test.ts +147 -0
  178. package/src/__tests__/extend-exceptions.test.ts +3 -3
  179. package/src/__tests__/iron-laws.test.ts +115 -91
  180. package/src/__tests__/no-hardcoded-credentials.test.ts +90 -0
  181. package/src/__tests__/presets.test.ts +7 -7
  182. package/src/__tests__/project-config-loader-extra.test.ts +41 -4
  183. package/src/__tests__/skip-semantics.test.ts +322 -0
  184. package/src/cli/commands/CONTEXT.md +5 -3
  185. package/src/cli/commands/__tests__/check-drift.test.ts +127 -0
  186. package/src/cli/commands/__tests__/check-skip-output.test.ts +128 -0
  187. package/src/cli/commands/__tests__/check.test.ts +14 -25
  188. package/src/cli/commands/__tests__/constraints-report.test.ts +327 -0
  189. package/src/cli/commands/__tests__/constraints-retire.test.ts +283 -0
  190. package/src/cli/commands/__tests__/init-injection.test.ts +234 -0
  191. package/src/cli/commands/__tests__/status-extra.test.ts +11 -11
  192. package/src/cli/commands/__tests__/status.test.ts +1 -1
  193. package/src/cli/commands/check.ts +72 -38
  194. package/src/cli/commands/constraints-report.ts +234 -0
  195. package/src/cli/commands/constraints-retire.ts +443 -0
  196. package/src/cli/commands/constraints.ts +5 -5
  197. package/src/cli/commands/index.ts +2 -1
  198. package/src/cli/commands/init.ts +94 -66
  199. package/src/cli/commands/report.ts +6 -6
  200. package/src/cli/commands/status.ts +3 -4
  201. package/src/cli/commands/sync-docs/capabilities-syncer.ts +5 -7
  202. package/src/cli/commands/validate.ts +1 -5
  203. package/src/core/CONTEXT.md +7 -4
  204. package/src/core/constraints/__tests__/injection-drift.test.ts +164 -0
  205. package/src/core/constraints/__tests__/interceptor.test.ts +4 -0
  206. package/src/core/constraints/capabilities-parser.ts +13 -0
  207. package/src/core/constraints/checker.ts +73 -28
  208. package/src/core/constraints/checkers/capability-sync.ts +72 -29
  209. package/src/core/constraints/checkers/context-doc-sync.ts +9 -2
  210. package/src/core/constraints/checkers/docs-freshness.ts +43 -0
  211. package/src/core/constraints/checkers/index.ts +38 -71
  212. package/src/core/constraints/checkers/iron-flags.ts +13 -49
  213. package/src/core/constraints/checkers/no-hardcoded-credentials.ts +93 -0
  214. package/src/core/constraints/checkers/types.ts +27 -5
  215. package/src/core/constraints/context-builder.ts +28 -19
  216. package/src/core/constraints/definitions/guidelines.ts +29 -597
  217. package/src/core/constraints/definitions/iron-laws.ts +48 -239
  218. package/src/core/constraints/definitions/prompts.ts +419 -0
  219. package/src/core/constraints/definitions.ts +18 -11
  220. package/src/core/constraints/index.ts +10 -1
  221. package/src/core/constraints/injection-drift.ts +139 -0
  222. package/src/core/constraints/injection-renderer.ts +44 -0
  223. package/src/core/constraints/interceptor.ts +3 -2
  224. package/src/core/constraints/usage-report.ts +254 -0
  225. package/src/core/effective-constraints.ts +85 -0
  226. package/src/core/index.ts +4 -1
  227. package/src/core/project-config-loader.ts +59 -9
  228. package/src/dashboard/__tests__/data.test.ts +5 -12
  229. package/src/dashboard/data.ts +9 -19
  230. package/src/dashboard/types.ts +18 -1
  231. package/src/index.ts +0 -12
  232. package/src/knowledge/CONTEXT.md +2 -2
  233. package/src/monitoring/CONTEXT.md +3 -4
  234. package/src/monitoring/index.ts +0 -2
  235. package/src/monitoring/knowledge-evolver.ts +1 -1
  236. package/src/monitoring/trace-analyzer.ts +15 -10
  237. package/src/monitoring/traces.ts +10 -6
  238. package/src/presets/__tests__/standard.test.ts +11 -9
  239. package/src/presets/standard.ts +24 -15
  240. package/src/types/constraint.ts +59 -14
  241. package/src/types/index.ts +1 -3
  242. package/src/types/monitoring-types.ts +2 -84
  243. package/src/types/project-config.ts +30 -1
  244. package/src/types/trace.ts +18 -7
  245. package/src/verification/CONTEXT.md +1 -1
  246. package/dist/cli/commands/flow.d.ts +0 -22
  247. package/dist/cli/commands/flow.d.ts.map +0 -1
  248. package/dist/cli/commands/flow.js +0 -275
  249. package/dist/cli/commands/flow.js.map +0 -1
  250. package/dist/constraints/lifecycle-runner.d.ts +0 -52
  251. package/dist/constraints/lifecycle-runner.d.ts.map +0 -1
  252. package/dist/constraints/lifecycle-runner.js +0 -151
  253. package/dist/constraints/lifecycle-runner.js.map +0 -1
  254. package/dist/constraints/registry.d.ts +0 -27
  255. package/dist/constraints/registry.d.ts.map +0 -1
  256. package/dist/constraints/registry.js +0 -128
  257. package/dist/constraints/registry.js.map +0 -1
  258. package/dist/constraints/types.d.ts +0 -53
  259. package/dist/constraints/types.d.ts.map +0 -1
  260. package/dist/constraints/types.js +0 -8
  261. package/dist/constraints/types.js.map +0 -1
  262. package/dist/core/constraints/checkers/always-pass.d.ts +0 -17
  263. package/dist/core/constraints/checkers/always-pass.d.ts.map +0 -1
  264. package/dist/core/constraints/checkers/always-pass.js +0 -23
  265. package/dist/core/constraints/checkers/always-pass.js.map +0 -1
  266. package/dist/core/constraints/checkers/guideline-flags.d.ts +0 -9
  267. package/dist/core/constraints/checkers/guideline-flags.d.ts.map +0 -1
  268. package/dist/core/constraints/checkers/guideline-flags.js +0 -13
  269. package/dist/core/constraints/checkers/guideline-flags.js.map +0 -1
  270. package/dist/core/constraints/checkers/no-any-type.d.ts +0 -6
  271. package/dist/core/constraints/checkers/no-any-type.d.ts.map +0 -1
  272. package/dist/core/constraints/checkers/no-any-type.js +0 -42
  273. package/dist/core/constraints/checkers/no-any-type.js.map +0 -1
  274. package/dist/core/constraints/checkers/no-excuse-patterns.d.ts +0 -6
  275. package/dist/core/constraints/checkers/no-excuse-patterns.d.ts.map +0 -1
  276. package/dist/core/constraints/checkers/no-excuse-patterns.js +0 -25
  277. package/dist/core/constraints/checkers/no-excuse-patterns.js.map +0 -1
  278. package/dist/core/constraints/checkers/no-fuzzy-completion-claim.d.ts +0 -6
  279. package/dist/core/constraints/checkers/no-fuzzy-completion-claim.d.ts.map +0 -1
  280. package/dist/core/constraints/checkers/no-fuzzy-completion-claim.js +0 -34
  281. package/dist/core/constraints/checkers/no-fuzzy-completion-claim.js.map +0 -1
  282. package/dist/core/constraints/checkers/no-performative-agreement.d.ts +0 -8
  283. package/dist/core/constraints/checkers/no-performative-agreement.d.ts.map +0 -1
  284. package/dist/core/constraints/checkers/no-performative-agreement.js +0 -23
  285. package/dist/core/constraints/checkers/no-performative-agreement.js.map +0 -1
  286. package/dist/core/constraints/checkers/no-simplification-without-approval.d.ts +0 -6
  287. package/dist/core/constraints/checkers/no-simplification-without-approval.d.ts.map +0 -1
  288. package/dist/core/constraints/checkers/no-simplification-without-approval.js +0 -30
  289. package/dist/core/constraints/checkers/no-simplification-without-approval.js.map +0 -1
  290. package/dist/core/constraints/checkers/test-coverage.d.ts +0 -6
  291. package/dist/core/constraints/checkers/test-coverage.d.ts.map +0 -1
  292. package/dist/core/constraints/checkers/test-coverage.js +0 -33
  293. package/dist/core/constraints/checkers/test-coverage.js.map +0 -1
  294. package/dist/core/constraints/checkers/yagni.d.ts +0 -8
  295. package/dist/core/constraints/checkers/yagni.d.ts.map +0 -1
  296. package/dist/core/constraints/checkers/yagni.js +0 -96
  297. package/dist/core/constraints/checkers/yagni.js.map +0 -1
  298. package/dist/core/constraints/definitions/tips.d.ts +0 -7
  299. package/dist/core/constraints/definitions/tips.d.ts.map +0 -1
  300. package/dist/core/constraints/definitions/tips.js +0 -62
  301. package/dist/core/constraints/definitions/tips.js.map +0 -1
  302. package/dist/evolution/auto-evolve.d.ts +0 -35
  303. package/dist/evolution/auto-evolve.d.ts.map +0 -1
  304. package/dist/evolution/auto-evolve.js +0 -64
  305. package/dist/evolution/auto-evolve.js.map +0 -1
  306. package/dist/evolution/index.d.ts +0 -2
  307. package/dist/evolution/index.d.ts.map +0 -1
  308. package/dist/evolution/index.js +0 -18
  309. package/dist/evolution/index.js.map +0 -1
  310. package/dist/monitoring/constraint-evolver.d.ts +0 -120
  311. package/dist/monitoring/constraint-evolver.d.ts.map +0 -1
  312. package/dist/monitoring/constraint-evolver.js +0 -410
  313. package/dist/monitoring/constraint-evolver.js.map +0 -1
  314. package/src/__tests__/constraint-evolver.test.ts +0 -405
  315. package/src/__tests__/doctor-evolver.test.ts +0 -381
  316. package/src/cli/commands/__tests__/flow.test.ts +0 -343
  317. package/src/cli/commands/flow.ts +0 -277
  318. package/src/constraints/__tests__/lifecycle-runner.test.ts +0 -246
  319. package/src/constraints/__tests__/registry.test.ts +0 -196
  320. package/src/constraints/lifecycle-runner.ts +0 -184
  321. package/src/constraints/registry.ts +0 -134
  322. package/src/constraints/types.ts +0 -59
  323. package/src/core/constraints/checkers/always-pass.ts +0 -22
  324. package/src/core/constraints/checkers/guideline-flags.ts +0 -30
  325. package/src/core/constraints/checkers/no-any-type.ts +0 -42
  326. package/src/core/constraints/checkers/no-excuse-patterns.ts +0 -24
  327. package/src/core/constraints/checkers/no-fuzzy-completion-claim.ts +0 -33
  328. package/src/core/constraints/checkers/no-performative-agreement.ts +0 -22
  329. package/src/core/constraints/checkers/no-simplification-without-approval.ts +0 -29
  330. package/src/core/constraints/checkers/test-coverage.ts +0 -35
  331. package/src/core/constraints/checkers/yagni.ts +0 -65
  332. package/src/core/constraints/definitions/tips.ts +0 -63
  333. package/src/evolution/CONTEXT.md +0 -22
  334. package/src/evolution/__tests__/auto-evolve.test.ts +0 -319
  335. package/src/evolution/auto-evolve.ts +0 -98
  336. package/src/evolution/index.ts +0 -1
  337. package/src/monitoring/constraint-evolver.ts +0 -501
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * harness check 命令
3
3
  *
4
- * 检查约束是否满足(三层:Iron Laws / Guidelines / Tips)
5
- * 工单 23:触发条件与证据检测迁至 core/constraints/context-builder;--preset 接入 applyPreset
4
+ * 检查约束是否满足(check 层:Iron Laws / Guidelines;prompt 层仅注入不检查)
5
+ * 工单 23:触发条件与证据检测迁至 core/constraints/context-builder;--preset mergeConstraints 生效
6
+ * ADR-0001:约束集统一走 mergeConstraints 生效集链路(preset/config 禁用/custom/scenes)
6
7
  */
7
8
 
8
9
  import chalk from 'chalk';
@@ -10,10 +11,11 @@ import * as fs from 'fs';
10
11
  import * as path from 'path';
11
12
  import { constraintChecker } from '../../core/constraints/checker';
12
13
  import { getTraceCollector } from '../../monitoring/traces';
13
- import { IRON_LAWS, GUIDELINES, TIPS } from '../../core/constraints/definitions';
14
+ import { IRON_LAWS, GUIDELINES, PROMPTS } from '../../core/constraints/definitions';
14
15
  import { ProjectConfigLoader } from '../../core/project-config-loader';
15
16
  import { buildConstraintContext } from '../../core/constraints/context-builder';
16
- import { applyPreset } from '../../presets';
17
+ import { detectInjectionDrift } from '../../core/constraints/injection-drift';
18
+ import { DEFAULT_TRACE_FILE } from '../../types/trace';
17
19
  import type { ConstraintTrigger } from '../../types/constraint';
18
20
 
19
21
  export interface CheckOptions {
@@ -41,13 +43,22 @@ export async function check(options: CheckOptions): Promise<void> {
41
43
  configLoader.load();
42
44
  constraintChecker.setTraceRecorder(getTraceCollector());
43
45
 
44
- if (configLoader.hasCustomConfig()) {
45
- const merged = configLoader.mergeConstraints();
46
- constraintChecker.setCustomConfig(merged);
46
+ // 生效约束集(ADR-0001):内置 → preset → config.yml 禁用 → custom 追加 → scenes 过滤。
47
+ // --preset 仅在没有项目自定义配置时覆盖 config.yml 的 preset(保持工单 23 语义:
48
+ // 项目自定义配置优先于 CLI 预设)。
49
+ const merged = configLoader.hasCustomConfig()
50
+ ? configLoader.mergeConstraints()
51
+ : configLoader.mergeConstraints({ preset: options.preset || 'standard' });
52
+ constraintChecker.setCustomConfig(merged);
53
+ if (merged.custom.length > 0) {
47
54
  console.log(chalk.gray(`自定义约束: ${merged.custom.length} 条`));
48
- if (merged.disabled.length > 0) {
49
- console.log(chalk.gray(`已禁用约束: ${merged.disabled.join(', ')}`));
50
- }
55
+ }
56
+ if (merged.disabled.length > 0) {
57
+ console.log(chalk.gray(`已禁用约束: ${merged.disabled.join(', ')}`));
58
+ }
59
+ const unknownIds = merged.unknownIds ?? [];
60
+ if (unknownIds.length > 0) {
61
+ console.log(chalk.yellow(`⚠️ 配置中存在未知约束 id(已忽略,可清理): ${unknownIds.join(', ')}`));
51
62
  }
52
63
 
53
64
  // 构建上下文(工单 23:触发条件与证据检测收敛至 core/constraints/context-builder)
@@ -60,28 +71,26 @@ export async function check(options: CheckOptions): Promise<void> {
60
71
  if (changedFiles.length > 0) {
61
72
  console.log(chalk.gray(`变更文件: ${changedFiles.length} 个`));
62
73
  }
63
- console.log(chalk.gray(`触发条件: ${context.operation}`));
64
-
65
- // 预设(工单 23:--preset 真正生效;项目自定义配置优先于预设)
66
- let presetConfig;
67
- if (!configLoader.hasCustomConfig()) {
68
- try {
69
- presetConfig = applyPreset(options.preset || 'standard');
70
- } catch {
71
- presetConfig = undefined; // 未知预设名回退内置全集
72
- }
73
- }
74
+ console.log(chalk.gray(`触发条件: ${[context.operation, ...(context.extraTriggers ?? [])].join(', ')}`));
74
75
 
75
76
  // 执行三层检查
76
- const result = await constraintChecker.checkConstraints(context, presetConfig);
77
+ const result = await constraintChecker.checkConstraints(context);
77
78
 
78
79
  // 输出结果
79
80
  console.log();
80
81
 
82
+ // skipped(约定未采用/证据未接线)单独列示,不进 pass/fail 统计(ADR-0001)
83
+ const skippedResults = [
84
+ ...result.ironLaws,
85
+ ...result.guidelines,
86
+ ...result.tips,
87
+ ].filter(r => r.skipped);
88
+
81
89
  // Iron Laws
82
- const ironLawViolations = result.ironLaws.filter(r => !r.satisfied);
83
- if (ironLawViolations.length === 0 && result.ironLaws.length > 0) {
84
- console.log(chalk.green(`✅ 铁律: 全部通过 (${result.ironLaws.length} )`));
90
+ const evaluatedIronLaws = result.ironLaws.filter(r => !r.skipped);
91
+ const ironLawViolations = evaluatedIronLaws.filter(r => !r.satisfied);
92
+ if (ironLawViolations.length === 0 && evaluatedIronLaws.length > 0) {
93
+ console.log(chalk.green(`✅ 铁律: 全部通过 (${evaluatedIronLaws.length} 条)`));
85
94
  } else if (ironLawViolations.length > 0) {
86
95
  console.log(chalk.red(`❌ 铁律违规: ${ironLawViolations.length} 条`));
87
96
  ironLawViolations.forEach(r => {
@@ -104,8 +113,9 @@ export async function check(options: CheckOptions): Promise<void> {
104
113
  }
105
114
  });
106
115
  } else if (result.guidelines.length > 0) {
107
- const passedGuidelines = result.guidelines.filter(r => r.satisfied).length;
108
- console.log(chalk.green(`✅ 指导原则: ${passedGuidelines}/${result.guidelines.length} 通过`));
116
+ const evaluatedGuidelines = result.guidelines.filter(r => !r.skipped);
117
+ const passedGuidelines = evaluatedGuidelines.filter(r => r.satisfied).length;
118
+ console.log(chalk.green(`✅ 指导原则: ${passedGuidelines}/${evaluatedGuidelines.length} 通过`));
109
119
  }
110
120
 
111
121
  // Tips
@@ -118,6 +128,36 @@ export async function check(options: CheckOptions): Promise<void> {
118
128
  });
119
129
  }
120
130
 
131
+ // Skipped:约定未采用 / 证据未接线,未评估(不计通过/失败)
132
+ if (skippedResults.length > 0) {
133
+ console.log(chalk.gray(`⏭️ 跳过评估: ${skippedResults.length} 条(约定未采用或证据未接线,不计通过/失败)`));
134
+ skippedResults.forEach(r => {
135
+ console.log(chalk.gray(` - ${r.id}`));
136
+ });
137
+ }
138
+
139
+ // 注入漂移校验(ADR-0001 决策 7):黄色警告块,不改 exit code、不影响门禁结果。
140
+ // 无漂移/未注入零输出;漂移检测自身异常静默吞掉,绝不影响 check。
141
+ try {
142
+ const drift = detectInjectionDrift(projectPath);
143
+ if (drift.hasDrift) {
144
+ console.log();
145
+ console.log(chalk.yellow('⚠️ 检测到 CLAUDE.md 约束注入漂移(仅警告,不阻断):'));
146
+ if (drift.versionDrift) {
147
+ console.log(chalk.yellow(` ⚠️⚠️ 注入段版本 (${drift.versionDrift.actual}) ≠ 已安装 harness 版本 (${drift.versionDrift.expected}):agent 上下文中的规则与已安装 harness 版本不一致`));
148
+ }
149
+ if (drift.contentDrift) {
150
+ console.log(chalk.yellow(` 内容漂移: 缺失 ${drift.contentDrift.missing.length} 条 / 多余 ${drift.contentDrift.extra.length} 条(条目级差异见 harness constraints report)`));
151
+ }
152
+ if (drift.duplicateHeading) {
153
+ console.log(chalk.yellow(' 检测到重复的 "## Governance Rules" 章节'));
154
+ }
155
+ console.log(chalk.yellow(` 修复: ${drift.fixHint}`));
156
+ }
157
+ } catch {
158
+ // 漂移检测失败不影响 check 结果
159
+ }
160
+
121
161
  console.log();
122
162
  console.log(chalk.green('✅ 约束检查通过'));
123
163
 
@@ -140,7 +180,7 @@ export async function check(options: CheckOptions): Promise<void> {
140
180
  * 智能提示:检查是否需要提示用户下一步操作
141
181
  */
142
182
  async function getSmartHint(projectPath: string): Promise<string | null> {
143
- const tracesPath = path.join(projectPath, '.harness', 'traces', 'execution.log');
183
+ const tracesPath = path.join(projectPath, DEFAULT_TRACE_FILE);
144
184
  const statePath = path.join(projectPath, '.harness', '.state.json');
145
185
 
146
186
  // 检查 trace 文件是否存在
@@ -172,13 +212,7 @@ async function getSmartHint(projectPath: string): Promise<string | null> {
172
212
  state.shownHints.push('trace_50');
173
213
  }
174
214
 
175
- // 条件 2: 记录数达到 100 且从未运行过诊断
176
- if (traceCount >= 100 && !state.lastDiagnoseRun && !state.shownHints.includes('flow_suggest')) {
177
- hints.push('💡 数据充足,建议运行 harness flow 查看诊断');
178
- state.shownHints.push('flow_suggest');
179
- }
180
-
181
- // 条件 3: 检查异常趋势(简单检查绕过率)
215
+ // 条件 2: 检查异常趋势(简单检查绕过率)
182
216
  const bypassCount = lines.filter(line => {
183
217
  try {
184
218
  const trace = JSON.parse(line);
@@ -231,9 +265,9 @@ export function listLaws(): void {
231
265
  console.log();
232
266
  });
233
267
 
234
- // Tips
235
- console.log(chalk.blue('🔵 提示 (Tips) - 信息性,可忽略:\n'));
236
- Object.values(TIPS).forEach(constraint => {
268
+ // Prompts(ADR-0001:纯注入层,不执行检查)
269
+ console.log(chalk.blue('🔵 提示 (Prompts) - 纯文本注入,不参与检查:\n'));
270
+ Object.values(PROMPTS).forEach(constraint => {
237
271
  console.log(chalk.blue(` ${constraint.id}`));
238
272
  console.log(chalk.gray(` ${constraint.rule}`));
239
273
  console.log(chalk.gray(` ${constraint.message}`));
@@ -0,0 +1,234 @@
1
+ /**
2
+ * harness constraints report —— 约束使用报告(ADR-0001 决策 3/4)
3
+ *
4
+ * 只读。面向"人审约束"场景:
5
+ * - check 层统计表(total/pass/fail/skip、fail 率、首次/最近触发)
6
+ * - 退役候选诊断(零触发/零拦截/不可评估/高噪),retire 交互模式的数据源
7
+ * - 当前生效 prompt 注入清单
8
+ * - 配置健康(unknownIds 残留提示)
9
+ * - --export [file]:脱敏 markdown 摘要(不含项目路径)
10
+ */
11
+
12
+ import * as fs from 'fs';
13
+ import * as path from 'path';
14
+ import chalk from 'chalk';
15
+ import {
16
+ buildConstraintsUsageReport,
17
+ DEFAULT_DIAGNOSE_THRESHOLDS,
18
+ type ConstraintsUsageReport,
19
+ type ConstraintUsageStats,
20
+ type DiagnoseThresholds,
21
+ type RetireCandidate,
22
+ } from '../../core/constraints/usage-report';
23
+ import { getConstraintsMeta } from './constraints';
24
+ import { detectInjectionDrift, type InjectionDrift } from '../../core/constraints/injection-drift';
25
+
26
+ export interface ConstraintsReportOptions {
27
+ projectPath?: string;
28
+ /** --export [file]:true = 默认路径;string = 指定文件 */
29
+ export?: boolean | string;
30
+ json?: boolean;
31
+ /** 零拦截候选的最小评估样本数 */
32
+ zeroInterceptMin?: number;
33
+ /** 高噪候选 fail 率阈值 */
34
+ noiseFailRate?: number;
35
+ /** 高噪候选最小评估样本数 */
36
+ noiseMinTotal?: number;
37
+ }
38
+
39
+ const CANDIDATE_KIND_LABEL: Record<RetireCandidate['kind'], string> = {
40
+ zero_trigger: '零触发',
41
+ unevaluable: '不可评估',
42
+ high_noise: '高噪',
43
+ zero_intercept: '零拦截',
44
+ };
45
+
46
+ function formatTime(ts: number | undefined): string {
47
+ return ts === undefined ? '-' : new Date(ts).toISOString().slice(0, 10);
48
+ }
49
+
50
+ function formatPct(rate: number): string {
51
+ return `${Math.round(rate * 100)}%`;
52
+ }
53
+
54
+ /**
55
+ * 渲染统计表(纯文本行,供 console 与 export 共用单行内容)
56
+ */
57
+ function renderStatsRow(s: ConstraintUsageStats): string {
58
+ return `${s.id} total=${s.total} pass=${s.pass} fail=${s.fail} skip=${s.skip} fail率=${formatPct(s.failRate)} 首次=${formatTime(s.firstAt)} 最近=${formatTime(s.lastAt)}`;
59
+ }
60
+
61
+ /**
62
+ * 渲染脱敏 markdown 摘要(ADR-0001 决策 4)
63
+ *
64
+ * 脱敏约束:不含 projectPath 等本地敏感信息;
65
+ * 内容为 harness 版本、日期、统计表、候选清单、配置健康。
66
+ */
67
+ export function renderExportMarkdown(
68
+ report: ConstraintsUsageReport,
69
+ version: string,
70
+ now: Date = new Date()
71
+ ): string {
72
+ const lines: string[] = [];
73
+ lines.push('# Harness Constraints Report');
74
+ lines.push('');
75
+ lines.push(`- harness 版本: ${version}`);
76
+ lines.push(`- 日期: ${now.toISOString().slice(0, 10)}`);
77
+ lines.push('');
78
+
79
+ lines.push('## 统计表(check 层)');
80
+ lines.push('');
81
+ lines.push('| id | total | pass | fail | skip | fail 率 | 首次触发 | 最近触发 |');
82
+ lines.push('| --- | ---: | ---: | ---: | ---: | ---: | --- | --- |');
83
+ for (const s of report.stats) {
84
+ lines.push(
85
+ `| ${s.id} | ${s.total} | ${s.pass} | ${s.fail} | ${s.skip} | ${formatPct(s.failRate)} | ${formatTime(s.firstAt)} | ${formatTime(s.lastAt)} |`
86
+ );
87
+ }
88
+ lines.push('');
89
+
90
+ lines.push('## 退役候选');
91
+ lines.push('');
92
+ if (report.candidates.length === 0) {
93
+ lines.push('(无候选)');
94
+ } else {
95
+ for (const c of report.candidates) {
96
+ lines.push(`- [${CANDIDATE_KIND_LABEL[c.kind]}] \`${c.id}\` — ${c.reason}`);
97
+ }
98
+ }
99
+ lines.push('');
100
+
101
+ if (report.lint.unknownIds.length > 0) {
102
+ lines.push('## 配置健康');
103
+ lines.push('');
104
+ for (const id of report.lint.unknownIds) {
105
+ lines.push(`- config.yml 中禁用了不存在/已移除的约束 id: \`${id}\``);
106
+ }
107
+ lines.push('');
108
+ }
109
+
110
+ return lines.join('\n');
111
+ }
112
+
113
+ /**
114
+ * 渲染"注入漂移"小节的文本行(ADR-0001 决策 7:详细条目级差异进 report)
115
+ *
116
+ * 返回纯文本行数组(不含 chalk 着色),调用方逐行 console.log。
117
+ */
118
+ export function renderInjectionDriftLines(drift: InjectionDrift): string[] {
119
+ const lines: string[] = [];
120
+ if (drift.notInjected) {
121
+ lines.push(' CLAUDE.md 无约束注入标记段(未注入,不算漂移);可运行 npx harness init 注入');
122
+ if (drift.duplicateHeading) {
123
+ lines.push(' 另检测到多个 "## Governance Rules" 标题(历史遗留重复章节),建议手工清理后重跑 npx harness init');
124
+ }
125
+ return lines;
126
+ }
127
+ if (!drift.hasDrift) {
128
+ lines.push(' 无漂移');
129
+ return lines;
130
+ }
131
+ if (drift.versionDrift) {
132
+ lines.push(` 版本漂移: 注入段版本 (${drift.versionDrift.actual}) ≠ 当前 harness 版本 (${drift.versionDrift.expected})`);
133
+ }
134
+ if (drift.contentDrift) {
135
+ lines.push(' 内容漂移(条目级差异):');
136
+ for (const l of drift.contentDrift.missing) {
137
+ lines.push(` 缺失: ${l}`);
138
+ }
139
+ for (const l of drift.contentDrift.extra) {
140
+ lines.push(` 多余: ${l}`);
141
+ }
142
+ }
143
+ if (drift.duplicateHeading) {
144
+ lines.push(' 重复章节: 标记段之外还存在另一个 "## Governance Rules" 标题');
145
+ }
146
+ lines.push(` 修复: ${drift.fixHint}`);
147
+ return lines;
148
+ }
149
+
150
+ /**
151
+ * CLI handler: harness constraints report
152
+ */
153
+ export async function constraintsReport(options: ConstraintsReportOptions = {}): Promise<void> {
154
+ const projectRoot = options.projectPath || process.cwd();
155
+ const thresholds: Partial<DiagnoseThresholds> = {};
156
+ if (options.zeroInterceptMin !== undefined) thresholds.zeroInterceptMinEvaluated = options.zeroInterceptMin;
157
+ if (options.noiseFailRate !== undefined) thresholds.highNoiseFailRate = options.noiseFailRate;
158
+ if (options.noiseMinTotal !== undefined) thresholds.highNoiseMinEvaluated = options.noiseMinTotal;
159
+
160
+ const report = buildConstraintsUsageReport(projectRoot, thresholds);
161
+
162
+ if (options.json) {
163
+ console.log(JSON.stringify(report, null, 2));
164
+ return;
165
+ }
166
+
167
+ console.log(chalk.blue('📊 约束使用报告'));
168
+ if (!report.traceFileExists) {
169
+ console.log(chalk.gray(' (trace 文件不存在,全部按零触发统计)'));
170
+ }
171
+ console.log();
172
+
173
+ // 统计表
174
+ console.log(chalk.bold('统计表(check 层):'));
175
+ for (const s of report.stats) {
176
+ console.log(` ${renderStatsRow(s)}`);
177
+ }
178
+ console.log();
179
+
180
+ // 候选诊断
181
+ console.log(chalk.bold(`退役候选(${report.candidates.length} 条,阈值: 零拦截≥${thresholds.zeroInterceptMinEvaluated ?? DEFAULT_DIAGNOSE_THRESHOLDS.zeroInterceptMinEvaluated} 次评估, 高噪 fail率>${Math.round((thresholds.highNoiseFailRate ?? DEFAULT_DIAGNOSE_THRESHOLDS.highNoiseFailRate) * 100)}% 且 ≥${thresholds.highNoiseMinEvaluated ?? DEFAULT_DIAGNOSE_THRESHOLDS.highNoiseMinEvaluated} 次评估):`));
182
+ if (report.candidates.length === 0) {
183
+ console.log(chalk.green(' (无候选)'));
184
+ } else {
185
+ for (const c of report.candidates) {
186
+ console.log(` [${CANDIDATE_KIND_LABEL[c.kind]}] ${c.id} — ${c.reason}`);
187
+ }
188
+ console.log(chalk.gray(' 可运行 `harness constraints retire` 交互式处理候选'));
189
+ }
190
+ console.log();
191
+
192
+ // 注入清单
193
+ console.log(chalk.bold(`当前生效 prompt 注入(${report.activePromptIds.length} 条):`));
194
+ for (const id of report.activePromptIds) {
195
+ console.log(` ${id}`);
196
+ }
197
+ console.log();
198
+
199
+ // 配置健康
200
+ if (report.lint.unknownIds.length > 0) {
201
+ console.log(chalk.yellow('⚠️ 配置健康:'));
202
+ for (const id of report.lint.unknownIds) {
203
+ console.log(chalk.yellow(` config.yml 中禁用了不存在/已移除的约束 id: ${id}(残留配置,建议清理)`));
204
+ }
205
+ console.log();
206
+ }
207
+
208
+ // 注入漂移(ADR-0001 决策 7:条目级差异 + 修复指引;--export 摘要不含本地漂移状态)
209
+ console.log(chalk.bold('注入漂移:'));
210
+ const drift = detectInjectionDrift(projectRoot);
211
+ for (const line of renderInjectionDriftLines(drift)) {
212
+ console.log(drift.hasDrift ? chalk.yellow(line) : line);
213
+ }
214
+ console.log();
215
+
216
+ // --export
217
+ if (options.export !== undefined && options.export !== false) {
218
+ const version = getConstraintsMeta().version;
219
+ const now = new Date();
220
+ const markdown = renderExportMarkdown(report, version, now);
221
+
222
+ let exportPath: string;
223
+ if (typeof options.export === 'string' && options.export.length > 0) {
224
+ exportPath = path.isAbsolute(options.export) ? options.export : path.join(projectRoot, options.export);
225
+ } else {
226
+ const date = now.toISOString().slice(0, 10).replace(/-/g, '');
227
+ exportPath = path.join(projectRoot, '.harness', 'reports', `constraints-${date}.md`);
228
+ }
229
+
230
+ fs.mkdirSync(path.dirname(exportPath), { recursive: true });
231
+ fs.writeFileSync(exportPath, markdown, 'utf-8');
232
+ console.log(chalk.green(`✅ 脱敏报告已导出: ${exportPath}`));
233
+ }
234
+ }