@dommaker/harness 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (549) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/bin/harness.js +17 -1
  3. package/dist/agents/index.d.ts +6 -2
  4. package/dist/agents/index.d.ts.map +1 -1
  5. package/dist/agents/index.js +6 -16
  6. package/dist/agents/index.js.map +1 -1
  7. package/dist/cli/commands/__tests__/gate-decision.d.ts +18 -0
  8. package/dist/cli/commands/__tests__/gate-decision.d.ts.map +1 -0
  9. package/dist/cli/commands/__tests__/gate-decision.js +26 -0
  10. package/dist/cli/commands/__tests__/gate-decision.js.map +1 -0
  11. package/dist/cli/commands/acceptance.d.ts.map +1 -1
  12. package/dist/cli/commands/acceptance.js +17 -28
  13. package/dist/cli/commands/acceptance.js.map +1 -1
  14. package/dist/cli/commands/check.d.ts +11 -3
  15. package/dist/cli/commands/check.d.ts.map +1 -1
  16. package/dist/cli/commands/check.js +26 -11
  17. package/dist/cli/commands/check.js.map +1 -1
  18. package/dist/cli/commands/command.d.ts +0 -1
  19. package/dist/cli/commands/command.d.ts.map +1 -1
  20. package/dist/cli/commands/command.js +8 -6
  21. package/dist/cli/commands/command.js.map +1 -1
  22. package/dist/cli/commands/constraints-retire.d.ts.map +1 -1
  23. package/dist/cli/commands/constraints-retire.js +36 -57
  24. package/dist/cli/commands/constraints-retire.js.map +1 -1
  25. package/dist/cli/commands/contract.d.ts.map +1 -1
  26. package/dist/cli/commands/contract.js +36 -42
  27. package/dist/cli/commands/contract.js.map +1 -1
  28. package/dist/cli/commands/definitions.d.ts +2 -0
  29. package/dist/cli/commands/definitions.d.ts.map +1 -1
  30. package/dist/cli/commands/definitions.js +11 -6
  31. package/dist/cli/commands/definitions.js.map +1 -1
  32. package/dist/cli/commands/failure.d.ts.map +1 -1
  33. package/dist/cli/commands/failure.js +16 -2
  34. package/dist/cli/commands/failure.js.map +1 -1
  35. package/dist/cli/commands/init.d.ts +14 -8
  36. package/dist/cli/commands/init.d.ts.map +1 -1
  37. package/dist/cli/commands/init.js +172 -364
  38. package/dist/cli/commands/init.js.map +1 -1
  39. package/dist/cli/commands/knowledge-view.d.ts +90 -0
  40. package/dist/cli/commands/knowledge-view.d.ts.map +1 -0
  41. package/dist/cli/commands/knowledge-view.js +198 -0
  42. package/dist/cli/commands/knowledge-view.js.map +1 -0
  43. package/dist/cli/commands/knowledge.d.ts +137 -52
  44. package/dist/cli/commands/knowledge.d.ts.map +1 -1
  45. package/dist/cli/commands/knowledge.js +534 -400
  46. package/dist/cli/commands/knowledge.js.map +1 -1
  47. package/dist/cli/commands/passes-gate.d.ts +4 -1
  48. package/dist/cli/commands/passes-gate.d.ts.map +1 -1
  49. package/dist/cli/commands/passes-gate.js +11 -2
  50. package/dist/cli/commands/passes-gate.js.map +1 -1
  51. package/dist/cli/commands/performance.d.ts.map +1 -1
  52. package/dist/cli/commands/performance.js +19 -31
  53. package/dist/cli/commands/performance.js.map +1 -1
  54. package/dist/cli/commands/report.d.ts.map +1 -1
  55. package/dist/cli/commands/report.js +2 -1
  56. package/dist/cli/commands/report.js.map +1 -1
  57. package/dist/cli/commands/review.d.ts.map +1 -1
  58. package/dist/cli/commands/review.js +13 -25
  59. package/dist/cli/commands/review.js.map +1 -1
  60. package/dist/cli/commands/scaffold-templates.d.ts +73 -0
  61. package/dist/cli/commands/scaffold-templates.d.ts.map +1 -0
  62. package/dist/cli/commands/scaffold-templates.js +424 -0
  63. package/dist/cli/commands/scaffold-templates.js.map +1 -0
  64. package/dist/cli/commands/scaffold.d.ts +105 -0
  65. package/dist/cli/commands/scaffold.d.ts.map +1 -0
  66. package/dist/cli/commands/scaffold.js +263 -0
  67. package/dist/cli/commands/scaffold.js.map +1 -0
  68. package/dist/cli/commands/security.d.ts.map +1 -1
  69. package/dist/cli/commands/security.js +22 -24
  70. package/dist/cli/commands/security.js.map +1 -1
  71. package/dist/cli/commands/spec-baseline-check.d.ts +43 -0
  72. package/dist/cli/commands/spec-baseline-check.d.ts.map +1 -1
  73. package/dist/cli/commands/spec-baseline-check.js +109 -34
  74. package/dist/cli/commands/spec-baseline-check.js.map +1 -1
  75. package/dist/cli/commands/sync-docs/context-syncer.d.ts +21 -2
  76. package/dist/cli/commands/sync-docs/context-syncer.d.ts.map +1 -1
  77. package/dist/cli/commands/sync-docs/context-syncer.js +112 -28
  78. package/dist/cli/commands/sync-docs/context-syncer.js.map +1 -1
  79. package/dist/cli/commands/sync-docs/index.d.ts +1 -1
  80. package/dist/cli/commands/sync-docs/index.d.ts.map +1 -1
  81. package/dist/cli/commands/sync-docs/index.js +86 -27
  82. package/dist/cli/commands/sync-docs/index.js.map +1 -1
  83. package/dist/cli/commands/sync-docs/project-reader.d.ts +24 -1
  84. package/dist/cli/commands/sync-docs/project-reader.d.ts.map +1 -1
  85. package/dist/cli/commands/sync-docs/project-reader.js +33 -7
  86. package/dist/cli/commands/sync-docs/project-reader.js.map +1 -1
  87. package/dist/cli/commands/validate.d.ts +0 -16
  88. package/dist/cli/commands/validate.d.ts.map +1 -1
  89. package/dist/cli/commands/validate.js +2 -97
  90. package/dist/cli/commands/validate.js.map +1 -1
  91. package/dist/cli/gate-command.d.ts +37 -0
  92. package/dist/cli/gate-command.d.ts.map +1 -0
  93. package/dist/cli/gate-command.js +64 -0
  94. package/dist/cli/gate-command.js.map +1 -0
  95. package/dist/completion-checkers/index.d.ts +1 -1
  96. package/dist/completion-checkers/index.d.ts.map +1 -1
  97. package/dist/completion-checkers/index.js +0 -15
  98. package/dist/completion-checkers/index.js.map +1 -1
  99. package/dist/context/knowledge-injector.d.ts +4 -2
  100. package/dist/context/knowledge-injector.d.ts.map +1 -1
  101. package/dist/context/knowledge-injector.js +13 -6
  102. package/dist/context/knowledge-injector.js.map +1 -1
  103. package/dist/core/constraints/agent-prompt-renderer.js +2 -2
  104. package/dist/core/constraints/agent-prompt-renderer.js.map +1 -1
  105. package/dist/core/constraints/capabilities-reconcile.d.ts +20 -0
  106. package/dist/core/constraints/capabilities-reconcile.d.ts.map +1 -1
  107. package/dist/core/constraints/capabilities-reconcile.js +26 -4
  108. package/dist/core/constraints/capabilities-reconcile.js.map +1 -1
  109. package/dist/core/constraints/check-cache.d.ts +1 -1
  110. package/dist/core/constraints/check-cache.js +1 -1
  111. package/dist/core/constraints/checker.d.ts +8 -3
  112. package/dist/core/constraints/checker.d.ts.map +1 -1
  113. package/dist/core/constraints/checker.js +30 -19
  114. package/dist/core/constraints/checker.js.map +1 -1
  115. package/dist/core/constraints/checkers/capability-sync.d.ts +3 -1
  116. package/dist/core/constraints/checkers/capability-sync.d.ts.map +1 -1
  117. package/dist/core/constraints/checkers/capability-sync.js +17 -24
  118. package/dist/core/constraints/checkers/capability-sync.js.map +1 -1
  119. package/dist/core/constraints/checkers/context-doc-sync.d.ts +1 -1
  120. package/dist/core/constraints/checkers/context-doc-sync.d.ts.map +1 -1
  121. package/dist/core/constraints/checkers/context-doc-sync.js +9 -6
  122. package/dist/core/constraints/checkers/context-doc-sync.js.map +1 -1
  123. package/dist/core/constraints/checkers/docs-freshness.d.ts.map +1 -1
  124. package/dist/core/constraints/checkers/docs-freshness.js +24 -30
  125. package/dist/core/constraints/checkers/docs-freshness.js.map +1 -1
  126. package/dist/core/constraints/checkers/governance-presence.d.ts.map +1 -1
  127. package/dist/core/constraints/checkers/governance-presence.js +10 -4
  128. package/dist/core/constraints/checkers/governance-presence.js.map +1 -1
  129. package/dist/core/constraints/checkers/types.d.ts +10 -6
  130. package/dist/core/constraints/checkers/types.d.ts.map +1 -1
  131. package/dist/core/constraints/checkers/types.js +7 -3
  132. package/dist/core/constraints/checkers/types.js.map +1 -1
  133. package/dist/core/constraints/context-builder.d.ts +11 -10
  134. package/dist/core/constraints/context-builder.d.ts.map +1 -1
  135. package/dist/core/constraints/context-builder.js +31 -27
  136. package/dist/core/constraints/context-builder.js.map +1 -1
  137. package/dist/core/constraints/context-reconcile.d.ts +75 -0
  138. package/dist/core/constraints/context-reconcile.d.ts.map +1 -0
  139. package/dist/core/constraints/context-reconcile.js +161 -0
  140. package/dist/core/constraints/context-reconcile.js.map +1 -0
  141. package/dist/core/constraints/doc-freshness/runner.d.ts +7 -0
  142. package/dist/core/constraints/doc-freshness/runner.d.ts.map +1 -1
  143. package/dist/core/constraints/doc-freshness/runner.js +8 -3
  144. package/dist/core/constraints/doc-freshness/runner.js.map +1 -1
  145. package/dist/core/constraints/git-evidence.js +1 -1
  146. package/dist/core/constraints/git-evidence.js.map +1 -1
  147. package/dist/core/constraints/injection-drift.d.ts +7 -2
  148. package/dist/core/constraints/injection-drift.d.ts.map +1 -1
  149. package/dist/core/constraints/injection-drift.js +13 -7
  150. package/dist/core/constraints/injection-drift.js.map +1 -1
  151. package/dist/core/constraints/run-env.d.ts +92 -0
  152. package/dist/core/constraints/run-env.d.ts.map +1 -0
  153. package/dist/core/constraints/run-env.js +175 -0
  154. package/dist/core/constraints/run-env.js.map +1 -0
  155. package/dist/core/constraints/triggers.d.ts +22 -0
  156. package/dist/core/constraints/triggers.d.ts.map +1 -0
  157. package/dist/core/constraints/triggers.js +31 -0
  158. package/dist/core/constraints/triggers.js.map +1 -0
  159. package/dist/core/effective-constraints.d.ts +13 -4
  160. package/dist/core/effective-constraints.d.ts.map +1 -1
  161. package/dist/core/effective-constraints.js +16 -6
  162. package/dist/core/effective-constraints.js.map +1 -1
  163. package/dist/core/effective-set.d.ts +8 -15
  164. package/dist/core/effective-set.d.ts.map +1 -1
  165. package/dist/core/effective-set.js +7 -12
  166. package/dist/core/effective-set.js.map +1 -1
  167. package/dist/core/index.d.ts +1 -0
  168. package/dist/core/index.d.ts.map +1 -1
  169. package/dist/core/index.js.map +1 -1
  170. package/dist/core/project-config-loader.d.ts +39 -17
  171. package/dist/core/project-config-loader.d.ts.map +1 -1
  172. package/dist/core/project-config-loader.js +51 -122
  173. package/dist/core/project-config-loader.js.map +1 -1
  174. package/dist/core/validators/check-handlers/http.d.ts +2 -2
  175. package/dist/core/validators/check-handlers/http.d.ts.map +1 -1
  176. package/dist/core/validators/check-handlers/http.js +12 -7
  177. package/dist/core/validators/check-handlers/http.js.map +1 -1
  178. package/dist/failure/classifier.d.ts +1 -1
  179. package/dist/failure/classifier.d.ts.map +1 -1
  180. package/dist/failure/classifier.js +8 -8
  181. package/dist/failure/classifier.js.map +1 -1
  182. package/dist/failure/index.d.ts +2 -1
  183. package/dist/failure/index.d.ts.map +1 -1
  184. package/dist/failure/index.js +9 -17
  185. package/dist/failure/index.js.map +1 -1
  186. package/dist/failure/recorder.d.ts +1 -1
  187. package/dist/failure/recorder.d.ts.map +1 -1
  188. package/dist/gates/checker-gate.d.ts +2 -1
  189. package/dist/gates/checker-gate.d.ts.map +1 -1
  190. package/dist/gates/checker-gate.js +3 -2
  191. package/dist/gates/checker-gate.js.map +1 -1
  192. package/dist/gates/command.d.ts +10 -4
  193. package/dist/gates/command.d.ts.map +1 -1
  194. package/dist/gates/command.js +36 -62
  195. package/dist/gates/command.js.map +1 -1
  196. package/dist/gates/contract.d.ts.map +1 -1
  197. package/dist/gates/contract.js +0 -4
  198. package/dist/gates/contract.js.map +1 -1
  199. package/dist/gates/definitions.d.ts +2 -1
  200. package/dist/gates/definitions.d.ts.map +1 -1
  201. package/dist/gates/definitions.js +6 -5
  202. package/dist/gates/definitions.js.map +1 -1
  203. package/dist/gates/index.d.ts +0 -4
  204. package/dist/gates/index.d.ts.map +1 -1
  205. package/dist/gates/index.js +1 -6
  206. package/dist/gates/index.js.map +1 -1
  207. package/dist/gates/performance.d.ts.map +1 -1
  208. package/dist/gates/performance.js +0 -4
  209. package/dist/gates/performance.js.map +1 -1
  210. package/dist/gates/runner.d.ts +1 -1
  211. package/dist/gates/runner.js +1 -1
  212. package/dist/gates/security.d.ts +1 -1
  213. package/dist/gates/security.d.ts.map +1 -1
  214. package/dist/gates/security.js +5 -6
  215. package/dist/gates/security.js.map +1 -1
  216. package/dist/gates/types.d.ts +14 -17
  217. package/dist/gates/types.d.ts.map +1 -1
  218. package/dist/gates/types.js.map +1 -1
  219. package/dist/hooks/bootstrap.d.ts +6 -4
  220. package/dist/hooks/bootstrap.d.ts.map +1 -1
  221. package/dist/hooks/bootstrap.js +25 -13
  222. package/dist/hooks/bootstrap.js.map +1 -1
  223. package/dist/hooks/config.d.ts +6 -2
  224. package/dist/hooks/config.d.ts.map +1 -1
  225. package/dist/hooks/config.js +5 -1
  226. package/dist/hooks/config.js.map +1 -1
  227. package/dist/hooks/index.d.ts +1 -1
  228. package/dist/hooks/index.d.ts.map +1 -1
  229. package/dist/hooks/index.js +0 -15
  230. package/dist/hooks/index.js.map +1 -1
  231. package/dist/hooks/pipeline.d.ts.map +1 -1
  232. package/dist/hooks/pipeline.js +2 -4
  233. package/dist/hooks/pipeline.js.map +1 -1
  234. package/dist/hooks/registry.d.ts +11 -8
  235. package/dist/hooks/registry.d.ts.map +1 -1
  236. package/dist/hooks/registry.js +22 -7
  237. package/dist/hooks/registry.js.map +1 -1
  238. package/dist/hooks/types.d.ts +23 -7
  239. package/dist/hooks/types.d.ts.map +1 -1
  240. package/dist/index.d.ts +3 -3
  241. package/dist/index.d.ts.map +1 -1
  242. package/dist/index.js +3 -4
  243. package/dist/index.js.map +1 -1
  244. package/dist/knowledge/audit-scoring.d.ts +87 -0
  245. package/dist/knowledge/audit-scoring.d.ts.map +1 -0
  246. package/dist/knowledge/audit-scoring.js +470 -0
  247. package/dist/knowledge/audit-scoring.js.map +1 -0
  248. package/dist/knowledge/audit.d.ts +11 -59
  249. package/dist/knowledge/audit.d.ts.map +1 -1
  250. package/dist/knowledge/audit.js +47 -522
  251. package/dist/knowledge/audit.js.map +1 -1
  252. package/dist/knowledge/import.d.ts.map +1 -1
  253. package/dist/knowledge/import.js +2 -0
  254. package/dist/knowledge/import.js.map +1 -1
  255. package/dist/knowledge/index-generator.d.ts.map +1 -1
  256. package/dist/knowledge/index-generator.js +4 -5
  257. package/dist/knowledge/index-generator.js.map +1 -1
  258. package/dist/knowledge/index.d.ts +3 -2
  259. package/dist/knowledge/index.d.ts.map +1 -1
  260. package/dist/knowledge/index.js +3 -16
  261. package/dist/knowledge/index.js.map +1 -1
  262. package/dist/knowledge/ingest.js +1 -1
  263. package/dist/knowledge/ingest.js.map +1 -1
  264. package/dist/knowledge/lifecycle.d.ts.map +1 -1
  265. package/dist/knowledge/lifecycle.js +4 -2
  266. package/dist/knowledge/lifecycle.js.map +1 -1
  267. package/dist/knowledge/migration.d.ts +3 -0
  268. package/dist/knowledge/migration.d.ts.map +1 -1
  269. package/dist/knowledge/migration.js +8 -2
  270. package/dist/knowledge/migration.js.map +1 -1
  271. package/dist/knowledge/query.d.ts +6 -0
  272. package/dist/knowledge/query.d.ts.map +1 -1
  273. package/dist/knowledge/query.js +8 -2
  274. package/dist/knowledge/query.js.map +1 -1
  275. package/dist/knowledge/reference-tracker.d.ts.map +1 -1
  276. package/dist/knowledge/reference-tracker.js +4 -6
  277. package/dist/knowledge/reference-tracker.js.map +1 -1
  278. package/dist/knowledge/store.d.ts +22 -16
  279. package/dist/knowledge/store.d.ts.map +1 -1
  280. package/dist/knowledge/store.js +53 -12
  281. package/dist/knowledge/store.js.map +1 -1
  282. package/dist/knowledge/tree-walker.d.ts +19 -0
  283. package/dist/knowledge/tree-walker.d.ts.map +1 -0
  284. package/dist/knowledge/tree-walker.js +30 -0
  285. package/dist/knowledge/tree-walker.js.map +1 -0
  286. package/dist/knowledge/types.d.ts +16 -0
  287. package/dist/knowledge/types.d.ts.map +1 -1
  288. package/dist/monitoring/traces.d.ts +5 -3
  289. package/dist/monitoring/traces.d.ts.map +1 -1
  290. package/dist/monitoring/traces.js +19 -5
  291. package/dist/monitoring/traces.js.map +1 -1
  292. package/dist/test-setup/jsonl-fake-fs.d.ts +30 -0
  293. package/dist/test-setup/jsonl-fake-fs.d.ts.map +1 -0
  294. package/dist/test-setup/jsonl-fake-fs.js +49 -0
  295. package/dist/test-setup/jsonl-fake-fs.js.map +1 -0
  296. package/dist/tools/index.d.ts +4 -1
  297. package/dist/tools/index.d.ts.map +1 -1
  298. package/dist/tools/index.js +7 -15
  299. package/dist/tools/index.js.map +1 -1
  300. package/dist/types/checkpoint.d.ts +5 -0
  301. package/dist/types/checkpoint.d.ts.map +1 -1
  302. package/dist/types/project-config.d.ts +18 -0
  303. package/dist/types/project-config.d.ts.map +1 -1
  304. package/dist/types/trace.d.ts +13 -4
  305. package/dist/types/trace.d.ts.map +1 -1
  306. package/dist/types/trace.js +4 -3
  307. package/dist/types/trace.js.map +1 -1
  308. package/dist/utils/exec.d.ts +4 -27
  309. package/dist/utils/exec.d.ts.map +1 -1
  310. package/dist/utils/exec.js +4 -94
  311. package/dist/utils/exec.js.map +1 -1
  312. package/dist/utils/jsonl.d.ts +17 -7
  313. package/dist/utils/jsonl.d.ts.map +1 -1
  314. package/dist/utils/jsonl.js +144 -17
  315. package/dist/utils/jsonl.js.map +1 -1
  316. package/dist/utils/numeric-flag.d.ts +44 -0
  317. package/dist/utils/numeric-flag.d.ts.map +1 -0
  318. package/dist/utils/numeric-flag.js +62 -0
  319. package/dist/utils/numeric-flag.js.map +1 -0
  320. package/package.json +1 -1
  321. package/src/CONTEXT.md +5 -2
  322. package/src/__tests__/acceptance-gate.test.ts +7 -4
  323. package/src/__tests__/checker-extra.test.ts +3 -2
  324. package/src/__tests__/checker.test.ts +4 -3
  325. package/src/__tests__/checkpoint.test.ts +26 -9
  326. package/src/__tests__/context-files-resolution.test.ts +29 -15
  327. package/src/__tests__/contract-gate.test.ts +19 -40
  328. package/src/__tests__/error-classifier.test.ts +1 -1
  329. package/src/__tests__/exec.test.ts +45 -107
  330. package/src/__tests__/failure-recorder.test.ts +7 -5
  331. package/src/__tests__/hooks-pipeline.test.ts +34 -47
  332. package/src/__tests__/layering.test.ts +217 -25
  333. package/src/__tests__/passes-gate.test.ts +9 -4
  334. package/src/__tests__/performance-gate.test.ts +3 -15
  335. package/src/__tests__/project-config-loader-extra.test.ts +31 -57
  336. package/src/__tests__/project-config-loader.test.ts +6 -3
  337. package/src/__tests__/public-exports.test.ts +0 -1
  338. package/src/__tests__/public-type-surface.test.ts +5 -4
  339. package/src/__tests__/public-value-surface.test.ts +182 -0
  340. package/src/__tests__/review-gate.test.ts +4 -6
  341. package/src/__tests__/security-gate.test.ts +5 -20
  342. package/src/__tests__/skip-semantics.test.ts +5 -3
  343. package/src/__tests__/spec-validator.test.ts +3 -2
  344. package/src/__tests__/sub-barrels-explicit.test.ts +87 -0
  345. package/src/__tests__/test-fixture-hygiene.test.ts +53 -0
  346. package/src/__tests__/trace-analyzer-extra.test.ts +5 -3
  347. package/src/__tests__/trace-analyzer.test.ts +5 -3
  348. package/src/__tests__/trace-collector.test.ts +5 -3
  349. package/src/agents/index.ts +13 -2
  350. package/src/cli/__tests__/gate-command.test.ts +162 -0
  351. package/src/cli/commands/CONTEXT.md +29 -5
  352. package/src/cli/commands/__tests__/acceptance.test.ts +24 -25
  353. package/src/cli/commands/__tests__/bin-exit-mapping.test.ts +15 -0
  354. package/src/cli/commands/__tests__/check-drift.test.ts +42 -1
  355. package/src/cli/commands/__tests__/check-read-count.test.ts +167 -0
  356. package/src/cli/commands/__tests__/check-skip-output.test.ts +4 -1
  357. package/src/cli/commands/__tests__/check.test.ts +43 -36
  358. package/src/cli/commands/__tests__/command-gate-dead-options.test.ts +60 -0
  359. package/src/cli/commands/__tests__/command.test.ts +33 -17
  360. package/src/cli/commands/__tests__/constraints-retire.test.ts +52 -0
  361. package/src/cli/commands/__tests__/context-syncer.test.ts +141 -0
  362. package/src/cli/commands/__tests__/contract.test.ts +20 -20
  363. package/src/cli/commands/__tests__/failure.test.ts +5 -4
  364. package/src/cli/commands/__tests__/gate-decision.ts +30 -0
  365. package/src/cli/commands/__tests__/init-dead-options.test.ts +50 -0
  366. package/src/cli/commands/__tests__/init-governance-io.test.ts +139 -0
  367. package/src/cli/commands/__tests__/init-injection.test.ts +3 -3
  368. package/src/cli/commands/__tests__/init-ondisk.test.ts +867 -0
  369. package/src/cli/commands/__tests__/init.test.ts +82 -6
  370. package/src/cli/commands/__tests__/knowledge-audit-threshold.test.ts +146 -0
  371. package/src/cli/commands/__tests__/knowledge-flywheel-consistency.test.ts +1 -1
  372. package/src/cli/commands/__tests__/knowledge-tone-mapping.test.ts +244 -0
  373. package/src/cli/commands/__tests__/knowledge-view.test.ts +839 -0
  374. package/src/cli/commands/__tests__/knowledge.test.ts +33 -15
  375. package/src/cli/commands/__tests__/numeric-flag-assembly.test.ts +368 -0
  376. package/src/cli/commands/__tests__/performance.test.ts +19 -21
  377. package/src/cli/commands/__tests__/posteval-plan.test.ts +5 -3
  378. package/src/cli/commands/__tests__/pre-push-hook.test.ts +181 -0
  379. package/src/cli/commands/__tests__/project-path-anchoring.test.ts +95 -2
  380. package/src/cli/commands/__tests__/project-path-convention.test.ts +103 -25
  381. package/src/cli/commands/__tests__/registry.test.ts +2 -0
  382. package/src/cli/commands/__tests__/report.test.ts +23 -1
  383. package/src/cli/commands/__tests__/review.test.ts +10 -17
  384. package/src/cli/commands/__tests__/scaffold.test.ts +505 -0
  385. package/src/cli/commands/__tests__/security-default-scan.test.ts +75 -0
  386. package/src/cli/commands/__tests__/security.test.ts +21 -24
  387. package/src/cli/commands/__tests__/spec-baseline-check.test.ts +3 -2
  388. package/src/cli/commands/__tests__/spec-baseline-index-cap.test.ts +131 -0
  389. package/src/cli/commands/__tests__/spec-baseline-read-count.test.ts +325 -0
  390. package/src/cli/commands/__tests__/sync-docs-agents.test.ts +19 -4
  391. package/src/cli/commands/__tests__/sync-docs-context-drift.test.ts +232 -0
  392. package/src/cli/commands/__tests__/sync-docs-module-order.test.ts +111 -0
  393. package/src/cli/commands/__tests__/sync-docs-read-count.test.ts +192 -0
  394. package/src/cli/commands/__tests__/sync-docs.test.ts +3 -2
  395. package/src/cli/commands/__tests__/validate.test.ts +1 -48
  396. package/src/cli/commands/acceptance.ts +24 -29
  397. package/src/cli/commands/check.ts +40 -17
  398. package/src/cli/commands/command.ts +9 -8
  399. package/src/cli/commands/constraints-retire.ts +57 -70
  400. package/src/cli/commands/contract.ts +44 -47
  401. package/src/cli/commands/definitions.ts +12 -6
  402. package/src/cli/commands/failure.ts +16 -3
  403. package/src/cli/commands/init.ts +242 -389
  404. package/src/cli/commands/knowledge-view.ts +224 -0
  405. package/src/cli/commands/knowledge.ts +643 -448
  406. package/src/cli/commands/passes-gate.ts +12 -3
  407. package/src/cli/commands/performance.ts +31 -38
  408. package/src/cli/commands/report.ts +3 -2
  409. package/src/cli/commands/review.ts +22 -28
  410. package/src/cli/commands/scaffold-templates.ts +406 -0
  411. package/src/cli/commands/scaffold.ts +302 -0
  412. package/src/cli/commands/security.ts +27 -23
  413. package/src/cli/commands/spec-baseline-check.ts +158 -33
  414. package/src/cli/commands/sync-docs/__tests__/context-export-surface.test.ts +102 -0
  415. package/src/cli/commands/sync-docs/__tests__/module-descriptions.test.ts +196 -0
  416. package/src/cli/commands/sync-docs/context-syncer.ts +137 -31
  417. package/src/cli/commands/sync-docs/index.ts +103 -28
  418. package/src/cli/commands/sync-docs/project-reader.ts +51 -7
  419. package/src/cli/commands/validate.ts +1 -104
  420. package/src/cli/gate-command.ts +87 -0
  421. package/src/completion-checkers/index.ts +10 -1
  422. package/src/context/CONTEXT.md +2 -1
  423. package/src/context/__tests__/knowledge-injector.test.ts +27 -0
  424. package/src/context/__tests__/session-manager.test.ts +19 -12
  425. package/src/context/knowledge-injector.ts +14 -7
  426. package/src/core/CONTEXT.md +10 -7
  427. package/src/core/__tests__/effective-set.test.ts +36 -60
  428. package/src/core/constraints/__tests__/context-reconcile.test.ts +246 -0
  429. package/src/core/constraints/__tests__/run-env.test.ts +377 -0
  430. package/src/core/constraints/__tests__/triggers.test.ts +70 -0
  431. package/src/core/constraints/agent-prompt-renderer.ts +1 -1
  432. package/src/core/constraints/capabilities-reconcile.ts +28 -4
  433. package/src/core/constraints/check-cache.ts +1 -1
  434. package/src/core/constraints/checker.ts +30 -14
  435. package/src/core/constraints/checkers/__tests__/context-doc-sync.test.ts +8 -3
  436. package/src/core/constraints/checkers/__tests__/governance-presence.test.ts +16 -7
  437. package/src/core/constraints/checkers/__tests__/no-hardcoded-credentials.test.ts +2 -1
  438. package/src/core/constraints/checkers/capability-sync.ts +27 -28
  439. package/src/core/constraints/checkers/context-doc-sync.ts +9 -7
  440. package/src/core/constraints/checkers/docs-freshness.ts +28 -33
  441. package/src/core/constraints/checkers/governance-presence.ts +10 -6
  442. package/src/core/constraints/checkers/types.ts +14 -8
  443. package/src/core/constraints/context-builder.ts +35 -26
  444. package/src/core/constraints/context-reconcile.ts +200 -0
  445. package/src/core/constraints/doc-freshness/__tests__/runner.test.ts +25 -0
  446. package/src/core/constraints/doc-freshness/runner.ts +18 -4
  447. package/src/core/constraints/git-evidence.ts +1 -1
  448. package/src/core/constraints/injection-drift.ts +19 -8
  449. package/src/core/constraints/run-env.ts +207 -0
  450. package/src/core/constraints/triggers.ts +33 -0
  451. package/src/core/effective-constraints.ts +17 -6
  452. package/src/core/effective-set.ts +8 -24
  453. package/src/core/index.ts +2 -0
  454. package/src/core/project-config-loader.ts +54 -102
  455. package/src/core/validators/__tests__/http-retry-sleep.test.ts +231 -0
  456. package/src/core/validators/check-handlers/http.ts +18 -7
  457. package/src/failure/CONTEXT.md +2 -1
  458. package/src/failure/classifier.ts +2 -2
  459. package/src/failure/index.ts +14 -2
  460. package/src/failure/recorder.ts +1 -1
  461. package/src/gates/CONTEXT.md +13 -7
  462. package/src/gates/__tests__/checker-gate.test.ts +1 -1
  463. package/src/gates/__tests__/command-single-predicate.test.ts +135 -0
  464. package/src/gates/__tests__/command.test.ts +8 -15
  465. package/src/gates/__tests__/contract.test.ts +5 -5
  466. package/src/gates/__tests__/gate-interface.test.ts +0 -17
  467. package/src/gates/__tests__/performance.test.ts +0 -13
  468. package/src/gates/__tests__/review.test.ts +0 -1
  469. package/src/gates/__tests__/runner.test.ts +1 -1
  470. package/src/gates/__tests__/security-default-scan.test.ts +97 -0
  471. package/src/gates/__tests__/security.test.ts +0 -13
  472. package/src/gates/checker-gate.ts +3 -2
  473. package/src/gates/command.ts +51 -74
  474. package/src/gates/contract.ts +0 -5
  475. package/src/gates/definitions.ts +6 -5
  476. package/src/gates/index.ts +0 -5
  477. package/src/gates/performance.ts +1 -6
  478. package/src/gates/runner.ts +1 -1
  479. package/src/gates/security.ts +9 -11
  480. package/src/gates/types.ts +20 -23
  481. package/src/hooks/CONTEXT.md +10 -9
  482. package/src/hooks/__tests__/bootstrap.test.ts +29 -6
  483. package/src/hooks/__tests__/pipeline.test.ts +28 -17
  484. package/src/hooks/__tests__/registry.test.ts +51 -3
  485. package/src/hooks/bootstrap.ts +35 -15
  486. package/src/hooks/config.ts +6 -2
  487. package/src/hooks/index.ts +10 -1
  488. package/src/hooks/pipeline.ts +4 -6
  489. package/src/hooks/registry.ts +31 -12
  490. package/src/hooks/types.ts +24 -7
  491. package/src/index.ts +1 -2
  492. package/src/knowledge/CONTEXT.md +14 -7
  493. package/src/knowledge/__tests__/audit-labels.test.ts +8 -5
  494. package/src/knowledge/__tests__/audit-scoring.test.ts +230 -0
  495. package/src/knowledge/__tests__/audit-write-count.test.ts +131 -0
  496. package/src/knowledge/__tests__/audit.test.ts +291 -208
  497. package/src/knowledge/__tests__/doctor.test.ts +3 -2
  498. package/src/knowledge/__tests__/ingest.test.ts +3 -2
  499. package/src/knowledge/__tests__/lifecycle.test.ts +57 -2
  500. package/src/knowledge/__tests__/migration.test.ts +35 -6
  501. package/src/knowledge/__tests__/query.test.ts +3 -2
  502. package/src/knowledge/__tests__/reference-tracker.test.ts +23 -2
  503. package/src/knowledge/__tests__/store.test.ts +149 -4
  504. package/src/knowledge/__tests__/tree-walker.test.ts +132 -0
  505. package/src/knowledge/audit-scoring.ts +589 -0
  506. package/src/knowledge/audit.ts +55 -599
  507. package/src/knowledge/import.ts +2 -0
  508. package/src/knowledge/index-generator.ts +4 -6
  509. package/src/knowledge/index.ts +27 -2
  510. package/src/knowledge/ingest.ts +1 -1
  511. package/src/knowledge/lifecycle.ts +5 -2
  512. package/src/knowledge/migration.ts +8 -2
  513. package/src/knowledge/query.ts +8 -1
  514. package/src/knowledge/reference-tracker.ts +5 -7
  515. package/src/knowledge/store.ts +75 -16
  516. package/src/knowledge/tree-walker.ts +29 -0
  517. package/src/knowledge/types.ts +19 -0
  518. package/src/monitoring/CONTEXT.md +5 -2
  519. package/src/monitoring/__tests__/context-tracker.test.ts +16 -8
  520. package/src/monitoring/__tests__/trace-file-anchoring.test.ts +80 -0
  521. package/src/monitoring/traces.ts +19 -5
  522. package/src/release/CONTEXT.md +1 -1
  523. package/src/release/__tests__/integrity.test.ts +21 -12
  524. package/src/test-setup/__tests__/jsonl-fake-fs.test.ts +98 -0
  525. package/src/test-setup/jsonl-fake-fs.ts +59 -0
  526. package/src/tools/index.ts +5 -1
  527. package/src/types/checkpoint.ts +6 -0
  528. package/src/types/project-config.ts +21 -0
  529. package/src/types/trace.ts +14 -4
  530. package/src/utils/__tests__/file-walk.test.ts +3 -2
  531. package/src/utils/__tests__/jsonl-bounded-read.test.ts +106 -0
  532. package/src/utils/__tests__/jsonl-skip-disposition.test.ts +10 -6
  533. package/src/utils/__tests__/jsonl.test.ts +61 -14
  534. package/src/utils/__tests__/numeric-flag.test.ts +80 -0
  535. package/src/utils/__tests__/package-version.test.ts +2 -2
  536. package/src/utils/exec.ts +4 -64
  537. package/src/utils/jsonl.ts +159 -20
  538. package/src/utils/numeric-flag.ts +64 -0
  539. package/dist/failure/types.d.ts +0 -9
  540. package/dist/failure/types.d.ts.map +0 -1
  541. package/dist/failure/types.js +0 -25
  542. package/dist/failure/types.js.map +0 -1
  543. package/dist/gates/effective-gates.d.ts +0 -30
  544. package/dist/gates/effective-gates.d.ts.map +0 -1
  545. package/dist/gates/effective-gates.js +0 -81
  546. package/dist/gates/effective-gates.js.map +0 -1
  547. package/src/failure/types.ts +0 -9
  548. package/src/gates/__tests__/effective-gates.test.ts +0 -77
  549. package/src/gates/effective-gates.ts +0 -99
