@dommaker/harness 1.7.0 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (563) hide show
  1. package/CHANGELOG.md +44 -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 +19 -3
  15. package/dist/cli/commands/check.d.ts.map +1 -1
  16. package/dist/cli/commands/check.js +36 -22
  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/status.d.ts +8 -0
  76. package/dist/cli/commands/status.d.ts.map +1 -1
  77. package/dist/cli/commands/status.js +5 -7
  78. package/dist/cli/commands/status.js.map +1 -1
  79. package/dist/cli/commands/sync-docs/context-syncer.d.ts +21 -2
  80. package/dist/cli/commands/sync-docs/context-syncer.d.ts.map +1 -1
  81. package/dist/cli/commands/sync-docs/context-syncer.js +112 -28
  82. package/dist/cli/commands/sync-docs/context-syncer.js.map +1 -1
  83. package/dist/cli/commands/sync-docs/index.d.ts +1 -1
  84. package/dist/cli/commands/sync-docs/index.d.ts.map +1 -1
  85. package/dist/cli/commands/sync-docs/index.js +86 -27
  86. package/dist/cli/commands/sync-docs/index.js.map +1 -1
  87. package/dist/cli/commands/sync-docs/project-reader.d.ts +24 -1
  88. package/dist/cli/commands/sync-docs/project-reader.d.ts.map +1 -1
  89. package/dist/cli/commands/sync-docs/project-reader.js +33 -7
  90. package/dist/cli/commands/sync-docs/project-reader.js.map +1 -1
  91. package/dist/cli/commands/validate.d.ts +0 -16
  92. package/dist/cli/commands/validate.d.ts.map +1 -1
  93. package/dist/cli/commands/validate.js +2 -97
  94. package/dist/cli/commands/validate.js.map +1 -1
  95. package/dist/cli/gate-command.d.ts +37 -0
  96. package/dist/cli/gate-command.d.ts.map +1 -0
  97. package/dist/cli/gate-command.js +64 -0
  98. package/dist/cli/gate-command.js.map +1 -0
  99. package/dist/cli/state-io.d.ts +34 -0
  100. package/dist/cli/state-io.d.ts.map +1 -0
  101. package/dist/cli/state-io.js +71 -0
  102. package/dist/cli/state-io.js.map +1 -0
  103. package/dist/completion-checkers/index.d.ts +1 -1
  104. package/dist/completion-checkers/index.d.ts.map +1 -1
  105. package/dist/completion-checkers/index.js +0 -15
  106. package/dist/completion-checkers/index.js.map +1 -1
  107. package/dist/context/knowledge-injector.d.ts +4 -2
  108. package/dist/context/knowledge-injector.d.ts.map +1 -1
  109. package/dist/context/knowledge-injector.js +13 -6
  110. package/dist/context/knowledge-injector.js.map +1 -1
  111. package/dist/core/constraints/agent-prompt-renderer.js +2 -2
  112. package/dist/core/constraints/agent-prompt-renderer.js.map +1 -1
  113. package/dist/core/constraints/capabilities-reconcile.d.ts +20 -0
  114. package/dist/core/constraints/capabilities-reconcile.d.ts.map +1 -1
  115. package/dist/core/constraints/capabilities-reconcile.js +26 -4
  116. package/dist/core/constraints/capabilities-reconcile.js.map +1 -1
  117. package/dist/core/constraints/check-cache.d.ts +1 -1
  118. package/dist/core/constraints/check-cache.js +1 -1
  119. package/dist/core/constraints/checker.d.ts +8 -3
  120. package/dist/core/constraints/checker.d.ts.map +1 -1
  121. package/dist/core/constraints/checker.js +30 -19
  122. package/dist/core/constraints/checker.js.map +1 -1
  123. package/dist/core/constraints/checkers/capability-sync.d.ts +3 -1
  124. package/dist/core/constraints/checkers/capability-sync.d.ts.map +1 -1
  125. package/dist/core/constraints/checkers/capability-sync.js +17 -24
  126. package/dist/core/constraints/checkers/capability-sync.js.map +1 -1
  127. package/dist/core/constraints/checkers/context-doc-sync.d.ts +1 -1
  128. package/dist/core/constraints/checkers/context-doc-sync.d.ts.map +1 -1
  129. package/dist/core/constraints/checkers/context-doc-sync.js +9 -6
  130. package/dist/core/constraints/checkers/context-doc-sync.js.map +1 -1
  131. package/dist/core/constraints/checkers/docs-freshness.d.ts.map +1 -1
  132. package/dist/core/constraints/checkers/docs-freshness.js +24 -30
  133. package/dist/core/constraints/checkers/docs-freshness.js.map +1 -1
  134. package/dist/core/constraints/checkers/governance-presence.d.ts.map +1 -1
  135. package/dist/core/constraints/checkers/governance-presence.js +10 -4
  136. package/dist/core/constraints/checkers/governance-presence.js.map +1 -1
  137. package/dist/core/constraints/checkers/types.d.ts +10 -6
  138. package/dist/core/constraints/checkers/types.d.ts.map +1 -1
  139. package/dist/core/constraints/checkers/types.js +7 -3
  140. package/dist/core/constraints/checkers/types.js.map +1 -1
  141. package/dist/core/constraints/context-builder.d.ts +11 -10
  142. package/dist/core/constraints/context-builder.d.ts.map +1 -1
  143. package/dist/core/constraints/context-builder.js +31 -27
  144. package/dist/core/constraints/context-builder.js.map +1 -1
  145. package/dist/core/constraints/context-reconcile.d.ts +75 -0
  146. package/dist/core/constraints/context-reconcile.d.ts.map +1 -0
  147. package/dist/core/constraints/context-reconcile.js +161 -0
  148. package/dist/core/constraints/context-reconcile.js.map +1 -0
  149. package/dist/core/constraints/doc-freshness/runner.d.ts +7 -0
  150. package/dist/core/constraints/doc-freshness/runner.d.ts.map +1 -1
  151. package/dist/core/constraints/doc-freshness/runner.js +8 -3
  152. package/dist/core/constraints/doc-freshness/runner.js.map +1 -1
  153. package/dist/core/constraints/git-evidence.js +1 -1
  154. package/dist/core/constraints/git-evidence.js.map +1 -1
  155. package/dist/core/constraints/injection-drift.d.ts +7 -2
  156. package/dist/core/constraints/injection-drift.d.ts.map +1 -1
  157. package/dist/core/constraints/injection-drift.js +13 -7
  158. package/dist/core/constraints/injection-drift.js.map +1 -1
  159. package/dist/core/constraints/run-env.d.ts +92 -0
  160. package/dist/core/constraints/run-env.d.ts.map +1 -0
  161. package/dist/core/constraints/run-env.js +175 -0
  162. package/dist/core/constraints/run-env.js.map +1 -0
  163. package/dist/core/constraints/triggers.d.ts +22 -0
  164. package/dist/core/constraints/triggers.d.ts.map +1 -0
  165. package/dist/core/constraints/triggers.js +31 -0
  166. package/dist/core/constraints/triggers.js.map +1 -0
  167. package/dist/core/effective-constraints.d.ts +13 -4
  168. package/dist/core/effective-constraints.d.ts.map +1 -1
  169. package/dist/core/effective-constraints.js +16 -6
  170. package/dist/core/effective-constraints.js.map +1 -1
  171. package/dist/core/effective-set.d.ts +8 -15
  172. package/dist/core/effective-set.d.ts.map +1 -1
  173. package/dist/core/effective-set.js +7 -12
  174. package/dist/core/effective-set.js.map +1 -1
  175. package/dist/core/index.d.ts +1 -0
  176. package/dist/core/index.d.ts.map +1 -1
  177. package/dist/core/index.js.map +1 -1
  178. package/dist/core/project-config-loader.d.ts +39 -17
  179. package/dist/core/project-config-loader.d.ts.map +1 -1
  180. package/dist/core/project-config-loader.js +51 -122
  181. package/dist/core/project-config-loader.js.map +1 -1
  182. package/dist/core/validators/check-handlers/http.d.ts +2 -2
  183. package/dist/core/validators/check-handlers/http.d.ts.map +1 -1
  184. package/dist/core/validators/check-handlers/http.js +12 -7
  185. package/dist/core/validators/check-handlers/http.js.map +1 -1
  186. package/dist/failure/classifier.d.ts +1 -1
  187. package/dist/failure/classifier.d.ts.map +1 -1
  188. package/dist/failure/classifier.js +8 -8
  189. package/dist/failure/classifier.js.map +1 -1
  190. package/dist/failure/index.d.ts +2 -1
  191. package/dist/failure/index.d.ts.map +1 -1
  192. package/dist/failure/index.js +9 -17
  193. package/dist/failure/index.js.map +1 -1
  194. package/dist/failure/recorder.d.ts +1 -1
  195. package/dist/failure/recorder.d.ts.map +1 -1
  196. package/dist/gates/checker-gate.d.ts +2 -1
  197. package/dist/gates/checker-gate.d.ts.map +1 -1
  198. package/dist/gates/checker-gate.js +3 -2
  199. package/dist/gates/checker-gate.js.map +1 -1
  200. package/dist/gates/command.d.ts +10 -4
  201. package/dist/gates/command.d.ts.map +1 -1
  202. package/dist/gates/command.js +36 -62
  203. package/dist/gates/command.js.map +1 -1
  204. package/dist/gates/contract.d.ts.map +1 -1
  205. package/dist/gates/contract.js +0 -4
  206. package/dist/gates/contract.js.map +1 -1
  207. package/dist/gates/definitions.d.ts +2 -1
  208. package/dist/gates/definitions.d.ts.map +1 -1
  209. package/dist/gates/definitions.js +6 -5
  210. package/dist/gates/definitions.js.map +1 -1
  211. package/dist/gates/index.d.ts +0 -4
  212. package/dist/gates/index.d.ts.map +1 -1
  213. package/dist/gates/index.js +1 -6
  214. package/dist/gates/index.js.map +1 -1
  215. package/dist/gates/performance.d.ts.map +1 -1
  216. package/dist/gates/performance.js +0 -4
  217. package/dist/gates/performance.js.map +1 -1
  218. package/dist/gates/runner.d.ts +1 -1
  219. package/dist/gates/runner.js +1 -1
  220. package/dist/gates/security.d.ts +1 -1
  221. package/dist/gates/security.d.ts.map +1 -1
  222. package/dist/gates/security.js +5 -6
  223. package/dist/gates/security.js.map +1 -1
  224. package/dist/gates/types.d.ts +14 -17
  225. package/dist/gates/types.d.ts.map +1 -1
  226. package/dist/gates/types.js.map +1 -1
  227. package/dist/hooks/bootstrap.d.ts +6 -4
  228. package/dist/hooks/bootstrap.d.ts.map +1 -1
  229. package/dist/hooks/bootstrap.js +25 -13
  230. package/dist/hooks/bootstrap.js.map +1 -1
  231. package/dist/hooks/config.d.ts +6 -2
  232. package/dist/hooks/config.d.ts.map +1 -1
  233. package/dist/hooks/config.js +5 -1
  234. package/dist/hooks/config.js.map +1 -1
  235. package/dist/hooks/index.d.ts +1 -1
  236. package/dist/hooks/index.d.ts.map +1 -1
  237. package/dist/hooks/index.js +0 -15
  238. package/dist/hooks/index.js.map +1 -1
  239. package/dist/hooks/pipeline.d.ts +19 -1
  240. package/dist/hooks/pipeline.d.ts.map +1 -1
  241. package/dist/hooks/pipeline.js +42 -4
  242. package/dist/hooks/pipeline.js.map +1 -1
  243. package/dist/hooks/registry.d.ts +11 -8
  244. package/dist/hooks/registry.d.ts.map +1 -1
  245. package/dist/hooks/registry.js +22 -7
  246. package/dist/hooks/registry.js.map +1 -1
  247. package/dist/hooks/types.d.ts +25 -7
  248. package/dist/hooks/types.d.ts.map +1 -1
  249. package/dist/index.d.ts +3 -3
  250. package/dist/index.d.ts.map +1 -1
  251. package/dist/index.js +3 -4
  252. package/dist/index.js.map +1 -1
  253. package/dist/knowledge/audit-scoring.d.ts +87 -0
  254. package/dist/knowledge/audit-scoring.d.ts.map +1 -0
  255. package/dist/knowledge/audit-scoring.js +470 -0
  256. package/dist/knowledge/audit-scoring.js.map +1 -0
  257. package/dist/knowledge/audit.d.ts +11 -59
  258. package/dist/knowledge/audit.d.ts.map +1 -1
  259. package/dist/knowledge/audit.js +47 -522
  260. package/dist/knowledge/audit.js.map +1 -1
  261. package/dist/knowledge/import.d.ts.map +1 -1
  262. package/dist/knowledge/import.js +2 -0
  263. package/dist/knowledge/import.js.map +1 -1
  264. package/dist/knowledge/index-generator.d.ts.map +1 -1
  265. package/dist/knowledge/index-generator.js +4 -5
  266. package/dist/knowledge/index-generator.js.map +1 -1
  267. package/dist/knowledge/index.d.ts +3 -2
  268. package/dist/knowledge/index.d.ts.map +1 -1
  269. package/dist/knowledge/index.js +3 -16
  270. package/dist/knowledge/index.js.map +1 -1
  271. package/dist/knowledge/ingest.js +1 -1
  272. package/dist/knowledge/ingest.js.map +1 -1
  273. package/dist/knowledge/lifecycle.d.ts.map +1 -1
  274. package/dist/knowledge/lifecycle.js +4 -2
  275. package/dist/knowledge/lifecycle.js.map +1 -1
  276. package/dist/knowledge/migration.d.ts +3 -0
  277. package/dist/knowledge/migration.d.ts.map +1 -1
  278. package/dist/knowledge/migration.js +8 -2
  279. package/dist/knowledge/migration.js.map +1 -1
  280. package/dist/knowledge/query.d.ts +6 -0
  281. package/dist/knowledge/query.d.ts.map +1 -1
  282. package/dist/knowledge/query.js +8 -2
  283. package/dist/knowledge/query.js.map +1 -1
  284. package/dist/knowledge/reference-tracker.d.ts.map +1 -1
  285. package/dist/knowledge/reference-tracker.js +4 -6
  286. package/dist/knowledge/reference-tracker.js.map +1 -1
  287. package/dist/knowledge/store.d.ts +22 -16
  288. package/dist/knowledge/store.d.ts.map +1 -1
  289. package/dist/knowledge/store.js +53 -12
  290. package/dist/knowledge/store.js.map +1 -1
  291. package/dist/knowledge/tree-walker.d.ts +19 -0
  292. package/dist/knowledge/tree-walker.d.ts.map +1 -0
  293. package/dist/knowledge/tree-walker.js +30 -0
  294. package/dist/knowledge/tree-walker.js.map +1 -0
  295. package/dist/knowledge/types.d.ts +16 -0
  296. package/dist/knowledge/types.d.ts.map +1 -1
  297. package/dist/monitoring/traces.d.ts +5 -3
  298. package/dist/monitoring/traces.d.ts.map +1 -1
  299. package/dist/monitoring/traces.js +19 -5
  300. package/dist/monitoring/traces.js.map +1 -1
  301. package/dist/test-setup/jsonl-fake-fs.d.ts +30 -0
  302. package/dist/test-setup/jsonl-fake-fs.d.ts.map +1 -0
  303. package/dist/test-setup/jsonl-fake-fs.js +49 -0
  304. package/dist/test-setup/jsonl-fake-fs.js.map +1 -0
  305. package/dist/tools/index.d.ts +4 -1
  306. package/dist/tools/index.d.ts.map +1 -1
  307. package/dist/tools/index.js +7 -15
  308. package/dist/tools/index.js.map +1 -1
  309. package/dist/types/checkpoint.d.ts +5 -0
  310. package/dist/types/checkpoint.d.ts.map +1 -1
  311. package/dist/types/project-config.d.ts +18 -0
  312. package/dist/types/project-config.d.ts.map +1 -1
  313. package/dist/types/trace.d.ts +13 -4
  314. package/dist/types/trace.d.ts.map +1 -1
  315. package/dist/types/trace.js +4 -3
  316. package/dist/types/trace.js.map +1 -1
  317. package/dist/utils/exec.d.ts +4 -27
  318. package/dist/utils/exec.d.ts.map +1 -1
  319. package/dist/utils/exec.js +4 -94
  320. package/dist/utils/exec.js.map +1 -1
  321. package/dist/utils/jsonl.d.ts +17 -7
  322. package/dist/utils/jsonl.d.ts.map +1 -1
  323. package/dist/utils/jsonl.js +144 -17
  324. package/dist/utils/jsonl.js.map +1 -1
  325. package/dist/utils/numeric-flag.d.ts +44 -0
  326. package/dist/utils/numeric-flag.d.ts.map +1 -0
  327. package/dist/utils/numeric-flag.js +62 -0
  328. package/dist/utils/numeric-flag.js.map +1 -0
  329. package/package.json +1 -1
  330. package/src/CONTEXT.md +5 -2
  331. package/src/__tests__/acceptance-gate.test.ts +7 -4
  332. package/src/__tests__/checker-extra.test.ts +3 -2
  333. package/src/__tests__/checker.test.ts +4 -3
  334. package/src/__tests__/checkpoint.test.ts +26 -9
  335. package/src/__tests__/context-files-resolution.test.ts +29 -15
  336. package/src/__tests__/contract-gate.test.ts +19 -40
  337. package/src/__tests__/error-classifier.test.ts +1 -1
  338. package/src/__tests__/exec.test.ts +45 -107
  339. package/src/__tests__/failure-recorder.test.ts +7 -5
  340. package/src/__tests__/hooks-pipeline.test.ts +34 -47
  341. package/src/__tests__/layering.test.ts +217 -25
  342. package/src/__tests__/passes-gate.test.ts +9 -4
  343. package/src/__tests__/performance-gate.test.ts +3 -15
  344. package/src/__tests__/project-config-loader-extra.test.ts +31 -57
  345. package/src/__tests__/project-config-loader.test.ts +6 -3
  346. package/src/__tests__/public-exports.test.ts +0 -1
  347. package/src/__tests__/public-type-surface.test.ts +5 -4
  348. package/src/__tests__/public-value-surface.test.ts +182 -0
  349. package/src/__tests__/review-gate.test.ts +4 -6
  350. package/src/__tests__/security-gate.test.ts +5 -20
  351. package/src/__tests__/skip-semantics.test.ts +5 -3
  352. package/src/__tests__/spec-validator.test.ts +3 -2
  353. package/src/__tests__/sub-barrels-explicit.test.ts +87 -0
  354. package/src/__tests__/test-fixture-hygiene.test.ts +53 -0
  355. package/src/__tests__/trace-analyzer-extra.test.ts +5 -3
  356. package/src/__tests__/trace-analyzer.test.ts +5 -3
  357. package/src/__tests__/trace-collector.test.ts +5 -3
  358. package/src/agents/index.ts +13 -2
  359. package/src/cli/__tests__/gate-command.test.ts +162 -0
  360. package/src/cli/__tests__/state-io.test.ts +50 -0
  361. package/src/cli/commands/CONTEXT.md +30 -5
  362. package/src/cli/commands/__tests__/acceptance.test.ts +24 -25
  363. package/src/cli/commands/__tests__/bin-exit-mapping.test.ts +15 -0
  364. package/src/cli/commands/__tests__/check-drift.test.ts +42 -1
  365. package/src/cli/commands/__tests__/check-read-count.test.ts +170 -0
  366. package/src/cli/commands/__tests__/check-skip-output.test.ts +4 -1
  367. package/src/cli/commands/__tests__/check.test.ts +63 -44
  368. package/src/cli/commands/__tests__/command-gate-dead-options.test.ts +60 -0
  369. package/src/cli/commands/__tests__/command.test.ts +33 -17
  370. package/src/cli/commands/__tests__/constraints-retire.test.ts +52 -0
  371. package/src/cli/commands/__tests__/context-syncer.test.ts +141 -0
  372. package/src/cli/commands/__tests__/contract.test.ts +20 -20
  373. package/src/cli/commands/__tests__/failure.test.ts +5 -4
  374. package/src/cli/commands/__tests__/gate-decision.ts +30 -0
  375. package/src/cli/commands/__tests__/init-dead-options.test.ts +50 -0
  376. package/src/cli/commands/__tests__/init-governance-io.test.ts +139 -0
  377. package/src/cli/commands/__tests__/init-injection.test.ts +3 -3
  378. package/src/cli/commands/__tests__/init-ondisk.test.ts +867 -0
  379. package/src/cli/commands/__tests__/init.test.ts +82 -6
  380. package/src/cli/commands/__tests__/knowledge-audit-threshold.test.ts +146 -0
  381. package/src/cli/commands/__tests__/knowledge-flywheel-consistency.test.ts +1 -1
  382. package/src/cli/commands/__tests__/knowledge-tone-mapping.test.ts +244 -0
  383. package/src/cli/commands/__tests__/knowledge-view.test.ts +839 -0
  384. package/src/cli/commands/__tests__/knowledge.test.ts +33 -15
  385. package/src/cli/commands/__tests__/numeric-flag-assembly.test.ts +368 -0
  386. package/src/cli/commands/__tests__/performance.test.ts +19 -21
  387. package/src/cli/commands/__tests__/posteval-plan.test.ts +5 -3
  388. package/src/cli/commands/__tests__/pre-push-hook.test.ts +181 -0
  389. package/src/cli/commands/__tests__/project-path-anchoring.test.ts +95 -2
  390. package/src/cli/commands/__tests__/project-path-convention.test.ts +103 -25
  391. package/src/cli/commands/__tests__/registry.test.ts +2 -0
  392. package/src/cli/commands/__tests__/report.test.ts +23 -1
  393. package/src/cli/commands/__tests__/review.test.ts +10 -17
  394. package/src/cli/commands/__tests__/scaffold.test.ts +505 -0
  395. package/src/cli/commands/__tests__/security-default-scan.test.ts +75 -0
  396. package/src/cli/commands/__tests__/security.test.ts +21 -24
  397. package/src/cli/commands/__tests__/spec-baseline-check.test.ts +3 -2
  398. package/src/cli/commands/__tests__/spec-baseline-index-cap.test.ts +131 -0
  399. package/src/cli/commands/__tests__/spec-baseline-read-count.test.ts +325 -0
  400. package/src/cli/commands/__tests__/status-extra.test.ts +25 -8
  401. package/src/cli/commands/__tests__/status.test.ts +46 -18
  402. package/src/cli/commands/__tests__/sync-docs-agents.test.ts +19 -4
  403. package/src/cli/commands/__tests__/sync-docs-context-drift.test.ts +232 -0
  404. package/src/cli/commands/__tests__/sync-docs-module-order.test.ts +111 -0
  405. package/src/cli/commands/__tests__/sync-docs-read-count.test.ts +192 -0
  406. package/src/cli/commands/__tests__/sync-docs.test.ts +3 -2
  407. package/src/cli/commands/__tests__/validate.test.ts +1 -48
  408. package/src/cli/commands/acceptance.ts +24 -29
  409. package/src/cli/commands/check.ts +60 -35
  410. package/src/cli/commands/command.ts +9 -8
  411. package/src/cli/commands/constraints-retire.ts +57 -70
  412. package/src/cli/commands/contract.ts +44 -47
  413. package/src/cli/commands/definitions.ts +12 -6
  414. package/src/cli/commands/failure.ts +16 -3
  415. package/src/cli/commands/init.ts +242 -389
  416. package/src/cli/commands/knowledge-view.ts +224 -0
  417. package/src/cli/commands/knowledge.ts +643 -448
  418. package/src/cli/commands/passes-gate.ts +12 -3
  419. package/src/cli/commands/performance.ts +31 -38
  420. package/src/cli/commands/report.ts +3 -2
  421. package/src/cli/commands/review.ts +22 -28
  422. package/src/cli/commands/scaffold-templates.ts +406 -0
  423. package/src/cli/commands/scaffold.ts +302 -0
  424. package/src/cli/commands/security.ts +27 -23
  425. package/src/cli/commands/spec-baseline-check.ts +158 -33
  426. package/src/cli/commands/status.ts +12 -7
  427. package/src/cli/commands/sync-docs/__tests__/context-export-surface.test.ts +102 -0
  428. package/src/cli/commands/sync-docs/__tests__/module-descriptions.test.ts +196 -0
  429. package/src/cli/commands/sync-docs/context-syncer.ts +137 -31
  430. package/src/cli/commands/sync-docs/index.ts +103 -28
  431. package/src/cli/commands/sync-docs/project-reader.ts +51 -7
  432. package/src/cli/commands/validate.ts +1 -104
  433. package/src/cli/gate-command.ts +87 -0
  434. package/src/cli/state-io.ts +53 -0
  435. package/src/completion-checkers/index.ts +10 -1
  436. package/src/context/CONTEXT.md +2 -1
  437. package/src/context/__tests__/knowledge-injector.test.ts +27 -0
  438. package/src/context/__tests__/session-manager.test.ts +19 -12
  439. package/src/context/knowledge-injector.ts +14 -7
  440. package/src/core/CONTEXT.md +10 -7
  441. package/src/core/__tests__/effective-set.test.ts +36 -60
  442. package/src/core/constraints/__tests__/context-reconcile.test.ts +246 -0
  443. package/src/core/constraints/__tests__/run-env.test.ts +377 -0
  444. package/src/core/constraints/__tests__/triggers.test.ts +70 -0
  445. package/src/core/constraints/agent-prompt-renderer.ts +1 -1
  446. package/src/core/constraints/capabilities-reconcile.ts +28 -4
  447. package/src/core/constraints/check-cache.ts +1 -1
  448. package/src/core/constraints/checker.ts +30 -14
  449. package/src/core/constraints/checkers/__tests__/context-doc-sync.test.ts +8 -3
  450. package/src/core/constraints/checkers/__tests__/governance-presence.test.ts +16 -7
  451. package/src/core/constraints/checkers/__tests__/no-hardcoded-credentials.test.ts +2 -1
  452. package/src/core/constraints/checkers/capability-sync.ts +27 -28
  453. package/src/core/constraints/checkers/context-doc-sync.ts +9 -7
  454. package/src/core/constraints/checkers/docs-freshness.ts +28 -33
  455. package/src/core/constraints/checkers/governance-presence.ts +10 -6
  456. package/src/core/constraints/checkers/types.ts +14 -8
  457. package/src/core/constraints/context-builder.ts +35 -26
  458. package/src/core/constraints/context-reconcile.ts +200 -0
  459. package/src/core/constraints/doc-freshness/__tests__/runner.test.ts +25 -0
  460. package/src/core/constraints/doc-freshness/runner.ts +18 -4
  461. package/src/core/constraints/git-evidence.ts +1 -1
  462. package/src/core/constraints/injection-drift.ts +19 -8
  463. package/src/core/constraints/run-env.ts +207 -0
  464. package/src/core/constraints/triggers.ts +33 -0
  465. package/src/core/effective-constraints.ts +17 -6
  466. package/src/core/effective-set.ts +8 -24
  467. package/src/core/index.ts +2 -0
  468. package/src/core/project-config-loader.ts +54 -102
  469. package/src/core/validators/__tests__/http-retry-sleep.test.ts +231 -0
  470. package/src/core/validators/check-handlers/http.ts +18 -7
  471. package/src/failure/CONTEXT.md +2 -1
  472. package/src/failure/classifier.ts +2 -2
  473. package/src/failure/index.ts +14 -2
  474. package/src/failure/recorder.ts +1 -1
  475. package/src/gates/CONTEXT.md +13 -7
  476. package/src/gates/__tests__/checker-gate.test.ts +1 -1
  477. package/src/gates/__tests__/command-single-predicate.test.ts +135 -0
  478. package/src/gates/__tests__/command.test.ts +8 -15
  479. package/src/gates/__tests__/contract.test.ts +5 -5
  480. package/src/gates/__tests__/gate-interface.test.ts +0 -17
  481. package/src/gates/__tests__/performance.test.ts +0 -13
  482. package/src/gates/__tests__/review.test.ts +0 -1
  483. package/src/gates/__tests__/runner.test.ts +1 -1
  484. package/src/gates/__tests__/security-default-scan.test.ts +97 -0
  485. package/src/gates/__tests__/security.test.ts +0 -13
  486. package/src/gates/checker-gate.ts +3 -2
  487. package/src/gates/command.ts +51 -74
  488. package/src/gates/contract.ts +0 -5
  489. package/src/gates/definitions.ts +6 -5
  490. package/src/gates/index.ts +0 -5
  491. package/src/gates/performance.ts +1 -6
  492. package/src/gates/runner.ts +1 -1
  493. package/src/gates/security.ts +9 -11
  494. package/src/gates/types.ts +20 -23
  495. package/src/hooks/CONTEXT.md +10 -9
  496. package/src/hooks/__tests__/bootstrap.test.ts +29 -6
  497. package/src/hooks/__tests__/pipeline.test.ts +133 -17
  498. package/src/hooks/__tests__/registry.test.ts +51 -3
  499. package/src/hooks/bootstrap.ts +35 -15
  500. package/src/hooks/config.ts +6 -2
  501. package/src/hooks/index.ts +10 -1
  502. package/src/hooks/pipeline.ts +51 -6
  503. package/src/hooks/registry.ts +31 -12
  504. package/src/hooks/types.ts +26 -7
  505. package/src/index.ts +1 -2
  506. package/src/knowledge/CONTEXT.md +14 -7
  507. package/src/knowledge/__tests__/audit-labels.test.ts +8 -5
  508. package/src/knowledge/__tests__/audit-scoring.test.ts +230 -0
  509. package/src/knowledge/__tests__/audit-write-count.test.ts +131 -0
  510. package/src/knowledge/__tests__/audit.test.ts +291 -208
  511. package/src/knowledge/__tests__/doctor.test.ts +3 -2
  512. package/src/knowledge/__tests__/ingest.test.ts +3 -2
  513. package/src/knowledge/__tests__/lifecycle.test.ts +57 -2
  514. package/src/knowledge/__tests__/migration.test.ts +35 -6
  515. package/src/knowledge/__tests__/query.test.ts +3 -2
  516. package/src/knowledge/__tests__/reference-tracker.test.ts +23 -2
  517. package/src/knowledge/__tests__/store.test.ts +149 -4
  518. package/src/knowledge/__tests__/tree-walker.test.ts +132 -0
  519. package/src/knowledge/audit-scoring.ts +589 -0
  520. package/src/knowledge/audit.ts +55 -599
  521. package/src/knowledge/import.ts +2 -0
  522. package/src/knowledge/index-generator.ts +4 -6
  523. package/src/knowledge/index.ts +27 -2
  524. package/src/knowledge/ingest.ts +1 -1
  525. package/src/knowledge/lifecycle.ts +5 -2
  526. package/src/knowledge/migration.ts +8 -2
  527. package/src/knowledge/query.ts +8 -1
  528. package/src/knowledge/reference-tracker.ts +5 -7
  529. package/src/knowledge/store.ts +75 -16
  530. package/src/knowledge/tree-walker.ts +29 -0
  531. package/src/knowledge/types.ts +19 -0
  532. package/src/monitoring/CONTEXT.md +5 -2
  533. package/src/monitoring/__tests__/context-tracker.test.ts +16 -8
  534. package/src/monitoring/__tests__/trace-file-anchoring.test.ts +80 -0
  535. package/src/monitoring/traces.ts +19 -5
  536. package/src/release/CONTEXT.md +1 -1
  537. package/src/release/__tests__/integrity.test.ts +21 -12
  538. package/src/test-setup/__tests__/jsonl-fake-fs.test.ts +98 -0
  539. package/src/test-setup/jsonl-fake-fs.ts +59 -0
  540. package/src/tools/index.ts +5 -1
  541. package/src/types/checkpoint.ts +6 -0
  542. package/src/types/project-config.ts +21 -0
  543. package/src/types/trace.ts +14 -4
  544. package/src/utils/__tests__/file-walk.test.ts +3 -2
  545. package/src/utils/__tests__/jsonl-bounded-read.test.ts +106 -0
  546. package/src/utils/__tests__/jsonl-skip-disposition.test.ts +10 -6
  547. package/src/utils/__tests__/jsonl.test.ts +61 -14
  548. package/src/utils/__tests__/numeric-flag.test.ts +80 -0
  549. package/src/utils/__tests__/package-version.test.ts +2 -2
  550. package/src/utils/exec.ts +4 -64
  551. package/src/utils/jsonl.ts +159 -20
  552. package/src/utils/numeric-flag.ts +64 -0
  553. package/dist/failure/types.d.ts +0 -9
  554. package/dist/failure/types.d.ts.map +0 -1
  555. package/dist/failure/types.js +0 -25
  556. package/dist/failure/types.js.map +0 -1
  557. package/dist/gates/effective-gates.d.ts +0 -30
  558. package/dist/gates/effective-gates.d.ts.map +0 -1
  559. package/dist/gates/effective-gates.js +0 -81
  560. package/dist/gates/effective-gates.js.map +0 -1
  561. package/src/failure/types.ts +0 -9
  562. package/src/gates/__tests__/effective-gates.test.ts +0 -77
  563. package/src/gates/effective-gates.ts +0 -99
