@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
@@ -40,7 +40,7 @@ import { getConstraint } from '../../core/constraints/definitions';
40
40
  import { renderConstraintsSection, CONSTRAINTS_START_MARKER, CONSTRAINTS_END_MARKER } from '../../core/constraints/injection-renderer';
41
41
  import { replaceStandaloneRange, resolveInjectionTarget } from '../../core/constraints/injection-writer';
42
42
  import { getEffectiveConstraints } from '../../core/effective-constraints';
43
- import { loadRawProjectConfig, ProjectConfigLoader } from '../../core/project-config-loader';
43
+ import { isConstraintRetired, ProjectConfigLoader } from '../../core/project-config-loader';
44
44
  import { getHarnessPackageVersion } from '../../utils/package-version';
45
45
  import { FileKnowledgeStore } from '../../knowledge/store';
46
46
  import type { KnowledgeEntry } from '../../knowledge/types';
@@ -97,8 +97,14 @@ interface RetireTargetInfo {
97
97
 
98
98
  /**
99
99
  * 查找约束定义(内置 definitions + 项目 custom-constraints)
100
+ *
101
+ * loader 由调用方给(一次退役一份观察面,见 retireConstraint):本函数只读它的装载结果,
102
+ * 不再自造 ProjectConfigLoader。
100
103
  */
101
- function findRetireTarget(projectRoot: string, id: string): RetireTargetInfo | undefined {
104
+ function findRetireTarget(
105
+ loader: ProjectConfigLoader,
106
+ id: string
107
+ ): RetireTargetInfo | undefined {
102
108
  const builtIn = getConstraint(id);
103
109
  if (builtIn) {
104
110
  return {
@@ -112,8 +118,6 @@ function findRetireTarget(projectRoot: string, id: string): RetireTargetInfo | u
112
118
  };
113
119
  }
114
120
 
115
- const loader = new ProjectConfigLoader(projectRoot);
116
- loader.load();
117
121
  const custom = loader.getCustomConstraints()[id];
118
122
  if (custom) {
119
123
  const level = custom.level || 'guideline';
@@ -132,52 +136,20 @@ function findRetireTarget(projectRoot: string, id: string): RetireTargetInfo | u
132
136
  }
133
137
 
134
138
  /**
135
- * config.yml 退役段(ADR-0001 决策 5
139
+ * YAML 条目的读-改-写单点(harness#137
136
140
  *
137
- * js-yaml 不保留注释:原文件含注释行时重写会丢失,console 说明。
141
+ * 内置与 custom 两处退役落点原本是两段同型的读-改-写,只差键路径与 patch 内容。
142
+ * js-yaml 不保留注释:原文件含注释行时重写会丢失,console 说明(`label` 是给用户看的
143
+ * 文件名,与合并前两处逐字一致)。落盘字节由 `__tests__/constraints-retire.test.ts`
144
+ * 的逐字节冻结用例钉住——合并属内部重构,对外产物不得漂移。
138
145
  */
139
- function writeRetireConfig(
140
- projectRoot: string,
146
+ function setYamlEntry(
147
+ filePath: string,
148
+ label: string,
149
+ section: string,
141
150
  id: string,
142
- retiredMeta: { at: string; reason: string; stats: { total: number; fail: number; failRate: number } }
151
+ patch: Record<string, unknown>
143
152
  ): void {
144
- const configPath = path.join(projectRoot, '.harness', 'config.yml');
145
-
146
- let raw: Record<string, unknown> = {};
147
- let hadComments = false;
148
- if (fs.existsSync(configPath)) {
149
- const original = fs.readFileSync(configPath, 'utf-8');
150
- hadComments = original.split('\n').some(l => l.trimStart().startsWith('#'));
151
- raw = (yaml.load(original) as Record<string, unknown>) ?? {};
152
- }
153
-
154
- const constraints = (raw.constraints ?? {}) as Record<string, unknown>;
155
- const prev = (constraints[id] ?? {}) as Record<string, unknown>;
156
- constraints[id] = { ...prev, enabled: false, retired: retiredMeta };
157
- raw.constraints = constraints;
158
-
159
- fs.mkdirSync(path.dirname(configPath), { recursive: true });
160
- fs.writeFileSync(configPath, yaml.dump(raw, { lineWidth: 120 }), 'utf-8');
161
-
162
- if (hadComments) {
163
- console.log(chalk.yellow(' ⚠️ config.yml 已重写:js-yaml 不保留原文件注释'));
164
- }
165
- }
166
-
167
- /**
168
- * 写 custom-constraints.yml 退役段(studio#82 D6 统一落点)
169
- *
170
- * 在 custom_constraints.<id> 条目内追加 retired 元数据,保留规则原文。
171
- * js-yaml 不保留注释:原文件含注释行时重写会丢失,console 说明。
172
- */
173
- function writeCustomRetireYml(
174
- projectRoot: string,
175
- fileName: string,
176
- id: string,
177
- retiredMeta: { at: string; reason: string; stats: { total: number; fail: number; failRate: number } }
178
- ): void {
179
- const filePath = path.join(projectRoot, '.harness', fileName);
180
-
181
153
  let raw: Record<string, unknown> = {};
182
154
  let hadComments = false;
183
155
  if (fs.existsSync(filePath)) {
@@ -186,16 +158,16 @@ function writeCustomRetireYml(
186
158
  raw = (yaml.load(original) as Record<string, unknown>) ?? {};
187
159
  }
188
160
 
189
- const customs = (raw.custom_constraints ?? {}) as Record<string, Record<string, unknown>>;
190
- const prev = customs[id] ?? {};
191
- customs[id] = { ...prev, retired: retiredMeta };
192
- raw.custom_constraints = customs;
161
+ const entries = (raw[section] ?? {}) as Record<string, unknown>;
162
+ const prev = (entries[id] ?? {}) as Record<string, unknown>;
163
+ entries[id] = { ...prev, ...patch };
164
+ raw[section] = entries;
193
165
 
194
166
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
195
167
  fs.writeFileSync(filePath, yaml.dump(raw, { lineWidth: 120 }), 'utf-8');
196
168
 
197
169
  if (hadComments) {
198
- console.log(chalk.yellow(' ⚠️ custom-constraints.yml 已重写:js-yaml 不保留原文件注释'));
170
+ console.log(chalk.yellow(` ⚠️ ${label} 已重写:js-yaml 不保留原文件注释`));
199
171
  }
200
172
  }
201
173
 
@@ -293,7 +265,13 @@ export function retireConstraint(
293
265
  const iso = now.toISOString();
294
266
  const reason = options.reason ?? '';
295
267
 
296
- const target = findRetireTarget(projectRoot, id);
268
+ // 一次退役一份观察面(ADR-0023 决策 2):定义查找、already_retired 判定与 custom 文件名
269
+ // 解析共用这一份装载结果。此前同一次调用 new 了 2–3 枚加载器、各带一次 load()(harness#137)。
270
+ // 只覆盖写盘**之前**的读取:写盘后 syncGovernanceInjection 必须读到新状态,另起观察面。
271
+ const loader = new ProjectConfigLoader(projectRoot);
272
+ loader.load();
273
+
274
+ const target = findRetireTarget(loader, id);
297
275
  const emptyStats = { total: 0, fail: 0, failRate: 0 };
298
276
  const landing: RetireResult['landing'] =
299
277
  target?.source === 'custom' ? 'custom-constraints.yml' : 'config.yml';
@@ -301,17 +279,12 @@ export function retireConstraint(
301
279
  return { id, status: 'unknown_id', isIronLaw: false, landing, stats: emptyStats, injectionSynced: false };
302
280
  }
303
281
 
304
- // 已退役保护:内置看 config.yml constraints.<id>.enabled === false;
305
- // custom 看 yml 条目 retired 元数据(历史落点 config.yml enabled:false 同样保护)
306
- const rawConfig = loadRawProjectConfig(projectRoot);
307
- const existing = (rawConfig?.constraints as Record<string, { enabled?: boolean; retired?: unknown }> | undefined)?.[id];
308
- if (target.source === 'custom') {
309
- const loader = new ProjectConfigLoader(projectRoot);
310
- loader.load();
311
- if (loader.getCustomConstraints()[id]?.retired || existing?.enabled === false) {
312
- return { id, status: 'already_retired', isIronLaw: target.isIronLaw, landing, stats: emptyStats, injectionSynced: false };
313
- }
314
- } else if (existing?.enabled === false) {
282
+ // 已退役保护:判定单点在 core/project-config-loader isConstraintRetired
283
+ // (内置看 config.yml enabled:false;custom 看 yml 条目 retired 元数据,
284
+ // 历史落点 config.yml enabled:false 同样保护)
285
+ const disabledInConfig = loader.getConfig().constraints?.[id]?.enabled === false;
286
+ const customDef = target.source === 'custom' ? loader.getCustomConstraints()[id] : undefined;
287
+ if (isConstraintRetired(customDef, disabledInConfig)) {
315
288
  return { id, status: 'already_retired', isIronLaw: target.isIronLaw, landing, stats: emptyStats, injectionSynced: false };
316
289
  }
317
290
 
@@ -327,14 +300,26 @@ export function retireConstraint(
327
300
  failRate: evaluated > 0 ? (usage!.fail / evaluated) : 0,
328
301
  };
329
302
 
330
- // 1. 落盘退役(custom → yml 条目 retired 段;内置 → config.yml,原文均保留)
303
+ // 1. 落盘退役(custom → yml 条目 retired 段;内置 → config.yml enabled:false + retired 段,
304
+ // 两处原文均保留)
305
+ const retiredMeta = { at: iso, reason, stats };
331
306
  if (target.source === 'custom') {
332
- const loader = new ProjectConfigLoader(projectRoot);
333
- loader.load();
334
307
  const customFile = loader.getConfig().custom_constraints_file ?? 'custom-constraints.yml';
335
- writeCustomRetireYml(projectRoot, customFile, id, { at: iso, reason, stats });
308
+ setYamlEntry(
309
+ path.join(projectRoot, '.harness', customFile),
310
+ 'custom-constraints.yml',
311
+ 'custom_constraints',
312
+ id,
313
+ { retired: retiredMeta }
314
+ );
336
315
  } else {
337
- writeRetireConfig(projectRoot, id, { at: iso, reason, stats });
316
+ setYamlEntry(
317
+ path.join(projectRoot, '.harness', 'config.yml'),
318
+ 'config.yml',
319
+ 'constraints',
320
+ id,
321
+ { enabled: false, retired: retiredMeta }
322
+ );
338
323
  }
339
324
 
340
325
  // 2. KnowledgeStore
@@ -454,10 +439,12 @@ export async function runRetireInteractive(
454
439
  selectedIds = [...new Set(selectedIds)];
455
440
  }
456
441
 
457
- // 逐条收集 reason + iron 二次确认
442
+ // 逐条收集 reason + iron 二次确认(一次交互一份装载结果:候选到确认之间不写盘)
443
+ const planLoader = new ProjectConfigLoader(projectRoot);
444
+ planLoader.load();
458
445
  const plan: { id: string; reason: string; source: RetireTargetInfo['source'] }[] = [];
459
446
  for (const id of selectedIds) {
460
- const target = findRetireTarget(projectRoot, id);
447
+ const target = findRetireTarget(planLoader, id);
461
448
  if (!target) {
462
449
  console.log(chalk.red(`❌ ${id}: 约束不存在,跳过`));
463
450
  continue;
@@ -9,6 +9,7 @@ import * as fs from 'fs/promises';
9
9
  import * as path from 'path';
10
10
  import { ContractGate } from '../../gates/contract';
11
11
  import { log, processIO, type CommandIO, type CommandResult } from '../command-contract';
12
+ import { reportGateDecision, reportGateError } from '../gate-command';
12
13
 
13
14
  export interface ContractOptions {
14
15
  /** 项目路径 */
@@ -52,55 +53,51 @@ export async function contract(
52
53
  });
53
54
 
54
55
  try {
55
- const result = await gate.check({
56
- projectPath,
57
- } as any);
58
-
59
- if (result.passed) {
60
- log(io);
61
- log(io, chalk.green('✅ 契约门控检查通过'));
62
-
63
- if (result.details) {
64
- log(io, chalk.gray(` Schema 有效: ✅`));
65
- if (result.details.endpoints) {
66
- log(io, chalk.gray(` 端点数: ${result.details.endpoints}`));
67
- }
68
- if (result.details.breakingChanges === false) {
69
- log(io, chalk.gray(` 破坏性变更: 无`));
70
- }
71
- }
72
- } else {
73
- log(io);
74
- log(io, chalk.red('❌ 契约门控检查失败'));
75
- log(io, chalk.red(` ${result.message}`));
76
-
77
- if (result.details?.errors) {
78
- log(io);
79
- log(io, chalk.red('验证错误:'));
80
- (result.details.errors as string[]).forEach((error: string) => {
81
- log(io, chalk.red(` - ${error}`));
82
- });
83
- }
84
-
85
- if (result.details?.breakingChanges) {
86
- log(io);
87
- log(io, chalk.red('破坏性变更:'));
88
- (result.details.breakingChanges as any[]).forEach((change: any) => {
89
- log(io, chalk.red(` - ${change.type}: ${change.path}`));
90
- if (change.description) {
91
- log(io, chalk.gray(` ${change.description}`));
56
+ const decision = await gate.evaluate({ projectPath });
57
+
58
+ return reportGateDecision(
59
+ io,
60
+ {
61
+ gateId: 'contract',
62
+ label: '契约门控',
63
+ onPass: (r) => {
64
+ if (!r.details) return [];
65
+ const lines = [chalk.gray(` Schema 有效: ✅`)];
66
+ if (r.details.endpoints) {
67
+ lines.push(chalk.gray(` 端点数: ${r.details.endpoints}`));
68
+ }
69
+ if (r.details.breakingChanges === false) {
70
+ lines.push(chalk.gray(` 破坏性变更: 无`));
71
+ }
72
+ return lines;
73
+ },
74
+ onFail: (r) => {
75
+ const lines: string[] = [];
76
+
77
+ if (r.details?.errors) {
78
+ lines.push('', chalk.red('验证错误:'));
79
+ (r.details.errors as string[]).forEach((issue: string) => {
80
+ lines.push(chalk.red(` - ${issue}`));
81
+ });
92
82
  }
93
- });
94
- }
95
83
 
96
- return { kind: 'fail', reason: `contract gate denied: ${result.message}` };
97
- }
98
- return { kind: 'ok' };
99
- } catch (error: any) {
100
- log(io);
101
- log(io, chalk.red('❌ 契约门控检查出错'));
102
- log(io, chalk.red(` ${error.message}`));
103
- return { kind: 'fail', reason: `contract gate error: ${error.message}` };
84
+ if (r.details?.breakingChanges) {
85
+ lines.push('', chalk.red('破坏性变更:'));
86
+ (r.details.breakingChanges as any[]).forEach((change: any) => {
87
+ lines.push(chalk.red(` - ${change.type}: ${change.path}`));
88
+ if (change.description) {
89
+ lines.push(chalk.gray(` ${change.description}`));
90
+ }
91
+ });
92
+ }
93
+
94
+ return lines;
95
+ },
96
+ },
97
+ decision
98
+ );
99
+ } catch (error) {
100
+ return reportGateError(io, 'contract', '契约门控', error);
104
101
  }
105
102
  }
106
103
 
@@ -11,8 +11,12 @@
11
11
  * 子命令别名是数据(aliases),实参编组归各命令模块的具名导出
12
12
  * (那才是它的 interface/测试面);保证 --help/--version 懒加载不被破坏;
13
13
  * 注册表完整性断言(引用实现可解析)在 __tests__/registry.test.ts 构建/测试期校验。
14
+ * - 唯一例外 import:`utils/numeric-flag` 纯函数解析器(harness#154 口径条目指名的
15
+ * 数值旗帜唯一解析器)——非命令实现、零 IO,不破坏懒加载。
14
16
  */
15
17
 
18
+ import { requireNumericFlag } from '../../utils/numeric-flag';
19
+
16
20
  /**
17
21
  * 命令 CLI 选项元数据(直接映射 commander `.option()`)
18
22
  */
@@ -99,7 +103,9 @@ export const COMMAND_DEFINITIONS: CommandDefinition[] = [
99
103
  command: 'check',
100
104
  description: '检查铁律是否满足',
101
105
  options: [
102
- { flags: '-p, --preset <preset>', description: '预设名称', defaultValue: 'standard' },
106
+ // 不给缺省值:「没传 -p」与「传了 standard」必须可区分,否则生效集侧的覆盖规则恒触发、
107
+ // config.yml 的 preset 静默失效(漂移检测侧按 config.yml 算,两边就会稳定对不上)
108
+ { flags: '-p, --preset <preset>', description: '预设名称(缺省按项目 config.yml)' },
103
109
  { flags: '-s, --staged', description: '只检查暂存文件', defaultValue: false },
104
110
  { flags: '-t, --trigger <trigger>', description: '触发条件' },
105
111
  { flags: '--project-path <path>', description: '项目路径' },
@@ -143,10 +149,10 @@ export const COMMAND_DEFINITIONS: CommandDefinition[] = [
143
149
  options: [
144
150
  { flags: '-p, --preset <preset>', description: '预设名称 (strict/standard/relaxed)', defaultValue: 'standard' },
145
151
  { flags: '-g, --governance <level>', description: '治理级别 (minimal/standard/strict)' },
146
- { flags: '-t, --type <type>', description: '项目类型 (node-api/nextjs-app/python-api/custom)' },
147
152
  { flags: '--project-path <path>', description: '项目路径' },
148
153
  { flags: '--no-git-hooks', description: '不创建 Git hooks' },
149
- { flags: '--no-github-actions', description: '不创建 GitHub Actions' },
154
+ { flags: '--ci <platform>', description: '服务端 CI 接线平台 (github/gitlab/none);none = 不创建任何 CI 文件(治理 CI 面亦不建),缺省按 .harness/config.yml 的 ci.platform' },
155
+ { flags: '--no-github-actions', description: '不创建 GitHub Actions(已废弃:等价 --ci none)' },
150
156
  { flags: '--print-snippets', description: '只输出代码片段,不创建文件' },
151
157
  ],
152
158
  action: { module: 'init', export: 'init' },
@@ -331,9 +337,9 @@ export const COMMAND_DEFINITIONS: CommandDefinition[] = [
331
337
  projectPath: options.projectPath,
332
338
  export: options.export,
333
339
  json: options.json,
334
- zeroInterceptMin: parseInt(String(options.zeroInterceptMin), 10),
335
- noiseFailRate: parseFloat(String(options.noiseFailRate)),
336
- noiseMinTotal: parseInt(String(options.noiseMinTotal), 10),
340
+ zeroInterceptMin: requireNumericFlag('--zero-intercept-min', options.zeroInterceptMin as string | undefined, 'int'),
341
+ noiseFailRate: requireNumericFlag('--noise-fail-rate', options.noiseFailRate as string | undefined, 'float'),
342
+ noiseMinTotal: requireNumericFlag('--noise-min-total', options.noiseMinTotal as string | undefined, 'int'),
337
343
  }],
338
344
  },
339
345
  {
@@ -8,7 +8,8 @@ import chalk from 'chalk';
8
8
  import * as path from 'path';
9
9
  import { FailureRecorder } from '../../failure/recorder';
10
10
  import { DEFAULT_FAILURE_LOG_FILE } from '../../types/failure';
11
- import { log, processIO, type CommandIO, type CommandResult } from '../command-contract';
11
+ import { log, logError, processIO, type CommandIO, type CommandResult } from '../command-contract';
12
+ import { numericFlagMessage, parseNumericFlag } from '../../utils/numeric-flag';
12
13
 
13
14
  export interface FailureOptions {
14
15
  /** 项目路径 */
@@ -34,6 +35,20 @@ export async function failureList(
34
35
  options: FailureOptions & { limit?: number | string; type?: string; level?: string },
35
36
  io: CommandIO = processIO,
36
37
  ): Promise<CommandResult> {
38
+ // CLI 直传时 limit 为 commander 字符串值;程序内调用传 number(候选7:编组在命令函数)。
39
+ // 字符串形先过装配窄化(harness#154):脏输入 fail-loud 且不构造 recorder(零落盘),
40
+ // 原先 parseInt 出 NaN → falsy → 静默不截断。
41
+ let limit: number | undefined;
42
+ if (typeof options.limit === 'string') {
43
+ const parsed = parseNumericFlag(options.limit, 'int');
44
+ if (!parsed.ok) {
45
+ logError(io, numericFlagMessage('--limit', parsed.raw, 'int'));
46
+ return { kind: 'usage-error', reason: `failure list --limit 非法限制: "${parsed.raw}"` };
47
+ }
48
+ limit = parsed.value;
49
+ } else {
50
+ limit = options.limit;
51
+ }
37
52
  const recorder = getRecorder(options.projectPath);
38
53
 
39
54
  let records = await recorder.getHistory();
@@ -44,8 +59,6 @@ export async function failureList(
44
59
  if (options.level) {
45
60
  records = records.filter(r => r.level === options.level);
46
61
  }
47
- // CLI 直传时 limit 为 commander 字符串值;程序内调用传 number(候选7:编组在命令函数)
48
- const limit = typeof options.limit === 'string' ? parseInt(options.limit, 10) : options.limit;
49
62
  if (limit && limit > 0) {
50
63
  records = records.slice(-limit);
51
64
  }