@@ -5,7 +5,7 @@
5
5
  * 检查命令是否安全,防止执行危险操作
6
6
  */
7
7
 
8
- import { pass, gateResult } from './types';
8
+ import { gateResult } from './types';
9
9
  import type { GateResult, CommandGateConfig, CommandBlacklistRule, Gate, GateContext, GateDecision } from './types';
10
10
  import { decisionFromResult } from './decision';
11
11
 
@@ -194,6 +194,17 @@ export const DEFAULT_COMMAND_BLACKLIST: CommandBlacklistRule[] = [
194
194
  },
195
195
  ];
196
196
 
197
+ /**
198
+ * 三投影共用的裁决(模块内类型,不入公共面)
199
+ */
200
+ interface CommandVerdict {
201
+ allowed: boolean;
202
+ blocked: CommandBlacklistRule[];
203
+ warnings: CommandBlacklistRule[];
204
+ audits: CommandBlacklistRule[];
205
+ riskLevel: 'high' | 'medium' | 'low';
206
+ }
207
+
197
208
  /**
198
209
  * 命令门禁
199
210
  */
@@ -205,17 +216,10 @@ export class CommandGate implements Gate {
205
216
 
206
217
  constructor(config: Partial<CommandGateConfig> = {}) {
207
218
  this.config = {
208
- enabled: config.enabled ?? true,
209
- strict: config.strict ?? false,
210
- customBlacklist: config.customBlacklist ?? [],
211
219
  ignoreCategories: config.ignoreCategories ?? [],
212
220
  };
213
221
 
214
- // 合并默认黑名单和自定义黑名单
215
- this.blacklist = [
216
- ...DEFAULT_COMMAND_BLACKLIST,
217
- ...this.config.customBlacklist,
218
- ];
222
+ this.blacklist = [...DEFAULT_COMMAND_BLACKLIST];
219
223
  }
220
224
 
221
225
  /**
@@ -232,40 +236,30 @@ export class CommandGate implements Gate {
232
236
  async check(command: string): Promise<GateResult> {
233
237
  const startTime = Date.now();
234
238
 
235
- if (!this.config.enabled) {
236
- return pass('command', '命令门禁已禁用', startTime);
237
- }
238
-
239
- const result = this.checkBlacklist(command);
239
+ const verdict = this.judge(command);
240
240
 
241
241
  return gateResult(
242
242
  'command',
243
- result.allowed,
244
- result.allowed
245
- ? this.formatSuccessMessage(result)
246
- : this.formatBlockMessage(result),
243
+ verdict.allowed,
244
+ verdict.allowed
245
+ ? this.formatSuccessMessage(verdict)
246
+ : this.formatBlockMessage(verdict),
247
247
  startTime,
248
248
  {
249
- blocked: result.blocked,
250
- warnings: result.warnings,
251
- audits: result.audits,
249
+ blocked: verdict.blocked,
250
+ warnings: verdict.warnings,
251
+ audits: verdict.audits,
252
252
  command,
253
253
  }
254
254
  );
255
255
  }
256
256
 
257
257
  /**
258
- * 检查黑名单
258
+ * 唯一匹配谓词(#135):类别忽略与规则模式测试只在此处发生。
259
+ * 三个入口一律经 judge() 取它的投影,不再各写一遍匹配循环。
259
260
  */
260
- private checkBlacklist(command: string): {
261
- allowed: boolean;
262
- blocked: CommandBlacklistRule[];
263
- warnings: CommandBlacklistRule[];
264
- audits: CommandBlacklistRule[];
265
- } {
266
- const blocked: CommandBlacklistRule[] = [];
267
- const warnings: CommandBlacklistRule[] = [];
268
- const audits: CommandBlacklistRule[] = [];
261
+ private matchCommand(command: string): CommandBlacklistRule[] {
262
+ const hits: CommandBlacklistRule[] = [];
269
263
 
270
264
  for (const rule of this.blacklist) {
271
265
  // 跳过忽略的类别
@@ -274,25 +268,36 @@ export class CommandGate implements Gate {
274
268
  }
275
269
 
276
270
  if (rule.pattern.test(command)) {
277
- switch (rule.level) {
278
- case 'block':
279
- blocked.push(rule);
280
- break;
281
- case 'warn':
282
- warnings.push(rule);
283
- break;
284
- case 'audit':
285
- audits.push(rule);
286
- break;
287
- }
271
+ hits.push(rule);
288
272
  }
289
273
  }
290
274
 
275
+ return hits;
276
+ }
277
+
278
+ /**
279
+ * 命中集合 → 裁决:级别(block/warn/audit)语义只在此处解释一次,
280
+ * 三投影因此对同一输入不可能互相矛盾。
281
+ */
282
+ private judge(command: string): CommandVerdict {
283
+ const hits = this.matchCommand(command);
284
+ const blocked = hits.filter(rule => rule.level === 'block');
285
+ const warnings = hits.filter(rule => rule.level === 'warn');
286
+ const audits = hits.filter(rule => rule.level === 'audit');
287
+
288
+ let riskLevel: 'high' | 'medium' | 'low' = 'low';
289
+ if (blocked.length > 0) {
290
+ riskLevel = 'high';
291
+ } else if (warnings.length > 0) {
292
+ riskLevel = 'medium';
293
+ }
294
+
291
295
  return {
292
296
  allowed: blocked.length === 0,
293
297
  blocked,
294
298
  warnings,
295
299
  audits,
300
+ riskLevel,
296
301
  };
297
302
  }
298
303
 
@@ -335,45 +340,17 @@ export class CommandGate implements Gate {
335
340
  }
336
341
 
337
342
  /**
338
- * 快速检查(不生成完整 GateResult
343
+ * 快速检查(不生成完整 GateResult)——谓词裁决的布尔投影,hook 侧入口
339
344
  */
340
345
  isAllowed(command: string): boolean {
341
- if (!this.config.enabled) return true;
342
-
343
- for (const rule of this.blacklist) {
344
- if (this.config.ignoreCategories.includes(rule.category)) {
345
- continue;
346
- }
347
-
348
- if (rule.level === 'block' && rule.pattern.test(command)) {
349
- return false;
350
- }
351
- }
352
-
353
- return true;
346
+ return this.judge(command).allowed;
354
347
  }
355
348
 
356
349
  /**
357
- * 获取命令风险等级
350
+ * 获取命令风险等级——谓词裁决的等级投影:命中集合里的最高档
358
351
  */
359
352
  getRiskLevel(command: string): 'high' | 'medium' | 'low' {
360
- if (!this.config.enabled) return 'low';
361
-
362
- for (const rule of this.blacklist) {
363
- if (this.config.ignoreCategories.includes(rule.category)) {
364
- continue;
365
- }
366
-
367
- if (rule.pattern.test(command)) {
368
- switch (rule.level) {
369
- case 'block': return 'high';
370
- case 'warn': return 'medium';
371
- case 'audit': return 'low';
372
- }
373
- }
374
- }
375
-
376
- return 'low';
353
+ return this.judge(command).riskLevel;
377
354
  }
378
355
 
379
356
  /**
@@ -23,7 +23,6 @@ export class ContractGate implements Gate {
23
23
 
24
24
  constructor(config: Partial<ContractGateConfig> = {}) {
25
25
  this.config = {
26
- enabled: config.enabled ?? true,
27
26
  strict: config.strict ?? true,
28
27
  allowBreakingChanges: config.allowBreakingChanges ?? false,
29
28
  contractPath: config.contractPath ?? 'openapi.yaml',
@@ -43,10 +42,6 @@ export class ContractGate implements Gate {
43
42
  async check(context: GateContext): Promise<GateResult> {
44
43
  const startTime = Date.now();
45
44
 
46
- if (!this.config.enabled) {
47
- return pass('contract', '契约门禁已禁用', startTime);
48
- }
49
-
50
45
  try {
51
46
  const contractPath = context.newContractPath ??
52
47
  path.join(context.projectPath, this.config.contractPath);
@@ -11,10 +11,12 @@
11
11
  * bareRunsAction:true(无位置参数时跑默认 action 而非显示帮助)。
12
12
  * - 本模块禁止 import 任何门禁/命令实现(仅 type import,运行时零依赖)——
13
13
  * bin 启动期只加载本纯数据模块(保持 --help/--version 懒加载,
14
- * 闭环校验在 registry 加载期执行)。
14
+ * 闭环校验在 registry 加载期执行)。唯一例外 import:`utils/numeric-flag`
15
+ * 纯函数解析器(harness#154 口径条目指名的数值旗帜唯一解析器)。
15
16
  */
16
17
 
17
18
  import type { CommandDefinition } from '../cli/commands/definitions';
19
+ import { requireNumericFlag } from '../utils/numeric-flag';
18
20
 
19
21
  /**
20
22
  * 门禁定义
@@ -70,7 +72,6 @@ export const GATE_DEFINITIONS: GateDefinition[] = [
70
72
  { flags: '-l, --level', description: '显示风险等级' },
71
73
  { flags: '--list', description: '列出所有黑名单规则' },
72
74
  { flags: '--json', description: 'JSON 格式输出' },
73
- { flags: '--strict', description: '严格模式(warn 也阻止)' },
74
75
  ],
75
76
  action: { module: 'command', export: 'executeCommand' },
76
77
  mapActionArgs: (positionals, options) => [positionals[0], options],
@@ -117,9 +118,9 @@ export const GATE_DEFINITIONS: GateDefinition[] = [
117
118
  {
118
119
  projectPath: options.projectPath,
119
120
  coverage: options.coverage,
120
- coverageThreshold: parseInt(String(options.coverageThreshold), 10),
121
+ coverageThreshold: requireNumericFlag('--coverage-threshold', options.coverageThreshold as string | undefined, 'int'),
121
122
  bundle: options.bundle,
122
- bundleThreshold: parseInt(String(options.bundleThreshold), 10),
123
+ bundleThreshold: requireNumericFlag('--bundle-threshold', options.bundleThreshold as string | undefined, 'int'),
123
124
  },
124
125
  ],
125
126
  },
@@ -146,7 +147,7 @@ export const GATE_DEFINITIONS: GateDefinition[] = [
146
147
  mapActionArgs: (_positionals, options) => [
147
148
  {
148
149
  projectPath: options.projectPath,
149
- minReviewers: parseInt(String(options.minReviewers), 10),
150
+ minReviewers: requireNumericFlag('--min-reviewers', options.minReviewers as string | undefined, 'int'),
150
151
  requireApproval: options.requireApproval,
151
152
  blockOnChangesRequested: options.blockOnChanges,
152
153
  allowedReviewers: options.allowedReviewers,
@@ -47,11 +47,6 @@ export { getGate, listRegisteredGates, registeredGateCount, assertGateRegistryCl
47
47
  */
48
48
  export { runGates, type GateRunResult } from './runner';
49
49
 
50
- /**
51
- * 生效门禁集:config.yml gates.order / gates.<id>.enabled 声明式裁剪
52
- */
53
- export { getEffectiveGates, type GatesConfig } from './effective-gates';
54
-
55
50
  /**
56
51
  * checker-as-guard 接线点:ConstraintCheck → Gate(studio #129 随动)
57
52
  */
@@ -18,7 +18,7 @@
18
18
  import { execAsync } from '../utils/exec';
19
19
  import * as fs from 'fs/promises';
20
20
  import * as path from 'path';
21
- import { pass, gateResult, fromError } from './types';
21
+ import { gateResult, fromError } from './types';
22
22
  import type { GateResult, GateContext, PerformanceGateConfig, PerformanceThresholds, Gate, GateDecision } from './types';
23
23
  import { decisionFromResult } from './decision';
24
24
 
@@ -45,7 +45,6 @@ export class PerformanceGate implements Gate {
45
45
 
46
46
  constructor(config: Partial<ExtendedPerformanceGateConfig> = {}) {
47
47
  this.config = {
48
- enabled: config.enabled ?? true,
49
48
  thresholds: config.thresholds ?? {},
50
49
  coverageTimeout: config.coverageTimeout ?? DEFAULT_TIMEOUTS.coverage,
51
50
  };
@@ -64,10 +63,6 @@ export class PerformanceGate implements Gate {
64
63
  async check(context: GateContext): Promise<GateResult> {
65
64
  const startTime = Date.now();
66
65
 
67
- if (!this.config.enabled) {
68
- return pass('performance', '性能门禁已禁用', startTime);
69
- }
70
-
71
66
  try {
72
67
  const thresholds = context.performanceThresholds ?? this.config.thresholds;
73
68
  const metrics = await this.collectMetrics(context.projectPath, thresholds);
@@ -26,7 +26,7 @@ export interface GateRunResult {
26
26
  /**
27
27
  * 依次执行门禁链(按 order 升序,稳定排序)
28
28
  *
29
- * @param gates 参与执行的门禁(通常来自 getEffectiveGates)
29
+ * @param gates 参与执行的门禁(顺序由本函数按 order 排定,调用方不必预排)
30
30
  * @param ctx 门禁上下文
31
31
  */
32
32
  export async function runGates(
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  import { execAsync } from '../utils/exec';
11
- import { pass, gateResult, fromError } from './types';
11
+ import { gateResult, fromError } from './types';
12
12
  import type { GateResult, GateContext, SecurityGateConfig, Gate, GateDecision } from './types';
13
13
  import { decisionFromResult } from './decision';
14
14
 
@@ -18,12 +18,13 @@ import { decisionFromResult } from './decision';
18
18
  export class SecurityGate implements Gate {
19
19
  readonly id = 'security';
20
20
  order = 0;
21
- private config: Required<SecurityGateConfig>;
21
+ private config: SecurityGateConfig;
22
22
 
23
23
  constructor(config: Partial<SecurityGateConfig> = {}) {
24
24
  this.config = {
25
- enabled: config.enabled ?? true,
26
- scanCommand: config.scanCommand ?? '',
25
+ // 空串归一为 undefined:`?? ''` 曾把「未提供」表示成空串,令下方 `??` 链恒停在
26
+ // 第二级、detectScanCommand() 不可达(#138)。「未提供」的唯一表示是 undefined。
27
+ scanCommand: config.scanCommand || undefined,
27
28
  ignoreWarnings: config.ignoreWarnings ?? false,
28
29
  ignoreDevDependencies: config.ignoreDevDependencies ?? false,
29
30
  severityThreshold: config.severityThreshold ?? 'high',
@@ -43,13 +44,10 @@ export class SecurityGate implements Gate {
43
44
  async scan(context: GateContext): Promise<GateResult> {
44
45
  const startTime = Date.now();
45
46
 
46
- if (!this.config.enabled) {
47
- return pass('security', '安全门禁已禁用', startTime);
48
- }
49
-
50
47
  try {
51
- // 使用自定义命令或默认 npm audit
52
- const scanCommand = context.securityScanCommand ??
48
+ // 三级优先级(自上而下取第一个「已提供」者):context 覆盖 > 构造配置 > 自动探测。
49
+ // 缺省(未给命令)落到 detectScanCommand()——本行曾因构造器兜空串而恒停在第二级(#138)。
50
+ const scanCommand = context.securityScanCommand ??
53
51
  this.config.scanCommand ??
54
52
  this.detectScanCommand(context.projectPath);
55
53
 
@@ -234,7 +232,7 @@ export class SecurityGate implements Gate {
234
232
  /**
235
233
  * 获取配置
236
234
  */
237
- getConfig(): Required<SecurityGateConfig> {
235
+ getConfig(): SecurityGateConfig {
238
236
  return { ...this.config };
239
237
  }
240
238
  }
@@ -2,6 +2,8 @@
2
2
  * 门禁类型定义 + GateResult 构造器
3
3
  */
4
4
 
5
+ import type { RunEnv } from '../core/constraints/run-env';
6
+
5
7
  /**
6
8
  * 门禁结果(报告结构,保留)
7
9
  *
@@ -115,38 +117,39 @@ export interface Gate {
115
117
  }
116
118
 
117
119
  /**
118
- * 门禁上下文
120
+ * 门禁上下文:只带「这次在哪跑、跑什么」这类运行信息
121
+ *
122
+ * 配置一律走构造器(`ReviewGateConfig` 等),不要往这里加字段——
123
+ * 本类型曾有 6 个无人读取的配置型字段与构造器配置平行,填了不生效。
119
124
  */
120
125
  export interface GateContext {
121
- projectId: string;
122
- taskId?: string;
123
126
  projectPath: string;
124
-
127
+ taskId?: string;
128
+
125
129
  // Review Gate
126
130
  prNumber?: number;
127
- minReviewers?: number;
128
- reviewers?: string[];
129
-
131
+
130
132
  // Security Gate
131
133
  securityScanCommand?: string;
132
- ignoreWarnings?: boolean;
133
-
134
+
134
135
  // Performance Gate
135
136
  performanceThresholds?: PerformanceThresholds;
136
-
137
+
137
138
  // Contract Gate
138
139
  oldContractPath?: string;
139
140
  newContractPath?: string;
140
- openApiSpec?: string;
141
141
 
142
142
  // Command Gate
143
143
  command?: string;
144
144
 
145
145
  // Acceptance Gate
146
146
  tasksPath?: string;
147
-
148
- // 通用
149
- timeout?: number;
147
+
148
+ /**
149
+ * 本 run 的运行级观察面(ADR-0023)。一条守卫链传同一枚 → 项目配置文件整链至多读一次;
150
+ * 不传 = 各门禁自造一枚一次性观察面(判定不变,只是不共享读取)
151
+ */
152
+ runEnv?: RunEnv;
150
153
  }
151
154
 
152
155
  /**
@@ -172,7 +175,6 @@ export interface ReviewGateConfig {
172
175
  * 安全门禁配置
173
176
  */
174
177
  export interface SecurityGateConfig {
175
- enabled: boolean;
176
178
  scanCommand?: string;
177
179
  ignoreWarnings: boolean;
178
180
  ignoreDevDependencies: boolean;
@@ -183,7 +185,6 @@ export interface SecurityGateConfig {
183
185
  * 性能门禁配置
184
186
  */
185
187
  export interface PerformanceGateConfig {
186
- enabled: boolean;
187
188
  thresholds: PerformanceThresholds;
188
189
  }
189
190
 
@@ -191,7 +192,6 @@ export interface PerformanceGateConfig {
191
192
  * 契约门禁配置
192
193
  */
193
194
  export interface ContractGateConfig {
194
- enabled: boolean;
195
195
  strict: boolean;
196
196
  allowBreakingChanges: boolean;
197
197
  contractPath?: string;
@@ -252,14 +252,11 @@ export interface CommandBlacklistRule {
252
252
 
253
253
  /**
254
254
  * 命令门禁配置
255
+ *
256
+ * `strict`(从不被判定读取)与 `customBlacklist`(零生产注入者,运行时扩展点是
257
+ * `CommandGate.addRule()`)两个配置位已删除,裁决见 ADR-0024(#135)。
255
258
  */
256
259
  export interface CommandGateConfig {
257
- /** 是否启用 */
258
- enabled?: boolean;
259
- /** 严格模式(warn 也阻止) */
260
- strict?: boolean;
261
- /** 自定义黑名单规则 */
262
- customBlacklist?: CommandBlacklistRule[];
263
260
  /** 忽略的类别 */
264
261
  ignoreCategories?: string[];
265
262
  }
@@ -5,26 +5,27 @@
5
5
 
6
6
  H5(#44)起增加两个机制(G2/G7):
7
7
  - **注册表闭环**:`assertHookRegistryClosed(configs, hooks)` 声明(HookConfig)↔ 实现(HookDefinition)双向校验——引用未注册/注册无定义/重复均抛错,复制 checker 闭环模式;断言限构建/测试期,不进运行时热路径
8
- - **配置归一**:`HookConfig { name, enabled, errorStrategy }` 为 per-hook 配置唯一真相;`toErrorStrategy(blocking)` 承载 studio `blocking` → errorStrategy 的无损映射
8
+ - **配置归一**:`HookConfig { name, enabled, errorStrategy }` 为 per-hook 配置唯一真相,且自 #159 起是 `enabled` / `errorStrategy` 的**唯一声明点**——`HookDefinition` 不再携带这两个字段,注册环节以配置表填充有效值(`EffectiveHook`),声明一处、读取一处,两侧矛盾在构造上不可能出现;`toErrorStrategy(blocking)` 承载 studio `blocking` → errorStrategy 的无损映射
9
9
 
10
10
  ## 核心导出
11
- - `HookRegistry` — Hook 注册表(register/get/getEnabled/setEnabled/clear/listAll)
12
- - `HookPipeline` — Hook 执行管线(注册/排序/错误隔离/采样;errorStrategy block/warn/ignore
11
+ - `HookRegistry` — Hook 注册表(register/registerAll/unregister/get/getEnabled/listNames/listAll/setEnabled/clear;register 以 HookConfig 填充有效值)
12
+ - `HookPipeline` — Hook 执行管线(注册/排序/错误隔离/采样;errorStrategy block/warn)
13
13
  - `assertHookRegistryClosed` — 注册表闭环双向校验(构建/测试期)
14
- - `HookConfig`(type)— per-hook 配置声明(归一后形状)
14
+ - `HookConfig`(type)— per-hook 配置声明(enabled / errorStrategy 唯一声明点)
15
+ - `EffectiveHook`(type)— HookDefinition + 配置填充的有效 enabled / errorStrategy(管线与注册表判定只读它)
15
16
  - `toErrorStrategy` — blocking → errorStrategy 无损映射(G7)
16
- - `bootstrapHarness` / `bootstrapHarnessSync` — Harness 启动引导;也是 trace 记录器的组合根:`new ConstraintChecker(getTraceCollector())`(harness#88core 不上行依赖 monitoring,故由本层接线)
17
+ - `bootstrapHarness` / `bootstrapHarnessSync` — Harness 启动引导;也是 trace 记录器的组合根:`new ConstraintChecker(new TraceCollector({ projectPath }))`(harness#88 接线,core 不上行依赖 monitoring,故由本层接线;#139 收根:两个入口本就收 projectPath,落点随之锚定,不再取 cwd 锚定的 `getTraceCollector()` 单例)
17
18
 
18
19
  ## 依赖关系
19
- - 依赖 `src/types/` Hook 相关类型
20
- - `src/core/` 核心引擎消费
21
- - CLI 初始化流程消费
20
+ - 类型正本在**本模块** `src/hooks/types.ts`(`HookPhase`/`HookErrorStrategy`/`HookConfig`/`HookDefinition`/`EffectiveHook`/`HookResult`/`PipelineResult`);`src/types/` 里没有 hook 类型,本层只从 `src/types/project-config` 取 `MergedConstraintsConfig` 类型
21
+ - 向下依赖(仅 `bootstrap.ts` 组合根):`core/constraints/checker`、`core/project-config-loader`、`context/session-manager`、`monitoring/traces`——`registry/pipeline/config/types` 四文件零上层依赖,是纯管线
22
+ - 消费方:包根 `src/index.ts` 的 `./hooks` 出口与下游项目(studio 的 hook 装配)。**harness 内部无生产消费方**——core/cli 侧的调用边已随零消费者清账删除(harness#141 同判据,ADR-0022),「被 core 核心引擎/CLI 初始化流程消费」的旧说法已失效(harness#142 核对)
22
23
 
23
24
  ## 约定
24
25
  - 无业务逻辑,只提供管线能力
25
26
  - Consumer 自行定义 hook 名称和触发时机
26
27
  - **闭环**:声明配置与注册实现必须一一对应,缺一抛错(消灭「hook 定义不注册 = 死代码」类人记规矩)
27
- - **映射语义**:blocking=true → 'block'(失败阻断管线,停止后续 hook、passed=false);blocking=false → 'warn'(记录警告继续);未声明 strategy 静默跳过(历史行为保留)
28
+ - **映射语义**:blocking=true → 'block'(失败阻断管线,停止后续 hook、passed=false);blocking=false → 'warn'(记录警告继续);有效策略集合仅 'block' | 'warn'(#159 起原 'ignore' 与「未声明 strategy」形态退出有效面——策略由 HookConfig 必填声明)
28
29
  - 错误隔离:单个 hook 失败不影响其他 hook
29
30
 
30
31
  ## 注意事项
@@ -11,7 +11,11 @@ import * as fs from 'fs';
11
11
  import * as path from 'path';
12
12
  import * as yaml from 'js-yaml';
13
13
  import { bootstrapHarnessSync, bootstrapHarness } from '../bootstrap';
14
- import type { HookDefinition } from '../types';
14
+ import type { HookConfig, HookDefinition } from '../types';
15
+
16
+ function makeHookConfig(name: string, overrides: Partial<HookConfig> = {}): HookConfig {
17
+ return { name, enabled: true, errorStrategy: 'warn', ...overrides };
18
+ }
15
19
 
16
20
  function setupTempDir(dir: string): string {
17
21
  const harnessDir = path.join(dir, '.harness');
@@ -51,14 +55,24 @@ describe('bootstrapHarness', () => {
51
55
  expect(result.projectPath).toBe(tempDir);
52
56
  });
53
57
 
54
- it('registers hook definitions when provided', async () => {
58
+ it('registers hook definitions when provided (with configs)', async () => {
55
59
  const hookDef: HookDefinition = {
56
60
  name: 'async-hook',
57
61
  phase: 'before',
58
62
  execute: async () => ({ passed: true }),
59
63
  };
60
- const result = await bootstrapHarness(tempDir, [hookDef]);
64
+ const result = await bootstrapHarness(tempDir, [hookDef], [makeHookConfig('async-hook')]);
61
65
  expect(result.hooks.listNames()).toContain('async-hook');
66
+ expect(result.hooks.get('async-hook')?.errorStrategy).toBe('warn');
67
+ });
68
+
69
+ it('throws when definitions are provided without configs (#159)', async () => {
70
+ const hookDef: HookDefinition = {
71
+ name: 'async-hook',
72
+ phase: 'before',
73
+ execute: async () => ({ passed: true }),
74
+ };
75
+ await expect(bootstrapHarness(tempDir, [hookDef])).rejects.toThrow(/HookConfig/);
62
76
  });
63
77
 
64
78
  it('does not register hooks when no definitions provided', async () => {
@@ -126,16 +140,25 @@ describe('bootstrapHarnessSync', () => {
126
140
  expect(result.mergedConstraints).toHaveProperty('guidelines');
127
141
  });
128
142
 
129
- it('registers hook definitions when provided', () => {
143
+ it('registers hook definitions when provided (with configs)', () => {
130
144
  const hookDef: HookDefinition = {
131
145
  name: 'test-hook',
132
146
  phase: 'before',
133
147
  execute: async () => ({ passed: true }),
134
148
  };
135
- const result = bootstrapHarnessSync(tempDir, [hookDef]);
149
+ const result = bootstrapHarnessSync(tempDir, [hookDef], [makeHookConfig('test-hook')]);
136
150
  expect(result.hooks.listNames()).toContain('test-hook');
137
151
  });
138
152
 
153
+ it('throws when definitions are provided without configs (#159)', () => {
154
+ const hookDef: HookDefinition = {
155
+ name: 'test-hook',
156
+ phase: 'before',
157
+ execute: async () => ({ passed: true }),
158
+ };
159
+ expect(() => bootstrapHarnessSync(tempDir, [hookDef])).toThrow(/HookConfig/);
160
+ });
161
+
139
162
  it('does not register hooks when no definitions provided', () => {
140
163
  const result = bootstrapHarnessSync(tempDir, []);
141
164
  expect(result.hooks.listNames()).toEqual([]);
@@ -165,7 +188,7 @@ describe('bootstrapHarnessSync', () => {
165
188
  phase: 'after',
166
189
  execute: async () => ({ passed: true, data: 'ok' }),
167
190
  };
168
- const result = bootstrapHarnessSync(tempDir, [hookDef]);
191
+ const result = bootstrapHarnessSync(tempDir, [hookDef], [makeHookConfig('pipeline-hook')]);
169
192
  expect(result.pipeline).toBeDefined();
170
193
  });
171
194