@dommaker/harness 0.16.8 → 0.17.0

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 (344) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +33 -32
  3. package/bin/harness.js +34 -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 +19 -2
  34. package/dist/cli/commands/sync-docs/capabilities-syncer.d.ts.map +1 -1
  35. package/dist/cli/commands/sync-docs/capabilities-syncer.js +79 -19
  36. package/dist/cli/commands/sync-docs/capabilities-syncer.js.map +1 -1
  37. package/dist/cli/commands/sync-docs/index.d.ts +2 -0
  38. package/dist/cli/commands/sync-docs/index.d.ts.map +1 -1
  39. package/dist/cli/commands/sync-docs/index.js +83 -20
  40. package/dist/cli/commands/sync-docs/index.js.map +1 -1
  41. package/dist/cli/commands/validate.d.ts.map +1 -1
  42. package/dist/cli/commands/validate.js +1 -5
  43. package/dist/cli/commands/validate.js.map +1 -1
  44. package/dist/core/constraints/capabilities-parser.d.ts +14 -0
  45. package/dist/core/constraints/capabilities-parser.d.ts.map +1 -1
  46. package/dist/core/constraints/capabilities-parser.js +30 -0
  47. package/dist/core/constraints/capabilities-parser.js.map +1 -1
  48. package/dist/core/constraints/checker.d.ts +13 -5
  49. package/dist/core/constraints/checker.d.ts.map +1 -1
  50. package/dist/core/constraints/checker.js +62 -25
  51. package/dist/core/constraints/checker.js.map +1 -1
  52. package/dist/core/constraints/checkers/capability-sync.d.ts +10 -0
  53. package/dist/core/constraints/checkers/capability-sync.d.ts.map +1 -1
  54. package/dist/core/constraints/checkers/capability-sync.js +73 -11
  55. package/dist/core/constraints/checkers/capability-sync.js.map +1 -1
  56. package/dist/core/constraints/checkers/context-doc-sync.d.ts +3 -0
  57. package/dist/core/constraints/checkers/context-doc-sync.d.ts.map +1 -1
  58. package/dist/core/constraints/checkers/context-doc-sync.js +8 -2
  59. package/dist/core/constraints/checkers/context-doc-sync.js.map +1 -1
  60. package/dist/core/constraints/checkers/docs-freshness.d.ts +1 -0
  61. package/dist/core/constraints/checkers/docs-freshness.d.ts.map +1 -1
  62. package/dist/core/constraints/checkers/docs-freshness.js +39 -0
  63. package/dist/core/constraints/checkers/docs-freshness.js.map +1 -1
  64. package/dist/core/constraints/checkers/index.d.ts +8 -4
  65. package/dist/core/constraints/checkers/index.d.ts.map +1 -1
  66. package/dist/core/constraints/checkers/index.js +29 -46
  67. package/dist/core/constraints/checkers/index.js.map +1 -1
  68. package/dist/core/constraints/checkers/iron-flags.d.ts +6 -7
  69. package/dist/core/constraints/checkers/iron-flags.d.ts.map +1 -1
  70. package/dist/core/constraints/checkers/iron-flags.js +10 -17
  71. package/dist/core/constraints/checkers/iron-flags.js.map +1 -1
  72. package/dist/core/constraints/checkers/no-hardcoded-credentials.d.ts +13 -0
  73. package/dist/core/constraints/checkers/no-hardcoded-credentials.d.ts.map +1 -0
  74. package/dist/core/constraints/checkers/no-hardcoded-credentials.js +91 -0
  75. package/dist/core/constraints/checkers/no-hardcoded-credentials.js.map +1 -0
  76. package/dist/core/constraints/checkers/types.d.ts +15 -4
  77. package/dist/core/constraints/checkers/types.d.ts.map +1 -1
  78. package/dist/core/constraints/checkers/types.js +16 -4
  79. package/dist/core/constraints/checkers/types.js.map +1 -1
  80. package/dist/core/constraints/context-builder.d.ts +6 -3
  81. package/dist/core/constraints/context-builder.d.ts.map +1 -1
  82. package/dist/core/constraints/context-builder.js +29 -20
  83. package/dist/core/constraints/context-builder.js.map +1 -1
  84. package/dist/core/constraints/definitions/guidelines.d.ts +6 -2
  85. package/dist/core/constraints/definitions/guidelines.d.ts.map +1 -1
  86. package/dist/core/constraints/definitions/guidelines.js +33 -574
  87. package/dist/core/constraints/definitions/guidelines.js.map +1 -1
  88. package/dist/core/constraints/definitions/iron-laws.d.ts +6 -2
  89. package/dist/core/constraints/definitions/iron-laws.d.ts.map +1 -1
  90. package/dist/core/constraints/definitions/iron-laws.js +48 -231
  91. package/dist/core/constraints/definitions/iron-laws.js.map +1 -1
  92. package/dist/core/constraints/definitions/prompts.d.ts +12 -0
  93. package/dist/core/constraints/definitions/prompts.d.ts.map +1 -0
  94. package/dist/core/constraints/definitions/prompts.js +405 -0
  95. package/dist/core/constraints/definitions/prompts.js.map +1 -0
  96. package/dist/core/constraints/definitions.d.ts +15 -9
  97. package/dist/core/constraints/definitions.d.ts.map +1 -1
  98. package/dist/core/constraints/definitions.js +18 -12
  99. package/dist/core/constraints/definitions.js.map +1 -1
  100. package/dist/core/constraints/index.d.ts +3 -2
  101. package/dist/core/constraints/index.d.ts.map +1 -1
  102. package/dist/core/constraints/index.js +8 -2
  103. package/dist/core/constraints/index.js.map +1 -1
  104. package/dist/core/constraints/injection-drift.d.ts +48 -0
  105. package/dist/core/constraints/injection-drift.d.ts.map +1 -0
  106. package/dist/core/constraints/injection-drift.js +140 -0
  107. package/dist/core/constraints/injection-drift.js.map +1 -0
  108. package/dist/core/constraints/injection-renderer.d.ts +23 -0
  109. package/dist/core/constraints/injection-renderer.d.ts.map +1 -0
  110. package/dist/core/constraints/injection-renderer.js +44 -0
  111. package/dist/core/constraints/injection-renderer.js.map +1 -0
  112. package/dist/core/constraints/interceptor.d.ts.map +1 -1
  113. package/dist/core/constraints/interceptor.js +3 -2
  114. package/dist/core/constraints/interceptor.js.map +1 -1
  115. package/dist/core/constraints/usage-report.d.ts +95 -0
  116. package/dist/core/constraints/usage-report.d.ts.map +1 -0
  117. package/dist/core/constraints/usage-report.js +206 -0
  118. package/dist/core/constraints/usage-report.js.map +1 -0
  119. package/dist/core/effective-constraints.d.ts +47 -0
  120. package/dist/core/effective-constraints.d.ts.map +1 -0
  121. package/dist/core/effective-constraints.js +60 -0
  122. package/dist/core/effective-constraints.js.map +1 -0
  123. package/dist/core/index.d.ts +1 -0
  124. package/dist/core/index.d.ts.map +1 -1
  125. package/dist/core/index.js +2 -0
  126. package/dist/core/index.js.map +1 -1
  127. package/dist/core/project-config-loader.d.ts +28 -3
  128. package/dist/core/project-config-loader.d.ts.map +1 -1
  129. package/dist/core/project-config-loader.js +74 -8
  130. package/dist/core/project-config-loader.js.map +1 -1
  131. package/dist/dashboard/data.d.ts +1 -9
  132. package/dist/dashboard/data.d.ts.map +1 -1
  133. package/dist/dashboard/data.js +7 -15
  134. package/dist/dashboard/data.js.map +1 -1
  135. package/dist/dashboard/types.d.ts +13 -1
  136. package/dist/dashboard/types.d.ts.map +1 -1
  137. package/dist/index.d.ts +0 -4
  138. package/dist/index.d.ts.map +1 -1
  139. package/dist/index.js +1 -13
  140. package/dist/index.js.map +1 -1
  141. package/dist/monitoring/index.d.ts +0 -2
  142. package/dist/monitoring/index.d.ts.map +1 -1
  143. package/dist/monitoring/index.js +0 -2
  144. package/dist/monitoring/index.js.map +1 -1
  145. package/dist/monitoring/knowledge-evolver.d.ts +1 -1
  146. package/dist/monitoring/knowledge-evolver.js +1 -1
  147. package/dist/monitoring/trace-analyzer.d.ts +1 -1
  148. package/dist/monitoring/trace-analyzer.d.ts.map +1 -1
  149. package/dist/monitoring/trace-analyzer.js +16 -10
  150. package/dist/monitoring/trace-analyzer.js.map +1 -1
  151. package/dist/monitoring/traces.d.ts +2 -1
  152. package/dist/monitoring/traces.d.ts.map +1 -1
  153. package/dist/monitoring/traces.js +5 -3
  154. package/dist/monitoring/traces.js.map +1 -1
  155. package/dist/presets/standard.d.ts +3 -1
  156. package/dist/presets/standard.d.ts.map +1 -1
  157. package/dist/presets/standard.js +18 -8
  158. package/dist/presets/standard.js.map +1 -1
  159. package/dist/types/constraint.d.ts +51 -11
  160. package/dist/types/constraint.d.ts.map +1 -1
  161. package/dist/types/constraint.js +8 -4
  162. package/dist/types/constraint.js.map +1 -1
  163. package/dist/types/index.d.ts +1 -1
  164. package/dist/types/index.d.ts.map +1 -1
  165. package/dist/types/index.js.map +1 -1
  166. package/dist/types/monitoring-types.d.ts +2 -63
  167. package/dist/types/monitoring-types.d.ts.map +1 -1
  168. package/dist/types/monitoring-types.js +2 -2
  169. package/dist/types/project-config.d.ts +32 -1
  170. package/dist/types/project-config.d.ts.map +1 -1
  171. package/dist/types/trace.d.ts +16 -7
  172. package/dist/types/trace.d.ts.map +1 -1
  173. package/dist/types/trace.js +8 -0
  174. package/dist/types/trace.js.map +1 -1
  175. package/package.json +1 -1
  176. package/src/CONTEXT.md +2 -2
  177. package/src/__tests__/checker-extra.test.ts +356 -331
  178. package/src/__tests__/checker.test.ts +87 -724
  179. package/src/__tests__/constraint-doctor.test.ts +5 -5
  180. package/src/__tests__/doctor-extra.test.ts +164 -0
  181. package/src/__tests__/effective-constraints.test.ts +147 -0
  182. package/src/__tests__/extend-exceptions.test.ts +3 -3
  183. package/src/__tests__/iron-laws.test.ts +115 -91
  184. package/src/__tests__/no-hardcoded-credentials.test.ts +90 -0
  185. package/src/__tests__/presets.test.ts +7 -7
  186. package/src/__tests__/project-config-loader-extra.test.ts +4 -4
  187. package/src/__tests__/project-config-loader.test.ts +40 -1
  188. package/src/__tests__/skip-semantics.test.ts +322 -0
  189. package/src/cli/commands/CONTEXT.md +5 -3
  190. package/src/cli/commands/__tests__/check-drift.test.ts +127 -0
  191. package/src/cli/commands/__tests__/check-skip-output.test.ts +128 -0
  192. package/src/cli/commands/__tests__/check.test.ts +14 -25
  193. package/src/cli/commands/__tests__/constraints-report.test.ts +327 -0
  194. package/src/cli/commands/__tests__/constraints-retire.test.ts +283 -0
  195. package/src/cli/commands/__tests__/init-injection.test.ts +234 -0
  196. package/src/cli/commands/__tests__/status-extra.test.ts +11 -11
  197. package/src/cli/commands/__tests__/status.test.ts +1 -1
  198. package/src/cli/commands/__tests__/sync-docs.test.ts +163 -0
  199. package/src/cli/commands/check.ts +72 -38
  200. package/src/cli/commands/constraints-report.ts +234 -0
  201. package/src/cli/commands/constraints-retire.ts +443 -0
  202. package/src/cli/commands/constraints.ts +5 -5
  203. package/src/cli/commands/index.ts +2 -1
  204. package/src/cli/commands/init.ts +94 -66
  205. package/src/cli/commands/report.ts +6 -6
  206. package/src/cli/commands/status.ts +3 -4
  207. package/src/cli/commands/sync-docs/capabilities-syncer.ts +90 -15
  208. package/src/cli/commands/sync-docs/index.ts +87 -24
  209. package/src/cli/commands/validate.ts +1 -5
  210. package/src/core/CONTEXT.md +7 -4
  211. package/src/core/constraints/__tests__/injection-drift.test.ts +164 -0
  212. package/src/core/constraints/__tests__/interceptor.test.ts +4 -0
  213. package/src/core/constraints/capabilities-parser.ts +28 -0
  214. package/src/core/constraints/checker.ts +73 -28
  215. package/src/core/constraints/checkers/capability-sync.ts +89 -18
  216. package/src/core/constraints/checkers/context-doc-sync.ts +9 -2
  217. package/src/core/constraints/checkers/docs-freshness.ts +43 -0
  218. package/src/core/constraints/checkers/index.ts +38 -71
  219. package/src/core/constraints/checkers/iron-flags.ts +13 -49
  220. package/src/core/constraints/checkers/no-hardcoded-credentials.ts +93 -0
  221. package/src/core/constraints/checkers/types.ts +27 -5
  222. package/src/core/constraints/context-builder.ts +28 -19
  223. package/src/core/constraints/definitions/guidelines.ts +33 -599
  224. package/src/core/constraints/definitions/iron-laws.ts +48 -239
  225. package/src/core/constraints/definitions/prompts.ts +419 -0
  226. package/src/core/constraints/definitions.ts +18 -11
  227. package/src/core/constraints/index.ts +10 -1
  228. package/src/core/constraints/injection-drift.ts +139 -0
  229. package/src/core/constraints/injection-renderer.ts +44 -0
  230. package/src/core/constraints/interceptor.ts +3 -2
  231. package/src/core/constraints/usage-report.ts +254 -0
  232. package/src/core/effective-constraints.ts +85 -0
  233. package/src/core/index.ts +4 -1
  234. package/src/core/project-config-loader.ts +82 -9
  235. package/src/dashboard/__tests__/data.test.ts +5 -12
  236. package/src/dashboard/data.ts +9 -19
  237. package/src/dashboard/types.ts +18 -1
  238. package/src/index.ts +0 -12
  239. package/src/knowledge/CONTEXT.md +2 -2
  240. package/src/monitoring/CONTEXT.md +3 -4
  241. package/src/monitoring/index.ts +0 -2
  242. package/src/monitoring/knowledge-evolver.ts +1 -1
  243. package/src/monitoring/trace-analyzer.ts +15 -10
  244. package/src/monitoring/traces.ts +10 -6
  245. package/src/presets/__tests__/standard.test.ts +11 -9
  246. package/src/presets/standard.ts +24 -15
  247. package/src/types/constraint.ts +59 -14
  248. package/src/types/index.ts +1 -3
  249. package/src/types/monitoring-types.ts +2 -84
  250. package/src/types/project-config.ts +37 -1
  251. package/src/types/trace.ts +18 -7
  252. package/src/verification/CONTEXT.md +1 -1
  253. package/dist/cli/commands/flow.d.ts +0 -22
  254. package/dist/cli/commands/flow.d.ts.map +0 -1
  255. package/dist/cli/commands/flow.js +0 -275
  256. package/dist/cli/commands/flow.js.map +0 -1
  257. package/dist/constraints/lifecycle-runner.d.ts +0 -52
  258. package/dist/constraints/lifecycle-runner.d.ts.map +0 -1
  259. package/dist/constraints/lifecycle-runner.js +0 -151
  260. package/dist/constraints/lifecycle-runner.js.map +0 -1
  261. package/dist/constraints/registry.d.ts +0 -27
  262. package/dist/constraints/registry.d.ts.map +0 -1
  263. package/dist/constraints/registry.js +0 -128
  264. package/dist/constraints/registry.js.map +0 -1
  265. package/dist/constraints/types.d.ts +0 -53
  266. package/dist/constraints/types.d.ts.map +0 -1
  267. package/dist/constraints/types.js +0 -8
  268. package/dist/constraints/types.js.map +0 -1
  269. package/dist/core/constraints/checkers/always-pass.d.ts +0 -17
  270. package/dist/core/constraints/checkers/always-pass.d.ts.map +0 -1
  271. package/dist/core/constraints/checkers/always-pass.js +0 -23
  272. package/dist/core/constraints/checkers/always-pass.js.map +0 -1
  273. package/dist/core/constraints/checkers/guideline-flags.d.ts +0 -9
  274. package/dist/core/constraints/checkers/guideline-flags.d.ts.map +0 -1
  275. package/dist/core/constraints/checkers/guideline-flags.js +0 -13
  276. package/dist/core/constraints/checkers/guideline-flags.js.map +0 -1
  277. package/dist/core/constraints/checkers/no-any-type.d.ts +0 -6
  278. package/dist/core/constraints/checkers/no-any-type.d.ts.map +0 -1
  279. package/dist/core/constraints/checkers/no-any-type.js +0 -42
  280. package/dist/core/constraints/checkers/no-any-type.js.map +0 -1
  281. package/dist/core/constraints/checkers/no-excuse-patterns.d.ts +0 -6
  282. package/dist/core/constraints/checkers/no-excuse-patterns.d.ts.map +0 -1
  283. package/dist/core/constraints/checkers/no-excuse-patterns.js +0 -25
  284. package/dist/core/constraints/checkers/no-excuse-patterns.js.map +0 -1
  285. package/dist/core/constraints/checkers/no-fuzzy-completion-claim.d.ts +0 -6
  286. package/dist/core/constraints/checkers/no-fuzzy-completion-claim.d.ts.map +0 -1
  287. package/dist/core/constraints/checkers/no-fuzzy-completion-claim.js +0 -34
  288. package/dist/core/constraints/checkers/no-fuzzy-completion-claim.js.map +0 -1
  289. package/dist/core/constraints/checkers/no-performative-agreement.d.ts +0 -8
  290. package/dist/core/constraints/checkers/no-performative-agreement.d.ts.map +0 -1
  291. package/dist/core/constraints/checkers/no-performative-agreement.js +0 -23
  292. package/dist/core/constraints/checkers/no-performative-agreement.js.map +0 -1
  293. package/dist/core/constraints/checkers/no-simplification-without-approval.d.ts +0 -6
  294. package/dist/core/constraints/checkers/no-simplification-without-approval.d.ts.map +0 -1
  295. package/dist/core/constraints/checkers/no-simplification-without-approval.js +0 -30
  296. package/dist/core/constraints/checkers/no-simplification-without-approval.js.map +0 -1
  297. package/dist/core/constraints/checkers/test-coverage.d.ts +0 -6
  298. package/dist/core/constraints/checkers/test-coverage.d.ts.map +0 -1
  299. package/dist/core/constraints/checkers/test-coverage.js +0 -33
  300. package/dist/core/constraints/checkers/test-coverage.js.map +0 -1
  301. package/dist/core/constraints/checkers/yagni.d.ts +0 -8
  302. package/dist/core/constraints/checkers/yagni.d.ts.map +0 -1
  303. package/dist/core/constraints/checkers/yagni.js +0 -96
  304. package/dist/core/constraints/checkers/yagni.js.map +0 -1
  305. package/dist/core/constraints/definitions/tips.d.ts +0 -7
  306. package/dist/core/constraints/definitions/tips.d.ts.map +0 -1
  307. package/dist/core/constraints/definitions/tips.js +0 -62
  308. package/dist/core/constraints/definitions/tips.js.map +0 -1
  309. package/dist/evolution/auto-evolve.d.ts +0 -35
  310. package/dist/evolution/auto-evolve.d.ts.map +0 -1
  311. package/dist/evolution/auto-evolve.js +0 -64
  312. package/dist/evolution/auto-evolve.js.map +0 -1
  313. package/dist/evolution/index.d.ts +0 -2
  314. package/dist/evolution/index.d.ts.map +0 -1
  315. package/dist/evolution/index.js +0 -18
  316. package/dist/evolution/index.js.map +0 -1
  317. package/dist/monitoring/constraint-evolver.d.ts +0 -120
  318. package/dist/monitoring/constraint-evolver.d.ts.map +0 -1
  319. package/dist/monitoring/constraint-evolver.js +0 -410
  320. package/dist/monitoring/constraint-evolver.js.map +0 -1
  321. package/src/__tests__/constraint-evolver.test.ts +0 -405
  322. package/src/__tests__/doctor-evolver.test.ts +0 -381
  323. package/src/cli/commands/__tests__/flow.test.ts +0 -343
  324. package/src/cli/commands/flow.ts +0 -277
  325. package/src/constraints/__tests__/lifecycle-runner.test.ts +0 -246
  326. package/src/constraints/__tests__/registry.test.ts +0 -196
  327. package/src/constraints/lifecycle-runner.ts +0 -184
  328. package/src/constraints/registry.ts +0 -134
  329. package/src/constraints/types.ts +0 -59
  330. package/src/core/constraints/checkers/always-pass.ts +0 -22
  331. package/src/core/constraints/checkers/guideline-flags.ts +0 -30
  332. package/src/core/constraints/checkers/no-any-type.ts +0 -42
  333. package/src/core/constraints/checkers/no-excuse-patterns.ts +0 -24
  334. package/src/core/constraints/checkers/no-fuzzy-completion-claim.ts +0 -33
  335. package/src/core/constraints/checkers/no-performative-agreement.ts +0 -22
  336. package/src/core/constraints/checkers/no-simplification-without-approval.ts +0 -29
  337. package/src/core/constraints/checkers/test-coverage.ts +0 -35
  338. package/src/core/constraints/checkers/yagni.ts +0 -65
  339. package/src/core/constraints/definitions/tips.ts +0 -63
  340. package/src/evolution/CONTEXT.md +0 -22
  341. package/src/evolution/__tests__/auto-evolve.test.ts +0 -319
  342. package/src/evolution/auto-evolve.ts +0 -98
  343. package/src/evolution/index.ts +0 -1
  344. package/src/monitoring/constraint-evolver.ts +0 -501