@@ -9,8 +9,9 @@
9
9
  */
10
10
 
11
11
  import { describe, it, expect } from '@jest/globals';
12
+ import { join } from 'path';
12
13
  import { contextDocSync } from '../context-doc-sync';
13
- import { buildCheckEnv } from '../types';
14
+ import { buildCheckEnv, normalizeCheckOutcome } from '../types';
14
15
  import { createProjectFixture } from '../../../../test-setup/project-fixture';
15
16
  import type { ConstraintContext } from '../../../../types/constraint';
16
17
 
@@ -65,9 +66,13 @@ describe('context_doc_sync — 判定', () => {
65
66
  expect(await evaluate(dir)).toBe(true);
66
67
  });
67
68
 
68
- it('任一目录缺 CONTEXT.md → fail', async () => {
69
+ it('任一目录缺 CONTEXT.md → fail,证据点名缺的那一个(ADR-0016 补迁)', async () => {
69
70
  const dir = setupDir('one-missing', CTX_FILES(true, ['src', 'bin']), ['src']);
70
- expect(await evaluate(dir)).toBe(false);
71
+ const outcome = normalizeCheckOutcome(await evaluate(dir));
72
+ expect(outcome.satisfied).toBe(false);
73
+ expect(outcome.skipped).toBe(false);
74
+ expect(outcome.evidence.join('\n')).toContain(join('bin', 'CONTEXT.md'));
75
+ expect(outcome.evidence.join('\n')).not.toContain(join('src', 'CONTEXT.md'));
71
76
  });
72
77
 
73
78
  it('配置解析失败 → skip(不炸不报)', async () => {
@@ -18,12 +18,13 @@ import {
18
18
  } from '../governance-presence';
19
19
  import { detectInjectionDrift } from '../../injection-drift';
20
20
  import { createProjectFixture, writeProjectConfig } from '../../../../test-setup/project-fixture';
21
- import type { CheckEnv } from '../types';
21
+ import { normalizeCheckOutcome, type CheckEnv } from '../types';
22
+ import { createRunEnv } from '../../run-env';
22
23
 
23
24
  function makeEnv(projectPath: string): CheckEnv {
24
25
  return {
26
+ ...createRunEnv(projectPath),
25
27
  context: { operation: 'commit', projectPath },
26
- projectPath,
27
28
  stagedDiff: async () => '',
28
29
  stagedDiffNames: async () => '',
29
30
  srcScan: () => [],
@@ -87,12 +88,20 @@ describe('governance_presence checker', () => {
87
88
  expect(await governancePresence.evaluate(makeEnv(tempDir))).toBe(true);
88
89
  });
89
90
 
90
- it('两处都没有治理契约 fail 并报警(防静默丢失)', async () => {
91
+ /** 判定与证据的统一读法(harness#119/ADR-0016:布尔与 CheckDetail 两种形状同一断言) */
92
+ const outcomeOf = async (projectPath: string) =>
93
+ normalizeCheckOutcome(await governancePresence.evaluate(makeEnv(projectPath)));
94
+
95
+ it('两处都没有治理契约 → fail,证据点名两处落点与修复入口(不再走 stderr 侧信道)', async () => {
91
96
  writeConfig();
92
97
  fs.writeFileSync(path.join(tempDir, 'AGENTS.md'), '# AGENTS.md\n\n只有机器生成内容\n');
93
98
  fs.writeFileSync(path.join(tempDir, 'CLAUDE.md'), '# CLAUDE.md\n\n@AGENTS.md\n');
94
- expect(await governancePresence.evaluate(makeEnv(tempDir))).toBe(false);
95
- expect(errorSpy).toHaveBeenCalledWith(expect.stringContaining('治理契约缺失'));
99
+ const outcome = await outcomeOf(tempDir);
100
+ expect(outcome.satisfied).toBe(false);
101
+ expect(outcome.evidence.join('\n')).toContain('治理契约');
102
+ expect(outcome.evidence.join('\n')).toContain('harness init');
103
+ // ADR-0016:证据只有一个出口。侧信道留着会让 CLI 结构化输出与 trace 两头口径不一致
104
+ expect(errorSpy).not.toHaveBeenCalled();
96
105
  });
97
106
 
98
107
  it('PRESERVE:governance 段为空(被掏空)且 CLAUDE.md 无治理块 → fail', async () => {
@@ -101,7 +110,7 @@ describe('governance_presence checker', () => {
101
110
  path.join(tempDir, 'AGENTS.md'),
102
111
  '# AGENTS.md\n\n<!-- PRESERVE:governance -->\n\n<!-- /PRESERVE:governance -->\n'
103
112
  );
104
- expect(await governancePresence.evaluate(makeEnv(tempDir))).toBe(false);
113
+ expect((await outcomeOf(tempDir)).satisfied).toBe(false);
105
114
  });
106
115
 
107
116
  it('PRESERVE:governance 标记未闭合视为不在场 → fail', async () => {
@@ -110,7 +119,7 @@ describe('governance_presence checker', () => {
110
119
  path.join(tempDir, 'AGENTS.md'),
111
120
  '# AGENTS.md\n\n<!-- PRESERVE:governance -->\n## Governance Rules\n内容\n'
112
121
  );
113
- expect(await governancePresence.evaluate(makeEnv(tempDir))).toBe(false);
122
+ expect((await outcomeOf(tempDir)).satisfied).toBe(false);
114
123
  });
115
124
  });
116
125
 
@@ -12,11 +12,12 @@ import {
12
12
  containsHardcodedCredential,
13
13
  } from '../no-hardcoded-credentials';
14
14
  import type { CheckEnv } from '../types';
15
+ import { createRunEnv } from '../../run-env';
15
16
 
16
17
  function makeEnv(stagedDiff: string): CheckEnv {
17
18
  return {
19
+ ...createRunEnv('/nonexistent'),
18
20
  context: { operation: 'commit', projectPath: '/nonexistent' },
19
- projectPath: '/nonexistent',
20
21
  stagedDiff: async () => stagedDiff,
21
22
  stagedDiffNames: async () => '',
22
23
  srcScan: () => [],
@@ -17,7 +17,9 @@
17
17
  *
18
18
  * 例外:「有表格但零条目」= 文档被清空,判违规(历史门,此前靠 Step 2 兜,现显式化)。
19
19
  *
20
- * 覆盖/漏登判定不在本文件实现,统一走 capabilities-reconcile(ADR-0009):
20
+ * 覆盖/漏登判定不在本文件实现:全量对照(解析文档 + 代码实况 + 覆盖/幽灵)由
21
+ * capabilities-reconcile 一次算好并与 docs_freshness 共用(ADR-0009 + ADR-0023 决策 4),
22
+ * 本文件只按导出的唯一覆盖规则 `isCoveredByEntries` 算「本次变更」那一维(增量清单属 git 证据)。
21
23
  * 目录条目(以 / 结尾)前缀匹配,文件条目精确匹配或路径边界后缀匹配;
22
24
  * module 模式下目录条目参与覆盖,未覆盖文件按源码根下第一级子目录聚合。
23
25
  *
@@ -28,12 +30,15 @@
28
30
  * 不计 pass/fail,避免在未采用约定的项目上全量误报。
29
31
  */
30
32
 
31
- import { existsSync, readFileSync } from 'fs';
33
+ import { existsSync } from 'fs';
32
34
  import { join } from 'path';
33
- import { isCapabilityListingFormat } from '../capabilities-parser';
34
35
  import { getCapabilitiesMode } from '../../project-config-loader';
35
- import { detectSourceRoots } from '../../../utils/detect-source-roots';
36
- import { reconcileCapabilities, significantCodeChanges } from '../capabilities-reconcile';
36
+ import {
37
+ collectPopulationFiles,
38
+ isCoveredByEntries,
39
+ significantCodeChanges,
40
+ } from '../capabilities-reconcile';
41
+ import { CAPABILITIES_FILE_REL } from '../run-env';
37
42
  import { formatEvidence, type ConstraintCheck } from './types';
38
43
 
39
44
  export const capabilitySync: ConstraintCheck = {
@@ -41,41 +46,35 @@ export const capabilitySync: ConstraintCheck = {
41
46
  async evaluate(env) {
42
47
  const projectPath = env.projectPath;
43
48
  // ADR-0001 存在性探测:项目未采用 CAPABILITIES.md 约定 → skip(不计 pass/fail)
44
- if (!existsSync(join(projectPath, 'CAPABILITIES.md'))) {
49
+ if (!existsSync(join(projectPath, CAPABILITIES_FILE_REL))) {
45
50
  return 'skip';
46
51
  }
47
52
  try {
48
- const capabilitiesPath = join(projectPath, 'CAPABILITIES.md');
49
- const content = readFileSync(capabilitiesPath, 'utf-8');
50
- const capabilitiesMode = getCapabilitiesMode(projectPath);
53
+ const capabilitiesMode = getCapabilitiesMode(env);
54
+ // 文档原文 + 源码根 + 代码实况 + 对照判定 = run 内一份,与 docs_freshness 共用(ADR-0023 决策 4)
55
+ const caps = env.capabilities(
56
+ collectPopulationFiles(projectPath, env.sourceRoots(), (root) => env.srcScan(root))
57
+ );
58
+ if (!caps) return 'skip'; // 探测与取数之间文档消失:与上方同一语义
59
+ const verdict = caps.verdict;
51
60
 
52
61
  // 清单格式(计数行)没有文件表可核对,计数由 sync-docs 维护,直接放行
53
- if (capabilitiesMode === 'listing' || isCapabilityListingFormat(content)) {
62
+ if (capabilitiesMode === 'listing' || verdict.listingFormat) {
54
63
  return true;
55
64
  }
56
65
 
57
- const sourceRoots = detectSourceRoots(projectPath);
58
- const population: string[] = [];
59
- for (const root of sourceRoots) {
60
- if (existsSync(join(projectPath, root))) {
61
- population.push(...env.srcScan(root));
62
- }
63
- }
64
-
65
66
  const diffNames = (await env.stagedDiffNames()).split('\n').filter(Boolean);
66
- const verdict = reconcileCapabilities({
67
- content,
68
- populationFiles: population,
69
- changedFiles: significantCodeChanges(diffNames),
70
- sourceRoots,
71
- });
67
+ // 增量覆盖判定留在本文件:变更清单属 git 证据(#87),不在上行数据面
68
+ const uncoveredChanges = significantCodeChanges(diffNames).filter(
69
+ (f) => !isCoveredByEntries(verdict.coverageEntries, f)
70
+ );
72
71
 
73
72
  // 无表格的散文文档:历史放行语义
74
73
  if (!verdict.hasTable) return true;
75
74
 
76
75
  // 文档退化门:有表格却什么都没登记(限定「源码根下确有文件」——空仓 + 空表没有可登记
77
76
  // 对象,历史行为是放行,本票不顺手扩大 fail 面)
78
- if (verdict.coverageEntries.length === 0 && population.length > 0) {
77
+ if (verdict.coverageEntries.length === 0 && caps.populationFiles.length > 0) {
79
78
  return {
80
79
  pass: false,
81
80
  evidence: ['CAPABILITIES.md 有表格但零条目登记,运行 harness sync-docs 或直接补登记'],
@@ -83,12 +82,12 @@ export const capabilitySync: ConstraintCheck = {
83
82
  }
84
83
 
85
84
  // ── Step 1: Git diff 增量检查(与本次变更有因果,每个变更文件都必须被覆盖)──
86
- if (verdict.uncoveredChanges.length > 0) {
85
+ if (uncoveredChanges.length > 0) {
87
86
  return {
88
87
  pass: false,
89
88
  evidence: formatEvidence(
90
- `本次变更有 ${verdict.uncoveredChanges.length} 个文件未登记进 CAPABILITIES.md`,
91
- verdict.uncoveredChanges
89
+ `本次变更有 ${uncoveredChanges.length} 个文件未登记进 CAPABILITIES.md`,
90
+ uncoveredChanges
92
91
  ),
93
92
  };
94
93
  }
@@ -10,22 +10,24 @@
10
10
  import { existsSync } from 'fs';
11
11
  import { join } from 'path';
12
12
  import { resolveContextFiles } from '../../project-config-loader';
13
- import type { ConstraintCheck } from './types';
13
+ import { formatEvidence, type ConstraintCheck } from './types';
14
14
 
15
15
  export const contextDocSync: ConstraintCheck = {
16
16
  id: 'context_doc_sync',
17
17
  async evaluate(env) {
18
18
  const projectPath = env.projectPath;
19
- const resolution = resolveContextFiles(projectPath);
19
+ const resolution = resolveContextFiles(env);
20
20
  if (resolution.state !== 'enabled') {
21
21
  return 'skip'; // 未配置或约定已立但无目标,跳过评估
22
22
  }
23
23
 
24
- for (const dir of resolution.dirs) {
25
- const contextPath = join(projectPath, dir, 'CONTEXT.md');
26
- if (!existsSync(contextPath)) {
27
- return false;
28
- }
24
+ // 证据随判定一并返回(ADR-0016 补迁):此前只回裸 false,
25
+ // 多个 required_dirs 里到底哪个没落 CONTEXT.md,CLI 与 trace 两头都看不出来
26
+ const missing = resolution.dirs
27
+ .map(dir => join(dir, 'CONTEXT.md'))
28
+ .filter(rel => !existsSync(join(projectPath, rel)));
29
+ if (missing.length > 0) {
30
+ return { pass: false, evidence: formatEvidence('关键目录缺 CONTEXT.md', missing) };
29
31
  }
30
32
 
31
33
  return true;
@@ -7,12 +7,12 @@
7
7
  * 3. 无配置时注入内置默认配置(等价旧硬编码行为)
8
8
  */
9
9
 
10
- import { existsSync, readFileSync } from 'fs';
10
+ import { existsSync } from 'fs';
11
11
  import { join } from 'path';
12
12
  import { getGovernanceConfig, resolveContextFiles } from '../../project-config-loader';
13
13
  import { FreshnessRunner, type FreshnessCheckResult } from '../doc-freshness/runner';
14
- import { detectSourceRoots } from '../../../utils/detect-source-roots';
15
- import { reconcileCapabilities } from '../capabilities-reconcile';
14
+ import { collectPopulationFiles } from '../capabilities-reconcile';
15
+ import { CAPABILITIES_FILE_REL } from '../run-env';
16
16
  import type { DocFreshnessCheck } from '../../../types/project-config';
17
17
  import type { ConstraintCheck, CheckEnv } from './types';
18
18
  import { formatEvidence } from './types';
@@ -33,28 +33,19 @@ function getBuiltInDocFreshnessConfig(): DocFreshnessCheck[] {
33
33
 
34
34
  /**
35
35
  * CAPABILITIES.md 文件表新鲜度:登记的条目(文件与目录)必须仍存在(ADR-0009 口径从严)。
36
- * 判定逻辑统一走 capabilities-reconcile;多根查找支持不同项目的源码根
37
- * (harness=src/, studio=apps/api/src/ 等)。无表格(能力清单格式)时自然零幽灵。
36
+ * 判定逻辑与取数都在 run 级:文档原文、源码根、代码实况清单、对照判定一次算好,
37
+ * capability_sync 共用同一份(ADR-0023 决策 4;此前两边各读一遍、各解析一遍)。
38
+ * 无表格(能力清单格式)时自然零幽灵。
38
39
  */
39
- function findDeadCapabilityEntries(projectPath: string, env: CheckEnv): string[] {
40
+ function findDeadCapabilityEntries(env: CheckEnv): string[] {
40
41
  try {
41
- const capabilitiesPath = join(projectPath, 'CAPABILITIES.md');
42
- if (!existsSync(capabilitiesPath)) return [];
43
- const content = readFileSync(capabilitiesPath, 'utf-8');
44
-
45
- const sourceRoots = detectSourceRoots(projectPath);
46
- const population: string[] = [];
47
- for (const root of sourceRoots) {
48
- if (existsSync(join(projectPath, root))) population.push(...env.srcScan(root));
49
- }
50
-
51
- const verdict = reconcileCapabilities({
52
- content,
53
- populationFiles: population,
54
- sourceRoots,
55
- fileExists: (rel) => existsSync(join(projectPath, rel)),
56
- });
57
- return verdict.deadEntries;
42
+ // 先探存在性再取数:只有 CHANGELOG 而无 CAPABILITIES.md 的项目不该为此扫一遍源码树
43
+ if (!existsSync(join(env.projectPath, CAPABILITIES_FILE_REL))) return [];
44
+ const population = collectPopulationFiles(env.projectPath, env.sourceRoots(), (root) =>
45
+ env.srcScan(root)
46
+ );
47
+ const caps = env.capabilities(population);
48
+ return caps ? caps.verdict.deadEntries : [];
58
49
  } catch {
59
50
  return [];
60
51
  }
@@ -71,18 +62,19 @@ function findDeadCapabilityEntries(projectPath: string, env: CheckEnv): string[]
71
62
  *
72
63
  * 全部缺失 → 项目未采用该约定,调用方应 skip 而非评估内置默认配置。
73
64
  */
74
- function hasFreshnessTargets(projectPath: string): boolean {
75
- if (existsSync(join(projectPath, 'CAPABILITIES.md'))) return true;
65
+ function hasFreshnessTargets(env: CheckEnv): boolean {
66
+ const projectPath = env.projectPath;
67
+ if (existsSync(join(projectPath, CAPABILITIES_FILE_REL))) return true;
76
68
  if (existsSync(join(projectPath, 'CHANGELOG.md')) || existsSync(join(projectPath, 'CHANGELOG'))) {
77
69
  return true;
78
70
  }
79
71
 
80
- const governance = getGovernanceConfig(projectPath);
72
+ const governance = getGovernanceConfig(env);
81
73
  if (governance?.doc_freshness?.checks && governance.doc_freshness.checks.length > 0) {
82
74
  return true;
83
75
  }
84
76
 
85
- return resolveContextFiles(projectPath).state === 'enabled';
77
+ return resolveContextFiles(env).state === 'enabled';
86
78
  }
87
79
 
88
80
  export const docsFreshness: ConstraintCheck = {
@@ -91,10 +83,10 @@ export const docsFreshness: ConstraintCheck = {
91
83
  const projectPath = env.projectPath;
92
84
 
93
85
  // ADR-0001 存在性探测:项目无任何 freshness 配置/目标 → skip(不计 pass/fail)
94
- if (!hasFreshnessTargets(projectPath)) return 'skip';
86
+ if (!hasFreshnessTargets(env)) return 'skip';
95
87
 
96
88
  // Step 1: 文件表格式 — 登记的条目(文件+目录)是否仍存在(ADR-0009)
97
- const deadEntries = findDeadCapabilityEntries(projectPath, env);
89
+ const deadEntries = findDeadCapabilityEntries(env);
98
90
  if (deadEntries.length > 0) {
99
91
  // 证据通道点名条目(harness#119):此前是 console.error 侧信道(2026-08-08 studio
100
92
  // CI 4 连红时的临时办法),CLI 结构化输出与 trace 两头都拿不到,
@@ -107,11 +99,11 @@ export const docsFreshness: ConstraintCheck = {
107
99
 
108
100
  // Step 2: 能力清单格式 + CLAUDE.md + CHANGELOG — 通过 FreshnessRunner
109
101
  try {
110
- const freshnessConfig = getGovernanceConfig(projectPath)?.doc_freshness;
102
+ const freshnessConfig = getGovernanceConfig(env)?.doc_freshness;
111
103
 
112
104
  // context_files 三态统一口径(工单 84):约定已立但无目标(enabled 但
113
105
  // required_dirs 缺失/空)→ skip,与 context_doc_sync 同构;不再静默放行
114
- const contextFiles = resolveContextFiles(projectPath);
106
+ const contextFiles = resolveContextFiles(env);
115
107
  if (contextFiles.state === 'enabled-empty') return 'skip';
116
108
  const requiredDirs = contextFiles.state === 'enabled' ? contextFiles.dirs : undefined;
117
109
 
@@ -119,9 +111,12 @@ export const docsFreshness: ConstraintCheck = {
119
111
  let results: FreshnessCheckResult[];
120
112
 
121
113
  if (freshnessConfig?.checks && freshnessConfig.checks.length > 0) {
122
- results = runner.runAll(freshnessConfig, projectPath, { requiredDirs });
114
+ results = runner.runAll(freshnessConfig, projectPath, { requiredDirs, sourceRoots: () => env.sourceRoots() });
123
115
  } else {
124
- results = runner.runAll({ checks: getBuiltInDocFreshnessConfig() }, projectPath, { requiredDirs });
116
+ results = runner.runAll({ checks: getBuiltInDocFreshnessConfig() }, projectPath, {
117
+ requiredDirs,
118
+ sourceRoots: () => env.sourceRoots(),
119
+ });
125
120
  }
126
121
 
127
122
  const failed = results.filter(r => !r.pass);
@@ -38,7 +38,7 @@ export const governancePresence: ConstraintCheck = {
38
38
  // 存在性探测:无 harness 配置 = 未采用治理约定 → skip(不计 pass/fail)
39
39
  let adopted = false;
40
40
  try {
41
- adopted = loadRawProjectConfig(projectPath) !== undefined;
41
+ adopted = loadRawProjectConfig(env) !== undefined;
42
42
  } catch {
43
43
  adopted = false;
44
44
  }
@@ -47,10 +47,14 @@ export const governancePresence: ConstraintCheck = {
47
47
  if (hasGovernancePreserveBlock(join(projectPath, 'AGENTS.md'))) return true;
48
48
  if (hasClaudeGovernance(join(projectPath, 'CLAUDE.md'))) return true;
49
49
 
50
- console.error(
51
- '[governance_presence] 治理契约缺失:AGENTS.md 无非空 PRESERVE:governance 段,' +
52
- '且 CLAUDE.md 无 Governance Rules 块——约束正本静默丢失,请恢复其一'
53
- );
54
- return false;
50
+ // 证据随判定一并返回(ADR-0016 补迁):此前这里是 console.error 侧信道——
51
+ // 只进本地 stderr,进不了 CLI 结论块与 trace,铁律拦截时用户看不到该恢复哪个正本
52
+ return {
53
+ pass: false,
54
+ evidence: [
55
+ '治理契约缺失:AGENTS.md 无非空 PRESERVE:governance 段,CLAUDE.md 也无 Governance Rules 块(正本静默丢失)',
56
+ '修复: 恢复其一(重跑 `harness init` 会同步注入段)',
57
+ ],
58
+ };
55
59
  },
56
60
  };
@@ -6,18 +6,20 @@
6
6
  */
7
7
 
8
8
  import type { ConstraintContext } from '../../../types/constraint';
9
+ import { createRunEnv, type RunEnv } from '../run-env';
9
10
 
10
11
  /**
11
- * 检查环境:单次 run 内共享的上下文与 memoized I/O
12
+ * 检查环境:一次 run 内共享的观察面与证据提供者(ADR-0023 决策 1)
12
13
  *
13
- * - stagedDiff/stagedDiffNames:run git 命令至多一次(工单 18)
14
+ * = `RunEnv`(项目上行数据的读取:config.yml / trace 尾部 / 源根,run 内至多一次)
15
+ * + `context` + git/扫描证据。前者不含 context,故只能派生不能合并成一个对象。
16
+ *
17
+ * - stagedDiff/stagedDiffNames:run 内 git 命令至多一次(工单 18 / #87)
14
18
  * - srcScan:run 内同根源码扫描至多一次(CheckCache)
15
19
  */
16
- export interface CheckEnv {
20
+ export interface CheckEnv extends RunEnv {
17
21
  /** 约束上下文(operation/changedFiles/各类证据标志) */
18
22
  context: ConstraintContext;
19
- /** 项目根路径(context.projectPath || process.cwd()) */
20
- projectPath: string;
21
23
  /** staged 全量 diff(run 内 memoized) */
22
24
  stagedDiff(): Promise<string>;
23
25
  /** staged 变更文件名列表(run 内 memoized) */
@@ -48,24 +50,28 @@ export interface EvidenceProviders {
48
50
  * - 'none' = 显式不接证据:证据函数返回空;evidence flag 未接线的
49
51
  * checker 按契约返回 'skip'(见 contextEvidenceFlag),直接读空
50
52
  * 证据的 checker 在自然输入下判定
53
+ * - runEnv = 本 run 的运行级观察面(ADR-0023):传入即与 context-builder 及
54
+ * 其余 checker 共用同一份上行数据读取;不传则自造一枚,只服务本次调用
51
55
  *
52
56
  * studio 侧若需 git 证据(#129),传真实 providers 即可。
53
57
  */
54
58
  export function buildCheckEnv(
55
59
  context: ConstraintContext,
56
- evidence: EvidenceProviders | 'none'
60
+ evidence: EvidenceProviders | 'none',
61
+ runEnv?: RunEnv
57
62
  ): CheckEnv {
58
63
  const projectPath = context.projectPath || process.cwd();
64
+ const run = runEnv ?? createRunEnv(projectPath);
59
65
  if (evidence === 'none') {
60
66
  return {
67
+ ...run,
61
68
  context,
62
- projectPath,
63
69
  stagedDiff: async () => '',
64
70
  stagedDiffNames: async () => '',
65
71
  srcScan: () => [],
66
72
  };
67
73
  }
68
- return { context, projectPath, ...evidence };
74
+ return { ...run, context, ...evidence };
69
75
  }
70
76
 
71
77
  /**
@@ -8,14 +8,16 @@
8
8
  * 架构评审 #87:本模块只做装配不做取证——git 证据一律经 git-evidence
9
9
  * adapter 取(缺省真 git adapter,调用方可注入与 checker 层同源的那一份),
10
10
  * 因此此处不再有 child_process / raw execSync。
11
+ *
12
+ * ADR-0023:同理,trace 记录与源码根探测改经运行级观察面 `RunEnv` 取——
13
+ * 此前本模块的两个证据探测各自整读一次 traces.log、detectTrigger 与 checker 层
14
+ * 各探一次源码根,同一次运行内重复读同一批文件。缺省自造一份 env,调用方(CLI check)
15
+ * 注入即全 run 共用。
11
16
  */
12
17
 
13
18
  import * as fs from 'fs';
14
19
  import * as path from 'path';
15
- import { detectSourceRoots } from '../../utils/detect-source-roots';
16
- import { readJsonl } from '../../utils/jsonl';
17
- import { DEFAULT_TRACE_FILE } from '../../types/trace';
18
- import type { ExecutionTrace } from '../../types/trace';
20
+ import { createRunEnv, TRACE_TAIL_WINDOW, type RunEnv } from './run-env';
19
21
  import type { ConstraintContext, ConstraintTrigger } from '../../types/constraint';
20
22
  import { createGitEvidence, splitFileNames, type GitEvidence } from './git-evidence';
21
23
 
@@ -51,6 +53,8 @@ export function detectTrigger(
51
53
  trigger?: ConstraintTrigger;
52
54
  projectPath?: string;
53
55
  evidence?: GitEvidence;
56
+ /** 运行级观察面(ADR-0023):注入即与其余消费方共用同一份源根探测 */
57
+ runEnv?: RunEnv;
54
58
  }
55
59
  ): ConstraintTrigger | ConstraintTrigger[] {
56
60
  if (options.trigger) return options.trigger;
@@ -62,7 +66,7 @@ export function detectTrigger(
62
66
  // pre-commit 场景下变更含代码文件 → 附加 code_implementation 推断
63
67
  const hasCodeChange = changedFiles.some(f => CODE_FILE_REGEX.test(f));
64
68
  const projectPath = options.projectPath || process.cwd();
65
- const sourceRoots = detectSourceRoots(projectPath);
69
+ const sourceRoots = (options.runEnv ?? createRunEnv(projectPath)).sourceRoots();
66
70
  const hasModuleChange = changedFiles.some(f =>
67
71
  sourceRoots.some(root => f.startsWith(root + '/') || f.startsWith(root + '\\')) && !f.includes('__tests__')
68
72
  );
@@ -85,17 +89,14 @@ export function detectTrigger(
85
89
  }
86
90
 
87
91
  /**
88
- * 检测是否有失败的测试记录
89
- * 扫描 trace 文件(DEFAULT_TRACE_FILE)中最近的记录
92
+ * 检测是否有失败的测试记录(取运行级观察面的最近 20 条)
90
93
  */
91
- export async function detectFailingTest(projectPath: string): Promise<boolean> {
94
+ async function detectFailingTest(env: RunEnv): Promise<boolean> {
92
95
  try {
93
- const traceFile = path.join(projectPath, DEFAULT_TRACE_FILE);
94
- // 坏行策略:skip(原逐行 catch→false 语义不变);只 parse 最近 20 行
95
- // 计数去向:豁免(harness#100)——布尔证据探测,坏行只会让证据变少(判定方向保守),
96
- // 消费面是 check pass/fail 判定,没有可挂计数的输出位
97
- const { records } = readJsonl<ExecutionTrace>(traceFile, 'skip', { tail: 20 });
98
- return records.some(trace => trace.result === 'fail');
96
+ // 坏行策略与计数去向见 run-env 的读点(ADR-0023 合并两处独立 tail 读为一份窗口)
97
+ return env
98
+ .traceTail(TRACE_TAIL_WINDOW)
99
+ .records.some(trace => trace.result === 'fail');
99
100
  } catch {
100
101
  return false;
101
102
  }
@@ -123,19 +124,18 @@ export function detectRootCauseInvestigation(projectPath: string): boolean {
123
124
  return false;
124
125
  }
125
126
 
127
+ /** 验证证据的尾部窗口(工单 23 原口径:只看最近 10 条) */
128
+ const VERIFICATION_EVIDENCE_TAIL = 10;
129
+
126
130
  /**
127
- * 检测是否有验证证据
128
- * 检查 trace 文件(DEFAULT_TRACE_FILE)中最近的成功验证记录
131
+ * 检测是否有验证证据(取运行级观察面的最近 10 条)
129
132
  */
130
- export async function detectVerificationEvidence(projectPath: string): Promise<boolean> {
133
+ async function detectVerificationEvidence(env: RunEnv): Promise<boolean> {
131
134
  try {
132
- const traceFile = path.join(projectPath, DEFAULT_TRACE_FILE);
133
- // 坏行策略:skip(原逐行 catch→false 语义不变);只 parse 最近 10 行
134
135
  // tail 在 parse 之前截断 → 坏行会占用尾部槽位(#82 裁决范围外的既有口径,本票不改)
135
- // 计数去向:豁免(harness#100)——同 detectFailingTest:布尔证据探测无计数输出位,
136
- // 坏行只会让证据变少
137
- const { records } = readJsonl<ExecutionTrace>(traceFile, 'skip', { tail: 10 });
138
- return records.some(trace => trace.result === 'pass');
136
+ return env
137
+ .traceTail(VERIFICATION_EVIDENCE_TAIL)
138
+ .records.some(trace => trace.result === 'pass');
139
139
  } catch {
140
140
  return false;
141
141
  }
@@ -191,17 +191,26 @@ export function detectReuseCheck(projectPath: string): boolean {
191
191
  *
192
192
  * options.evidence(#87):git 证据适配器。调用方(CLI check)注入同一实例给
193
193
  * checkConstraints,即可让 context-builder 与 checker 层共用同一证据来源。
194
+ * options.runEnv(ADR-0023):运行级观察面。注入即本函数内的源根探测与两处 trace
195
+ * 证据探测与其余消费方共用同一份读取,缺省自造一份(只服务本次调用)。
194
196
  */
195
197
  export async function buildConstraintContext(options: {
196
198
  projectPath?: string;
197
199
  staged: boolean;
198
200
  trigger?: ConstraintTrigger;
199
201
  evidence?: GitEvidence;
202
+ runEnv?: RunEnv;
200
203
  }): Promise<ConstraintContext> {
201
204
  const projectPath = options.projectPath || process.cwd();
205
+ const runEnv = options.runEnv ?? createRunEnv(projectPath);
202
206
  const evidence = options.evidence ?? createGitEvidence(projectPath);
203
207
  const changedFiles = splitFileNames(evidence.changedFileNames(options.staged));
204
- const inferred = detectTrigger(changedFiles, { trigger: options.trigger, projectPath, evidence });
208
+ const inferred = detectTrigger(changedFiles, {
209
+ trigger: options.trigger,
210
+ projectPath,
211
+ evidence,
212
+ runEnv,
213
+ });
205
214
  const triggers = Array.isArray(inferred) ? inferred : [inferred];
206
215
 
207
216
  return {
@@ -210,9 +219,9 @@ export async function buildConstraintContext(options: {
210
219
  projectPath,
211
220
  changedFiles,
212
221
  hasTest: changedFiles.some(f => f.includes('.test.') || f.includes('.spec.')),
213
- hasFailingTest: await detectFailingTest(projectPath),
222
+ hasFailingTest: await detectFailingTest(runEnv),
214
223
  hasRootCauseInvestigation: detectRootCauseInvestigation(projectPath),
215
- hasVerificationEvidence: await detectVerificationEvidence(projectPath),
224
+ hasVerificationEvidence: await detectVerificationEvidence(runEnv),
216
225
  hasReuseCheck: detectReuseCheck(projectPath),
217
226
  hasRequirement: detectRequirement(projectPath),
218
227
  };