@dommaker/harness 0.13.0 → 0.13.2

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 (420) hide show
  1. package/CHANGELOG.md +169 -0
  2. package/bin/harness-knowledge-capture.js +99 -0
  3. package/bin/harness-knowledge-check.js +149 -0
  4. package/bin/harness-knowledge-track.js +92 -0
  5. package/bin/harness-knowledge-track.sh +47 -0
  6. package/bin/harness-sensitive-check.sh +67 -0
  7. package/dist/cli/commands/init.js +34 -2
  8. package/dist/cli/commands/init.js.map +1 -1
  9. package/package.json +6 -3
  10. package/src/CONTEXT.md +34 -0
  11. package/src/__tests__/acceptance-gate.test.ts +364 -0
  12. package/src/__tests__/annotation-checker.test.ts +183 -0
  13. package/src/__tests__/architecture-engine.test.ts +619 -0
  14. package/src/__tests__/checker-extra.test.ts +1627 -0
  15. package/src/__tests__/checker.test.ts +1268 -0
  16. package/src/__tests__/checkpoint.test.ts +697 -0
  17. package/src/__tests__/clean-state-extra.test.ts +301 -0
  18. package/src/__tests__/clean-state.test.ts +169 -0
  19. package/src/__tests__/constraint-doctor.test.ts +410 -0
  20. package/src/__tests__/constraint-evolver.test.ts +404 -0
  21. package/src/__tests__/constraint-handler.test.ts +136 -0
  22. package/src/__tests__/context/progressive-loader.test.ts +131 -0
  23. package/src/__tests__/contract-gate.test.ts +321 -0
  24. package/src/__tests__/cross-project-checker.test.ts +318 -0
  25. package/src/__tests__/cso-validator.test.ts +205 -0
  26. package/src/__tests__/detect-source-roots.test.ts +98 -0
  27. package/src/__tests__/doctor-evolver.test.ts +381 -0
  28. package/src/__tests__/error-classifier.test.ts +304 -0
  29. package/src/__tests__/exec.test.ts +83 -0
  30. package/src/__tests__/extend-exceptions.test.ts +149 -0
  31. package/src/__tests__/failure-recorder.test.ts +335 -0
  32. package/src/__tests__/hooks-pipeline.test.ts +214 -0
  33. package/src/__tests__/interceptor.test.ts +89 -0
  34. package/src/__tests__/iron-laws.test.ts +246 -0
  35. package/src/__tests__/long-running.test.ts +17 -0
  36. package/src/__tests__/passes-gate-check.test.ts +138 -0
  37. package/src/__tests__/passes-gate-extension.test.ts +151 -0
  38. package/src/__tests__/passes-gate-extra.test.ts +238 -0
  39. package/src/__tests__/passes-gate.test.ts +231 -0
  40. package/src/__tests__/performance-analyzer.test.ts +501 -0
  41. package/src/__tests__/performance-collector.test.ts +276 -0
  42. package/src/__tests__/performance-gate.test.ts +74 -0
  43. package/src/__tests__/presets.test.ts +104 -0
  44. package/src/__tests__/project-config-loader-extra.test.ts +269 -0
  45. package/src/__tests__/project-config-loader.test.ts +127 -0
  46. package/src/__tests__/review-gate.test.ts +92 -0
  47. package/src/__tests__/security-gate.test.ts +100 -0
  48. package/src/__tests__/session-startup.test.ts +334 -0
  49. package/src/__tests__/spec-validator.test.ts +57 -0
  50. package/src/__tests__/token-budget.test.ts +252 -0
  51. package/src/__tests__/trace-analyzer-extra.test.ts +307 -0
  52. package/src/__tests__/trace-analyzer.test.ts +131 -0
  53. package/src/__tests__/trace-collector.test.ts +258 -0
  54. package/src/__tests__/traces.test.ts +347 -0
  55. package/src/agents/CONTEXT.md +21 -0
  56. package/src/agents/__tests__/lifecycle.test.ts +248 -0
  57. package/src/agents/index.ts +2 -0
  58. package/src/agents/lifecycle.ts +201 -0
  59. package/src/agents/types.ts +46 -0
  60. package/src/architecture/CONTEXT.md +22 -0
  61. package/src/architecture/constraint-engine.ts +356 -0
  62. package/src/architecture/cross-project-checker.ts +563 -0
  63. package/src/cli/commands/CONTEXT.md +24 -0
  64. package/src/cli/commands/__tests__/acceptance.test.ts +180 -0
  65. package/src/cli/commands/__tests__/check.test.ts +598 -0
  66. package/src/cli/commands/__tests__/command.test.ts +149 -0
  67. package/src/cli/commands/__tests__/contract.test.ts +151 -0
  68. package/src/cli/commands/__tests__/failure.test.ts +199 -0
  69. package/src/cli/commands/__tests__/flow.test.ts +343 -0
  70. package/src/cli/commands/__tests__/init.test.ts +306 -0
  71. package/src/cli/commands/__tests__/passes-gate.test.ts +256 -0
  72. package/src/cli/commands/__tests__/performance.test.ts +116 -0
  73. package/src/cli/commands/__tests__/posteval-plan.test.ts +201 -0
  74. package/src/cli/commands/__tests__/report-extra.test.ts +98 -0
  75. package/src/cli/commands/__tests__/report.test.ts +109 -0
  76. package/src/cli/commands/__tests__/review.test.ts +153 -0
  77. package/src/cli/commands/__tests__/security.test.ts +147 -0
  78. package/src/cli/commands/__tests__/spec.test.ts +193 -0
  79. package/src/cli/commands/__tests__/status-extra.test.ts +223 -0
  80. package/src/cli/commands/__tests__/status.test.ts +306 -0
  81. package/src/cli/commands/__tests__/sync-docs.test.ts +335 -0
  82. package/src/cli/commands/__tests__/validate.test.ts +139 -0
  83. package/src/cli/commands/acceptance.ts +111 -0
  84. package/src/cli/commands/analyze-sessions.ts +488 -0
  85. package/src/cli/commands/check.ts +441 -0
  86. package/src/cli/commands/command.ts +90 -0
  87. package/src/cli/commands/constraints.ts +86 -0
  88. package/src/cli/commands/contract.ts +168 -0
  89. package/src/cli/commands/failure.ts +117 -0
  90. package/src/cli/commands/flow.ts +275 -0
  91. package/src/cli/commands/index.ts +26 -0
  92. package/src/cli/commands/init.ts +832 -0
  93. package/src/cli/commands/knowledge.ts +391 -0
  94. package/src/cli/commands/passes-gate.ts +158 -0
  95. package/src/cli/commands/performance.ts +108 -0
  96. package/src/cli/commands/posteval-plan.ts +85 -0
  97. package/src/cli/commands/release.ts +159 -0
  98. package/src/cli/commands/report.ts +198 -0
  99. package/src/cli/commands/review.ts +118 -0
  100. package/src/cli/commands/security.ts +122 -0
  101. package/src/cli/commands/spec.ts +158 -0
  102. package/src/cli/commands/status.ts +169 -0
  103. package/src/cli/commands/sync-docs.ts +743 -0
  104. package/src/cli/commands/update-user-model.ts +527 -0
  105. package/src/cli/commands/validate.ts +222 -0
  106. package/src/constraints/__tests__/lifecycle-runner.test.ts +246 -0
  107. package/src/constraints/__tests__/registry.test.ts +196 -0
  108. package/src/constraints/index.ts +3 -0
  109. package/src/constraints/lifecycle-runner.ts +184 -0
  110. package/src/constraints/registry.ts +134 -0
  111. package/src/constraints/types.ts +59 -0
  112. package/src/context/CONTEXT.md +28 -0
  113. package/src/context/__tests__/compaction.test.ts +169 -0
  114. package/src/context/__tests__/file-budget.test.ts +142 -0
  115. package/src/context/__tests__/knowledge-injector.test.ts +148 -0
  116. package/src/context/__tests__/progressive-loader.test.ts +264 -0
  117. package/src/context/__tests__/session-manager.test.ts +300 -0
  118. package/src/context/__tests__/token-budget.test.ts +338 -0
  119. package/src/context/__tests__/token-pipeline.test.ts +178 -0
  120. package/src/context/__tests__/tool-output-budget.test.ts +95 -0
  121. package/src/context/compaction.ts +202 -0
  122. package/src/context/file-budget.ts +142 -0
  123. package/src/context/index.ts +15 -0
  124. package/src/context/knowledge-injector.ts +168 -0
  125. package/src/context/progressive-loader.ts +260 -0
  126. package/src/context/session-manager.ts +343 -0
  127. package/src/context/token-budget.ts +295 -0
  128. package/src/context/token-pipeline.ts +265 -0
  129. package/src/context/tool-output-budget.ts +178 -0
  130. package/src/context/types.ts +160 -0
  131. package/src/core/CONTEXT.md +26 -0
  132. package/src/core/constraints/__tests__/default-executors.test.ts +57 -0
  133. package/src/core/constraints/__tests__/interceptor.test.ts +251 -0
  134. package/src/core/constraints/__tests__/prompt-injection.test.ts +89 -0
  135. package/src/core/constraints/check-cache.ts +96 -0
  136. package/src/core/constraints/checker.ts +1169 -0
  137. package/src/core/constraints/default-executors.ts +92 -0
  138. package/src/core/constraints/definitions.ts +1119 -0
  139. package/src/core/constraints/doc-freshness/__tests__/runner.test.ts +551 -0
  140. package/src/core/constraints/doc-freshness/auto-fix.ts +69 -0
  141. package/src/core/constraints/doc-freshness/runner.ts +486 -0
  142. package/src/core/constraints/index.ts +78 -0
  143. package/src/core/constraints/interceptor.ts +220 -0
  144. package/src/core/constraints/prompt-injection.ts +73 -0
  145. package/src/core/index.ts +23 -0
  146. package/src/core/project-config-loader.ts +252 -0
  147. package/src/core/session/__tests__/startup.test.ts +281 -0
  148. package/src/core/session/clean-state.ts +178 -0
  149. package/src/core/session/index.ts +15 -0
  150. package/src/core/session/startup.ts +253 -0
  151. package/src/core/spec/__tests__/validator.test.ts +379 -0
  152. package/src/core/spec/index.ts +7 -0
  153. package/src/core/spec/validator.ts +383 -0
  154. package/src/core/validators/__tests__/passes-gate.test.ts +131 -0
  155. package/src/core/validators/checkpoint.ts +547 -0
  156. package/src/core/validators/cso.ts +124 -0
  157. package/src/core/validators/index.ts +25 -0
  158. package/src/core/validators/passes-gate.ts +613 -0
  159. package/src/dashboard/CONTEXT.md +21 -0
  160. package/src/dashboard/__tests__/data.test.ts +115 -0
  161. package/src/dashboard/__tests__/stats.test.ts +156 -0
  162. package/src/dashboard/data.ts +113 -0
  163. package/src/dashboard/index.ts +3 -0
  164. package/src/dashboard/stats.ts +127 -0
  165. package/src/dashboard/types.ts +113 -0
  166. package/src/evolution/CONTEXT.md +22 -0
  167. package/src/evolution/__tests__/auto-evolve.test.ts +320 -0
  168. package/src/evolution/auto-evolve.ts +98 -0
  169. package/src/evolution/index.ts +1 -0
  170. package/src/failure/CONTEXT.md +24 -0
  171. package/src/failure/classifier.ts +156 -0
  172. package/src/failure/constraint-handler.ts +173 -0
  173. package/src/failure/index.ts +35 -0
  174. package/src/failure/recorder.ts +201 -0
  175. package/src/failure/types.ts +165 -0
  176. package/src/gates/CONTEXT.md +27 -0
  177. package/src/gates/__tests__/acceptance.test.ts +608 -0
  178. package/src/gates/__tests__/command.test.ts +206 -0
  179. package/src/gates/__tests__/performance.test.ts +381 -0
  180. package/src/gates/__tests__/review.test.ts +302 -0
  181. package/src/gates/__tests__/security.test.ts +332 -0
  182. package/src/gates/acceptance.ts +493 -0
  183. package/src/gates/command.ts +444 -0
  184. package/src/gates/contract.ts +260 -0
  185. package/src/gates/index.ts +67 -0
  186. package/src/gates/performance.ts +359 -0
  187. package/src/gates/review.ts +169 -0
  188. package/src/gates/security.ts +244 -0
  189. package/src/gates/types.ts +159 -0
  190. package/src/governance/CONTEXT.md +22 -0
  191. package/src/governance/__tests__/executor.test.ts +249 -0
  192. package/src/governance/executor.ts +229 -0
  193. package/src/governance/index.ts +13 -0
  194. package/src/governance/types.ts +53 -0
  195. package/src/hooks/CONTEXT.md +23 -0
  196. package/src/hooks/__tests__/bootstrap.test.ts +184 -0
  197. package/src/hooks/bootstrap.ts +144 -0
  198. package/src/hooks/index.ts +15 -0
  199. package/src/hooks/pipeline.ts +157 -0
  200. package/src/hooks/registry.ts +88 -0
  201. package/src/hooks/types.ts +80 -0
  202. package/src/index.ts +198 -0
  203. package/src/knowledge/CONTEXT.md +29 -0
  204. package/src/knowledge/__tests__/doctor.test.ts +272 -0
  205. package/src/knowledge/__tests__/import.test.ts +376 -0
  206. package/src/knowledge/__tests__/ingest.test.ts +125 -0
  207. package/src/knowledge/__tests__/lifecycle-hooks.test.ts +137 -0
  208. package/src/knowledge/__tests__/lifecycle.test.ts +248 -0
  209. package/src/knowledge/__tests__/lint.test.ts +401 -0
  210. package/src/knowledge/__tests__/query.test.ts +185 -0
  211. package/src/knowledge/__tests__/reference-tracker.test.ts +129 -0
  212. package/src/knowledge/__tests__/store.test.ts +238 -0
  213. package/src/knowledge/doctor.ts +104 -0
  214. package/src/knowledge/import.ts +505 -0
  215. package/src/knowledge/index.ts +16 -0
  216. package/src/knowledge/ingest.ts +126 -0
  217. package/src/knowledge/lifecycle-hooks.ts +199 -0
  218. package/src/knowledge/lifecycle.ts +175 -0
  219. package/src/knowledge/lint.ts +360 -0
  220. package/src/knowledge/query.ts +150 -0
  221. package/src/knowledge/reference-tracker.ts +99 -0
  222. package/src/knowledge/store.ts +264 -0
  223. package/src/knowledge/types.ts +139 -0
  224. package/src/llm/CONTEXT.md +21 -0
  225. package/src/llm/__tests__/adapter.test.ts +172 -0
  226. package/src/llm/adapter.ts +149 -0
  227. package/src/llm/index.ts +2 -0
  228. package/src/llm/types.ts +81 -0
  229. package/src/monitoring/CONTEXT.md +29 -0
  230. package/src/monitoring/__tests__/context-tracker.test.ts +172 -0
  231. package/src/monitoring/__tests__/knowledge-doctor.test.ts +276 -0
  232. package/src/monitoring/__tests__/knowledge-evolver.test.ts +365 -0
  233. package/src/monitoring/__tests__/performance-analyzer.test.ts +137 -0
  234. package/src/monitoring/__tests__/performance-collector.test.ts +332 -0
  235. package/src/monitoring/__tests__/traces.test.ts +190 -0
  236. package/src/monitoring/constraint-doctor.ts +499 -0
  237. package/src/monitoring/constraint-evolver.ts +573 -0
  238. package/src/monitoring/context-tracker.ts +148 -0
  239. package/src/monitoring/index.ts +23 -0
  240. package/src/monitoring/knowledge-doctor.ts +323 -0
  241. package/src/monitoring/knowledge-evolver.ts +289 -0
  242. package/src/monitoring/performance-analyzer.ts +450 -0
  243. package/src/monitoring/performance-collector.ts +348 -0
  244. package/src/monitoring/trace-analyzer.ts +470 -0
  245. package/src/monitoring/traces.ts +339 -0
  246. package/src/presets/__tests__/standard.test.ts +104 -0
  247. package/src/presets/index.ts +16 -0
  248. package/src/presets/standard.ts +163 -0
  249. package/src/safety/CONTEXT.md +23 -0
  250. package/src/safety/__tests__/input-guardrail.test.ts +105 -0
  251. package/src/safety/__tests__/output-guardrail.test.ts +108 -0
  252. package/src/safety/__tests__/sandbox.test.ts +158 -0
  253. package/src/safety/__tests__/tool-guardrail.test.ts +127 -0
  254. package/src/safety/index.ts +5 -0
  255. package/src/safety/input-guardrail.ts +133 -0
  256. package/src/safety/output-guardrail.ts +174 -0
  257. package/src/safety/sandbox.ts +148 -0
  258. package/src/safety/tool-guardrail.ts +176 -0
  259. package/src/safety/types.ts +124 -0
  260. package/src/spec/CONTEXT.md +19 -0
  261. package/src/spec/__tests__/annotation-checker.test.ts +289 -0
  262. package/src/spec/annotation-checker.ts +342 -0
  263. package/src/tools/CONTEXT.md +25 -0
  264. package/src/tools/__tests__/loader.test.ts +252 -0
  265. package/src/tools/__tests__/registry.test.ts +157 -0
  266. package/src/tools/core/__tests__/core.test.ts +122 -0
  267. package/src/tools/core/index.ts +201 -0
  268. package/src/tools/core/package.json +7 -0
  269. package/src/tools/core/pnpm-lock.yaml +232 -0
  270. package/src/tools/definitions/core/code/fingerprint.sh +273 -0
  271. package/src/tools/definitions/core/code/fingerprint.yml +72 -0
  272. package/src/tools/definitions/core/code/parse.yml +68 -0
  273. package/src/tools/definitions/core/code/register-language.sh +475 -0
  274. package/src/tools/definitions/core/code/register-language.yml +74 -0
  275. package/src/tools/definitions/core/docker/build.yml +73 -0
  276. package/src/tools/definitions/core/docker/run.yml +81 -0
  277. package/src/tools/definitions/core/file/copy.yml +88 -0
  278. package/src/tools/definitions/core/file/read.yml +69 -0
  279. package/src/tools/definitions/core/file/write.yml +75 -0
  280. package/src/tools/definitions/core/git/branch.yml +61 -0
  281. package/src/tools/definitions/core/git/cleanup-worktree.yml +50 -0
  282. package/src/tools/definitions/core/git/clone.yml +69 -0
  283. package/src/tools/definitions/core/git/commit.yml +65 -0
  284. package/src/tools/definitions/core/git/push.yml +79 -0
  285. package/src/tools/definitions/core/git/worktree.yml +96 -0
  286. package/src/tools/definitions/core/notification/notify.sh +152 -0
  287. package/src/tools/definitions/core/notification/notify.yml +60 -0
  288. package/src/tools/definitions/core/npm/build.yml +75 -0
  289. package/src/tools/definitions/core/npm/install.yml +58 -0
  290. package/src/tools/definitions/core/npm/test.yml +75 -0
  291. package/src/tools/definitions/core/validation/check-reuse.yml +170 -0
  292. package/src/tools/definitions/core/validation/validate-handlers.yml +118 -0
  293. package/src/tools/definitions/core/validation/validate-readme-stats.yml +155 -0
  294. package/src/tools/definitions/core/validation/validate-yaml-syntax.yml +134 -0
  295. package/src/tools/definitions/ext/browser/browser-automate.sh +255 -0
  296. package/src/tools/definitions/ext/browser/browser-automate.yml +166 -0
  297. package/src/tools/definitions/ext/browser/browser-close.sh +104 -0
  298. package/src/tools/definitions/ext/browser/browser-close.yml +55 -0
  299. package/src/tools/definitions/ext/browser/browser-mcp-debug.sh +682 -0
  300. package/src/tools/definitions/ext/browser/browser-mcp-debug.yml +167 -0
  301. package/src/tools/definitions/ext/browser/browser-start.sh +101 -0
  302. package/src/tools/definitions/ext/browser/browser-start.yml +62 -0
  303. package/src/tools/definitions/registry.json +795 -0
  304. package/src/tools/definitions/std/README.md +350 -0
  305. package/src/tools/definitions/std/analysis/analyze-codebase.yml +72 -0
  306. package/src/tools/definitions/std/analysis/analyze-diff.yml +182 -0
  307. package/src/tools/definitions/std/analysis/analyze-git-diff.yml +70 -0
  308. package/src/tools/definitions/std/analysis/analyze-impact.yml +78 -0
  309. package/src/tools/definitions/std/analysis/analyze-requirements.yml +105 -0
  310. package/src/tools/definitions/std/analysis/brainstorm-options.yml +106 -0
  311. package/src/tools/definitions/std/analysis/build-graph.yml +154 -0
  312. package/src/tools/definitions/std/analysis/clarify-requirements.yml +90 -0
  313. package/src/tools/definitions/std/analysis/detect-context.yml +109 -0
  314. package/src/tools/definitions/std/analysis/detect-layers.yml +125 -0
  315. package/src/tools/definitions/std/analysis/generate-tour.yml +102 -0
  316. package/src/tools/definitions/std/analysis/search-enhance.yml +105 -0
  317. package/src/tools/definitions/std/backlog/add.yml +51 -0
  318. package/src/tools/definitions/std/backlog/decide.yml +39 -0
  319. package/src/tools/definitions/std/backlog/github-sync.yml +161 -0
  320. package/src/tools/definitions/std/backlog/list.yml +53 -0
  321. package/src/tools/definitions/std/backlog/load.yml +46 -0
  322. package/src/tools/definitions/std/backlog/resolve.yml +37 -0
  323. package/src/tools/definitions/std/backlog/update.yml +42 -0
  324. package/src/tools/definitions/std/bugfix/diagnose.yml +68 -0
  325. package/src/tools/definitions/std/bugfix/fix.yml +66 -0
  326. package/src/tools/definitions/std/bugfix/verify.yml +69 -0
  327. package/src/tools/definitions/std/constraint/check-decomposition.yml +103 -0
  328. package/src/tools/definitions/std/constraint/check-feature-list.yml +77 -0
  329. package/src/tools/definitions/std/constraint/check-progress.yml +97 -0
  330. package/src/tools/definitions/std/constraint/generate-report.yml +147 -0
  331. package/src/tools/definitions/std/deploy/commit-push.yml +33 -0
  332. package/src/tools/definitions/std/deploy/deploy-backend.yml +37 -0
  333. package/src/tools/definitions/std/deploy/deploy-frontend.yml +37 -0
  334. package/src/tools/definitions/std/deploy/rollback.yml +148 -0
  335. package/src/tools/definitions/std/design/analyze-architecture-impact.yml +113 -0
  336. package/src/tools/definitions/std/design/design-api.yml +55 -0
  337. package/src/tools/definitions/std/design/design-architecture.yml +97 -0
  338. package/src/tools/definitions/std/design/design-db.yml +81 -0
  339. package/src/tools/definitions/std/design/generate-spec.yml +182 -0
  340. package/src/tools/definitions/std/development/develop-api.yml +85 -0
  341. package/src/tools/definitions/std/development/develop-backend.yml +88 -0
  342. package/src/tools/definitions/std/development/develop-frontend.yml +87 -0
  343. package/src/tools/definitions/std/development/develop-shared-types.yml +74 -0
  344. package/src/tools/definitions/std/development/develop-task.yml +122 -0
  345. package/src/tools/definitions/std/development/develop-tests.yml +76 -0
  346. package/src/tools/definitions/std/development/execute-batch.yml +152 -0
  347. package/src/tools/definitions/std/development/fix-issues.yml +100 -0
  348. package/src/tools/definitions/std/development/implement-task.yml +124 -0
  349. package/src/tools/definitions/std/development/review-fix-cycle.yml +232 -0
  350. package/src/tools/definitions/std/evolution/implement.yml +125 -0
  351. package/src/tools/definitions/std/evolution/prioritize.yml +112 -0
  352. package/src/tools/definitions/std/evolution/report-gap.yml +166 -0
  353. package/src/tools/definitions/std/file/read.yml +21 -0
  354. package/src/tools/definitions/std/governance/aggregate-opinions.sh +201 -0
  355. package/src/tools/definitions/std/governance/aggregate-opinions.yml +79 -0
  356. package/src/tools/definitions/std/governance/audit-task.yml +178 -0
  357. package/src/tools/definitions/std/governance/cast-vote.yml +129 -0
  358. package/src/tools/definitions/std/governance/collect-issues.yml +16 -0
  359. package/src/tools/definitions/std/governance/create-signed-document.yml +23 -0
  360. package/src/tools/definitions/std/governance/create-voting-session.yml +101 -0
  361. package/src/tools/definitions/std/governance/define-stance.sh +243 -0
  362. package/src/tools/definitions/std/governance/define-stance.yml +82 -0
  363. package/src/tools/definitions/std/governance/generate-review-report.yml +23 -0
  364. package/src/tools/definitions/std/governance/impeach.yml +179 -0
  365. package/src/tools/definitions/std/governance/multi-stance-review.yml +154 -0
  366. package/src/tools/definitions/std/governance/prepare-artifact.yml +20 -0
  367. package/src/tools/definitions/std/governance/review-spec-approval.yml +262 -0
  368. package/src/tools/definitions/std/governance/rollback.yml +186 -0
  369. package/src/tools/definitions/std/governance/stance-review.yml +149 -0
  370. package/src/tools/definitions/std/governance/track-effect.yml +199 -0
  371. package/src/tools/definitions/std/governance/vote-tally.yml +144 -0
  372. package/src/tools/definitions/std/patch/execute.yml +51 -0
  373. package/src/tools/definitions/std/planning/generate-tasks.yml +36 -0
  374. package/src/tools/definitions/std/planning/load-tasks.yml +44 -0
  375. package/src/tools/definitions/std/planning/split-batch.yml +481 -0
  376. package/src/tools/definitions/std/planning/split-tasks.yml +359 -0
  377. package/src/tools/definitions/std/planning/update-tasks.yml +51 -0
  378. package/src/tools/definitions/std/planning/validate-tasks.yml +46 -0
  379. package/src/tools/definitions/std/project/decide-next-workflow.yml +38 -0
  380. package/src/tools/definitions/std/project/load-state.yml +31 -0
  381. package/src/tools/definitions/std/project/save-state.yml +32 -0
  382. package/src/tools/definitions/std/quality/check-quality.yml +241 -0
  383. package/src/tools/definitions/std/quality/debug-systematic.yml +163 -0
  384. package/src/tools/definitions/std/quality/handle-feedback.yml +108 -0
  385. package/src/tools/definitions/std/quality/review-code.yml +128 -0
  386. package/src/tools/definitions/std/quality/review-spec.yml +140 -0
  387. package/src/tools/definitions/std/quality/review-task.yml +190 -0
  388. package/src/tools/definitions/std/quality/run-tests.yml +80 -0
  389. package/src/tools/definitions/std/quick/analyze.yml +56 -0
  390. package/src/tools/definitions/std/quick/implement.yml +67 -0
  391. package/src/tools/definitions/std/quick/verify.yml +71 -0
  392. package/src/tools/definitions/std/verification/verify_completion.yml +113 -0
  393. package/src/tools/definitions/std/verification/wait-condition.yml +107 -0
  394. package/src/tools/index.ts +5 -0
  395. package/src/tools/loader.ts +216 -0
  396. package/src/tools/paths.ts +15 -0
  397. package/src/tools/registry.ts +128 -0
  398. package/src/tools/types.ts +46 -0
  399. package/src/types/__tests__/types.test.ts +86 -0
  400. package/src/types/checkpoint.ts +174 -0
  401. package/src/types/constraint.ts +335 -0
  402. package/src/types/cso.ts +37 -0
  403. package/src/types/enforcement.ts +48 -0
  404. package/src/types/index.ts +59 -0
  405. package/src/types/iron-law.ts +50 -0
  406. package/src/types/passes-gate.ts +185 -0
  407. package/src/types/performance.ts +295 -0
  408. package/src/types/project-config.ts +251 -0
  409. package/src/types/session.ts +132 -0
  410. package/src/types/spec.ts +91 -0
  411. package/src/types/trace.ts +228 -0
  412. package/src/utils/detect-source-roots.ts +114 -0
  413. package/src/utils/exec.ts +61 -0
  414. package/src/verification/CONTEXT.md +23 -0
  415. package/src/verification/__tests__/loop.test.ts +303 -0
  416. package/src/verification/__tests__/rules-based.test.ts +240 -0
  417. package/src/verification/index.ts +3 -0
  418. package/src/verification/loop.ts +137 -0
  419. package/src/verification/rules-based.ts +153 -0
  420. package/src/verification/types.ts +81 -0
