@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
@@ -1,10 +1,14 @@
1
1
  /**
2
- * 单向分层守卫(架构评审 2026-09-02 · 候选9 / harness#88)
2
+ * 单向分层守卫(架构评审 2026-09-02 · 候选9 / harness#88;逐目录参数化 harness#137
3
3
  *
4
- * 分层 `types → utils → core → 领域层 → cli` 此前只是文档约定。本文件把它落成两件事:
5
- * 1. 真扫描:src/core/** 对 cli / gates / monitoring 零**值**导入(type-only 允许)
6
- * 2. 真规则:eslint.config.mjs no-restricted-imports 对上行值导入报 error,
7
- * 并允许 type-only(探针在纯 node 进程里跑仓内真配置,代码不落盘)
4
+ * 分层 `types → utils → core → 领域层 → cli` 此前只是文档约定。本文件把它落成三件事:
5
+ * 1. 真扫描:**每个顶层单元(目录或 src 根文件)声明允许值导入的下行集合**,集合外的跨目录
6
+ * import 一律红。harness#88 时只守 `src/core/** cli/gates/monitoring` 一条边,
7
+ * types/utils 的回边与领域层互 import 全部放行;#137 改成逐目录冻结。
8
+ * 2. 真规则:eslint.config.mjs 的 no-restricted-imports 对 core 上行值导入报 error,
9
+ * 并允许 type-only(探针在纯 node 进程里跑仓内真配置,代码不落盘)。
10
+ * 3. 反证:扫描器对合成 import 语句真报违例、指名到目录与边,且合法边不误报
11
+ * (不靠往 src 里塞临时文件——那是能被别的测试与 tsc 扫到的污染)。
8
12
  */
9
13
 
10
14
  import * as fs from 'fs';
