@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,13 @@
1
1
  /**
2
2
  * checker.ts 测试
3
+ *
4
+ * ADR-0001:只覆盖存活 check 约束的 checker 行为;
5
+ * prompt 类约束的短路语义见 'Prompt constraints' 一节;
6
+ * 已退役/被吸收约束的用例随之移除。
3
7
  */
4
8
 
5
- import { ConstraintChecker, checkConstraints, checkConstraint } from '../core/constraints/checker';
9
+ import { ConstraintChecker, checkConstraint } from '../core/constraints/checker';
10
+ import { PROMPTS } from '../core/constraints/definitions';
6
11
  import type { ConstraintContext } from '../types/constraint';
7
12
  import { writeFileSync, mkdirSync, rmSync } from 'fs';
8
13
  import { join } from 'path';
@@ -37,7 +42,7 @@ describe('ConstraintChecker', () => {
37
42
  };
38
43
 
39
44
  const result = await checker.check(
40
- { id: 'no_bypass_checkpoint', level: 'iron_law', rule: 'NO BYPASS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
45
+ { id: 'no_bypass_checkpoint', kind: 'check', level: 'guideline', rule: 'NO BYPASS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
41
46
  context
42
47
  );
43
48
 
@@ -54,38 +59,13 @@ describe('ConstraintChecker', () => {
54
59
  };
55
60
 
56
61
  const result = await checker.check(
57
- { id: 'no_bypass_checkpoint', level: 'iron_law', rule: 'NO BYPASS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
62
+ { id: 'no_bypass_checkpoint', kind: 'check', level: 'guideline', rule: 'NO BYPASS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
58
63
  context
59
64
  );
60
65
 
61
66
  expect(result.satisfied).toBe(true);
62
67
  });
63
68
 
64
- it('should check no_self_approval with test evidence', async () => {
65
- const contextWithTest: ConstraintContext = {
66
- operation: 'code_implementation',
67
- hasTest: true,
68
- };
69
-
70
- const contextWithoutTest: ConstraintContext = {
71
- operation: 'code_implementation',
72
- hasTest: false,
73
- };
74
-
75
- const resultWithTest = await checker.check(
76
- { id: 'no_self_approval', level: 'iron_law', rule: 'NO SELF APPROVAL', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
77
- contextWithTest
78
- );
79
-
80
- const resultWithoutTest = await checker.check(
81
- { id: 'no_self_approval', level: 'iron_law', rule: 'NO SELF APPROVAL', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
82
- contextWithoutTest
83
- );
84
-
85
- expect(resultWithTest.satisfied).toBe(true);
86
- expect(resultWithoutTest.satisfied).toBe(false);
87
- });
88
-
89
69
  it('should check no_completion_without_verification', async () => {
90
70
  const contextWithEvidence: ConstraintContext = {
91
71
  operation: 'code_implementation',
@@ -98,158 +78,19 @@ describe('ConstraintChecker', () => {
98
78
  };
99
79
 
100
80
  const resultWithEvidence = await checker.check(
101
- { id: 'no_completion_without_verification', level: 'iron_law', rule: 'NO COMPLETION', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
81
+ { id: 'no_completion_without_verification', kind: 'check', level: 'iron_law', rule: 'NO COMPLETION', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
102
82
  contextWithEvidence
103
83
  );
104
84
 
105
85
  const resultWithoutEvidence = await checker.check(
106
- { id: 'no_completion_without_verification', level: 'iron_law', rule: 'NO COMPLETION', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
86
+ { id: 'no_completion_without_verification', kind: 'check', level: 'iron_law', rule: 'NO COMPLETION', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
107
87
  contextWithoutEvidence
108
88
  );
109
89
 
110
90
  expect(resultWithEvidence.satisfied).toBe(true);
111
91
  expect(resultWithoutEvidence.satisfied).toBe(false);
112
92
  });
113
- });
114
-
115
- describe('Guidelines', () => {
116
- it('should check no_any_type with any in file', async () => {
117
- const anyFile = join(tempDir, 'any-test.ts');
118
- writeFileSync(anyFile, 'const x: any = "test";');
119
-
120
- const context: ConstraintContext = {
121
- operation: 'code_implementation',
122
- changedFiles: [anyFile],
123
- };
124
-
125
- const result = await checker.check(
126
- { id: 'no_any_type', level: 'guideline', rule: 'NO ANY', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
127
- context
128
- );
129
-
130
- expect(result.satisfied).toBe(false);
131
- });
132
-
133
- it('should pass no_any_type without any type', async () => {
134
- const safeFile = join(tempDir, 'safe-test.ts');
135
- writeFileSync(safeFile, 'const x: string = "test";');
136
-
137
- const context: ConstraintContext = {
138
- operation: 'code_implementation',
139
- changedFiles: [safeFile],
140
- };
141
-
142
- const result = await checker.check(
143
- { id: 'no_any_type', level: 'guideline', rule: 'NO ANY', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
144
- context
145
- );
146
-
147
- expect(result.satisfied).toBe(true);
148
- });
149
-
150
- it('should check capability_sync without CAPABILITIES.md', async () => {
151
- // 注意:tempDir 在 harness 仓库内,如果有缓存的变更,会检查到代码变更
152
- // 所以需要创建一个无代码变更的场景或创建 CAPABILITIES.md
153
- const context: ConstraintContext = {
154
- operation: 'commit',
155
- projectPath: tempDir,
156
- };
157
-
158
- // 创建 CAPABILITIES.md 文件确保测试通过
159
- const fs = require('fs');
160
- const path = require('path');
161
- const capabilitiesPath = path.join(tempDir, 'CAPABILITIES.md');
162
- fs.writeFileSync(capabilitiesPath, '# Capabilities\n');
163
-
164
- const result = await checker.check(
165
- { id: 'capability_sync', level: 'guideline', rule: 'CAPABILITY SYNC', message: 'test', trigger: 'commit', enforcement: 'test' },
166
- context
167
- );
168
-
169
- // 有 CAPABILITIES.md 文件,应该通过
170
- expect(result.satisfied).toBe(true);
171
-
172
- // 清理
173
- fs.unlinkSync(capabilitiesPath);
174
- });
175
-
176
- it('should check no_fix_without_root_cause', async () => {
177
- const contextWithInvestigation: ConstraintContext = {
178
- operation: 'code_implementation',
179
- hasRootCauseInvestigation: true,
180
- };
181
-
182
- const contextWithoutInvestigation: ConstraintContext = {
183
- operation: 'code_implementation',
184
- hasRootCauseInvestigation: false,
185
- };
186
-
187
- const resultWith = await checker.check(
188
- { id: 'no_fix_without_root_cause', level: 'guideline', rule: 'NO FIX', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
189
- contextWithInvestigation
190
- );
191
-
192
- const resultWithout = await checker.check(
193
- { id: 'no_fix_without_root_cause', level: 'guideline', rule: 'NO FIX', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
194
- contextWithoutInvestigation
195
- );
196
-
197
- expect(resultWith.satisfied).toBe(true);
198
- expect(resultWithout.satisfied).toBe(false);
199
- });
200
-
201
- it('should check no_code_without_test', async () => {
202
- const contextWithFailingTest: ConstraintContext = {
203
- operation: 'code_implementation',
204
- hasFailingTest: true,
205
- };
206
-
207
- const contextWithoutTest: ConstraintContext = {
208
- operation: 'code_implementation',
209
- hasFailingTest: false,
210
- };
211
-
212
- const resultWith = await checker.check(
213
- { id: 'no_code_without_test', level: 'guideline', rule: 'NO CODE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
214
- contextWithFailingTest
215
- );
216
-
217
- const resultWithout = await checker.check(
218
- { id: 'no_code_without_test', level: 'guideline', rule: 'NO CODE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
219
- contextWithoutTest
220
- );
221
-
222
- expect(resultWith.satisfied).toBe(true);
223
- expect(resultWithout.satisfied).toBe(false);
224
- });
225
-
226
- it('should check reuse-first guidelines', async () => {
227
- const contextWithReuseCheck: ConstraintContext = {
228
- operation: 'code_implementation',
229
- hasReuseCheck: true,
230
- };
231
-
232
- const contextWithoutReuseCheck: ConstraintContext = {
233
- operation: 'code_implementation',
234
- hasReuseCheck: false,
235
- };
236
-
237
- const resultWith = await checker.check(
238
- { id: 'no_creation_without_reuse_check', level: 'guideline', rule: 'REUSE FIRST', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
239
- contextWithReuseCheck
240
- );
241
-
242
- const resultWithout = await checker.check(
243
- { id: 'no_creation_without_reuse_check', level: 'guideline', rule: 'REUSE FIRST', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
244
- contextWithoutReuseCheck
245
- );
246
-
247
- expect(resultWith.satisfied).toBe(true);
248
- expect(resultWithout.satisfied).toBe(false);
249
- });
250
- });
251
93
 
252
- describe('New Iron Laws', () => {
253
94
  it('should check incremental_progress', async () => {
254
95
  const contextWithSingleTask: ConstraintContext = {
255
96
  operation: 'code_implementation',
@@ -262,12 +103,12 @@ describe('ConstraintChecker', () => {
262
103
  };
263
104
 
264
105
  const resultWith = await checker.check(
265
- { id: 'incremental_progress', level: 'iron_law', rule: 'ONE TASK', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
106
+ { id: 'incremental_progress', kind: 'check', level: 'iron_law', rule: 'ONE TASK', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
266
107
  contextWithSingleTask
267
108
  );
268
109
 
269
110
  const resultWithout = await checker.check(
270
- { id: 'incremental_progress', level: 'iron_law', rule: 'ONE TASK', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
111
+ { id: 'incremental_progress', kind: 'check', level: 'iron_law', rule: 'ONE TASK', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
271
112
  contextWithMultipleTasks
272
113
  );
273
114
 
@@ -275,67 +116,71 @@ describe('ConstraintChecker', () => {
275
116
  expect(resultWithout.satisfied).toBe(false);
276
117
  });
277
118
 
278
- it('should check verify_external_capability', async () => {
279
- const contextVerified: ConstraintContext = {
280
- operation: 'api_change',
281
- hasExternalCapabilityVerification: true,
119
+ it('should check no_implementation_without_requirement', async () => {
120
+ const contextWithRequirement: ConstraintContext = {
121
+ operation: 'code_implementation',
122
+ hasRequirement: true,
282
123
  };
283
124
 
284
- const contextNotVerified: ConstraintContext = {
285
- operation: 'api_change',
286
- hasExternalCapabilityVerification: false,
125
+ const contextWithoutRequirement: ConstraintContext = {
126
+ operation: 'code_implementation',
127
+ hasRequirement: false,
287
128
  };
288
129
 
289
- const resultVerified = await checker.check(
290
- { id: 'verify_external_capability', level: 'iron_law', rule: 'VERIFY', message: 'test', trigger: 'api_change', enforcement: 'test' },
291
- contextVerified
130
+ const resultWith = await checker.check(
131
+ { id: 'no_implementation_without_requirement', kind: 'check', level: 'iron_law', rule: 'REQ EXISTS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
132
+ contextWithRequirement
292
133
  );
293
134
 
294
- const resultNotVerified = await checker.check(
295
- { id: 'verify_external_capability', level: 'iron_law', rule: 'VERIFY', message: 'test', trigger: 'api_change', enforcement: 'test' },
296
- contextNotVerified
135
+ const resultWithout = await checker.check(
136
+ { id: 'no_implementation_without_requirement', kind: 'check', level: 'iron_law', rule: 'REQ EXISTS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
137
+ contextWithoutRequirement
297
138
  );
298
139
 
299
- expect(resultVerified.satisfied).toBe(true);
300
- expect(resultNotVerified.satisfied).toBe(false);
140
+ expect(resultWith.satisfied).toBe(true);
141
+ expect(resultWithout.satisfied).toBe(false);
301
142
  });
302
143
  });
303
144
 
304
- describe('Exception handling', () => {
305
- it('should apply exception for no_fix_without_root_cause with simple_typo', async () => {
145
+ describe('Guidelines', () => {
146
+ it('should check capability_sync without CAPABILITIES.md', async () => {
147
+ // 注意:tempDir 在 harness 仓库内,如果有缓存的变更,会检查到代码变更
148
+ // 所以需要创建一个无代码变更的场景或创建 CAPABILITIES.md
306
149
  const context: ConstraintContext = {
307
- operation: 'code_implementation',
308
- hasRootCauseInvestigation: false,
309
- isSimpleTypo: true,
150
+ operation: 'commit',
151
+ projectPath: tempDir,
310
152
  };
311
153
 
154
+ // 创建 CAPABILITIES.md 文件确保测试通过
155
+ const fs = require('fs');
156
+ const path = require('path');
157
+ const capabilitiesPath = path.join(tempDir, 'CAPABILITIES.md');
158
+ fs.writeFileSync(capabilitiesPath, '# Capabilities\n');
159
+
312
160
  const result = await checker.check(
313
- {
314
- id: 'no_fix_without_root_cause',
315
- level: 'guideline',
316
- rule: 'NO FIX',
317
- message: 'test',
318
- trigger: 'code_implementation',
319
- enforcement: 'test',
320
- exceptions: ['simple_typo'],
321
- },
161
+ { id: 'capability_sync', kind: 'check', level: 'guideline', rule: 'CAPABILITY SYNC', message: 'test', trigger: 'commit', enforcement: 'test' },
322
162
  context
323
163
  );
324
164
 
165
+ // 有 CAPABILITIES.md 文件,应该通过
325
166
  expect(result.satisfied).toBe(true);
326
- expect(result.message).toContain('豁免');
167
+
168
+ // 清理
169
+ fs.unlinkSync(capabilitiesPath);
327
170
  });
171
+ });
328
172
 
173
+ describe('Exception handling', () => {
329
174
  it('should apply exception for scalability_required', async () => {
330
175
  const context: ConstraintContext = {
331
176
  operation: 'code_implementation',
332
- hasReuseCheck: false,
333
177
  scalabilityRequired: true,
334
178
  };
335
179
 
336
180
  const result = await checker.check(
337
181
  {
338
182
  id: 'simplest_solution_first',
183
+ kind: 'check',
339
184
  level: 'guideline',
340
185
  rule: 'SIMPLEST FIRST',
341
186
  message: 'test',
@@ -352,13 +197,13 @@ describe('ConstraintChecker', () => {
352
197
  it('should apply exception for security_required', async () => {
353
198
  const context: ConstraintContext = {
354
199
  operation: 'code_implementation',
355
- hasReuseCheck: false,
356
200
  securityRequired: true,
357
201
  };
358
202
 
359
203
  const result = await checker.check(
360
204
  {
361
205
  id: 'simplest_solution_first',
206
+ kind: 'check',
362
207
  level: 'guideline',
363
208
  rule: 'SIMPLEST FIRST',
364
209
  message: 'test',
@@ -375,13 +220,13 @@ describe('ConstraintChecker', () => {
375
220
  it('should apply exception for performance_required', async () => {
376
221
  const context: ConstraintContext = {
377
222
  operation: 'code_implementation',
378
- hasReuseCheck: false,
379
223
  performanceRequired: true,
380
224
  };
381
225
 
382
226
  const result = await checker.check(
383
227
  {
384
228
  id: 'simplest_solution_first',
229
+ kind: 'check',
385
230
  level: 'guideline',
386
231
  rule: 'SIMPLEST FIRST',
387
232
  message: 'test',
@@ -398,13 +243,13 @@ describe('ConstraintChecker', () => {
398
243
  it('should apply exception for reliability_required', async () => {
399
244
  const context: ConstraintContext = {
400
245
  operation: 'code_implementation',
401
- hasReuseCheck: false,
402
246
  reliabilityRequired: true,
403
247
  };
404
248
 
405
249
  const result = await checker.check(
406
250
  {
407
251
  id: 'simplest_solution_first',
252
+ kind: 'check',
408
253
  level: 'guideline',
409
254
  rule: 'SIMPLEST FIRST',
410
255
  message: 'test',
@@ -421,13 +266,13 @@ describe('ConstraintChecker', () => {
421
266
  it('should apply exception for config_value_error', async () => {
422
267
  const context: ConstraintContext = {
423
268
  operation: 'code_implementation',
424
- hasRootCauseInvestigation: false,
425
269
  isConfigValueError: true,
426
270
  };
427
271
 
428
272
  const result = await checker.check(
429
273
  {
430
274
  id: 'no_fix_without_root_cause',
275
+ kind: 'check',
431
276
  level: 'guideline',
432
277
  rule: 'NO FIX',
433
278
  message: 'test',
@@ -444,13 +289,13 @@ describe('ConstraintChecker', () => {
444
289
  it('should apply exception for missing_config', async () => {
445
290
  const context: ConstraintContext = {
446
291
  operation: 'code_implementation',
447
- hasRootCauseInvestigation: false,
448
292
  isMissingConfig: true,
449
293
  };
450
294
 
451
295
  const result = await checker.check(
452
296
  {
453
297
  id: 'no_fix_without_root_cause',
298
+ kind: 'check',
454
299
  level: 'guideline',
455
300
  rule: 'NO FIX',
456
301
  message: 'test',
@@ -467,13 +312,13 @@ describe('ConstraintChecker', () => {
467
312
  it('should apply exception for config_file', async () => {
468
313
  const context: ConstraintContext = {
469
314
  operation: 'code_implementation',
470
- hasFailingTest: false,
471
315
  isConfigFile: true,
472
316
  };
473
317
 
474
318
  const result = await checker.check(
475
319
  {
476
320
  id: 'no_code_without_test',
321
+ kind: 'check',
477
322
  level: 'guideline',
478
323
  rule: 'NO CODE',
479
324
  message: 'test',
@@ -490,13 +335,13 @@ describe('ConstraintChecker', () => {
490
335
  it('should apply exception for type_definition', async () => {
491
336
  const context: ConstraintContext = {
492
337
  operation: 'code_implementation',
493
- hasFailingTest: false,
494
338
  isTypeDefinition: true,
495
339
  };
496
340
 
497
341
  const result = await checker.check(
498
342
  {
499
343
  id: 'no_code_without_test',
344
+ kind: 'check',
500
345
  level: 'guideline',
501
346
  rule: 'NO CODE',
502
347
  message: 'test',
@@ -513,13 +358,13 @@ describe('ConstraintChecker', () => {
513
358
  it('should apply exception for simple_accessor', async () => {
514
359
  const context: ConstraintContext = {
515
360
  operation: 'code_implementation',
516
- hasFailingTest: false,
517
361
  isSimpleAccessor: true,
518
362
  };
519
363
 
520
364
  const result = await checker.check(
521
365
  {
522
366
  id: 'no_code_without_test',
367
+ kind: 'check',
523
368
  level: 'guideline',
524
369
  rule: 'NO CODE',
525
370
  message: 'test',
@@ -536,13 +381,13 @@ describe('ConstraintChecker', () => {
536
381
  it('should apply exception for pure_display_component', async () => {
537
382
  const context: ConstraintContext = {
538
383
  operation: 'code_implementation',
539
- hasFailingTest: false,
540
384
  isPureDisplayComponent: true,
541
385
  };
542
386
 
543
387
  const result = await checker.check(
544
388
  {
545
389
  id: 'no_code_without_test',
390
+ kind: 'check',
546
391
  level: 'guideline',
547
392
  rule: 'NO CODE',
548
393
  message: 'test',
@@ -556,75 +401,6 @@ describe('ConstraintChecker', () => {
556
401
  expect(result.satisfied).toBe(true);
557
402
  });
558
403
 
559
- it('should apply exception for json_parse_result', async () => {
560
- const context: ConstraintContext = {
561
- operation: 'code_implementation',
562
- changedFiles: [],
563
- isJsonParseResult: true,
564
- };
565
-
566
- const result = await checker.check(
567
- {
568
- id: 'no_any_type',
569
- level: 'guideline',
570
- rule: 'NO ANY',
571
- message: 'test',
572
- trigger: 'code_implementation',
573
- enforcement: 'test',
574
- exceptions: ['json_parse_result'],
575
- },
576
- context
577
- );
578
-
579
- expect(result.satisfied).toBe(true);
580
- });
581
-
582
- it('should apply exception for third_party_no_types', async () => {
583
- const context: ConstraintContext = {
584
- operation: 'code_implementation',
585
- changedFiles: [],
586
- isThirdPartyNoTypes: true,
587
- };
588
-
589
- const result = await checker.check(
590
- {
591
- id: 'no_any_type',
592
- level: 'guideline',
593
- rule: 'NO ANY',
594
- message: 'test',
595
- trigger: 'code_implementation',
596
- enforcement: 'test',
597
- exceptions: ['third_party_no_types'],
598
- },
599
- context
600
- );
601
-
602
- expect(result.satisfied).toBe(true);
603
- });
604
-
605
- it('should apply exception for legacy_migration', async () => {
606
- const context: ConstraintContext = {
607
- operation: 'code_implementation',
608
- changedFiles: [],
609
- isLegacyMigration: true,
610
- };
611
-
612
- const result = await checker.check(
613
- {
614
- id: 'no_any_type',
615
- level: 'guideline',
616
- rule: 'NO ANY',
617
- message: 'test',
618
- trigger: 'code_implementation',
619
- enforcement: 'test',
620
- exceptions: ['legacy_migration'],
621
- },
622
- context
623
- );
624
-
625
- expect(result.satisfied).toBe(true);
626
- });
627
-
628
404
  it('should apply exception for internal_refactor', async () => {
629
405
  const context: ConstraintContext = {
630
406
  operation: 'commit',
@@ -635,6 +411,7 @@ describe('ConstraintChecker', () => {
635
411
  const result = await checker.check(
636
412
  {
637
413
  id: 'capability_sync',
414
+ kind: 'check',
638
415
  level: 'guideline',
639
416
  rule: 'CAPABILITY SYNC',
640
417
  message: 'test',
@@ -658,6 +435,7 @@ describe('ConstraintChecker', () => {
658
435
  const result = await checker.check(
659
436
  {
660
437
  id: 'capability_sync',
438
+ kind: 'check',
661
439
  level: 'guideline',
662
440
  rule: 'CAPABILITY SYNC',
663
441
  message: 'test',
@@ -681,6 +459,7 @@ describe('ConstraintChecker', () => {
681
459
  const result = await checker.check(
682
460
  {
683
461
  id: 'capability_sync',
462
+ kind: 'check',
684
463
  level: 'guideline',
685
464
  rule: 'CAPABILITY SYNC',
686
465
  message: 'test',
@@ -704,6 +483,7 @@ describe('ConstraintChecker', () => {
704
483
  const result = await checker.check(
705
484
  {
706
485
  id: 'no_simplification_without_approval',
486
+ kind: 'check',
707
487
  level: 'guideline',
708
488
  rule: 'NO SIMPLIFICATION',
709
489
  message: 'test',
@@ -727,6 +507,7 @@ describe('ConstraintChecker', () => {
727
507
  const result = await checker.check(
728
508
  {
729
509
  id: 'no_simplification_without_approval',
510
+ kind: 'check',
730
511
  level: 'guideline',
731
512
  rule: 'NO SIMPLIFICATION',
732
513
  message: 'test',
@@ -750,6 +531,7 @@ describe('ConstraintChecker', () => {
750
531
  const result = await checker.check(
751
532
  {
752
533
  id: 'no_simplification_without_approval',
534
+ kind: 'check',
753
535
  level: 'guideline',
754
536
  rule: 'NO SIMPLIFICATION',
755
537
  message: 'test',
@@ -764,472 +546,53 @@ describe('ConstraintChecker', () => {
764
546
  });
765
547
  });
766
548
 
767
- describe('Helper functions', () => {
768
- it('should check single constraint via checkConstraint', async () => {
769
- const context: ConstraintContext = {
770
- operation: 'code_implementation',
771
- hasTest: true,
772
- };
773
-
774
- const result = await checkConstraint('no_self_approval', context);
775
- expect(result.satisfied).toBe(true);
549
+ describe('Prompt constraints(ADR-0001:不执行 checker,check() 短路 satisfied)', () => {
550
+ it('所有内置 prompt 约束 check() 均短路通过', async () => {
551
+ const context: ConstraintContext = { operation: 'code_implementation' };
552
+ for (const prompt of Object.values(PROMPTS)) {
553
+ const result = await checker.check(prompt, context);
554
+ expect(result.satisfied).toBe(true);
555
+ }
776
556
  });
777
557
 
778
- it('should return false for unknown constraint', async () => {
779
- const context: ConstraintContext = {
780
- operation: 'code_implementation',
781
- };
782
-
783
- const result = await checkConstraint('unknown_constraint', context);
784
- expect(result.satisfied).toBe(false);
785
- expect(result.message).toContain('未知的约束');
558
+ it('prompt 短路不产生 requiredAction/message', async () => {
559
+ const context: ConstraintContext = { operation: 'code_implementation' };
560
+ const result = await checker.check(PROMPTS['no_fix_without_root_cause'], context);
561
+ expect(result.satisfied).toBe(true);
562
+ expect(result.message).toBeUndefined();
563
+ expect(result.requiredAction).toBeUndefined();
786
564
  });
787
565
  });
788
566
 
789
- describe('Text pattern constraints', () => {
790
- it('no_fuzzy_completion_claim should detect Chinese fuzzy words', async () => {
791
- const context: ConstraintContext = {
792
- operation: 'code_implementation',
793
- completionClaimText: '应该没问题,大概完成了',
794
- };
795
-
796
- const result = await checker.check(
797
- { id: 'no_fuzzy_completion_claim', level: 'iron_law', rule: 'NO FUZZY', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
798
- context
799
- );
800
-
801
- expect(result.satisfied).toBe(false);
802
- });
803
-
804
- it('no_fuzzy_completion_claim should pass clean text', async () => {
567
+ describe('Helper functions', () => {
568
+ it('should check single constraint via checkConstraint', async () => {
805
569
  const context: ConstraintContext = {
806
570
  operation: 'code_implementation',
807
- completionClaimText: '142 tests passed, coverage 87.3%',
571
+ hasVerificationEvidence: true,
808
572
  };
809
573
 
810
- const result = await checker.check(
811
- { id: 'no_fuzzy_completion_claim', level: 'iron_law', rule: 'NO FUZZY', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
812
- context
813
- );
814
-
574
+ const result = await checkConstraint('no_completion_without_verification', context);
815
575
  expect(result.satisfied).toBe(true);
816
576
  });
817
577
 
818
- it('no_fuzzy_completion_claim should pass with empty text', async () => {
578
+ it('prompt 约束经 checkConstraint 短路通过', async () => {
819
579
  const context: ConstraintContext = {
820
580
  operation: 'code_implementation',
821
- completionClaimText: '',
822
581
  };
823
582
 
824
- const result = await checker.check(
825
- { id: 'no_fuzzy_completion_claim', level: 'iron_law', rule: 'NO FUZZY', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
826
- context
827
- );
828
-
583
+ const result = await checkConstraint('no_fuzzy_completion_claim', context);
584
+ expect(result.id).toBe('no_fuzzy_completion_claim');
829
585
  expect(result.satisfied).toBe(true);
830
586
  });
831
587
 
832
- it('no_performative_agreement should detect performative patterns', async () => {
588
+ it('should return false for unknown constraint', async () => {
833
589
  const context: ConstraintContext = {
834
- operation: 'design_request',
835
- taskDescription: '好的,我来做',
590
+ operation: 'code_implementation',
836
591
  };
837
592
 
838
- const result = await checker.check(
839
- { id: 'no_performative_agreement', level: 'iron_law', rule: 'NO PERFORMATIVE', message: 'test', trigger: 'design_request', enforcement: 'test' },
840
- context
841
- );
842
-
593
+ const result = await checkConstraint('unknown_constraint', context);
843
594
  expect(result.satisfied).toBe(false);
844
- });
845
-
846
- it('no_performative_agreement should pass with analysis', async () => {
847
- const context: ConstraintContext = {
848
- operation: 'design_request',
849
- taskDescription: 'This is a detailed analysis of the problem with multiple considerations and proposed solutions.',
850
- };
851
-
852
- const result = await checker.check(
853
- { id: 'no_performative_agreement', level: 'iron_law', rule: 'NO PERFORMATIVE', message: 'test', trigger: 'design_request', enforcement: 'test' },
854
- context
855
- );
856
-
857
- expect(result.satisfied).toBe(true);
858
- });
859
-
860
- it('no_claim_without_evidence should pass with verification evidence', async () => {
861
- const context: ConstraintContext = {
862
- operation: 'code_implementation',
863
- hasVerificationEvidence: true,
864
- };
865
-
866
- const result = await checker.check(
867
- { id: 'no_claim_without_evidence', level: 'guideline', rule: 'NO CLAIM', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
868
- context
869
- );
870
-
871
- expect(result.satisfied).toBe(true);
872
- });
873
-
874
- it('no_claim_without_evidence should pass with taskDescription containing test', async () => {
875
- const context: ConstraintContext = {
876
- operation: 'code_implementation',
877
- hasVerificationEvidence: false,
878
- taskDescription: 'Need to run the test suite to verify',
879
- };
880
-
881
- const result = await checker.check(
882
- { id: 'no_claim_without_evidence', level: 'guideline', rule: 'NO CLAIM', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
883
- context
884
- );
885
-
886
- expect(result.satisfied).toBe(true);
887
- });
888
-
889
- it('no_claim_without_evidence should fail without evidence', async () => {
890
- const context: ConstraintContext = {
891
- operation: 'code_implementation',
892
- hasVerificationEvidence: false,
893
- hasTest: false,
894
- taskDescription: 'Did some work',
895
- };
896
-
897
- const result = await checker.check(
898
- { id: 'no_claim_without_evidence', level: 'guideline', rule: 'NO CLAIM', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
899
- context
900
- );
901
-
902
- expect(result.satisfied).toBe(false);
903
- });
904
-
905
- it('no_delete_without_context should pass with requirement review', async () => {
906
- const context: ConstraintContext = {
907
- operation: 'file_deletion',
908
- hasRequirementReview: true,
909
- };
910
-
911
- const result = await checker.check(
912
- { id: 'no_delete_without_context', level: 'guideline', rule: 'NO DELETE', message: 'test', trigger: 'file_deletion', enforcement: 'test' },
913
- context
914
- );
915
-
916
- expect(result.satisfied).toBe(true);
917
- });
918
-
919
- it('no_delete_without_context should pass with existing design', async () => {
920
- const context: ConstraintContext = {
921
- operation: 'file_deletion',
922
- hasRequirementReview: false,
923
- hasRequirement: false,
924
- isExistingDesign: true,
925
- };
926
-
927
- const result = await checker.check(
928
- { id: 'no_delete_without_context', level: 'guideline', rule: 'NO DELETE', message: 'test', trigger: 'file_deletion', enforcement: 'test' },
929
- context
930
- );
931
-
932
- expect(result.satisfied).toBe(true);
933
- });
934
-
935
- it('no_delete_without_context should fail without any context', async () => {
936
- const context: ConstraintContext = {
937
- operation: 'file_deletion',
938
- hasRequirementReview: false,
939
- hasRequirement: false,
940
- isExistingDesign: false,
941
- };
942
-
943
- const result = await checker.check(
944
- { id: 'no_delete_without_context', level: 'guideline', rule: 'NO DELETE', message: 'test', trigger: 'file_deletion', enforcement: 'test' },
945
- context
946
- );
947
-
948
- expect(result.satisfied).toBe(false);
949
- });
950
- });
951
-
952
- describe('Behavior guidelines (always true)', () => {
953
- it('surgical_changes_only should return true', async () => {
954
- const context: ConstraintContext = { operation: 'code_implementation' };
955
- const result = await checker.check(
956
- { id: 'surgical_changes_only', level: 'guideline', rule: 'SURGICAL', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
957
- context
958
- );
959
- expect(result.satisfied).toBe(true);
960
- });
961
-
962
- it('no_model_for_deterministic should return true', async () => {
963
- const context: ConstraintContext = { operation: 'code_implementation' };
964
- const result = await checker.check(
965
- { id: 'no_model_for_deterministic', level: 'guideline', rule: 'NO MODEL', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
966
- context
967
- );
968
- expect(result.satisfied).toBe(true);
969
- });
970
-
971
- it('no_conflict_blending should return true', async () => {
972
- const context: ConstraintContext = { operation: 'code_implementation' };
973
- const result = await checker.check(
974
- { id: 'no_conflict_blending', level: 'guideline', rule: 'NO BLEND', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
975
- context
976
- );
977
- expect(result.satisfied).toBe(true);
978
- });
979
-
980
- it('read_before_write should return true', async () => {
981
- const context: ConstraintContext = { operation: 'code_implementation' };
982
- const result = await checker.check(
983
- { id: 'read_before_write', level: 'guideline', rule: 'READ FIRST', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
984
- context
985
- );
986
- expect(result.satisfied).toBe(true);
987
- });
988
-
989
- it('first_principles_first should return true', async () => {
990
- const context: ConstraintContext = { operation: 'code_implementation' };
991
- const result = await checker.check(
992
- { id: 'first_principles_first', level: 'guideline', rule: 'PRINCIPLES', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
993
- context
994
- );
995
- expect(result.satisfied).toBe(true);
996
- });
997
-
998
- it('fix_the_problem_not_the_gate should return true', async () => {
999
- const context: ConstraintContext = { operation: 'code_implementation' };
1000
- const result = await checker.check(
1001
- { id: 'fix_the_problem_not_the_gate', level: 'guideline', rule: 'FIX PROBLEM', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1002
- context
1003
- );
1004
- expect(result.satisfied).toBe(true);
1005
- });
1006
-
1007
- it('diagnosis_to_fix_gate should return true', async () => {
1008
- const context: ConstraintContext = { operation: 'code_implementation' };
1009
- const result = await checker.check(
1010
- { id: 'diagnosis_to_fix_gate', level: 'guideline', rule: 'DIAGNOSIS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1011
- context
1012
- );
1013
- expect(result.satisfied).toBe(true);
1014
- });
1015
-
1016
- it('follow_conventions should return true', async () => {
1017
- const context: ConstraintContext = { operation: 'code_implementation' };
1018
- const result = await checker.check(
1019
- { id: 'follow_conventions', level: 'guideline', rule: 'CONVENTIONS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1020
- context
1021
- );
1022
- expect(result.satisfied).toBe(true);
1023
- });
1024
- });
1025
-
1026
- describe('Default guideline constraints', () => {
1027
- it('no_hardcoded_credentials should pass by default', async () => {
1028
- const context: ConstraintContext = { operation: 'code_implementation' };
1029
- const result = await checker.check(
1030
- { id: 'no_hardcoded_credentials', level: 'guideline', rule: 'NO CREDENTIALS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1031
- context
1032
- );
1033
- expect(result.satisfied).toBe(true);
1034
- });
1035
-
1036
- it('design_decision_requires_discussion should pass by default', async () => {
1037
- const context: ConstraintContext = { operation: 'code_implementation' };
1038
- const result = await checker.check(
1039
- { id: 'design_decision_requires_discussion', level: 'guideline', rule: 'DISCUSS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1040
- context
1041
- );
1042
- expect(result.satisfied).toBe(true);
1043
- });
1044
- });
1045
-
1046
- describe('Additional Iron Laws (pure context)', () => {
1047
- it('no_implementation_without_requirement_review should pass with review', async () => {
1048
- const context: ConstraintContext = { operation: 'code_implementation', hasRequirementReview: true };
1049
- const result = await checker.check(
1050
- { id: 'no_implementation_without_requirement_review', level: 'iron_law', rule: 'REVIEW REQ', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1051
- context
1052
- );
1053
- expect(result.satisfied).toBe(true);
1054
- });
1055
-
1056
- it('no_implementation_without_requirement_review should fail without review', async () => {
1057
- const context: ConstraintContext = { operation: 'code_implementation', hasRequirementReview: false };
1058
- const result = await checker.check(
1059
- { id: 'no_implementation_without_requirement_review', level: 'iron_law', rule: 'REVIEW REQ', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1060
- context
1061
- );
1062
- expect(result.satisfied).toBe(false);
1063
- });
1064
-
1065
- it('no_implementation_without_requirement should pass with requirement', async () => {
1066
- const context: ConstraintContext = { operation: 'code_implementation', hasRequirement: true };
1067
- const result = await checker.check(
1068
- { id: 'no_implementation_without_requirement', level: 'iron_law', rule: 'REQ EXISTS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1069
- context
1070
- );
1071
- expect(result.satisfied).toBe(true);
1072
- });
1073
-
1074
- it('no_implementation_without_requirement should fail without requirement', async () => {
1075
- const context: ConstraintContext = { operation: 'code_implementation', hasRequirement: false };
1076
- const result = await checker.check(
1077
- { id: 'no_implementation_without_requirement', level: 'iron_law', rule: 'REQ EXISTS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1078
- context
1079
- );
1080
- expect(result.satisfied).toBe(false);
1081
- });
1082
-
1083
- it('prefer_worktree should pass with worktree', async () => {
1084
- const context: ConstraintContext = { operation: 'code_implementation', hasWorktree: true };
1085
- const result = await checker.check(
1086
- { id: 'prefer_worktree', level: 'guideline', rule: 'WORKTREE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1087
- context
1088
- );
1089
- expect(result.satisfied).toBe(true);
1090
- });
1091
-
1092
- it('prefer_worktree should fail without worktree', async () => {
1093
- const context: ConstraintContext = { operation: 'code_implementation', hasWorktree: false };
1094
- const result = await checker.check(
1095
- { id: 'prefer_worktree', level: 'guideline', rule: 'WORKTREE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1096
- context
1097
- );
1098
- expect(result.satisfied).toBe(false);
1099
- });
1100
-
1101
- it('two_stage_review_required should pass with two-stage review', async () => {
1102
- const context: ConstraintContext = { operation: 'code_implementation', hasTwoStageReview: true };
1103
- const result = await checker.check(
1104
- { id: 'two_stage_review_required', level: 'iron_law', rule: 'TWO STAGE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1105
- context
1106
- );
1107
- expect(result.satisfied).toBe(true);
1108
- });
1109
-
1110
- it('two_stage_review_required should fail without two-stage review', async () => {
1111
- const context: ConstraintContext = { operation: 'code_implementation', hasTwoStageReview: false };
1112
- const result = await checker.check(
1113
- { id: 'two_stage_review_required', level: 'iron_law', rule: 'TWO STAGE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1114
- context
1115
- );
1116
- expect(result.satisfied).toBe(false);
1117
- });
1118
- });
1119
-
1120
- describe('Additional guidelines (pure context)', () => {
1121
- it('no_skill_without_test should pass with test', async () => {
1122
- const context: ConstraintContext = { operation: 'module_creation', hasTest: true };
1123
- const result = await checker.check(
1124
- { id: 'no_skill_without_test', level: 'guideline', rule: 'SKILL TEST', message: 'test', trigger: 'module_creation', enforcement: 'test' },
1125
- context
1126
- );
1127
- expect(result.satisfied).toBe(true);
1128
- });
1129
-
1130
- it('no_skill_without_test should fail without test', async () => {
1131
- const context: ConstraintContext = { operation: 'module_creation', hasTest: false };
1132
- const result = await checker.check(
1133
- { id: 'no_skill_without_test', level: 'guideline', rule: 'SKILL TEST', message: 'test', trigger: 'module_creation', enforcement: 'test' },
1134
- context
1135
- );
1136
- expect(result.satisfied).toBe(false);
1137
- });
1138
-
1139
- it('simplest_solution_first should pass with reuse check', async () => {
1140
- // matches trigger code_implementation
1141
- const context: ConstraintContext = { operation: 'code_implementation', hasReuseCheck: true };
1142
- const result = await checker.check(
1143
- { id: 'simplest_solution_first', level: 'guideline', rule: 'SIMPLEST', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1144
- context
1145
- );
1146
- expect(result.satisfied).toBe(true);
1147
- });
1148
-
1149
- it('simplest_solution_first should fail without reuse check', async () => {
1150
- const context: ConstraintContext = { operation: 'code_implementation', hasReuseCheck: false };
1151
- const result = await checker.check(
1152
- { id: 'simplest_solution_first', level: 'guideline', rule: 'SIMPLEST', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1153
- context
1154
- );
1155
- expect(result.satisfied).toBe(false);
1156
- });
1157
- });
1158
-
1159
- describe('Tip constraints', () => {
1160
- it('readme_required should always pass', async () => {
1161
- const context: ConstraintContext = { operation: 'module_creation' };
1162
- const result = await checker.check(
1163
- { id: 'readme_required', level: 'tip', rule: 'README', message: 'test', trigger: 'module_creation', enforcement: 'test' },
1164
- context
1165
- );
1166
- expect(result.satisfied).toBe(true);
1167
- });
1168
-
1169
- it('doc_required_for_public_api should always pass', async () => {
1170
- const context: ConstraintContext = { operation: 'export_change' };
1171
- const result = await checker.check(
1172
- { id: 'doc_required_for_public_api', level: 'tip', rule: 'DOC', message: 'test', trigger: 'export_change', enforcement: 'test' },
1173
- context
1174
- );
1175
- expect(result.satisfied).toBe(true);
1176
- });
1177
- });
1178
-
1179
- describe('no_excuse_patterns', () => {
1180
- it('should detect excuse patterns in completion claim', async () => {
1181
- const context: ConstraintContext = {
1182
- operation: 'code_implementation',
1183
- completionClaimText: '稍后修复这个bug',
1184
- };
1185
-
1186
- const result = await checker.check(
1187
- { id: 'no_excuse_patterns', level: 'guideline', rule: 'NO EXCUSE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1188
- context
1189
- );
1190
-
1191
- expect(result.satisfied).toBe(false);
1192
- });
1193
-
1194
- it('should detect excuse patterns in task description', async () => {
1195
- const context: ConstraintContext = {
1196
- operation: 'code_implementation',
1197
- taskDescription: '这是个临时方案,先这样',
1198
- };
1199
-
1200
- const result = await checker.check(
1201
- { id: 'no_excuse_patterns', level: 'guideline', rule: 'NO EXCUSE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1202
- context
1203
- );
1204
-
1205
- expect(result.satisfied).toBe(false);
1206
- });
1207
-
1208
- it('should pass with clean text', async () => {
1209
- const context: ConstraintContext = {
1210
- operation: 'code_implementation',
1211
- completionClaimText: 'Fixed by refactoring the validation logic in checker.ts',
1212
- };
1213
-
1214
- const result = await checker.check(
1215
- { id: 'no_excuse_patterns', level: 'guideline', rule: 'NO EXCUSE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1216
- context
1217
- );
1218
-
1219
- expect(result.satisfied).toBe(true);
1220
- });
1221
-
1222
- it('should pass with empty text', async () => {
1223
- const context: ConstraintContext = {
1224
- operation: 'code_implementation',
1225
- };
1226
-
1227
- const result = await checker.check(
1228
- { id: 'no_excuse_patterns', level: 'guideline', rule: 'NO EXCUSE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1229
- context
1230
- );
1231
-
1232
- expect(result.satisfied).toBe(true);
595
+ expect(result.message).toContain('未知的约束');
1233
596
  });
1234
597
  });
1235
- });
598
+ });