@@ -0,0 +1,1268 @@
1
+ /**
2
+ * checker.ts 测试
3
+ */
4
+
5
+ import { ConstraintChecker, checkConstraints, checkConstraint } from '../core/constraints/checker';
6
+ import type { ConstraintContext } from '../types/constraint';
7
+ import { writeFileSync, mkdirSync, rmSync } from 'fs';
8
+ import { join } from 'path';
9
+
10
+ describe('ConstraintChecker', () => {
11
+ const checker = ConstraintChecker.getInstance();
12
+ const tempDir = join(process.cwd(), 'temp-test-checker');
13
+
14
+ beforeAll(() => {
15
+ // 创建临时测试目录
16
+ mkdirSync(tempDir, { recursive: true });
17
+ });
18
+
19
+ afterAll(() => {
20
+ // 清理临时测试目录
21
+ try {
22
+ rmSync(tempDir, { recursive: true, force: true });
23
+ } catch {
24
+ // ignore
25
+ }
26
+ });
27
+
28
+ describe('Iron Laws', () => {
29
+ it('should check no_bypass_checkpoint with skip patterns', async () => {
30
+ // 创建包含 skip 的文件
31
+ const skipFile = join(tempDir, 'skip-test.ts');
32
+ writeFileSync(skipFile, 'test.skip("skipped test", () => {});');
33
+
34
+ const context: ConstraintContext = {
35
+ operation: 'code_implementation',
36
+ changedFiles: [skipFile],
37
+ };
38
+
39
+ const result = await checker.check(
40
+ { id: 'no_bypass_checkpoint', level: 'iron_law', rule: 'NO BYPASS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
41
+ context
42
+ );
43
+
44
+ expect(result.satisfied).toBe(false);
45
+ });
46
+
47
+ it('should pass no_bypass_checkpoint without skip patterns', async () => {
48
+ const normalFile = join(tempDir, 'normal-test.ts');
49
+ writeFileSync(normalFile, 'test("normal test", () => { expect(true).toBe(true); });');
50
+
51
+ const context: ConstraintContext = {
52
+ operation: 'code_implementation',
53
+ changedFiles: [normalFile],
54
+ };
55
+
56
+ const result = await checker.check(
57
+ { id: 'no_bypass_checkpoint', level: 'iron_law', rule: 'NO BYPASS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
58
+ context
59
+ );
60
+
61
+ expect(result.satisfied).toBe(true);
62
+ });
63
+
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
+ it('should check no_completion_without_verification', async () => {
90
+ const contextWithEvidence: ConstraintContext = {
91
+ operation: 'code_implementation',
92
+ hasVerificationEvidence: true,
93
+ };
94
+
95
+ const contextWithoutEvidence: ConstraintContext = {
96
+ operation: 'code_implementation',
97
+ hasVerificationEvidence: false,
98
+ };
99
+
100
+ const resultWithEvidence = await checker.check(
101
+ { id: 'no_completion_without_verification', level: 'iron_law', rule: 'NO COMPLETION', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
102
+ contextWithEvidence
103
+ );
104
+
105
+ const resultWithoutEvidence = await checker.check(
106
+ { id: 'no_completion_without_verification', level: 'iron_law', rule: 'NO COMPLETION', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
107
+ contextWithoutEvidence
108
+ );
109
+
110
+ expect(resultWithEvidence.satisfied).toBe(true);
111
+ expect(resultWithoutEvidence.satisfied).toBe(false);
112
+ });
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
+
252
+ describe('New Iron Laws', () => {
253
+ it('should check incremental_progress', async () => {
254
+ const contextWithSingleTask: ConstraintContext = {
255
+ operation: 'code_implementation',
256
+ hasSingleTask: true,
257
+ };
258
+
259
+ const contextWithMultipleTasks: ConstraintContext = {
260
+ operation: 'code_implementation',
261
+ hasSingleTask: false,
262
+ };
263
+
264
+ const resultWith = await checker.check(
265
+ { id: 'incremental_progress', level: 'iron_law', rule: 'ONE TASK', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
266
+ contextWithSingleTask
267
+ );
268
+
269
+ const resultWithout = await checker.check(
270
+ { id: 'incremental_progress', level: 'iron_law', rule: 'ONE TASK', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
271
+ contextWithMultipleTasks
272
+ );
273
+
274
+ expect(resultWith.satisfied).toBe(true);
275
+ expect(resultWithout.satisfied).toBe(false);
276
+ });
277
+
278
+ it('should check verify_external_capability', async () => {
279
+ const contextVerified: ConstraintContext = {
280
+ operation: 'api_change',
281
+ hasExternalCapabilityVerification: true,
282
+ };
283
+
284
+ const contextNotVerified: ConstraintContext = {
285
+ operation: 'api_change',
286
+ hasExternalCapabilityVerification: false,
287
+ };
288
+
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
292
+ );
293
+
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
297
+ );
298
+
299
+ expect(resultVerified.satisfied).toBe(true);
300
+ expect(resultNotVerified.satisfied).toBe(false);
301
+ });
302
+ });
303
+
304
+ describe('Exception handling', () => {
305
+ it('should apply exception for no_fix_without_root_cause with simple_typo', async () => {
306
+ const context: ConstraintContext = {
307
+ operation: 'code_implementation',
308
+ hasRootCauseInvestigation: false,
309
+ isSimpleTypo: true,
310
+ };
311
+
312
+ 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
+ },
322
+ context
323
+ );
324
+
325
+ expect(result.satisfied).toBe(true);
326
+ expect(result.message).toContain('豁免');
327
+ });
328
+
329
+ it('should apply exception for scalability_required', async () => {
330
+ const context: ConstraintContext = {
331
+ operation: 'code_implementation',
332
+ hasReuseCheck: false,
333
+ scalabilityRequired: true,
334
+ };
335
+
336
+ const result = await checker.check(
337
+ {
338
+ id: 'simplest_solution_first',
339
+ level: 'guideline',
340
+ rule: 'SIMPLEST FIRST',
341
+ message: 'test',
342
+ trigger: 'code_implementation',
343
+ enforcement: 'test',
344
+ exceptions: ['scalability_required'],
345
+ },
346
+ context
347
+ );
348
+
349
+ expect(result.satisfied).toBe(true);
350
+ });
351
+
352
+ it('should apply exception for security_required', async () => {
353
+ const context: ConstraintContext = {
354
+ operation: 'code_implementation',
355
+ hasReuseCheck: false,
356
+ securityRequired: true,
357
+ };
358
+
359
+ const result = await checker.check(
360
+ {
361
+ id: 'simplest_solution_first',
362
+ level: 'guideline',
363
+ rule: 'SIMPLEST FIRST',
364
+ message: 'test',
365
+ trigger: 'code_implementation',
366
+ enforcement: 'test',
367
+ exceptions: ['security_required'],
368
+ },
369
+ context
370
+ );
371
+
372
+ expect(result.satisfied).toBe(true);
373
+ });
374
+
375
+ it('should apply exception for performance_required', async () => {
376
+ const context: ConstraintContext = {
377
+ operation: 'code_implementation',
378
+ hasReuseCheck: false,
379
+ performanceRequired: true,
380
+ };
381
+
382
+ const result = await checker.check(
383
+ {
384
+ id: 'simplest_solution_first',
385
+ level: 'guideline',
386
+ rule: 'SIMPLEST FIRST',
387
+ message: 'test',
388
+ trigger: 'code_implementation',
389
+ enforcement: 'test',
390
+ exceptions: ['performance_required'],
391
+ },
392
+ context
393
+ );
394
+
395
+ expect(result.satisfied).toBe(true);
396
+ });
397
+
398
+ it('should apply exception for reliability_required', async () => {
399
+ const context: ConstraintContext = {
400
+ operation: 'code_implementation',
401
+ hasReuseCheck: false,
402
+ reliabilityRequired: true,
403
+ };
404
+
405
+ const result = await checker.check(
406
+ {
407
+ id: 'simplest_solution_first',
408
+ level: 'guideline',
409
+ rule: 'SIMPLEST FIRST',
410
+ message: 'test',
411
+ trigger: 'code_implementation',
412
+ enforcement: 'test',
413
+ exceptions: ['reliability_required'],
414
+ },
415
+ context
416
+ );
417
+
418
+ expect(result.satisfied).toBe(true);
419
+ });
420
+
421
+ it('should apply exception for config_value_error', async () => {
422
+ const context: ConstraintContext = {
423
+ operation: 'code_implementation',
424
+ hasRootCauseInvestigation: false,
425
+ isConfigValueError: true,
426
+ };
427
+
428
+ const result = await checker.check(
429
+ {
430
+ id: 'no_fix_without_root_cause',
431
+ level: 'guideline',
432
+ rule: 'NO FIX',
433
+ message: 'test',
434
+ trigger: 'code_implementation',
435
+ enforcement: 'test',
436
+ exceptions: ['config_value_error'],
437
+ },
438
+ context
439
+ );
440
+
441
+ expect(result.satisfied).toBe(true);
442
+ });
443
+
444
+ it('should apply exception for missing_config', async () => {
445
+ const context: ConstraintContext = {
446
+ operation: 'code_implementation',
447
+ hasRootCauseInvestigation: false,
448
+ isMissingConfig: true,
449
+ };
450
+
451
+ const result = await checker.check(
452
+ {
453
+ id: 'no_fix_without_root_cause',
454
+ level: 'guideline',
455
+ rule: 'NO FIX',
456
+ message: 'test',
457
+ trigger: 'code_implementation',
458
+ enforcement: 'test',
459
+ exceptions: ['missing_config'],
460
+ },
461
+ context
462
+ );
463
+
464
+ expect(result.satisfied).toBe(true);
465
+ });
466
+
467
+ it('should apply exception for config_file', async () => {
468
+ const context: ConstraintContext = {
469
+ operation: 'code_implementation',
470
+ hasFailingTest: false,
471
+ isConfigFile: true,
472
+ };
473
+
474
+ const result = await checker.check(
475
+ {
476
+ id: 'no_code_without_test',
477
+ level: 'guideline',
478
+ rule: 'NO CODE',
479
+ message: 'test',
480
+ trigger: 'code_implementation',
481
+ enforcement: 'test',
482
+ exceptions: ['config_file'],
483
+ },
484
+ context
485
+ );
486
+
487
+ expect(result.satisfied).toBe(true);
488
+ });
489
+
490
+ it('should apply exception for type_definition', async () => {
491
+ const context: ConstraintContext = {
492
+ operation: 'code_implementation',
493
+ hasFailingTest: false,
494
+ isTypeDefinition: true,
495
+ };
496
+
497
+ const result = await checker.check(
498
+ {
499
+ id: 'no_code_without_test',
500
+ level: 'guideline',
501
+ rule: 'NO CODE',
502
+ message: 'test',
503
+ trigger: 'code_implementation',
504
+ enforcement: 'test',
505
+ exceptions: ['type_definition'],
506
+ },
507
+ context
508
+ );
509
+
510
+ expect(result.satisfied).toBe(true);
511
+ });
512
+
513
+ it('should apply exception for simple_accessor', async () => {
514
+ const context: ConstraintContext = {
515
+ operation: 'code_implementation',
516
+ hasFailingTest: false,
517
+ isSimpleAccessor: true,
518
+ };
519
+
520
+ const result = await checker.check(
521
+ {
522
+ id: 'no_code_without_test',
523
+ level: 'guideline',
524
+ rule: 'NO CODE',
525
+ message: 'test',
526
+ trigger: 'code_implementation',
527
+ enforcement: 'test',
528
+ exceptions: ['simple_accessor'],
529
+ },
530
+ context
531
+ );
532
+
533
+ expect(result.satisfied).toBe(true);
534
+ });
535
+
536
+ it('should apply exception for pure_display_component', async () => {
537
+ const context: ConstraintContext = {
538
+ operation: 'code_implementation',
539
+ hasFailingTest: false,
540
+ isPureDisplayComponent: true,
541
+ };
542
+
543
+ const result = await checker.check(
544
+ {
545
+ id: 'no_code_without_test',
546
+ level: 'guideline',
547
+ rule: 'NO CODE',
548
+ message: 'test',
549
+ trigger: 'code_implementation',
550
+ enforcement: 'test',
551
+ exceptions: ['pure_display_component'],
552
+ },
553
+ context
554
+ );
555
+
556
+ expect(result.satisfied).toBe(true);
557
+ });
558
+
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
+ it('should apply exception for internal_refactor', async () => {
629
+ const context: ConstraintContext = {
630
+ operation: 'commit',
631
+ projectPath: tempDir,
632
+ isInternalRefactor: true,
633
+ };
634
+
635
+ const result = await checker.check(
636
+ {
637
+ id: 'capability_sync',
638
+ level: 'guideline',
639
+ rule: 'CAPABILITY SYNC',
640
+ message: 'test',
641
+ trigger: 'commit',
642
+ enforcement: 'test',
643
+ exceptions: ['internal_refactor'],
644
+ },
645
+ context
646
+ );
647
+
648
+ expect(result.satisfied).toBe(true);
649
+ });
650
+
651
+ it('should apply exception for bug_fix_only', async () => {
652
+ const context: ConstraintContext = {
653
+ operation: 'commit',
654
+ projectPath: tempDir,
655
+ isBugFixOnly: true,
656
+ };
657
+
658
+ const result = await checker.check(
659
+ {
660
+ id: 'capability_sync',
661
+ level: 'guideline',
662
+ rule: 'CAPABILITY SYNC',
663
+ message: 'test',
664
+ trigger: 'commit',
665
+ enforcement: 'test',
666
+ exceptions: ['bug_fix_only'],
667
+ },
668
+ context
669
+ );
670
+
671
+ expect(result.satisfied).toBe(true);
672
+ });
673
+
674
+ it('should apply exception for performance_optimization', async () => {
675
+ const context: ConstraintContext = {
676
+ operation: 'commit',
677
+ projectPath: tempDir,
678
+ isPerformanceOptimization: true,
679
+ };
680
+
681
+ const result = await checker.check(
682
+ {
683
+ id: 'capability_sync',
684
+ level: 'guideline',
685
+ rule: 'CAPABILITY SYNC',
686
+ message: 'test',
687
+ trigger: 'commit',
688
+ enforcement: 'test',
689
+ exceptions: ['performance_optimization'],
690
+ },
691
+ context
692
+ );
693
+
694
+ expect(result.satisfied).toBe(true);
695
+ });
696
+
697
+ it('should apply exception for redundant_code_cleanup', async () => {
698
+ const context: ConstraintContext = {
699
+ operation: 'commit',
700
+ projectPath: tempDir,
701
+ isRedundantCodeCleanup: true,
702
+ };
703
+
704
+ const result = await checker.check(
705
+ {
706
+ id: 'no_simplification_without_approval',
707
+ level: 'guideline',
708
+ rule: 'NO SIMPLIFICATION',
709
+ message: 'test',
710
+ trigger: 'commit',
711
+ enforcement: 'test',
712
+ exceptions: ['redundant_code_cleanup'],
713
+ },
714
+ context
715
+ );
716
+
717
+ expect(result.satisfied).toBe(true);
718
+ });
719
+
720
+ it('should apply exception for same_effect_refactor', async () => {
721
+ const context: ConstraintContext = {
722
+ operation: 'commit',
723
+ projectPath: tempDir,
724
+ isSameEffectRefactor: true,
725
+ };
726
+
727
+ const result = await checker.check(
728
+ {
729
+ id: 'no_simplification_without_approval',
730
+ level: 'guideline',
731
+ rule: 'NO SIMPLIFICATION',
732
+ message: 'test',
733
+ trigger: 'commit',
734
+ enforcement: 'test',
735
+ exceptions: ['same_effect_refactor'],
736
+ },
737
+ context
738
+ );
739
+
740
+ expect(result.satisfied).toBe(true);
741
+ });
742
+
743
+ it('should apply exception for unused_code_removal', async () => {
744
+ const context: ConstraintContext = {
745
+ operation: 'commit',
746
+ projectPath: tempDir,
747
+ isUnusedCodeRemoval: true,
748
+ };
749
+
750
+ const result = await checker.check(
751
+ {
752
+ id: 'no_simplification_without_approval',
753
+ level: 'guideline',
754
+ rule: 'NO SIMPLIFICATION',
755
+ message: 'test',
756
+ trigger: 'commit',
757
+ enforcement: 'test',
758
+ exceptions: ['unused_code_removal'],
759
+ },
760
+ context
761
+ );
762
+
763
+ expect(result.satisfied).toBe(true);
764
+ });
765
+ });
766
+
767
+ describe('Deprecated functions', () => {
768
+ it('getAllLaws should work', () => {
769
+ const { getAllLaws } = require('../core/constraints/definitions');
770
+ const laws = getAllLaws();
771
+ expect(Array.isArray(laws)).toBe(true);
772
+ expect(laws.length).toBeGreaterThan(0);
773
+ });
774
+
775
+ it('findLawsByTrigger should work', () => {
776
+ const { findLawsByTrigger } = require('../core/constraints/definitions');
777
+ const laws = findLawsByTrigger('code_implementation');
778
+ expect(Array.isArray(laws)).toBe(true);
779
+ });
780
+
781
+ it('getLaw should work', () => {
782
+ const { getLaw } = require('../core/constraints/definitions');
783
+ const law = getLaw('no_bypass_checkpoint');
784
+ expect(law).toBeDefined();
785
+ });
786
+
787
+ it('filterLawsBySeverity should work', () => {
788
+ const { filterLawsBySeverity } = require('../core/constraints/definitions');
789
+ const errors = filterLawsBySeverity('error');
790
+ expect(Array.isArray(errors)).toBe(true);
791
+
792
+ const warnings = filterLawsBySeverity('warning');
793
+ expect(Array.isArray(warnings)).toBe(true);
794
+
795
+ const infos = filterLawsBySeverity('info');
796
+ expect(Array.isArray(infos)).toBe(true);
797
+ });
798
+ });
799
+
800
+ describe('Helper functions', () => {
801
+ it('should check single constraint via checkConstraint', async () => {
802
+ const context: ConstraintContext = {
803
+ operation: 'code_implementation',
804
+ hasTest: true,
805
+ };
806
+
807
+ const result = await checkConstraint('no_self_approval', context);
808
+ expect(result.satisfied).toBe(true);
809
+ });
810
+
811
+ it('should return false for unknown constraint', async () => {
812
+ const context: ConstraintContext = {
813
+ operation: 'code_implementation',
814
+ };
815
+
816
+ const result = await checkConstraint('unknown_constraint', context);
817
+ expect(result.satisfied).toBe(false);
818
+ expect(result.message).toContain('未知的约束');
819
+ });
820
+ });
821
+
822
+ describe('Text pattern constraints', () => {
823
+ it('no_fuzzy_completion_claim should detect Chinese fuzzy words', async () => {
824
+ const context: ConstraintContext = {
825
+ operation: 'code_implementation',
826
+ completionClaimText: '应该没问题,大概完成了',
827
+ };
828
+
829
+ const result = await checker.check(
830
+ { id: 'no_fuzzy_completion_claim', level: 'iron_law', rule: 'NO FUZZY', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
831
+ context
832
+ );
833
+
834
+ expect(result.satisfied).toBe(false);
835
+ });
836
+
837
+ it('no_fuzzy_completion_claim should pass clean text', async () => {
838
+ const context: ConstraintContext = {
839
+ operation: 'code_implementation',
840
+ completionClaimText: '142 tests passed, coverage 87.3%',
841
+ };
842
+
843
+ const result = await checker.check(
844
+ { id: 'no_fuzzy_completion_claim', level: 'iron_law', rule: 'NO FUZZY', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
845
+ context
846
+ );
847
+
848
+ expect(result.satisfied).toBe(true);
849
+ });
850
+
851
+ it('no_fuzzy_completion_claim should pass with empty text', async () => {
852
+ const context: ConstraintContext = {
853
+ operation: 'code_implementation',
854
+ completionClaimText: '',
855
+ };
856
+
857
+ const result = await checker.check(
858
+ { id: 'no_fuzzy_completion_claim', level: 'iron_law', rule: 'NO FUZZY', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
859
+ context
860
+ );
861
+
862
+ expect(result.satisfied).toBe(true);
863
+ });
864
+
865
+ it('no_performative_agreement should detect performative patterns', async () => {
866
+ const context: ConstraintContext = {
867
+ operation: 'design_request',
868
+ taskDescription: '好的,我来做',
869
+ };
870
+
871
+ const result = await checker.check(
872
+ { id: 'no_performative_agreement', level: 'iron_law', rule: 'NO PERFORMATIVE', message: 'test', trigger: 'design_request', enforcement: 'test' },
873
+ context
874
+ );
875
+
876
+ expect(result.satisfied).toBe(false);
877
+ });
878
+
879
+ it('no_performative_agreement should pass with analysis', async () => {
880
+ const context: ConstraintContext = {
881
+ operation: 'design_request',
882
+ taskDescription: 'This is a detailed analysis of the problem with multiple considerations and proposed solutions.',
883
+ };
884
+
885
+ const result = await checker.check(
886
+ { id: 'no_performative_agreement', level: 'iron_law', rule: 'NO PERFORMATIVE', message: 'test', trigger: 'design_request', enforcement: 'test' },
887
+ context
888
+ );
889
+
890
+ expect(result.satisfied).toBe(true);
891
+ });
892
+
893
+ it('no_claim_without_evidence should pass with verification evidence', async () => {
894
+ const context: ConstraintContext = {
895
+ operation: 'code_implementation',
896
+ hasVerificationEvidence: true,
897
+ };
898
+
899
+ const result = await checker.check(
900
+ { id: 'no_claim_without_evidence', level: 'guideline', rule: 'NO CLAIM', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
901
+ context
902
+ );
903
+
904
+ expect(result.satisfied).toBe(true);
905
+ });
906
+
907
+ it('no_claim_without_evidence should pass with taskDescription containing test', async () => {
908
+ const context: ConstraintContext = {
909
+ operation: 'code_implementation',
910
+ hasVerificationEvidence: false,
911
+ taskDescription: 'Need to run the test suite to verify',
912
+ };
913
+
914
+ const result = await checker.check(
915
+ { id: 'no_claim_without_evidence', level: 'guideline', rule: 'NO CLAIM', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
916
+ context
917
+ );
918
+
919
+ expect(result.satisfied).toBe(true);
920
+ });
921
+
922
+ it('no_claim_without_evidence should fail without evidence', async () => {
923
+ const context: ConstraintContext = {
924
+ operation: 'code_implementation',
925
+ hasVerificationEvidence: false,
926
+ hasTest: false,
927
+ taskDescription: 'Did some work',
928
+ };
929
+
930
+ const result = await checker.check(
931
+ { id: 'no_claim_without_evidence', level: 'guideline', rule: 'NO CLAIM', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
932
+ context
933
+ );
934
+
935
+ expect(result.satisfied).toBe(false);
936
+ });
937
+
938
+ it('no_delete_without_context should pass with requirement review', async () => {
939
+ const context: ConstraintContext = {
940
+ operation: 'file_deletion',
941
+ hasRequirementReview: true,
942
+ };
943
+
944
+ const result = await checker.check(
945
+ { id: 'no_delete_without_context', level: 'guideline', rule: 'NO DELETE', message: 'test', trigger: 'file_deletion', enforcement: 'test' },
946
+ context
947
+ );
948
+
949
+ expect(result.satisfied).toBe(true);
950
+ });
951
+
952
+ it('no_delete_without_context should pass with existing design', async () => {
953
+ const context: ConstraintContext = {
954
+ operation: 'file_deletion',
955
+ hasRequirementReview: false,
956
+ hasRequirement: false,
957
+ isExistingDesign: true,
958
+ };
959
+
960
+ const result = await checker.check(
961
+ { id: 'no_delete_without_context', level: 'guideline', rule: 'NO DELETE', message: 'test', trigger: 'file_deletion', enforcement: 'test' },
962
+ context
963
+ );
964
+
965
+ expect(result.satisfied).toBe(true);
966
+ });
967
+
968
+ it('no_delete_without_context should fail without any context', async () => {
969
+ const context: ConstraintContext = {
970
+ operation: 'file_deletion',
971
+ hasRequirementReview: false,
972
+ hasRequirement: false,
973
+ isExistingDesign: false,
974
+ };
975
+
976
+ const result = await checker.check(
977
+ { id: 'no_delete_without_context', level: 'guideline', rule: 'NO DELETE', message: 'test', trigger: 'file_deletion', enforcement: 'test' },
978
+ context
979
+ );
980
+
981
+ expect(result.satisfied).toBe(false);
982
+ });
983
+ });
984
+
985
+ describe('Behavior guidelines (always true)', () => {
986
+ it('surgical_changes_only should return true', async () => {
987
+ const context: ConstraintContext = { operation: 'code_implementation' };
988
+ const result = await checker.check(
989
+ { id: 'surgical_changes_only', level: 'guideline', rule: 'SURGICAL', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
990
+ context
991
+ );
992
+ expect(result.satisfied).toBe(true);
993
+ });
994
+
995
+ it('no_model_for_deterministic should return true', async () => {
996
+ const context: ConstraintContext = { operation: 'code_implementation' };
997
+ const result = await checker.check(
998
+ { id: 'no_model_for_deterministic', level: 'guideline', rule: 'NO MODEL', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
999
+ context
1000
+ );
1001
+ expect(result.satisfied).toBe(true);
1002
+ });
1003
+
1004
+ it('no_conflict_blending should return true', async () => {
1005
+ const context: ConstraintContext = { operation: 'code_implementation' };
1006
+ const result = await checker.check(
1007
+ { id: 'no_conflict_blending', level: 'guideline', rule: 'NO BLEND', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1008
+ context
1009
+ );
1010
+ expect(result.satisfied).toBe(true);
1011
+ });
1012
+
1013
+ it('read_before_write should return true', async () => {
1014
+ const context: ConstraintContext = { operation: 'code_implementation' };
1015
+ const result = await checker.check(
1016
+ { id: 'read_before_write', level: 'guideline', rule: 'READ FIRST', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1017
+ context
1018
+ );
1019
+ expect(result.satisfied).toBe(true);
1020
+ });
1021
+
1022
+ it('first_principles_first should return true', async () => {
1023
+ const context: ConstraintContext = { operation: 'code_implementation' };
1024
+ const result = await checker.check(
1025
+ { id: 'first_principles_first', level: 'guideline', rule: 'PRINCIPLES', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1026
+ context
1027
+ );
1028
+ expect(result.satisfied).toBe(true);
1029
+ });
1030
+
1031
+ it('fix_the_problem_not_the_gate should return true', async () => {
1032
+ const context: ConstraintContext = { operation: 'code_implementation' };
1033
+ const result = await checker.check(
1034
+ { id: 'fix_the_problem_not_the_gate', level: 'guideline', rule: 'FIX PROBLEM', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1035
+ context
1036
+ );
1037
+ expect(result.satisfied).toBe(true);
1038
+ });
1039
+
1040
+ it('diagnosis_to_fix_gate should return true', async () => {
1041
+ const context: ConstraintContext = { operation: 'code_implementation' };
1042
+ const result = await checker.check(
1043
+ { id: 'diagnosis_to_fix_gate', level: 'guideline', rule: 'DIAGNOSIS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1044
+ context
1045
+ );
1046
+ expect(result.satisfied).toBe(true);
1047
+ });
1048
+
1049
+ it('follow_conventions should return true', async () => {
1050
+ const context: ConstraintContext = { operation: 'code_implementation' };
1051
+ const result = await checker.check(
1052
+ { id: 'follow_conventions', level: 'guideline', rule: 'CONVENTIONS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1053
+ context
1054
+ );
1055
+ expect(result.satisfied).toBe(true);
1056
+ });
1057
+ });
1058
+
1059
+ describe('Default guideline constraints', () => {
1060
+ it('no_hardcoded_credentials should pass by default', async () => {
1061
+ const context: ConstraintContext = { operation: 'code_implementation' };
1062
+ const result = await checker.check(
1063
+ { id: 'no_hardcoded_credentials', level: 'guideline', rule: 'NO CREDENTIALS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1064
+ context
1065
+ );
1066
+ expect(result.satisfied).toBe(true);
1067
+ });
1068
+
1069
+ it('design_decision_requires_discussion should pass by default', async () => {
1070
+ const context: ConstraintContext = { operation: 'code_implementation' };
1071
+ const result = await checker.check(
1072
+ { id: 'design_decision_requires_discussion', level: 'guideline', rule: 'DISCUSS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1073
+ context
1074
+ );
1075
+ expect(result.satisfied).toBe(true);
1076
+ });
1077
+ });
1078
+
1079
+ describe('Additional Iron Laws (pure context)', () => {
1080
+ it('no_implementation_without_requirement_review should pass with review', async () => {
1081
+ const context: ConstraintContext = { operation: 'code_implementation', hasRequirementReview: true };
1082
+ const result = await checker.check(
1083
+ { id: 'no_implementation_without_requirement_review', level: 'iron_law', rule: 'REVIEW REQ', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1084
+ context
1085
+ );
1086
+ expect(result.satisfied).toBe(true);
1087
+ });
1088
+
1089
+ it('no_implementation_without_requirement_review should fail without review', async () => {
1090
+ const context: ConstraintContext = { operation: 'code_implementation', hasRequirementReview: false };
1091
+ const result = await checker.check(
1092
+ { id: 'no_implementation_without_requirement_review', level: 'iron_law', rule: 'REVIEW REQ', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1093
+ context
1094
+ );
1095
+ expect(result.satisfied).toBe(false);
1096
+ });
1097
+
1098
+ it('no_implementation_without_requirement should pass with requirement', async () => {
1099
+ const context: ConstraintContext = { operation: 'code_implementation', hasRequirement: true };
1100
+ const result = await checker.check(
1101
+ { id: 'no_implementation_without_requirement', level: 'iron_law', rule: 'REQ EXISTS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1102
+ context
1103
+ );
1104
+ expect(result.satisfied).toBe(true);
1105
+ });
1106
+
1107
+ it('no_implementation_without_requirement should fail without requirement', async () => {
1108
+ const context: ConstraintContext = { operation: 'code_implementation', hasRequirement: false };
1109
+ const result = await checker.check(
1110
+ { id: 'no_implementation_without_requirement', level: 'iron_law', rule: 'REQ EXISTS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1111
+ context
1112
+ );
1113
+ expect(result.satisfied).toBe(false);
1114
+ });
1115
+
1116
+ it('must_use_worktree should pass with worktree', async () => {
1117
+ const context: ConstraintContext = { operation: 'code_implementation', hasWorktree: true };
1118
+ const result = await checker.check(
1119
+ { id: 'must_use_worktree', level: 'iron_law', rule: 'WORKTREE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1120
+ context
1121
+ );
1122
+ expect(result.satisfied).toBe(true);
1123
+ });
1124
+
1125
+ it('must_use_worktree should fail without worktree', async () => {
1126
+ const context: ConstraintContext = { operation: 'code_implementation', hasWorktree: false };
1127
+ const result = await checker.check(
1128
+ { id: 'must_use_worktree', level: 'iron_law', rule: 'WORKTREE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1129
+ context
1130
+ );
1131
+ expect(result.satisfied).toBe(false);
1132
+ });
1133
+
1134
+ it('two_stage_review_required should pass with two-stage review', async () => {
1135
+ const context: ConstraintContext = { operation: 'code_implementation', hasTwoStageReview: true };
1136
+ const result = await checker.check(
1137
+ { id: 'two_stage_review_required', level: 'iron_law', rule: 'TWO STAGE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1138
+ context
1139
+ );
1140
+ expect(result.satisfied).toBe(true);
1141
+ });
1142
+
1143
+ it('two_stage_review_required should fail without two-stage review', async () => {
1144
+ const context: ConstraintContext = { operation: 'code_implementation', hasTwoStageReview: false };
1145
+ const result = await checker.check(
1146
+ { id: 'two_stage_review_required', level: 'iron_law', rule: 'TWO STAGE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1147
+ context
1148
+ );
1149
+ expect(result.satisfied).toBe(false);
1150
+ });
1151
+ });
1152
+
1153
+ describe('Additional guidelines (pure context)', () => {
1154
+ it('no_skill_without_test should pass with test', async () => {
1155
+ const context: ConstraintContext = { operation: 'module_creation', hasTest: true };
1156
+ const result = await checker.check(
1157
+ { id: 'no_skill_without_test', level: 'guideline', rule: 'SKILL TEST', message: 'test', trigger: 'module_creation', enforcement: 'test' },
1158
+ context
1159
+ );
1160
+ expect(result.satisfied).toBe(true);
1161
+ });
1162
+
1163
+ it('no_skill_without_test should fail without test', async () => {
1164
+ const context: ConstraintContext = { operation: 'module_creation', hasTest: false };
1165
+ const result = await checker.check(
1166
+ { id: 'no_skill_without_test', level: 'guideline', rule: 'SKILL TEST', message: 'test', trigger: 'module_creation', enforcement: 'test' },
1167
+ context
1168
+ );
1169
+ expect(result.satisfied).toBe(false);
1170
+ });
1171
+
1172
+ it('simplest_solution_first should pass with reuse check', async () => {
1173
+ // matches trigger code_implementation
1174
+ const context: ConstraintContext = { operation: 'code_implementation', hasReuseCheck: true };
1175
+ const result = await checker.check(
1176
+ { id: 'simplest_solution_first', level: 'guideline', rule: 'SIMPLEST', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1177
+ context
1178
+ );
1179
+ expect(result.satisfied).toBe(true);
1180
+ });
1181
+
1182
+ it('simplest_solution_first should fail without reuse check', async () => {
1183
+ const context: ConstraintContext = { operation: 'code_implementation', hasReuseCheck: false };
1184
+ const result = await checker.check(
1185
+ { id: 'simplest_solution_first', level: 'guideline', rule: 'SIMPLEST', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1186
+ context
1187
+ );
1188
+ expect(result.satisfied).toBe(false);
1189
+ });
1190
+ });
1191
+
1192
+ describe('Tip constraints', () => {
1193
+ it('readme_required should always pass', async () => {
1194
+ const context: ConstraintContext = { operation: 'module_creation' };
1195
+ const result = await checker.check(
1196
+ { id: 'readme_required', level: 'tip', rule: 'README', message: 'test', trigger: 'module_creation', enforcement: 'test' },
1197
+ context
1198
+ );
1199
+ expect(result.satisfied).toBe(true);
1200
+ });
1201
+
1202
+ it('doc_required_for_public_api should always pass', async () => {
1203
+ const context: ConstraintContext = { operation: 'export_change' };
1204
+ const result = await checker.check(
1205
+ { id: 'doc_required_for_public_api', level: 'tip', rule: 'DOC', message: 'test', trigger: 'export_change', enforcement: 'test' },
1206
+ context
1207
+ );
1208
+ expect(result.satisfied).toBe(true);
1209
+ });
1210
+ });
1211
+
1212
+ describe('no_excuse_patterns', () => {
1213
+ it('should detect excuse patterns in completion claim', async () => {
1214
+ const context: ConstraintContext = {
1215
+ operation: 'code_implementation',
1216
+ completionClaimText: '稍后修复这个bug',
1217
+ };
1218
+
1219
+ const result = await checker.check(
1220
+ { id: 'no_excuse_patterns', level: 'guideline', rule: 'NO EXCUSE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1221
+ context
1222
+ );
1223
+
1224
+ expect(result.satisfied).toBe(false);
1225
+ });
1226
+
1227
+ it('should detect excuse patterns in task description', async () => {
1228
+ const context: ConstraintContext = {
1229
+ operation: 'code_implementation',
1230
+ taskDescription: '这是个临时方案,先这样',
1231
+ };
1232
+
1233
+ const result = await checker.check(
1234
+ { id: 'no_excuse_patterns', level: 'guideline', rule: 'NO EXCUSE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1235
+ context
1236
+ );
1237
+
1238
+ expect(result.satisfied).toBe(false);
1239
+ });
1240
+
1241
+ it('should pass with clean text', async () => {
1242
+ const context: ConstraintContext = {
1243
+ operation: 'code_implementation',
1244
+ completionClaimText: 'Fixed by refactoring the validation logic in checker.ts',
1245
+ };
1246
+
1247
+ const result = await checker.check(
1248
+ { id: 'no_excuse_patterns', level: 'guideline', rule: 'NO EXCUSE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1249
+ context
1250
+ );
1251
+
1252
+ expect(result.satisfied).toBe(true);
1253
+ });
1254
+
1255
+ it('should pass with empty text', async () => {
1256
+ const context: ConstraintContext = {
1257
+ operation: 'code_implementation',
1258
+ };
1259
+
1260
+ const result = await checker.check(
1261
+ { id: 'no_excuse_patterns', level: 'guideline', rule: 'NO EXCUSE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
1262
+ context
1263
+ );
1264
+
1265
+ expect(result.satisfied).toBe(true);
1266
+ });
1267
+ });
1268
+ });