@@ -74,7 +74,7 @@ describe('ConstraintDoctor', () => {
74
74
  it('应该返回诊断结果', async () => {
75
75
  const anomaly: TraceAnomaly = {
76
76
  type: 'rising_fail_rate',
77
- constraintId: 'no_self_approval',
77
+ constraintId: 'no_completion_without_verification',
78
78
  level: 'iron_law',
79
79
  message: '失败率上升',
80
80
  data: {
@@ -178,7 +178,7 @@ describe('ConstraintDoctor', () => {
178
178
  it('应该诊断 low_pass_rate', async () => {
179
179
  const anomaly: TraceAnomaly = {
180
180
  type: 'low_pass_rate',
181
- constraintId: 'no_any_type',
181
+ constraintId: 'capability_sync',
182
182
  level: 'guideline',
183
183
  message: '通过率过低',
184
184
  data: { currentRate: 0.1, threshold: 0.5 },
@@ -211,7 +211,7 @@ describe('ConstraintDoctor', () => {
211
211
  it('rising_fail_rate 应该设置 severity 为 high 当 iron_law', async () => {
212
212
  const anomaly: TraceAnomaly = {
213
213
  type: 'rising_fail_rate',
214
- constraintId: 'no_self_approval',
214
+ constraintId: 'no_completion_without_verification',
215
215
  level: 'iron_law',
216
216
  message: '失败率上升',
217
217
  data: { currentRate: 0.7, threshold: 0.3, trend: 'rising' },
@@ -237,7 +237,7 @@ describe('ConstraintDoctor', () => {
237
237
  },
238
238
  {
239
239
  type: 'low_pass_rate',
240
- constraintId: 'no_any_type',
240
+ constraintId: 'capability_sync',
241
241
  level: 'guideline',
242
242
  message: '通过率过低',
243
243
  data: { currentRate: 0.1, threshold: 0.5 },
@@ -249,7 +249,7 @@ describe('ConstraintDoctor', () => {
249
249
 
250
250
  expect(results.length).toBe(2);
251
251
  expect(results[0].constraintId).toBe('no_fix_without_root_cause');
252
- expect(results[1].constraintId).toBe('no_any_type');
252
+ expect(results[1].constraintId).toBe('capability_sync');
253
253
  });
254
254
  });
255
255
 
@@ -0,0 +1,164 @@
1
+ /**
2
+ * ConstraintDoctor 测试
3
+ */
4
+
5
+ import * as fs from 'fs';
6
+ import * as path from 'path';
7
+ import * as os from 'os';
8
+ import { TraceCollector } from '../monitoring/traces';
9
+ import { TraceAnalyzer } from '../monitoring/trace-analyzer';
10
+ import { ConstraintDoctor, createDoctor } from '../monitoring/constraint-doctor';
11
+ import type { ExecutionTrace, TraceAnomaly } from '../types/trace';
12
+
13
+ describe('ConstraintDoctor', () => {
14
+ let tempDir: string;
15
+ let collector: TraceCollector;
16
+ let analyzer: TraceAnalyzer;
17
+ let doctor: ConstraintDoctor;
18
+
19
+ beforeEach(() => {
20
+ tempDir = path.join(os.tmpdir(), `harness-traces-${Date.now()}`);
21
+ fs.mkdirSync(tempDir, { recursive: true });
22
+ collector = new TraceCollector({
23
+ traceFile: path.join(tempDir, 'execution.log'),
24
+ enabled: true,
25
+ });
26
+ analyzer = new TraceAnalyzer(collector);
27
+ doctor = createDoctor();
28
+ });
29
+
30
+ afterEach(() => {
31
+ if (fs.existsSync(tempDir)) {
32
+ fs.rmSync(tempDir, { recursive: true });
33
+ }
34
+ });
35
+
36
+ test('should diagnose high bypass rate anomaly', async () => {
37
+ // 创建异常
38
+ const anomaly: TraceAnomaly = {
39
+ type: 'high_bypass_rate',
40
+ constraintId: 'test_constraint',
41
+ level: 'guideline',
42
+ message: 'Bypass rate 40%',
43
+ data: {
44
+ currentRate: 0.4,
45
+ threshold: 0.3,
46
+ },
47
+ detectedAt: Date.now(),
48
+ suggestedAction: 'diagnose',
49
+ };
50
+
51
+ // 添加 traces
52
+ const traces: ExecutionTrace[] = [];
53
+ for (let i = 0; i < 10; i++) {
54
+ traces.push({
55
+ constraintId: 'test_constraint',
56
+ level: 'guideline',
57
+ timestamp: Date.now() - i * 60 * 1000,
58
+ result: i < 6 ? 'bypassed' : 'pass',
59
+ });
60
+ }
61
+ doctor.setData(traces);
62
+
63
+ // 诊断
64
+ const diagnosis = await doctor.diagnose(anomaly);
65
+
66
+ expect(diagnosis.constraintId).toBe('test_constraint');
67
+ expect(diagnosis.needsChange).toBe(true);
68
+ expect(diagnosis.rootCause.primary).toContain('过于严格');
69
+ expect(diagnosis.recommendations.length).toBeGreaterThan(0);
70
+ expect(diagnosis.recommendations[0].type).toBe('add_exception');
71
+ });
72
+
73
+ test('should diagnose rising fail rate anomaly', async () => {
74
+ const anomaly: TraceAnomaly = {
75
+ type: 'rising_fail_rate',
76
+ constraintId: 'another_constraint',
77
+ level: 'iron_law',
78
+ message: 'Fail rate rising',
79
+ data: {
80
+ currentRate: 0.6,
81
+ threshold: 0.5,
82
+ trend: 'rising',
83
+ },
84
+ detectedAt: Date.now(),
85
+ suggestedAction: 'diagnose',
86
+ };
87
+
88
+ doctor.setData([]);
89
+ const diagnosis = await doctor.diagnose(anomaly);
90
+
91
+ expect(diagnosis.needsChange).toBe(true);
92
+ expect(diagnosis.impact.severity).toBe('high'); // Iron law
93
+ expect(diagnosis.urgency).toBe('medium'); // Iron law 强制 medium+
94
+ });
95
+
96
+ test('should detect exception overuse', async () => {
97
+ const anomaly: TraceAnomaly = {
98
+ type: 'exception_overuse',
99
+ constraintId: 'constraint_with_exceptions',
100
+ level: 'guideline',
101
+ message: 'Exception rate 50%',
102
+ data: {
103
+ currentRate: 0.5,
104
+ threshold: 0.4,
105
+ },
106
+ detectedAt: Date.now(),
107
+ suggestedAction: 'add_exception',
108
+ };
109
+
110
+ doctor.setData([]);
111
+ const diagnosis = await doctor.diagnose(anomaly);
112
+
113
+ expect(diagnosis.rootCause.primary).toContain('过度使用');
114
+ expect(diagnosis.recommendations[0].type).toBe('modify_constraint');
115
+ });
116
+
117
+ test('should generate diagnosis report', async () => {
118
+ const anomaly: TraceAnomaly = {
119
+ type: 'high_bypass_rate',
120
+ constraintId: 'test',
121
+ level: 'guideline',
122
+ message: 'Test',
123
+ data: {
124
+ currentRate: 0.5,
125
+ threshold: 0.3,
126
+ },
127
+ detectedAt: Date.now(),
128
+ suggestedAction: 'diagnose',
129
+ };
130
+
131
+ doctor.setData([]);
132
+ const diagnosis = await doctor.diagnose(anomaly);
133
+ const report = doctor.generateReport(diagnosis);
134
+
135
+ expect(report).toContain('# Diagnosis Report');
136
+ expect(report).toContain('Root Cause');
137
+ expect(report).toContain('Recommendations');
138
+ expect(report).toContain('test');
139
+ });
140
+
141
+ test('should save and load diagnosis', async () => {
142
+ const anomaly: TraceAnomaly = {
143
+ type: 'high_bypass_rate',
144
+ constraintId: 'save_test',
145
+ level: 'guideline',
146
+ message: 'Test',
147
+ data: { currentRate: 0.5, threshold: 0.3 },
148
+ detectedAt: Date.now(),
149
+ suggestedAction: 'diagnose',
150
+ };
151
+
152
+ doctor.setData([]);
153
+ const diagnosis = await doctor.diagnose(anomaly);
154
+
155
+ const outputPath = path.join(tempDir, 'diagnosis.json');
156
+ doctor.saveDiagnosis(diagnosis, outputPath);
157
+
158
+ expect(fs.existsSync(outputPath)).toBe(true);
159
+
160
+ const loaded = doctor.loadDiagnosis(outputPath);
161
+ expect(loaded.constraintId).toBe('save_test');
162
+ expect(loaded.needsChange).toBe(true);
163
+ });
164
+ });
@@ -0,0 +1,147 @@
1
+ /**
2
+ * 生效约束集(getEffectiveConstraints / lintEffectiveConfig)测试
3
+ *
4
+ * 合并矩阵:preset 裁剪 / config.yml 禁用 / custom 追加 / scenes 过滤 / 未知 id 诊断
5
+ */
6
+
7
+ import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';
8
+ import * as fs from 'fs';
9
+ import * as path from 'path';
10
+ import {
11
+ getEffectiveConstraints,
12
+ lintEffectiveConfig,
13
+ } from '../core/effective-constraints';
14
+ import { IRON_LAWS, GUIDELINES, PROMPTS } from '../core/constraints/definitions';
15
+
16
+ const BUILTIN_TOTAL =
17
+ Object.keys(IRON_LAWS).length + Object.keys(GUIDELINES).length + Object.keys(PROMPTS).length;
18
+ /** 带 appliesTo 标签的内置 prompt(scenes 过滤对象) */
19
+ const SCENE_PROMPTS = Object.values(PROMPTS)
20
+ .filter(c => c.appliesTo && c.appliesTo.length > 0)
21
+ .map(c => c.id);
22
+
23
+ describe('getEffectiveConstraints / lintEffectiveConfig', () => {
24
+ let tempDir: string;
25
+ let counter = 0;
26
+
27
+ const setupProject = (configYaml?: string, customYaml?: string): string => {
28
+ const dir = path.join(tempDir, `p${counter++}`);
29
+ fs.mkdirSync(path.join(dir, '.harness'), { recursive: true });
30
+ if (configYaml !== undefined) {
31
+ fs.writeFileSync(path.join(dir, '.harness', 'config.yml'), configYaml);
32
+ }
33
+ if (customYaml !== undefined) {
34
+ fs.writeFileSync(path.join(dir, '.harness', 'custom-constraints.yml'), customYaml);
35
+ }
36
+ return dir;
37
+ };
38
+
39
+ beforeEach(() => {
40
+ tempDir = fs.mkdtempSync(path.join(process.cwd(), 'temp-test-effective-'));
41
+ });
42
+
43
+ afterEach(() => {
44
+ fs.rmSync(tempDir, { recursive: true, force: true });
45
+ });
46
+
47
+ describe('合并矩阵', () => {
48
+ it('无配置项目:内置全集减去场景专属 prompt(scenes 缺省为空)', () => {
49
+ const dir = setupProject();
50
+ const constraints = getEffectiveConstraints(dir);
51
+ const ids = constraints.map(c => c.id);
52
+
53
+ expect(constraints.length).toBe(BUILTIN_TOTAL - SCENE_PROMPTS.length);
54
+ for (const id of SCENE_PROMPTS) {
55
+ expect(ids).not.toContain(id);
56
+ }
57
+ // check + prompt 均带 kind
58
+ expect(constraints.every(c => c.kind === 'check' || c.kind === 'prompt')).toBe(true);
59
+ expect(constraints.filter(c => c.kind === 'check')).toHaveLength(
60
+ Object.keys(IRON_LAWS).length + Object.keys(GUIDELINES).length
61
+ );
62
+ });
63
+
64
+ it('scenes 命中:对应场景 prompt 进入生效集,其余场景 prompt 仍排除', () => {
65
+ const dir = setupProject(`scenes:\n - agent-skill\n`);
66
+ const ids = getEffectiveConstraints(dir).map(c => c.id);
67
+
68
+ expect(ids).toContain('no_skill_without_test');
69
+ expect(ids).not.toContain('no_model_for_deterministic');
70
+ });
71
+
72
+ it('config.yml 禁用:check 与 prompt 条目均从生效集移除', () => {
73
+ const dir = setupProject(`
74
+ constraints:
75
+ no_bypass_checkpoint:
76
+ enabled: false
77
+ no_fuzzy_completion_claim:
78
+ enabled: false
79
+ `);
80
+ const constraints = getEffectiveConstraints(dir);
81
+ const ids = constraints.map(c => c.id);
82
+
83
+ expect(ids).not.toContain('no_bypass_checkpoint');
84
+ expect(ids).not.toContain('no_fuzzy_completion_claim');
85
+ expect(constraints.length).toBe(BUILTIN_TOTAL - SCENE_PROMPTS.length - 2);
86
+ });
87
+
88
+ it('preset: relaxed 裁剪生效集', () => {
89
+ const dir = setupProject(`preset: relaxed\n`);
90
+ const constraints = getEffectiveConstraints(dir);
91
+ const ids = constraints.map(c => c.id);
92
+
93
+ expect(ids).toEqual(
94
+ expect.arrayContaining([
95
+ 'no_completion_without_verification',
96
+ 'incremental_progress',
97
+ 'no_implementation_without_requirement',
98
+ 'no_bypass_checkpoint',
99
+ 'no_hardcoded_credentials',
100
+ ])
101
+ );
102
+ expect(constraints).toHaveLength(5);
103
+ expect(constraints.every(c => c.kind === 'check')).toBe(true);
104
+ });
105
+
106
+ it('custom-constraints.yml 追加自定义约束(kind=prompt)', () => {
107
+ const dir = setupProject(undefined, `
108
+ custom_constraints:
109
+ my_project_rule:
110
+ level: guideline
111
+ rule: MY RULE
112
+ message: 项目自定义
113
+ trigger: code_implementation
114
+ `);
115
+ const constraints = getEffectiveConstraints(dir);
116
+ const custom = constraints.find(c => c.id === 'my_project_rule');
117
+
118
+ expect(custom).toBeDefined();
119
+ expect(custom!.kind).toBe('prompt');
120
+ expect(custom!.level).toBe('guideline');
121
+ });
122
+
123
+ it('禁用未知 id(已移除约束的残留配置):不报错,lint 可诊断', () => {
124
+ const dir = setupProject(`
125
+ constraints:
126
+ removed_legacy_constraint:
127
+ enabled: false
128
+ `);
129
+ // 生效集不受影响、不抛错
130
+ const constraints = getEffectiveConstraints(dir);
131
+ expect(constraints.length).toBe(BUILTIN_TOTAL - SCENE_PROMPTS.length);
132
+
133
+ const lint = lintEffectiveConfig(dir);
134
+ expect(lint.unknownIds).toContain('removed_legacy_constraint');
135
+ });
136
+
137
+ it('lintEffectiveConfig 报告 scenes 与被场景过滤的 prompt', () => {
138
+ const dir = setupProject(`scenes:\n - llm-app\n`);
139
+ const lint = lintEffectiveConfig(dir);
140
+
141
+ expect(lint.scenes).toEqual(['llm-app']);
142
+ expect(lint.sceneExcluded).toContain('no_skill_without_test');
143
+ expect(lint.sceneExcluded).not.toContain('no_model_for_deterministic');
144
+ expect(lint.unknownIds).toEqual([]);
145
+ });
146
+ });
147
+ });
@@ -38,8 +38,8 @@ custom_constraints:
38
38
  loader.load();
39
39
  const merged = loader.mergeConstraints();
40
40
 
41
- // 注意:no_fix_without_root_cause 是 GUIDELINE
42
- const constraint = merged.guidelines['no_fix_without_root_cause'];
41
+ // 注意:no_fix_without_root_cause 是 prompt 层约束(ADR-0001)
42
+ const constraint = merged.prompts!['no_fix_without_root_cause'];
43
43
  expect(constraint).toBeDefined();
44
44
  // 应该包含内置例外
45
45
  expect(constraint?.exceptions).toContain('simple_typo');
@@ -135,7 +135,7 @@ custom_constraints:
135
135
  loader.load();
136
136
  const merged = loader.mergeConstraints();
137
137
 
138
- const constraint = merged.guidelines['no_fix_without_root_cause'];
138
+ const constraint = merged.prompts!['no_fix_without_root_cause'];
139
139
  expect(constraint).toBeDefined();
140
140
  // 应该保留内置约束的 rule
141
141
  expect(constraint?.rule).toBeTruthy();
@@ -1,55 +1,110 @@
1
1
  /**
2
- * 约束系统测试
2
+ * 约束系统测试(ADR-0001:kind 二元模型,25 条清单构成 + 注册表闭环)
3
3
  */
4
4
 
5
5
  import { describe, it, expect } from '@jest/globals';
6
- import {
7
- IRON_LAWS,
8
- GUIDELINES,
9
- TIPS,
10
- getAllConstraints,
11
- findConstraintsByTrigger,
12
- getConstraint
6
+ import {
7
+ IRON_LAWS,
8
+ GUIDELINES,
9
+ PROMPTS,
10
+ getAllConstraints,
11
+ findConstraintsByTrigger,
12
+ getConstraint
13
13
  } from '../core/constraints/definitions';
14
14
  import { constraintChecker } from '../core/constraints/checker';
15
+ import { getConstraintCheck, registeredCheckCount } from '../core/constraints/checkers';
15
16
  import type { ConstraintContext } from '../types/constraint';
16
17
 
17
18
  describe('Constraint System', () => {
18
- describe('Iron Laws', () => {
19
- it('should have 12 iron laws defined', () => {
20
- expect(Object.keys(IRON_LAWS).length).toBeGreaterThan(0); // 数量随版本变动
19
+ describe('清单构成(ADR-0001:42 → 25)', () => {
20
+ it('getAllConstraints 返回 25 条:9 check + 16 prompt', () => {
21
+ const all = getAllConstraints();
22
+ expect(all).toHaveLength(25);
23
+ expect(all.filter(c => c.kind === 'check')).toHaveLength(9);
24
+ expect(all.filter(c => c.kind === 'prompt')).toHaveLength(16);
21
25
  });
22
26
 
23
- it('should have no exceptions for iron laws', () => {
24
- Object.values(IRON_LAWS).forEach(law => {
25
- expect(law.exceptions).toBeUndefined();
27
+ it('check 层 = 5 iron + 4 guideline', () => {
28
+ expect(Object.keys(IRON_LAWS)).toHaveLength(5);
29
+ expect(Object.keys(GUIDELINES)).toHaveLength(4);
30
+ Object.values(IRON_LAWS).forEach(c => {
31
+ expect(c.kind).toBe('check');
32
+ expect(c.level).toBe('iron_law');
33
+ });
34
+ Object.values(GUIDELINES).forEach(c => {
35
+ expect(c.kind).toBe('check');
36
+ expect(c.level).toBe('guideline');
26
37
  });
27
38
  });
28
- });
29
39
 
30
- describe('Guidelines', () => {
31
- it('should have guidelines defined', () => {
32
- expect(Object.keys(GUIDELINES).length).toBeGreaterThan(0);
40
+ it('prompt 层 16 条,level 统一为 prompt', () => {
41
+ expect(Object.keys(PROMPTS)).toHaveLength(16);
42
+ Object.values(PROMPTS).forEach(c => {
43
+ expect(c.kind).toBe('prompt');
44
+ expect(c.level).toBe('prompt');
45
+ });
33
46
  });
34
47
 
35
- it('should have exceptions for some guidelines', () => {
36
- const withExceptions = Object.values(GUIDELINES).filter(g => g.exceptions && g.exceptions.length > 0);
37
- expect(withExceptions.length).toBeGreaterThan(0);
48
+ it('被删除的 8 条不再存在', () => {
49
+ const retired = [
50
+ 'no_any_type',
51
+ 'test_coverage_required',
52
+ 'no_coverage_decrease',
53
+ 'readme_required',
54
+ 'doc_required_for_public_api',
55
+ 'two_stage_review_required',
56
+ 'prefer_worktree',
57
+ 'read_before_write',
58
+ ];
59
+ for (const id of retired) {
60
+ expect(getConstraint(id)).toBeUndefined();
61
+ }
38
62
  });
39
- });
40
63
 
41
- describe('Tips', () => {
42
- it('should have 2 tips defined', () => {
43
- expect(Object.keys(TIPS)).toHaveLength(2);
64
+ it('被吸收的成员不再单独存在', () => {
65
+ const absorbed = [
66
+ 'no_self_approval',
67
+ 'no_claim_without_evidence',
68
+ 'no_excuse_patterns',
69
+ 'no_fallback_without_root_cause',
70
+ 'analysis_verification_gate',
71
+ 'diagnosis_to_fix_gate',
72
+ 'no_creation_without_reuse_check',
73
+ 'yagni_check',
74
+ 'no_implementation_without_requirement_review',
75
+ ];
76
+ for (const id of absorbed) {
77
+ expect(getConstraint(id)).toBeUndefined();
78
+ }
79
+ });
80
+
81
+ it('场景标签:no_skill_without_test / no_model_for_deterministic', () => {
82
+ expect(PROMPTS['no_skill_without_test'].appliesTo).toEqual(['agent-skill']);
83
+ expect(PROMPTS['no_model_for_deterministic'].appliesTo).toEqual(['llm-app']);
44
84
  });
45
85
  });
46
86
 
47
- describe('Helper Functions', () => {
48
- it('should get all constraints', () => {
49
- const all = getAllConstraints();
50
- expect(all.length).toBeGreaterThan(0); // 约束数量随版本变动
87
+ describe('注册表闭环', () => {
88
+ it('每条 kind=check 约束都有已注册 checker', () => {
89
+ const checks = getAllConstraints().filter(c => c.kind === 'check');
90
+ for (const c of checks) {
91
+ expect(getConstraintCheck(c.id)).toBeDefined();
92
+ }
93
+ });
94
+
95
+ it('注册表数量与 check 约束数量一致(无孤儿 checker)', () => {
96
+ const checkCount = getAllConstraints().filter(c => c.kind === 'check').length;
97
+ expect(registeredCheckCount()).toBe(checkCount);
51
98
  });
52
99
 
100
+ it('prompt 约束不注册 checker', () => {
101
+ for (const c of Object.values(PROMPTS)) {
102
+ expect(getConstraintCheck(c.id)).toBeUndefined();
103
+ }
104
+ });
105
+ });
106
+
107
+ describe('Helper Functions', () => {
53
108
  it('should find constraints by trigger', () => {
54
109
  const constraints = findConstraintsByTrigger('code_implementation');
55
110
  expect(constraints.length).toBeGreaterThan(0);
@@ -58,7 +113,8 @@ describe('Constraint System', () => {
58
113
  it('should get single constraint by id', () => {
59
114
  const constraint = getConstraint('no_fix_without_root_cause');
60
115
  expect(constraint).toBeDefined();
61
- expect(constraint?.level).toBe('guideline');
116
+ expect(constraint?.kind).toBe('prompt');
117
+ expect(constraint?.level).toBe('prompt');
62
118
  });
63
119
 
64
120
  it('should return undefined for unknown constraint', () => {
@@ -80,54 +136,59 @@ describe('Constraint Checker', () => {
80
136
  };
81
137
 
82
138
  const result = constraintChecker.findApplicableConstraints(context);
83
- expect(result.ironLaws.length + result.guidelines.length + result.tips.length).toBeGreaterThan(0);
139
+ expect(result.ironLaws.length + result.guidelines.length).toBeGreaterThan(0);
84
140
  });
85
141
 
86
- it('should check constraint', async () => {
142
+ it('prompt 约束 check() 短路 satisfied,不查注册表', async () => {
87
143
  const context: ConstraintContext = {
88
144
  operation: 'code_implementation',
89
- hasRootCauseInvestigation: false,
90
145
  };
91
146
 
92
- const result = await constraintChecker.check(GUIDELINES['no_fix_without_root_cause'], context);
93
- expect(result.satisfied).toBe(false);
147
+ const result = await constraintChecker.check(PROMPTS['no_fix_without_root_cause'], context);
148
+ expect(result.satisfied).toBe(true);
94
149
  });
95
150
 
96
- it('should check constraint with satisfied precondition', async () => {
151
+ it('kind=check 但未注册 checker 的约束应抛错(不许静默 pass)', async () => {
97
152
  const context: ConstraintContext = {
98
153
  operation: 'code_implementation',
99
- hasRootCauseInvestigation: true,
100
154
  };
101
155
 
102
- const result = await constraintChecker.check(GUIDELINES['no_fix_without_root_cause'], context);
103
- expect(result.satisfied).toBe(true);
156
+ await expect(
157
+ constraintChecker.check(
158
+ {
159
+ id: 'ghost_check_constraint',
160
+ kind: 'check',
161
+ level: 'guideline',
162
+ rule: 'GHOST',
163
+ message: 'test',
164
+ trigger: 'code_implementation',
165
+ enforcement: 'test',
166
+ },
167
+ context
168
+ )
169
+ ).rejects.toThrow(/未注册 checker/);
104
170
  });
105
171
 
106
172
  it('should check all constraints', async () => {
107
173
  const context: ConstraintContext = {
108
174
  operation: 'code_implementation',
109
175
  hasRequirement: true,
110
- hasWorktree: true,
111
- hasTest: true,
112
176
  hasVerificationEvidence: true,
113
- taskDescription: 'Test task',
114
177
  hasSingleTask: true,
115
- hasRequirementReview: true,
116
- hasTwoStageReview: true,
117
- completionClaimText: '142 tests passed, coverage 87%',
118
178
  };
119
179
 
120
180
  const result = await constraintChecker.checkConstraints(context);
121
- expect(result.ironLaws.length + result.guidelines.length + result.tips.length).toBeGreaterThan(0);
181
+ expect(result.ironLaws.length + result.guidelines.length).toBeGreaterThan(0);
122
182
  });
123
183
 
124
- it('should fail incremental_progress when hasSingleTask is undefined', async () => {
184
+ it('should skip incremental_progress when hasSingleTask is undefined(未接线不评估)', async () => {
125
185
  const context: ConstraintContext = {
126
186
  operation: 'code_implementation',
127
187
  };
128
188
 
129
189
  const result = await constraintChecker.check(IRON_LAWS['incremental_progress'], context);
130
- expect(result.satisfied).toBe(false);
190
+ expect(result.skipped).toBe(true);
191
+ expect(result.satisfied).toBe(true);
131
192
  });
132
193
 
133
194
  it('should pass incremental_progress when hasSingleTask is true', async () => {
@@ -140,51 +201,14 @@ describe('Constraint Checker', () => {
140
201
  expect(result.satisfied).toBe(true);
141
202
  });
142
203
 
143
- it('should fail verify_external_capability when hasExternalCapabilityVerification is undefined', async () => {
144
- const context: ConstraintContext = {
145
- operation: 'api_change',
146
- };
147
-
148
- const result = await constraintChecker.check(IRON_LAWS['verify_external_capability'], context);
149
- expect(result.satisfied).toBe(false);
150
- });
151
-
152
- it('should pass verify_external_capability when hasExternalCapabilityVerification is true', async () => {
153
- const context: ConstraintContext = {
154
- operation: 'api_change',
155
- hasExternalCapabilityVerification: true,
156
- };
157
-
158
- const result = await constraintChecker.check(IRON_LAWS['verify_external_capability'], context);
159
- expect(result.satisfied).toBe(true);
160
- });
161
-
162
- it('should fail no_implementation_without_requirement_review when hasRequirementReview is undefined', async () => {
163
- const context: ConstraintContext = {
164
- operation: 'code_implementation',
165
- };
166
-
167
- const result = await constraintChecker.check(IRON_LAWS['no_implementation_without_requirement_review'], context);
168
- expect(result.satisfied).toBe(false);
169
- });
170
-
171
- it('should pass no_implementation_without_requirement_review when hasRequirementReview is true', async () => {
172
- const context: ConstraintContext = {
173
- operation: 'code_implementation',
174
- hasRequirementReview: true,
175
- };
176
-
177
- const result = await constraintChecker.check(IRON_LAWS['no_implementation_without_requirement_review'], context);
178
- expect(result.satisfied).toBe(true);
179
- });
180
-
181
- it('should fail no_implementation_without_requirement when hasRequirement is undefined', async () => {
204
+ it('should skip no_implementation_without_requirement when hasRequirement is undefined(未接线不评估)', async () => {
182
205
  const context: ConstraintContext = {
183
206
  operation: 'code_implementation',
184
207
  };
185
208
 
186
209
  const result = await constraintChecker.check(IRON_LAWS['no_implementation_without_requirement'], context);
187
- expect(result.satisfied).toBe(false);
210
+ expect(result.skipped).toBe(true);
211
+ expect(result.satisfied).toBe(true);
188
212
  });
189
213
 
190
214
  it('should pass no_implementation_without_requirement when hasRequirement is true', async () => {
@@ -211,9 +235,9 @@ describe('Constraint Levels', () => {
211
235
  });
212
236
  });
213
237
 
214
- it('should have correct level for tips', () => {
215
- Object.values(TIPS).forEach(tip => {
216
- expect(tip.level).toBe('tip');
238
+ it('should have correct level for prompts', () => {
239
+ Object.values(PROMPTS).forEach(prompt => {
240
+ expect(prompt.level).toBe('prompt');
217
241
  });
218
242
  });
219
243
  });