@@ -31,9 +35,73 @@ new FlatESLint({ cwd: process.cwd() })
31
35
  `;
32
36
 
33
37
  const REPO_ROOT = path.resolve(__dirname, '../..');
34
- const CORE_DIR = path.join(REPO_ROOT, 'src', 'core');
35
- /** core 之下不得出现值导入的上层目录 */
36
- const UPPER_LAYERS = ['cli', 'gates', 'monitoring'];
38
+ const SRC_DIR = path.join(REPO_ROOT, 'src');
39
+ const SEP = path.sep;
40
+
41
+ /** 声明「可下行到任意单元」的记号,只给顶层组合面与测试面用 */
42
+ const ANY = '*';
43
+
44
+ /**
45
+ * 每个顶层单元允许**值导入**的其他单元(目录名 / src 根文件名)。
46
+ *
47
+ * 口径:
48
+ * - 只管跨目录的**值** import:type-only 一律放行(与 eslint 侧 allowTypeImports 同口径),
49
+ * 同目录内的 import 也不管——本闸钉的是方向,不是模块粒度;
50
+ * - 集合 = 该单元的分层位置允许的下行面 + **现状冻结**的同层边(逐条注理由)。
51
+ * 新增一条跨目录边必须先在这里登记,diff 即评审材料;集合只多不减,
52
+ * 还清一条债就把对应条目删掉,留着即虚账(登记闸只管活账)。
53
+ */
54
+ const DOWNSTREAM: Record<string, string[]> = {
55
+ // ── 叶子层 ──
56
+ types: [], // 谁都能 import 它,它谁都不 import:回边即分层违例(#88 前无闸可跑)
57
+ utils: ['types'],
58
+ presets: ['types'], // 纯数据(CLAUDE.md),零内部依赖
59
+
60
+ // ── core:数据/能力由调用方注入(harness#88)──
61
+ // presets 属数据面,project-config-loader 合并 preset 不算上行
62
+ core: ['presets', 'types', 'utils'],
63
+
64
+ // ── 领域层:理想下行面 = core 以下;同层边逐条记名 ──
65
+ agents: ['types', 'utils'],
66
+ 'completion-checkers': ['types', 'utils'], // 纯判定函数库,commits 由调用方供给
67
+ failure: ['types', 'utils'],
68
+ gates: ['core', 'types', 'utils'],
69
+ knowledge: ['types', 'utils'],
70
+ monitoring: ['types', 'utils'],
71
+ release: [], // 「无内部依赖(只依赖 node fs/path)」= release/CONTEXT.md 的自我声明落成闸
72
+ sdd: ['types', 'utils'],
73
+ tools: ['types', 'utils'],
74
+ // 同层互 import(现状冻结,不是许可):context 注入取知识、SessionManager 取 trace 采集器。
75
+ // 收口方向同 harness#88 对 core 的裁决——改注入,另票评估
76
+ context: ['knowledge', 'monitoring', 'types', 'utils'],
77
+ // bootstrapHarness 是本包组合根(装配 checker / SessionManager / TraceCollector),
78
+ // monitoring 对它是下行而非债
79
+ hooks: ['context', 'core', 'monitoring', 'types', 'utils'],
80
+
81
+ // ── 测试夹具:被各目录的测试依赖,故排在它们之下 ──
82
+ 'test-setup': ['types', 'utils'],
83
+
84
+ // ── 顶层组合面 / 测试面:可下行到任何单元 ──
85
+ cli: [ANY], // CLI 是唯一的上层,per-command 懒加载各命令实现
86
+ 'index.ts': [ANY], // 包根 barrel(ADR-0003 显式清单)
87
+ 'pretool-use-hook.ts': ['gates', 'types', 'utils'], // 钩子入口:PreToolUse 决策取 CommandGate
88
+ __tests__: [ANY], // 根测试面:跨目录取生产码是本职
89
+ };
90
+
91
+ /**
92
+ * 测试文件(目录段含 `__tests__`)在 `DOWNSTREAM` 之外额外放行的边。
93
+ *
94
+ * 单列而不并进目录集合,是因为并进去等于宣布生产面也有这条边:
95
+ * - `'*'`:任何目录的测试都能用 test-setup 夹具;
96
+ * - core 的测试回读包根 barrel,钉「公共面确实经 `src/index.ts` 导出」这条链
97
+ * (`agent-prompt-renderer` / `check-cache` 两处,ADR-0022 手法);
98
+ * - failure 的 recorder 测试顺带覆盖 CLI `failure list/stats`。
99
+ */
100
+ const TEST_ONLY_EDGES: Record<string, string[]> = {
101
+ '*': ['test-setup'],
102
+ core: ['index.ts'],
103
+ failure: ['cli'],
104
+ };
37
105
 
38
106
  /** import / export-from / require / 动态 import 的源串 + 子句 */
39
107
  const MODULE_SOURCE_REGEX =
@@ -62,22 +130,68 @@ function isTypeOnlyClause(clause: string): boolean {
62
130
  return /^\s*type(\s|\{|$)/.test(clause);
63
131
  }
64
132
 
65
- /** 收集一个文件里所有指向上层的值导入源串 */
66
- function upwardValueImports(file: string): string[] {
67
- const text = stripComments(fs.readFileSync(file, 'utf-8'));
68
- const hits: string[] = [];
133
+ /** src 相对路径 → 顶层单元名(目录名,或 src 根文件名) */
134
+ function unitOf(relFromSrc: string): string {
135
+ const sep = relFromSrc.indexOf(SEP);
136
+ return sep === -1 ? relFromSrc : relFromSrc.slice(0, sep);
137
+ }
138
+
139
+ /** 一个 import 源串指向的单元;非相对路径(node/包名)与 src 之外返回 null */
140
+ function unitOfImport(fromFile: string, source: string): string | null {
141
+ if (!source.startsWith('.')) return null;
142
+ const resolved = path.resolve(path.dirname(fromFile), source);
143
+ const relToSrc = path.relative(SRC_DIR, resolved);
144
+ if (!relToSrc || relToSrc.startsWith('..')) return null;
145
+ const unit = unitOf(relToSrc);
146
+ // src 根文件的 import 不带扩展名(`'../index'` → src/index.ts):单元名按磁盘真名补回扩展,
147
+ // 否则根文件单元在 import 侧叫 index、在登记侧叫 index.ts,两边对不上
148
+ if (unit === relToSrc && fs.existsSync(path.join(SRC_DIR, `${unit}.ts`))) return `${unit}.ts`;
149
+ return unit;
150
+ }
151
+
152
+ function isTestFile(relFromSrc: string): boolean {
153
+ return `${SEP}${relFromSrc}${SEP}`.includes(`${SEP}__tests__${SEP}`);
154
+ }
155
+
156
+ interface Violation {
157
+ unit: string;
158
+ file: string;
159
+ target: string;
160
+ source: string;
161
+ }
162
+
163
+ /** 一个单元的允许集合(含测试放行与自身) */
164
+ function allowedTargetsFor(relFromSrc: string): Set<string> {
165
+ const unit = unitOf(relFromSrc);
166
+ const allowed = new Set(DOWNSTREAM[unit] ?? []);
167
+ if (isTestFile(relFromSrc)) {
168
+ for (const extra of TEST_ONLY_EDGES['*'] ?? []) allowed.add(extra);
169
+ for (const extra of TEST_ONLY_EDGES[unit] ?? []) allowed.add(extra);
170
+ }
171
+ allowed.add(unit);
172
+ return allowed;
173
+ }
174
+
175
+ /**
176
+ * 扫一段代码里越界的跨目录值 import(纯函数:代码不来自磁盘,真扫描与反证共用一把尺)
177
+ *
178
+ * `relPath` 用于算自身单元,并出现在报错形状里(指名到文件与边)。
179
+ */
180
+ function scanViolations(relPath: string, code: string): Violation[] {
181
+ const unit = unitOf(relPath);
182
+ const allowed = allowedTargetsFor(relPath);
183
+ const absFile = path.join(SRC_DIR, relPath);
184
+
185
+ const hits: Violation[] = [];
69
186
  MODULE_SOURCE_REGEX.lastIndex = 0;
70
187
  let match: RegExpExecArray | null;
71
- while ((match = MODULE_SOURCE_REGEX.exec(text)) !== null) {
188
+ while ((match = MODULE_SOURCE_REGEX.exec(code)) !== null) {
72
189
  const clause = match[1] ?? '';
73
190
  const source = match[2] ?? match[3];
74
191
  if (match[1] && isTypeOnlyClause(clause)) continue;
75
- if (!source.startsWith('.')) continue;
76
- const resolved = path.resolve(path.dirname(file), source);
77
- const relToSrc = path.relative(path.join(REPO_ROOT, 'src'), resolved);
78
- if (UPPER_LAYERS.some(layer => relToSrc === layer || relToSrc.startsWith(layer + path.sep))) {
79
- hits.push(source);
80
- }
192
+ const target = unitOfImport(absFile, source);
193
+ if (target === null || allowed.has(ANY) || allowed.has(target)) continue;
194
+ hits.push({ unit, file: relPath, target, source });
81
195
  }
82
196
  return hits;
83
197
  }
@@ -93,17 +207,95 @@ function probeCore(code: string, filePath = 'src/core/constraints/__layering_pro
93
207
  return messages.filter(m => m.ruleId === '@typescript-eslint/no-restricted-imports');
94
208
  }
95
209
 
96
- describe('core 单向分层(harness#88)', () => {
97
- describe('真扫描:core/** 零上行值导入', () => {
98
- it('src/core 下每个文件对 cli/gates/monitoring 都没有值导入', () => {
99
- const offenders = listTsFiles(CORE_DIR)
100
- .map(file => ({ file: path.relative(REPO_ROOT, file), hits: upwardValueImports(file) }))
101
- .filter(entry => entry.hits.length > 0);
210
+ /** src 下现存的顶层单元(目录 + 根 .ts 文件),供登记闸对撞 */
211
+ function currentUnits(): string[] {
212
+ const units: string[] = [];
213
+ for (const entry of fs.readdirSync(SRC_DIR, { withFileTypes: true })) {
214
+ if (entry.isDirectory()) units.push(entry.name);
215
+ else if (entry.isFile() && entry.name.endsWith('.ts') && !entry.name.endsWith('.d.ts')) {
216
+ units.push(entry.name);
217
+ }
218
+ }
219
+ return units;
220
+ }
221
+
222
+ describe('逐目录单向分层(harness#88 / #137)', () => {
223
+ describe('登记闸:每个顶层单元都声明了下行集合', () => {
224
+ it('src 下没有未登记的单元(新增目录先登记,不得绕过本闸)', () => {
225
+ const unregistered = currentUnits().filter(unit => !(unit in DOWNSTREAM));
226
+ expect(unregistered).toEqual([]);
227
+ });
228
+
229
+ it('登记的单元在 src 下真实存在(目录改名或删除后不留死账)', () => {
230
+ const alive = new Set(currentUnits());
231
+ const dead = Object.keys(DOWNSTREAM).filter(unit => !alive.has(unit));
232
+ expect(dead).toEqual([]);
233
+ });
234
+ });
102
235
 
236
+ describe('真扫描:每个文件的值 import 都落在声明过的下行集合内', () => {
237
+ it.each(Object.keys(DOWNSTREAM))('%s 零越界值 import', unit => {
238
+ const root = path.join(SRC_DIR, unit); // 目录或 src 根文件
239
+ const files = fs.statSync(root).isDirectory() ? listTsFiles(root) : [root];
240
+ const offenders = files
241
+ .map(file =>
242
+ scanViolations(path.relative(SRC_DIR, file), stripComments(fs.readFileSync(file, 'utf-8')))
243
+ )
244
+ .filter(hits => hits.length > 0);
103
245
  expect(offenders).toEqual([]);
104
246
  });
105
247
  });
106
248
 
249
+ describe('反证:越界方向真被报出并指名到目录与边', () => {
250
+ it.each([
251
+ // [注入位置(src 相对), 值 import 源串, 目录, 被禁目标]
252
+ ['types/probe.ts', '../cli/commands/definitions', 'types', 'cli'],
253
+ ['types/probe.ts', '../core/project-config-loader', 'types', 'core'],
254
+ ['types/probe.ts', '../utils/jsonl', 'types', 'utils'],
255
+ ['utils/probe.ts', '../core/constraints/checker', 'utils', 'core'],
256
+ ['core/constraints/probe.ts', '../../monitoring/traces', 'core', 'monitoring'],
257
+ ['core/constraints/probe.ts', '../../knowledge/store', 'core', 'knowledge'],
258
+ ['core/constraints/probe.ts', '../../cli/commands/definitions', 'core', 'cli'],
259
+ ['knowledge/probe.ts', '../context/session-manager', 'knowledge', 'context'],
260
+ ['monitoring/probe.ts', '../gates/registry', 'monitoring', 'gates'],
261
+ ['presets/probe.ts', '../core/constraints/definitions', 'presets', 'core'],
262
+ ['release/probe.ts', '../core/effective-constraints', 'release', 'core'],
263
+ ])('%s 值导入 %s 报违例(%s ↛ %s)', (rel, source, unit, target) => {
264
+ const code = `import { something } from '${source}';\nexport const use = something;\n`;
265
+ expect(scanViolations(rel, code)).toEqual([{ unit, file: rel, target, source }]);
266
+ });
267
+
268
+ it('报错形状带得出是哪条边(源串与文件都在内,不需人再 grep)', () => {
269
+ // 行首动态 import(正则的另一支;行中 require 从来不在 MODULE_SOURCE_REGEX 覆盖面内)
270
+ const [violation] = scanViolations(
271
+ 'types/probe.ts',
272
+ `import('../cli/commands/check').then(m => m.check);\n`
273
+ );
274
+ expect(violation).toMatchObject({ unit: 'types', target: 'cli', source: '../cli/commands/check' });
275
+ });
276
+
277
+ it.each([
278
+ ['core/constraints/probe.ts', `import type { GateDefinition } from '../../gates/definitions';`],
279
+ ['types/probe.ts', `import type { RunEnv } from '../core/constraints/run-env';`],
280
+ ['knowledge/probe.ts', `import { DEFAULT_DECAY_CONFIG } from './types';`],
281
+ ['context/probe.ts', `import { KnowledgeQuery } from '../knowledge/query';`],
282
+ ['hooks/probe.ts', `import { getTraceCollector } from '../monitoring/traces';`],
283
+ ['core/probe.ts', `import { PRESETS_BY_NAME } from '../presets';`],
284
+ ['failure/__tests__/probe.test.ts', `import { failureList } from '../../cli/commands/failure';`],
285
+ ['core/constraints/__tests__/probe.test.ts', `import { checkConstraints } from '../../index';`],
286
+ ['gates/__tests__/probe.test.ts', `import { createProjectFixture } from '../../test-setup/project-fixture';`],
287
+ ['monitoring/probe.ts', `import * as fs from 'fs';`],
288
+ ['monitoring/probe.ts', `const hint = 'src/gates/registry.ts';\nexport const h = hint;`],
289
+ ])('合法边与噪声不误报:%s', (rel, statement) => {
290
+ expect(scanViolations(rel, `${statement}\n`)).toEqual([]);
291
+ });
292
+
293
+ it('文档注释里的示例 import 不算依赖', () => {
294
+ const code = `/** 用法:import { check } from '../../cli/commands/check'; */\nexport const x = 1;\n`;
295
+ expect(scanViolations('core/constraints/probe.ts', code)).toEqual([]);
296
+ });
297
+ });
298
+
107
299
  describe('真规则:eslint 上行值导入报 error', () => {
108
300
  it.each([
109
301
  ['monitoring', '../../monitoring/traces'],
@@ -6,15 +6,16 @@ import { describe, it, expect, beforeAll, afterAll } from '@jest/globals';
6
6
  import { PassesGate, createPassesGate, detectTestCommand } from '../core/validators/passes-gate';
7
7
  import type { TaskTestResult } from '../types/passes-gate';
8
8
  import { createProjectFixture } from '../test-setup/project-fixture';
9
- import { mkdirSync, rmSync, writeFileSync } from 'fs';
9
+ import { mkdirSync, rmSync, writeFileSync, mkdtempSync } from 'fs';
10
10
  import { join } from 'path';
11
+ import { tmpdir } from 'os';
11
12
 
12
13
  describe('PassesGate', () => {
13
- const tempDir = join(process.cwd(), 'temp-test-passes-gate');
14
+ let tempDir: string;
14
15
  let gate: PassesGate;
15
16
 
16
17
  beforeAll(() => {
17
- mkdirSync(tempDir, { recursive: true });
18
+ tempDir = mkdtempSync(join(tmpdir(), 'temp-test-passes-gate-'));
18
19
 
19
20
  // 创建简单的 package.json
20
21
  writeFileSync(join(tempDir, 'package.json'), JSON.stringify({
@@ -47,13 +48,17 @@ describe('PassesGate', () => {
47
48
  // 探测正本行为钉住(架构评审 A2:CLI/core 双版收口后的统一语义,
48
49
  // 此前 e2e 优先级、echo 排除、兜底均无测试钉住)
49
50
  describe('detectTestCommand 正本(统一探测顺序)', () => {
50
- const detectDir = join(process.cwd(), 'temp-test-detect-command');
51
+ let detectDir: string;
51
52
 
52
53
  const writePkg = (dir: string, scripts: Record<string, string>) => {
53
54
  mkdirSync(dir, { recursive: true });
54
55
  writeFileSync(join(dir, 'package.json'), JSON.stringify({ name: 'detect-case', scripts }));
55
56
  };
56
57
 
58
+ beforeAll(() => {
59
+ detectDir = mkdtempSync(join(tmpdir(), 'temp-test-detect-command-'));
60
+ });
61
+
57
62
  afterAll(() => {
58
63
  try {
59
64
  rmSync(detectDir, { recursive: true, force: true });
@@ -6,12 +6,13 @@ import { describe, it, expect, beforeAll, afterAll } from '@jest/globals';
6
6
  import { PerformanceGate } from '../gates/performance';
7
7
  import * as fs from 'fs';
8
8
  import * as path from 'path';
9
+ import * as os from 'os';
9
10
 
10
11
  describe('PerformanceGate', () => {
11
- const tempDir = path.join(process.cwd(), 'temp-test-perf-gate');
12
+ let tempDir: string;
12
13
 
13
14
  beforeAll(() => {
14
- fs.mkdirSync(tempDir, { recursive: true });
15
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'temp-test-perf-gate-'));
15
16
  });
16
17
 
17
18
  afterAll(() => {
@@ -23,27 +24,14 @@ describe('PerformanceGate', () => {
23
24
  });
24
25
 
25
26
  describe('check', () => {
26
- it('禁用时应该返回通过', async () => {
27
- const gate = new PerformanceGate({ enabled: false });
28
-
29
- const result = await gate.check({
30
- projectId: 'test',
31
- projectPath: tempDir,
32
- });
33
-
34
- expect(result.passed).toBe(true);
35
- });
36
-
37
27
  it('应该返回检查结果', async () => {
38
28
  const gate = new PerformanceGate({
39
- enabled: true,
40
29
  thresholds: {
41
30
  maxBundleSize: 1000,
42
31
  },
43
32
  });
44
33
 
45
34
  const result = await gate.check({
46
- projectId: 'test',
47
35
  projectPath: tempDir,
48
36
  });
49
37
 
@@ -3,15 +3,18 @@
3
3
  */
4
4
 
5
5
  import { describe, it, expect, beforeAll, afterAll, jest } from '@jest/globals';
6
- import { ProjectConfigLoader } from '../core/project-config-loader';
6
+ import { ProjectConfigLoader, isConstraintRetired } from '../core/project-config-loader';
7
7
  import * as fs from 'fs';
8
8
  import * as path from 'path';
9
+ import * as os from 'os';
9
10
 
10
11
  describe('ProjectConfigLoader - 补充覆盖', () => {
11
- const tempDir = path.join(process.cwd(), 'temp-test-config-extra');
12
- const harnessDir = path.join(tempDir, '.harness');
12
+ let tempDir: string;
13
+ let harnessDir: string;
13
14
 
14
15
  beforeAll(() => {
16
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'temp-test-config-extra-'));
17
+ harnessDir = path.join(tempDir, '.harness');
15
18
  fs.mkdirSync(harnessDir, { recursive: true });
16
19
  });
17
20
 
@@ -123,71 +126,42 @@ custom_constraints:
123
126
  });
124
127
  });
125
128
 
126
- describe('isConstraintEnabled', () => {
127
- it('启用的约束应该返回 true', () => {
129
+ describe('零消费者收缩(harness#137)', () => {
130
+ /**
131
+ * `isConstraintEnabled` / `getConstraintSource` 属 ADR-0022 型漏收:
132
+ * 除本文件与自身测试外双仓零消费者,生效集判定唯一来源是
133
+ * `mergeConstraints` → `getEffectiveConstraints`(ADR-0001),这两个查询函数是它的平行复印。
134
+ */
135
+ it('isConstraintEnabled / getConstraintSource 已从类面删除', () => {
128
136
  const loader = new ProjectConfigLoader(tempDir);
129
137
  loader.load();
130
138
 
131
- expect(loader.isConstraintEnabled('no_bypass_checkpoint')).toBe(true);
132
- });
133
-
134
- it('禁用的约束应该返回 false', () => {
135
- fs.writeFileSync(
136
- path.join(harnessDir, 'config.yml'),
137
- `
138
- constraints:
139
- test_disabled:
140
- enabled: false
141
- `
142
- );
143
-
144
- const loader = new ProjectConfigLoader(tempDir);
145
- loader.load();
146
-
147
- expect(loader.isConstraintEnabled('test_disabled')).toBe(false);
139
+ // @ts-expect-error isConstraintEnabled 零消费者,随 harness#137 删除
140
+ expect(loader.isConstraintEnabled).toBeUndefined();
141
+ // @ts-expect-error getConstraintSource 零消费者,随 harness#137 删除
142
+ expect(loader.getConstraintSource).toBeUndefined();
143
+ expect(ProjectConfigLoader.prototype).not.toHaveProperty('isConstraintEnabled');
144
+ expect(ProjectConfigLoader.prototype).not.toHaveProperty('getConstraintSource');
148
145
  });
149
146
  });
150
147
 
151
- describe('getConstraintSource', () => {
152
- it('内置约束应该返回 built-in', () => {
153
- const loader = new ProjectConfigLoader(tempDir);
154
- loader.load();
155
-
156
- expect(loader.getConstraintSource('no_bypass_checkpoint')).toBe('built-in');
148
+ describe('isConstraintRetired(退役判定单点,harness#137)', () => {
149
+ it('config.yml enabled:false 即已退役,与 custom 条目无关', () => {
150
+ expect(isConstraintRetired(undefined, true)).toBe(true);
157
151
  });
158
152
 
159
- it('自定义约束应该返回 custom', () => {
160
- fs.writeFileSync(
161
- path.join(harnessDir, 'config.yml'),
162
- `
163
- custom_constraints:
164
- custom_source_test:
165
- rule: CUSTOM
166
- message: Custom
167
- trigger: commit
168
- `
169
- );
170
-
171
- const loader = new ProjectConfigLoader(tempDir);
172
- loader.load();
173
-
174
- expect(loader.getConstraintSource('custom_source_test')).toBe('custom');
153
+ it('custom 条目带 retired 元数据即已退役(studio#82 D6 落点在条目自身)', () => {
154
+ expect(isConstraintRetired({ retired: { at: '2026-08-08T12:00:00.000Z' } }, false)).toBe(true);
175
155
  });
176
156
 
177
- it('禁用约束应该返回 disabled', () => {
178
- fs.writeFileSync(
179
- path.join(harnessDir, 'config.yml'),
180
- `
181
- constraints:
182
- source_disabled:
183
- enabled: false
184
- `
185
- );
186
-
187
- const loader = new ProjectConfigLoader(tempDir);
188
- loader.load();
157
+ it('两个落点都没命中 → 未退役', () => {
158
+ expect(isConstraintRetired(undefined, false)).toBe(false);
159
+ expect(isConstraintRetired({ retired: undefined }, false)).toBe(false);
160
+ });
189
161
 
190
- expect(loader.getConstraintSource('source_disabled')).toBe('disabled');
162
+ it('retired 段的假值(null / 空串)不算退役——mergeConstraints 用的是 truthiness', () => {
163
+ expect(isConstraintRetired({ retired: null }, false)).toBe(false);
164
+ expect(isConstraintRetired({ retired: '' }, false)).toBe(false);
191
165
  });
192
166
  });
193
167
 
@@ -6,12 +6,15 @@ import { describe, it, expect, beforeAll, afterAll } from '@jest/globals';
6
6
  import { ProjectConfigLoader, getCapabilitiesMode } from '../core/project-config-loader';
7
7
  import * as fs from 'fs';
8
8
  import * as path from 'path';
9
+ import * as os from 'os';
9
10
 
10
11
  describe('ProjectConfigLoader', () => {
11
- const tempDir = path.join(process.cwd(), 'temp-test-config');
12
- const harnessDir = path.join(tempDir, '.harness');
12
+ let tempDir: string;
13
+ let harnessDir: string;
13
14
 
14
15
  beforeAll(() => {
16
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'temp-test-config-'));
17
+ harnessDir = path.join(tempDir, '.harness');
15
18
  fs.mkdirSync(harnessDir, { recursive: true });
16
19
  });
17
20
 
@@ -125,7 +128,7 @@ custom_rules:
125
128
  });
126
129
 
127
130
  describe('getCapabilitiesMode', () => {
128
- /** 建一个带独立 .harness/config.yml 的临时项目目录(避免进程级缓存串扰) */
131
+ /** 建一个带独立 .harness/config.yml 的临时项目目录(各用例独占自己的配置内容) */
129
132
  const setupConfigDir = (name: string, configYaml: string): string => {
130
133
  const dir = path.join(tempDir, name);
131
134
  fs.mkdirSync(path.join(dir, '.harness'), { recursive: true });
@@ -100,7 +100,6 @@ const EXPECTED_RUNTIME_EXPORTS = [
100
100
  'getConstraint',
101
101
  'getCriticalArtifacts',
102
102
  'getEffectiveConstraints',
103
- 'getEffectiveGates',
104
103
  'getFailureLevel',
105
104
  'getGate',
106
105
  'getRegistryPath',
@@ -37,8 +37,8 @@ const REPO_ROOT = path.join(__dirname, '../..');
37
37
  * ① `export { 值 } from '...'`;② `export type { 类型 } from '...'`;③ 内联值声明
38
38
  * `export function|const|let|var`(如 `src/gates/index.ts` 的 5 个 `create*Gate`)——纯值面,
39
39
  * 不属类型清单管辖。
40
- * 清单归类按**说明符自身**而非块形式:`export { getEffectiveGates, type GatesConfig }` 里的
41
- * `GatesConfig` 按 TS 语义就是类型导出,必须进类型清单(本闸的职责是如实刻画公开面,不是管写法)。
40
+ * 清单归类按**说明符自身**而非块形式:`export { runGates, type GateRunResult }` 里的
41
+ * `GateRunResult` 按 TS 语义就是类型导出,必须进类型清单(本闸的职责是如实刻画公开面,不是管写法)。
42
42
  * 其余行首 `export` 一律记为违禁而非跳过:`export *` / `export type *` 会让按名字扫描静默
43
43
  * 漏算;内联 `export interface|type|enum|class|declare` 更必须红——它绕过类型清单,而
44
44
  * `enum`/`class` 同时占值面与类型面,按单一分类必错一面。这正是 B1「公开面的定义比现实窄」
@@ -170,6 +170,7 @@ const PUBLISHED_ENTRY_TYPES: Record<string, string[]> = {
170
170
  'DocRegexCountCheck',
171
171
  'DocsSyncConfig',
172
172
  'EffectiveConfigLint',
173
+ 'EffectiveHook',
173
174
  'ErrorClassificationRule',
174
175
  'ErrorClassifierConfig',
175
176
  'EventHandler',
@@ -185,7 +186,6 @@ const PUBLISHED_ENTRY_TYPES: Record<string, string[]> = {
185
186
  'GateDefinition',
186
187
  'GateResult',
187
188
  'GateRunResult',
188
- 'GatesConfig',
189
189
  'GovernanceConfig',
190
190
  'GrepCountActual',
191
191
  'HarnessBootstrap',
@@ -281,6 +281,8 @@ const PUBLISHED_ENTRY_TYPES: Record<string, string[]> = {
281
281
  'IronLawContext',
282
282
  'PassesGateConfig',
283
283
  'RenderConstraintsByTriggerOptions',
284
+ 'RunEnv',
285
+ 'RunTarget',
284
286
  'SpecSchemaDefinition',
285
287
  'SpecType',
286
288
  'SpecValidationResult',
@@ -317,7 +319,6 @@ const PUBLISHED_ENTRY_TYPES: Record<string, string[]> = {
317
319
  'GateDefinition',
318
320
  'GateResult',
319
321
  'GateRunResult',
320
- 'GatesConfig',
321
322
  'PerformanceGateConfig',
322
323
  'PerformanceThresholds',
323
324
  'ReviewGateConfig',