@dommaker/harness 1.6.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (560) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/bin/harness.js +17 -1
  3. package/dist/agents/index.d.ts +6 -2
  4. package/dist/agents/index.d.ts.map +1 -1
  5. package/dist/agents/index.js +6 -16
  6. package/dist/agents/index.js.map +1 -1
  7. package/dist/cli/commands/__tests__/gate-decision.d.ts +18 -0
  8. package/dist/cli/commands/__tests__/gate-decision.d.ts.map +1 -0
  9. package/dist/cli/commands/__tests__/gate-decision.js +26 -0
  10. package/dist/cli/commands/__tests__/gate-decision.js.map +1 -0
  11. package/dist/cli/commands/acceptance.d.ts.map +1 -1
  12. package/dist/cli/commands/acceptance.js +17 -28
  13. package/dist/cli/commands/acceptance.js.map +1 -1
  14. package/dist/cli/commands/check.d.ts +11 -3
  15. package/dist/cli/commands/check.d.ts.map +1 -1
  16. package/dist/cli/commands/check.js +26 -11
  17. package/dist/cli/commands/check.js.map +1 -1
  18. package/dist/cli/commands/command.d.ts +0 -1
  19. package/dist/cli/commands/command.d.ts.map +1 -1
  20. package/dist/cli/commands/command.js +8 -6
  21. package/dist/cli/commands/command.js.map +1 -1
  22. package/dist/cli/commands/constraints-retire.d.ts.map +1 -1
  23. package/dist/cli/commands/constraints-retire.js +36 -57
  24. package/dist/cli/commands/constraints-retire.js.map +1 -1
  25. package/dist/cli/commands/contract.d.ts.map +1 -1
  26. package/dist/cli/commands/contract.js +36 -42
  27. package/dist/cli/commands/contract.js.map +1 -1
  28. package/dist/cli/commands/definitions.d.ts +2 -0
  29. package/dist/cli/commands/definitions.d.ts.map +1 -1
  30. package/dist/cli/commands/definitions.js +11 -6
  31. package/dist/cli/commands/definitions.js.map +1 -1
  32. package/dist/cli/commands/failure.d.ts.map +1 -1
  33. package/dist/cli/commands/failure.js +16 -2
  34. package/dist/cli/commands/failure.js.map +1 -1
  35. package/dist/cli/commands/init.d.ts +14 -8
  36. package/dist/cli/commands/init.d.ts.map +1 -1
  37. package/dist/cli/commands/init.js +172 -364
  38. package/dist/cli/commands/init.js.map +1 -1
  39. package/dist/cli/commands/knowledge-view.d.ts +90 -0
  40. package/dist/cli/commands/knowledge-view.d.ts.map +1 -0
  41. package/dist/cli/commands/knowledge-view.js +198 -0
  42. package/dist/cli/commands/knowledge-view.js.map +1 -0
  43. package/dist/cli/commands/knowledge.d.ts +137 -52
  44. package/dist/cli/commands/knowledge.d.ts.map +1 -1
  45. package/dist/cli/commands/knowledge.js +534 -400
  46. package/dist/cli/commands/knowledge.js.map +1 -1
  47. package/dist/cli/commands/passes-gate.d.ts +4 -1
  48. package/dist/cli/commands/passes-gate.d.ts.map +1 -1
  49. package/dist/cli/commands/passes-gate.js +11 -2
  50. package/dist/cli/commands/passes-gate.js.map +1 -1
  51. package/dist/cli/commands/performance.d.ts.map +1 -1
  52. package/dist/cli/commands/performance.js +19 -31
  53. package/dist/cli/commands/performance.js.map +1 -1
  54. package/dist/cli/commands/report.d.ts.map +1 -1
  55. package/dist/cli/commands/report.js +2 -1
  56. package/dist/cli/commands/report.js.map +1 -1
  57. package/dist/cli/commands/review.d.ts.map +1 -1
  58. package/dist/cli/commands/review.js +13 -25
  59. package/dist/cli/commands/review.js.map +1 -1
  60. package/dist/cli/commands/scaffold-templates.d.ts +73 -0
  61. package/dist/cli/commands/scaffold-templates.d.ts.map +1 -0
  62. package/dist/cli/commands/scaffold-templates.js +424 -0
  63. package/dist/cli/commands/scaffold-templates.js.map +1 -0
  64. package/dist/cli/commands/scaffold.d.ts +105 -0
  65. package/dist/cli/commands/scaffold.d.ts.map +1 -0
  66. package/dist/cli/commands/scaffold.js +263 -0
  67. package/dist/cli/commands/scaffold.js.map +1 -0
  68. package/dist/cli/commands/security.d.ts.map +1 -1
  69. package/dist/cli/commands/security.js +22 -24
  70. package/dist/cli/commands/security.js.map +1 -1
  71. package/dist/cli/commands/spec-baseline-check.d.ts +43 -0
  72. package/dist/cli/commands/spec-baseline-check.d.ts.map +1 -1
  73. package/dist/cli/commands/spec-baseline-check.js +109 -34
  74. package/dist/cli/commands/spec-baseline-check.js.map +1 -1
  75. package/dist/cli/commands/sync-docs/context-syncer.d.ts +21 -2
  76. package/dist/cli/commands/sync-docs/context-syncer.d.ts.map +1 -1
  77. package/dist/cli/commands/sync-docs/context-syncer.js +112 -28
  78. package/dist/cli/commands/sync-docs/context-syncer.js.map +1 -1
  79. package/dist/cli/commands/sync-docs/index.d.ts +1 -1
  80. package/dist/cli/commands/sync-docs/index.d.ts.map +1 -1
  81. package/dist/cli/commands/sync-docs/index.js +86 -27
  82. package/dist/cli/commands/sync-docs/index.js.map +1 -1
  83. package/dist/cli/commands/sync-docs/project-reader.d.ts +24 -1
  84. package/dist/cli/commands/sync-docs/project-reader.d.ts.map +1 -1
  85. package/dist/cli/commands/sync-docs/project-reader.js +33 -7
  86. package/dist/cli/commands/sync-docs/project-reader.js.map +1 -1
  87. package/dist/cli/commands/validate.d.ts +0 -16
  88. package/dist/cli/commands/validate.d.ts.map +1 -1
  89. package/dist/cli/commands/validate.js +2 -97
  90. package/dist/cli/commands/validate.js.map +1 -1
  91. package/dist/cli/gate-command.d.ts +37 -0
  92. package/dist/cli/gate-command.d.ts.map +1 -0
  93. package/dist/cli/gate-command.js +64 -0
  94. package/dist/cli/gate-command.js.map +1 -0
  95. package/dist/completion-checkers/index.d.ts +1 -1
  96. package/dist/completion-checkers/index.d.ts.map +1 -1
  97. package/dist/completion-checkers/index.js +0 -15
  98. package/dist/completion-checkers/index.js.map +1 -1
  99. package/dist/context/knowledge-injector.d.ts +4 -2
  100. package/dist/context/knowledge-injector.d.ts.map +1 -1
  101. package/dist/context/knowledge-injector.js +13 -6
  102. package/dist/context/knowledge-injector.js.map +1 -1
  103. package/dist/core/constraints/agent-prompt-renderer.js +2 -2
  104. package/dist/core/constraints/agent-prompt-renderer.js.map +1 -1
  105. package/dist/core/constraints/capabilities-reconcile.d.ts +20 -0
  106. package/dist/core/constraints/capabilities-reconcile.d.ts.map +1 -1
  107. package/dist/core/constraints/capabilities-reconcile.js +26 -4
  108. package/dist/core/constraints/capabilities-reconcile.js.map +1 -1
  109. package/dist/core/constraints/check-cache.d.ts +1 -1
  110. package/dist/core/constraints/check-cache.js +1 -1
  111. package/dist/core/constraints/checker.d.ts +8 -3
  112. package/dist/core/constraints/checker.d.ts.map +1 -1
  113. package/dist/core/constraints/checker.js +30 -19
  114. package/dist/core/constraints/checker.js.map +1 -1
  115. package/dist/core/constraints/checkers/capability-sync.d.ts +3 -1
  116. package/dist/core/constraints/checkers/capability-sync.d.ts.map +1 -1
  117. package/dist/core/constraints/checkers/capability-sync.js +17 -24
  118. package/dist/core/constraints/checkers/capability-sync.js.map +1 -1
  119. package/dist/core/constraints/checkers/context-doc-sync.d.ts +1 -1
  120. package/dist/core/constraints/checkers/context-doc-sync.d.ts.map +1 -1
  121. package/dist/core/constraints/checkers/context-doc-sync.js +9 -6
  122. package/dist/core/constraints/checkers/context-doc-sync.js.map +1 -1
  123. package/dist/core/constraints/checkers/docs-freshness.d.ts.map +1 -1
  124. package/dist/core/constraints/checkers/docs-freshness.js +24 -30
  125. package/dist/core/constraints/checkers/docs-freshness.js.map +1 -1
  126. package/dist/core/constraints/checkers/governance-presence.d.ts.map +1 -1
  127. package/dist/core/constraints/checkers/governance-presence.js +10 -4
  128. package/dist/core/constraints/checkers/governance-presence.js.map +1 -1
  129. package/dist/core/constraints/checkers/types.d.ts +10 -6
  130. package/dist/core/constraints/checkers/types.d.ts.map +1 -1
  131. package/dist/core/constraints/checkers/types.js +7 -3
  132. package/dist/core/constraints/checkers/types.js.map +1 -1
  133. package/dist/core/constraints/context-builder.d.ts +11 -10
  134. package/dist/core/constraints/context-builder.d.ts.map +1 -1
  135. package/dist/core/constraints/context-builder.js +31 -27
  136. package/dist/core/constraints/context-builder.js.map +1 -1
  137. package/dist/core/constraints/context-reconcile.d.ts +75 -0
  138. package/dist/core/constraints/context-reconcile.d.ts.map +1 -0
  139. package/dist/core/constraints/context-reconcile.js +161 -0
  140. package/dist/core/constraints/context-reconcile.js.map +1 -0
  141. package/dist/core/constraints/doc-freshness/runner.d.ts +7 -0
  142. package/dist/core/constraints/doc-freshness/runner.d.ts.map +1 -1
  143. package/dist/core/constraints/doc-freshness/runner.js +8 -3
  144. package/dist/core/constraints/doc-freshness/runner.js.map +1 -1
  145. package/dist/core/constraints/git-evidence.js +1 -1
  146. package/dist/core/constraints/git-evidence.js.map +1 -1
  147. package/dist/core/constraints/injection-drift.d.ts +7 -2
  148. package/dist/core/constraints/injection-drift.d.ts.map +1 -1
  149. package/dist/core/constraints/injection-drift.js +13 -7
  150. package/dist/core/constraints/injection-drift.js.map +1 -1
  151. package/dist/core/constraints/run-env.d.ts +92 -0
  152. package/dist/core/constraints/run-env.d.ts.map +1 -0
  153. package/dist/core/constraints/run-env.js +175 -0
  154. package/dist/core/constraints/run-env.js.map +1 -0
  155. package/dist/core/constraints/triggers.d.ts +22 -0
  156. package/dist/core/constraints/triggers.d.ts.map +1 -0
  157. package/dist/core/constraints/triggers.js +31 -0
  158. package/dist/core/constraints/triggers.js.map +1 -0
  159. package/dist/core/effective-constraints.d.ts +13 -4
  160. package/dist/core/effective-constraints.d.ts.map +1 -1
  161. package/dist/core/effective-constraints.js +16 -6
  162. package/dist/core/effective-constraints.js.map +1 -1
  163. package/dist/core/effective-set.d.ts +8 -15
  164. package/dist/core/effective-set.d.ts.map +1 -1
  165. package/dist/core/effective-set.js +7 -12
  166. package/dist/core/effective-set.js.map +1 -1
  167. package/dist/core/index.d.ts +2 -1
  168. package/dist/core/index.d.ts.map +1 -1
  169. package/dist/core/index.js.map +1 -1
  170. package/dist/core/project-config-loader.d.ts +39 -17
  171. package/dist/core/project-config-loader.d.ts.map +1 -1
  172. package/dist/core/project-config-loader.js +51 -122
  173. package/dist/core/project-config-loader.js.map +1 -1
  174. package/dist/core/validators/check-handlers/http.d.ts +2 -2
  175. package/dist/core/validators/check-handlers/http.d.ts.map +1 -1
  176. package/dist/core/validators/check-handlers/http.js +12 -7
  177. package/dist/core/validators/check-handlers/http.js.map +1 -1
  178. package/dist/core/validators/index.d.ts +1 -1
  179. package/dist/core/validators/index.d.ts.map +1 -1
  180. package/dist/core/validators/passes-gate.d.ts.map +1 -1
  181. package/dist/core/validators/passes-gate.js +2 -2
  182. package/dist/core/validators/passes-gate.js.map +1 -1
  183. package/dist/failure/classifier.d.ts +1 -1
  184. package/dist/failure/classifier.d.ts.map +1 -1
  185. package/dist/failure/classifier.js +8 -8
  186. package/dist/failure/classifier.js.map +1 -1
  187. package/dist/failure/index.d.ts +2 -1
  188. package/dist/failure/index.d.ts.map +1 -1
  189. package/dist/failure/index.js +9 -17
  190. package/dist/failure/index.js.map +1 -1
  191. package/dist/failure/recorder.d.ts +1 -1
  192. package/dist/failure/recorder.d.ts.map +1 -1
  193. package/dist/gates/checker-gate.d.ts +2 -1
  194. package/dist/gates/checker-gate.d.ts.map +1 -1
  195. package/dist/gates/checker-gate.js +3 -2
  196. package/dist/gates/checker-gate.js.map +1 -1
  197. package/dist/gates/command.d.ts +10 -4
  198. package/dist/gates/command.d.ts.map +1 -1
  199. package/dist/gates/command.js +36 -62
  200. package/dist/gates/command.js.map +1 -1
  201. package/dist/gates/contract.d.ts.map +1 -1
  202. package/dist/gates/contract.js +0 -4
  203. package/dist/gates/contract.js.map +1 -1
  204. package/dist/gates/definitions.d.ts +2 -1
  205. package/dist/gates/definitions.d.ts.map +1 -1
  206. package/dist/gates/definitions.js +6 -5
  207. package/dist/gates/definitions.js.map +1 -1
  208. package/dist/gates/index.d.ts +0 -4
  209. package/dist/gates/index.d.ts.map +1 -1
  210. package/dist/gates/index.js +1 -6
  211. package/dist/gates/index.js.map +1 -1
  212. package/dist/gates/performance.d.ts.map +1 -1
  213. package/dist/gates/performance.js +0 -4
  214. package/dist/gates/performance.js.map +1 -1
  215. package/dist/gates/runner.d.ts +1 -1
  216. package/dist/gates/runner.js +1 -1
  217. package/dist/gates/security.d.ts +1 -1
  218. package/dist/gates/security.d.ts.map +1 -1
  219. package/dist/gates/security.js +5 -6
  220. package/dist/gates/security.js.map +1 -1
  221. package/dist/gates/types.d.ts +14 -17
  222. package/dist/gates/types.d.ts.map +1 -1
  223. package/dist/gates/types.js.map +1 -1
  224. package/dist/hooks/bootstrap.d.ts +6 -4
  225. package/dist/hooks/bootstrap.d.ts.map +1 -1
  226. package/dist/hooks/bootstrap.js +25 -13
  227. package/dist/hooks/bootstrap.js.map +1 -1
  228. package/dist/hooks/config.d.ts +6 -2
  229. package/dist/hooks/config.d.ts.map +1 -1
  230. package/dist/hooks/config.js +5 -1
  231. package/dist/hooks/config.js.map +1 -1
  232. package/dist/hooks/index.d.ts +1 -1
  233. package/dist/hooks/index.d.ts.map +1 -1
  234. package/dist/hooks/index.js +0 -15
  235. package/dist/hooks/index.js.map +1 -1
  236. package/dist/hooks/pipeline.d.ts.map +1 -1
  237. package/dist/hooks/pipeline.js +2 -4
  238. package/dist/hooks/pipeline.js.map +1 -1
  239. package/dist/hooks/registry.d.ts +11 -8
  240. package/dist/hooks/registry.d.ts.map +1 -1
  241. package/dist/hooks/registry.js +22 -7
  242. package/dist/hooks/registry.js.map +1 -1
  243. package/dist/hooks/types.d.ts +23 -7
  244. package/dist/hooks/types.d.ts.map +1 -1
  245. package/dist/index.d.ts +4 -4
  246. package/dist/index.d.ts.map +1 -1
  247. package/dist/index.js +3 -4
  248. package/dist/index.js.map +1 -1
  249. package/dist/knowledge/audit-scoring.d.ts +87 -0
  250. package/dist/knowledge/audit-scoring.d.ts.map +1 -0
  251. package/dist/knowledge/audit-scoring.js +470 -0
  252. package/dist/knowledge/audit-scoring.js.map +1 -0
  253. package/dist/knowledge/audit.d.ts +11 -59
  254. package/dist/knowledge/audit.d.ts.map +1 -1
  255. package/dist/knowledge/audit.js +47 -522
  256. package/dist/knowledge/audit.js.map +1 -1
  257. package/dist/knowledge/import.d.ts.map +1 -1
  258. package/dist/knowledge/import.js +2 -0
  259. package/dist/knowledge/import.js.map +1 -1
  260. package/dist/knowledge/index-generator.d.ts.map +1 -1
  261. package/dist/knowledge/index-generator.js +4 -5
  262. package/dist/knowledge/index-generator.js.map +1 -1
  263. package/dist/knowledge/index.d.ts +3 -2
  264. package/dist/knowledge/index.d.ts.map +1 -1
  265. package/dist/knowledge/index.js +3 -16
  266. package/dist/knowledge/index.js.map +1 -1
  267. package/dist/knowledge/ingest.js +1 -1
  268. package/dist/knowledge/ingest.js.map +1 -1
  269. package/dist/knowledge/lifecycle.d.ts.map +1 -1
  270. package/dist/knowledge/lifecycle.js +4 -2
  271. package/dist/knowledge/lifecycle.js.map +1 -1
  272. package/dist/knowledge/migration.d.ts +3 -0
  273. package/dist/knowledge/migration.d.ts.map +1 -1
  274. package/dist/knowledge/migration.js +8 -2
  275. package/dist/knowledge/migration.js.map +1 -1
  276. package/dist/knowledge/query.d.ts +6 -0
  277. package/dist/knowledge/query.d.ts.map +1 -1
  278. package/dist/knowledge/query.js +8 -2
  279. package/dist/knowledge/query.js.map +1 -1
  280. package/dist/knowledge/reference-tracker.d.ts.map +1 -1
  281. package/dist/knowledge/reference-tracker.js +4 -6
  282. package/dist/knowledge/reference-tracker.js.map +1 -1
  283. package/dist/knowledge/store.d.ts +22 -16
  284. package/dist/knowledge/store.d.ts.map +1 -1
  285. package/dist/knowledge/store.js +53 -12
  286. package/dist/knowledge/store.js.map +1 -1
  287. package/dist/knowledge/tree-walker.d.ts +19 -0
  288. package/dist/knowledge/tree-walker.d.ts.map +1 -0
  289. package/dist/knowledge/tree-walker.js +30 -0
  290. package/dist/knowledge/tree-walker.js.map +1 -0
  291. package/dist/knowledge/types.d.ts +16 -0
  292. package/dist/knowledge/types.d.ts.map +1 -1
  293. package/dist/monitoring/traces.d.ts +5 -3
  294. package/dist/monitoring/traces.d.ts.map +1 -1
  295. package/dist/monitoring/traces.js +19 -5
  296. package/dist/monitoring/traces.js.map +1 -1
  297. package/dist/test-setup/jsonl-fake-fs.d.ts +30 -0
  298. package/dist/test-setup/jsonl-fake-fs.d.ts.map +1 -0
  299. package/dist/test-setup/jsonl-fake-fs.js +49 -0
  300. package/dist/test-setup/jsonl-fake-fs.js.map +1 -0
  301. package/dist/tools/index.d.ts +4 -1
  302. package/dist/tools/index.d.ts.map +1 -1
  303. package/dist/tools/index.js +7 -15
  304. package/dist/tools/index.js.map +1 -1
  305. package/dist/types/checkpoint.d.ts +5 -0
  306. package/dist/types/checkpoint.d.ts.map +1 -1
  307. package/dist/types/passes-gate.d.ts +0 -13
  308. package/dist/types/passes-gate.d.ts.map +1 -1
  309. package/dist/types/project-config.d.ts +18 -0
  310. package/dist/types/project-config.d.ts.map +1 -1
  311. package/dist/types/trace.d.ts +13 -4
  312. package/dist/types/trace.d.ts.map +1 -1
  313. package/dist/types/trace.js +4 -3
  314. package/dist/types/trace.js.map +1 -1
  315. package/dist/utils/exec.d.ts +4 -27
  316. package/dist/utils/exec.d.ts.map +1 -1
  317. package/dist/utils/exec.js +4 -94
  318. package/dist/utils/exec.js.map +1 -1
  319. package/dist/utils/jsonl.d.ts +17 -7
  320. package/dist/utils/jsonl.d.ts.map +1 -1
  321. package/dist/utils/jsonl.js +144 -17
  322. package/dist/utils/jsonl.js.map +1 -1
  323. package/dist/utils/numeric-flag.d.ts +44 -0
  324. package/dist/utils/numeric-flag.d.ts.map +1 -0
  325. package/dist/utils/numeric-flag.js +62 -0
  326. package/dist/utils/numeric-flag.js.map +1 -0
  327. package/package.json +1 -1
  328. package/src/CONTEXT.md +5 -2
  329. package/src/__tests__/acceptance-gate.test.ts +7 -4
  330. package/src/__tests__/checker-extra.test.ts +3 -2
  331. package/src/__tests__/checker.test.ts +4 -3
  332. package/src/__tests__/checkpoint.test.ts +26 -9
  333. package/src/__tests__/context-files-resolution.test.ts +29 -15
  334. package/src/__tests__/contract-gate.test.ts +19 -40
  335. package/src/__tests__/error-classifier.test.ts +1 -1
  336. package/src/__tests__/exec.test.ts +45 -107
  337. package/src/__tests__/failure-recorder.test.ts +7 -5
  338. package/src/__tests__/hooks-pipeline.test.ts +34 -47
  339. package/src/__tests__/layering.test.ts +217 -25
  340. package/src/__tests__/passes-gate.test.ts +9 -4
  341. package/src/__tests__/performance-gate.test.ts +3 -15
  342. package/src/__tests__/project-config-loader-extra.test.ts +31 -57
  343. package/src/__tests__/project-config-loader.test.ts +6 -3
  344. package/src/__tests__/public-exports.test.ts +27 -6
  345. package/src/__tests__/public-type-surface.test.ts +360 -0
  346. package/src/__tests__/public-value-surface.test.ts +182 -0
  347. package/src/__tests__/review-gate.test.ts +4 -6
  348. package/src/__tests__/security-gate.test.ts +5 -20
  349. package/src/__tests__/skip-semantics.test.ts +5 -3
  350. package/src/__tests__/spec-validator.test.ts +3 -2
  351. package/src/__tests__/sub-barrels-explicit.test.ts +87 -0
  352. package/src/__tests__/test-fixture-hygiene.test.ts +53 -0
  353. package/src/__tests__/trace-analyzer-extra.test.ts +5 -3
  354. package/src/__tests__/trace-analyzer.test.ts +5 -3
  355. package/src/__tests__/trace-collector.test.ts +5 -3
  356. package/src/agents/index.ts +13 -2
  357. package/src/cli/__tests__/gate-command.test.ts +162 -0
  358. package/src/cli/commands/CONTEXT.md +29 -5
  359. package/src/cli/commands/__tests__/acceptance.test.ts +24 -25
  360. package/src/cli/commands/__tests__/bin-exit-mapping.test.ts +15 -0
  361. package/src/cli/commands/__tests__/check-drift.test.ts +42 -1
  362. package/src/cli/commands/__tests__/check-read-count.test.ts +167 -0
  363. package/src/cli/commands/__tests__/check-skip-output.test.ts +4 -1
  364. package/src/cli/commands/__tests__/check.test.ts +43 -36
  365. package/src/cli/commands/__tests__/command-gate-dead-options.test.ts +60 -0
  366. package/src/cli/commands/__tests__/command.test.ts +33 -17
  367. package/src/cli/commands/__tests__/constraints-retire.test.ts +52 -0
  368. package/src/cli/commands/__tests__/context-syncer.test.ts +141 -0
  369. package/src/cli/commands/__tests__/contract.test.ts +20 -20
  370. package/src/cli/commands/__tests__/failure.test.ts +5 -4
  371. package/src/cli/commands/__tests__/gate-decision.ts +30 -0
  372. package/src/cli/commands/__tests__/init-dead-options.test.ts +50 -0
  373. package/src/cli/commands/__tests__/init-governance-io.test.ts +139 -0
  374. package/src/cli/commands/__tests__/init-injection.test.ts +3 -3
  375. package/src/cli/commands/__tests__/init-ondisk.test.ts +867 -0
  376. package/src/cli/commands/__tests__/init.test.ts +82 -6
  377. package/src/cli/commands/__tests__/knowledge-audit-threshold.test.ts +146 -0
  378. package/src/cli/commands/__tests__/knowledge-flywheel-consistency.test.ts +1 -1
  379. package/src/cli/commands/__tests__/knowledge-tone-mapping.test.ts +244 -0
  380. package/src/cli/commands/__tests__/knowledge-view.test.ts +839 -0
  381. package/src/cli/commands/__tests__/knowledge.test.ts +33 -15
  382. package/src/cli/commands/__tests__/numeric-flag-assembly.test.ts +368 -0
  383. package/src/cli/commands/__tests__/passes-gate-dead-options.test.ts +89 -1
  384. package/src/cli/commands/__tests__/performance.test.ts +19 -21
  385. package/src/cli/commands/__tests__/posteval-plan.test.ts +5 -3
  386. package/src/cli/commands/__tests__/pre-push-hook.test.ts +181 -0
  387. package/src/cli/commands/__tests__/project-path-anchoring.test.ts +95 -2
  388. package/src/cli/commands/__tests__/project-path-convention.test.ts +103 -25
  389. package/src/cli/commands/__tests__/registry.test.ts +2 -0
  390. package/src/cli/commands/__tests__/report.test.ts +23 -1
  391. package/src/cli/commands/__tests__/review.test.ts +10 -17
  392. package/src/cli/commands/__tests__/scaffold.test.ts +505 -0
  393. package/src/cli/commands/__tests__/security-default-scan.test.ts +75 -0
  394. package/src/cli/commands/__tests__/security.test.ts +21 -24
  395. package/src/cli/commands/__tests__/spec-baseline-check.test.ts +3 -2
  396. package/src/cli/commands/__tests__/spec-baseline-index-cap.test.ts +131 -0
  397. package/src/cli/commands/__tests__/spec-baseline-read-count.test.ts +325 -0
  398. package/src/cli/commands/__tests__/sync-docs-agents.test.ts +19 -4
  399. package/src/cli/commands/__tests__/sync-docs-context-drift.test.ts +232 -0
  400. package/src/cli/commands/__tests__/sync-docs-module-order.test.ts +111 -0
  401. package/src/cli/commands/__tests__/sync-docs-read-count.test.ts +192 -0
  402. package/src/cli/commands/__tests__/sync-docs.test.ts +3 -2
  403. package/src/cli/commands/__tests__/validate.test.ts +1 -48
  404. package/src/cli/commands/acceptance.ts +24 -29
  405. package/src/cli/commands/check.ts +40 -17
  406. package/src/cli/commands/command.ts +9 -8
  407. package/src/cli/commands/constraints-retire.ts +57 -70
  408. package/src/cli/commands/contract.ts +44 -47
  409. package/src/cli/commands/definitions.ts +12 -6
  410. package/src/cli/commands/failure.ts +16 -3
  411. package/src/cli/commands/init.ts +242 -389
  412. package/src/cli/commands/knowledge-view.ts +224 -0
  413. package/src/cli/commands/knowledge.ts +643 -448
  414. package/src/cli/commands/passes-gate.ts +12 -3
  415. package/src/cli/commands/performance.ts +31 -38
  416. package/src/cli/commands/report.ts +3 -2
  417. package/src/cli/commands/review.ts +22 -28
  418. package/src/cli/commands/scaffold-templates.ts +406 -0
  419. package/src/cli/commands/scaffold.ts +302 -0
  420. package/src/cli/commands/security.ts +27 -23
  421. package/src/cli/commands/spec-baseline-check.ts +158 -33
  422. package/src/cli/commands/sync-docs/__tests__/context-export-surface.test.ts +102 -0
  423. package/src/cli/commands/sync-docs/__tests__/module-descriptions.test.ts +196 -0
  424. package/src/cli/commands/sync-docs/context-syncer.ts +137 -31
  425. package/src/cli/commands/sync-docs/index.ts +103 -28
  426. package/src/cli/commands/sync-docs/project-reader.ts +51 -7
  427. package/src/cli/commands/validate.ts +1 -104
  428. package/src/cli/gate-command.ts +87 -0
  429. package/src/completion-checkers/index.ts +10 -1
  430. package/src/context/CONTEXT.md +2 -1
  431. package/src/context/__tests__/knowledge-injector.test.ts +27 -0
  432. package/src/context/__tests__/session-manager.test.ts +19 -12
  433. package/src/context/knowledge-injector.ts +14 -7
  434. package/src/core/CONTEXT.md +10 -7
  435. package/src/core/__tests__/effective-set.test.ts +36 -60
  436. package/src/core/constraints/__tests__/context-reconcile.test.ts +246 -0
  437. package/src/core/constraints/__tests__/run-env.test.ts +377 -0
  438. package/src/core/constraints/__tests__/triggers.test.ts +70 -0
  439. package/src/core/constraints/agent-prompt-renderer.ts +1 -1
  440. package/src/core/constraints/capabilities-reconcile.ts +28 -4
  441. package/src/core/constraints/check-cache.ts +1 -1
  442. package/src/core/constraints/checker.ts +30 -14
  443. package/src/core/constraints/checkers/__tests__/context-doc-sync.test.ts +8 -3
  444. package/src/core/constraints/checkers/__tests__/governance-presence.test.ts +16 -7
  445. package/src/core/constraints/checkers/__tests__/no-hardcoded-credentials.test.ts +2 -1
  446. package/src/core/constraints/checkers/capability-sync.ts +27 -28
  447. package/src/core/constraints/checkers/context-doc-sync.ts +9 -7
  448. package/src/core/constraints/checkers/docs-freshness.ts +28 -33
  449. package/src/core/constraints/checkers/governance-presence.ts +10 -6
  450. package/src/core/constraints/checkers/types.ts +14 -8
  451. package/src/core/constraints/context-builder.ts +35 -26
  452. package/src/core/constraints/context-reconcile.ts +200 -0
  453. package/src/core/constraints/doc-freshness/__tests__/runner.test.ts +25 -0
  454. package/src/core/constraints/doc-freshness/runner.ts +18 -4
  455. package/src/core/constraints/git-evidence.ts +1 -1
  456. package/src/core/constraints/injection-drift.ts +19 -8
  457. package/src/core/constraints/run-env.ts +207 -0
  458. package/src/core/constraints/triggers.ts +33 -0
  459. package/src/core/effective-constraints.ts +17 -6
  460. package/src/core/effective-set.ts +8 -24
  461. package/src/core/index.ts +2 -1
  462. package/src/core/project-config-loader.ts +54 -102
  463. package/src/core/validators/__tests__/http-retry-sleep.test.ts +231 -0
  464. package/src/core/validators/check-handlers/http.ts +18 -7
  465. package/src/core/validators/index.ts +0 -1
  466. package/src/core/validators/passes-gate.ts +2 -3
  467. package/src/failure/CONTEXT.md +2 -1
  468. package/src/failure/classifier.ts +2 -2
  469. package/src/failure/index.ts +14 -2
  470. package/src/failure/recorder.ts +1 -1
  471. package/src/gates/CONTEXT.md +13 -7
  472. package/src/gates/__tests__/checker-gate.test.ts +1 -1
  473. package/src/gates/__tests__/command-single-predicate.test.ts +135 -0
  474. package/src/gates/__tests__/command.test.ts +8 -15
  475. package/src/gates/__tests__/contract.test.ts +5 -5
  476. package/src/gates/__tests__/gate-interface.test.ts +0 -17
  477. package/src/gates/__tests__/performance.test.ts +0 -13
  478. package/src/gates/__tests__/review.test.ts +0 -1
  479. package/src/gates/__tests__/runner.test.ts +1 -1
  480. package/src/gates/__tests__/security-default-scan.test.ts +97 -0
  481. package/src/gates/__tests__/security.test.ts +0 -13
  482. package/src/gates/checker-gate.ts +3 -2
  483. package/src/gates/command.ts +51 -74
  484. package/src/gates/contract.ts +0 -5
  485. package/src/gates/definitions.ts +6 -5
  486. package/src/gates/index.ts +0 -5
  487. package/src/gates/performance.ts +1 -6
  488. package/src/gates/runner.ts +1 -1
  489. package/src/gates/security.ts +9 -11
  490. package/src/gates/types.ts +20 -23
  491. package/src/hooks/CONTEXT.md +10 -9
  492. package/src/hooks/__tests__/bootstrap.test.ts +29 -6
  493. package/src/hooks/__tests__/pipeline.test.ts +28 -17
  494. package/src/hooks/__tests__/registry.test.ts +51 -3
  495. package/src/hooks/bootstrap.ts +35 -15
  496. package/src/hooks/config.ts +6 -2
  497. package/src/hooks/index.ts +10 -1
  498. package/src/hooks/pipeline.ts +4 -6
  499. package/src/hooks/registry.ts +31 -12
  500. package/src/hooks/types.ts +24 -7
  501. package/src/index.ts +1 -3
  502. package/src/knowledge/CONTEXT.md +14 -7
  503. package/src/knowledge/__tests__/audit-labels.test.ts +8 -5
  504. package/src/knowledge/__tests__/audit-scoring.test.ts +230 -0
  505. package/src/knowledge/__tests__/audit-write-count.test.ts +131 -0
  506. package/src/knowledge/__tests__/audit.test.ts +291 -208
  507. package/src/knowledge/__tests__/doctor.test.ts +3 -2
  508. package/src/knowledge/__tests__/ingest.test.ts +3 -2
  509. package/src/knowledge/__tests__/lifecycle.test.ts +57 -2
  510. package/src/knowledge/__tests__/migration.test.ts +35 -6
  511. package/src/knowledge/__tests__/query.test.ts +3 -2
  512. package/src/knowledge/__tests__/reference-tracker.test.ts +23 -2
  513. package/src/knowledge/__tests__/store.test.ts +149 -4
  514. package/src/knowledge/__tests__/tree-walker.test.ts +132 -0
  515. package/src/knowledge/audit-scoring.ts +589 -0
  516. package/src/knowledge/audit.ts +55 -599
  517. package/src/knowledge/import.ts +2 -0
  518. package/src/knowledge/index-generator.ts +4 -6
  519. package/src/knowledge/index.ts +27 -2
  520. package/src/knowledge/ingest.ts +1 -1
  521. package/src/knowledge/lifecycle.ts +5 -2
  522. package/src/knowledge/migration.ts +8 -2
  523. package/src/knowledge/query.ts +8 -1
  524. package/src/knowledge/reference-tracker.ts +5 -7
  525. package/src/knowledge/store.ts +75 -16
  526. package/src/knowledge/tree-walker.ts +29 -0
  527. package/src/knowledge/types.ts +19 -0
  528. package/src/monitoring/CONTEXT.md +5 -2
  529. package/src/monitoring/__tests__/context-tracker.test.ts +16 -8
  530. package/src/monitoring/__tests__/trace-file-anchoring.test.ts +80 -0
  531. package/src/monitoring/traces.ts +19 -5
  532. package/src/release/CONTEXT.md +1 -1
  533. package/src/release/__tests__/integrity.test.ts +21 -12
  534. package/src/test-setup/__tests__/jsonl-fake-fs.test.ts +98 -0
  535. package/src/test-setup/jsonl-fake-fs.ts +59 -0
  536. package/src/tools/index.ts +5 -1
  537. package/src/types/checkpoint.ts +6 -0
  538. package/src/types/passes-gate.ts +0 -17
  539. package/src/types/project-config.ts +21 -0
  540. package/src/types/trace.ts +14 -4
  541. package/src/utils/__tests__/file-walk.test.ts +3 -2
  542. package/src/utils/__tests__/jsonl-bounded-read.test.ts +106 -0
  543. package/src/utils/__tests__/jsonl-skip-disposition.test.ts +10 -6
  544. package/src/utils/__tests__/jsonl.test.ts +61 -14
  545. package/src/utils/__tests__/numeric-flag.test.ts +80 -0
  546. package/src/utils/__tests__/package-version.test.ts +2 -2
  547. package/src/utils/exec.ts +4 -64
  548. package/src/utils/jsonl.ts +159 -20
  549. package/src/utils/numeric-flag.ts +64 -0
  550. package/dist/failure/types.d.ts +0 -9
  551. package/dist/failure/types.d.ts.map +0 -1
  552. package/dist/failure/types.js +0 -25
  553. package/dist/failure/types.js.map +0 -1
  554. package/dist/gates/effective-gates.d.ts +0 -30
  555. package/dist/gates/effective-gates.d.ts.map +0 -1
  556. package/dist/gates/effective-gates.js +0 -81
  557. package/dist/gates/effective-gates.js.map +0 -1
  558. package/src/failure/types.ts +0 -9
  559. package/src/gates/__tests__/effective-gates.test.ts +0 -77
  560. package/src/gates/effective-gates.ts +0 -99
@@ -10,7 +10,8 @@ import * as path from 'path';
10
10
  import { execAsync } from '../../utils/exec';
11
11
  import { PassesGate, detectTestCommand } from '../../core/validators/passes-gate';
12
12
  import type { PassesGateConfig } from '../../types/passes-gate';
13
- import { log, processIO, type CommandIO, type CommandResult } from '../command-contract';
13
+ import { log, logError, processIO, type CommandIO, type CommandResult } from '../command-contract';
14
+ import { numericFlagMessage, parseNumericFlag } from '../../utils/numeric-flag';
14
15
 
15
16
  export interface PassesGateOptions {
16
17
  /** 测试命令 */
@@ -92,16 +93,24 @@ export async function runPassesGate(
92
93
  }
93
94
 
94
95
  /**
95
- * --coverage 路由入口(候选7):projectPath 兜底 + 阈值强转编组,
96
+ * --coverage 路由入口(候选7):projectPath 兜底 + 阈值装配窄化,
96
97
  * 自 definitions.ts 的 optionRoutes args 闭包移回命令模块。
98
+ * `--coverage-threshold` 给到的恒是字符串(缺省 '80' 也是),脏输入 fail-loud
99
+ * (harness#154,原先 parseInt 出 NaN → `totalCoverage >= NaN` 恒 false →
100
+ * 打出自证异常的「覆盖率不足 (x% < NaN%)」),且先于任何覆盖率执行。
97
101
  */
98
102
  export async function coverageCheck(
99
103
  options: Record<string, unknown>,
100
104
  io: CommandIO = processIO,
101
105
  ): Promise<CommandResult> {
106
+ const threshold = parseNumericFlag(options.coverageThreshold as string | undefined, 'int');
107
+ if (!threshold.ok) {
108
+ logError(io, numericFlagMessage('--coverage-threshold', threshold.raw, 'int'));
109
+ return { kind: 'usage-error', reason: `passes-gate --coverage-threshold 非法阈值: "${threshold.raw}"` };
110
+ }
102
111
  return checkCoverage(
103
112
  (options.projectPath as string) || process.cwd(),
104
- parseInt(String(options.coverageThreshold), 10),
113
+ threshold.value,
105
114
  io,
106
115
  );
107
116
  }
@@ -6,8 +6,9 @@
6
6
 
7
7
  import chalk from 'chalk';
8
8
  import { PerformanceGate, type ExtendedPerformanceGateConfig } from '../../gates/performance';
9
- import type { GateContext, PerformanceThresholds } from '../../gates/types';
9
+ import type { PerformanceThresholds } from '../../gates/types';
10
10
  import { log, processIO, type CommandIO, type CommandResult } from '../command-contract';
11
+ import { reportGateDecision, reportGateError } from '../gate-command';
11
12
 
12
13
  export interface PerformanceOptions {
13
14
  /** 项目路径 */
@@ -54,46 +55,38 @@ export async function performance(
54
55
  const gate = new PerformanceGate(config);
55
56
 
56
57
  try {
57
- const result = await gate.check({ projectPath } as GateContext);
58
+ const decision = await gate.evaluate({ projectPath });
58
59
 
59
- if (result.passed) {
60
- log(io);
61
- log(io, chalk.green('✅ 性能门控检查通过'));
60
+ return reportGateDecision(
61
+ io,
62
+ {
63
+ gateId: 'performance',
64
+ label: '性能门控',
65
+ onPass: (r) => {
66
+ if (!r.details?.metrics) return [];
67
+ const metrics = r.details.metrics as any;
68
+ const lines = ['', chalk.gray('性能指标:')];
62
69
 
63
- // 显示详细指标
64
- if (result.details?.metrics) {
65
- log(io);
66
- log(io, chalk.gray('性能指标:'));
70
+ if (metrics.coverage !== undefined) {
71
+ const threshold = options.coverageThreshold || 80;
72
+ lines.push(chalk.gray(` 覆盖率: ${metrics.coverage.toFixed(2)}% ${metrics.coverage >= threshold ? '✅' : '❌'}`));
73
+ }
67
74
 
68
- const metrics = result.details.metrics as any;
69
- if (metrics.coverage !== undefined) {
70
- const threshold = options.coverageThreshold || 80;
71
- const status = metrics.coverage >= threshold ? '✅' : '❌';
72
- log(io, chalk.gray(` 覆盖率: ${metrics.coverage.toFixed(2)}% ${status}`));
73
- }
75
+ if (metrics.bundleSize !== undefined) {
76
+ const thresholdKB = options.bundleThreshold || 500;
77
+ lines.push(chalk.gray(` 打包大小: ${metrics.bundleSize} KB ${metrics.bundleSize <= thresholdKB ? '✅' : '❌'}`));
78
+ }
74
79
 
75
- if (metrics.bundleSize !== undefined) {
76
- const thresholdKB = options.bundleThreshold || 500;
77
- const status = metrics.bundleSize <= thresholdKB ? '✅' : '❌';
78
- log(io, chalk.gray(` 打包大小: ${metrics.bundleSize} KB ${status}`));
79
- }
80
- }
81
- } else {
82
- log(io);
83
- log(io, chalk.red('❌ 性能门控检查失败'));
84
- log(io, chalk.red(` ${result.message}`));
85
- if (result.details?.failures) {
86
- (result.details.failures as string[]).forEach((failure: string) => {
87
- log(io, chalk.red(` - ${failure}`));
88
- });
89
- }
90
- return { kind: 'fail', reason: `performance gate denied: ${result.message}` };
91
- }
92
- return { kind: 'ok' };
93
- } catch (error: any) {
94
- log(io);
95
- log(io, chalk.red('❌ 性能门控检查出错'));
96
- log(io, chalk.red(` ${error.message}`));
97
- return { kind: 'fail', reason: `performance gate error: ${error.message}` };
80
+ return lines;
81
+ },
82
+ onFail: (r) =>
83
+ r.details?.failures
84
+ ? (r.details.failures as string[]).map((failure: string) => chalk.red(` - ${failure}`))
85
+ : [],
86
+ },
87
+ decision
88
+ );
89
+ } catch (error) {
90
+ return reportGateError(io, 'performance', '性能门控', error);
98
91
  }
99
92
  }
@@ -8,7 +8,7 @@ import chalk from 'chalk';
8
8
  import * as fs from 'fs/promises';
9
9
  import { ConstraintChecker } from '../../core/constraints/checker';
10
10
  import { IRON_LAWS, GUIDELINES, PROMPTS } from '../../core/constraints/definitions';
11
- import { getTraceCollector } from '../../monitoring/traces';
11
+ import { TraceCollector } from '../../monitoring/traces';
12
12
  import type { ConstraintContext } from '../../types/constraint';
13
13
  import { log, processIO, type CommandIO, type CommandResult } from '../command-contract';
14
14
 
@@ -48,7 +48,8 @@ export async function report(options: ReportOptions, io: CommandIO = processIO):
48
48
 
49
49
  const projectPath = options.projectPath || process.cwd();
50
50
  // trace 记录器经构造参数接线(harness#88):本命令是组合根
51
- const checker = new ConstraintChecker(getTraceCollector());
51
+ // #139:收集器锚根构造——不传 projectPath trace 会落进调用方 cwd,B 侧读不到
52
+ const checker = new ConstraintChecker(new TraceCollector({ projectPath }));
52
53
 
53
54
  const allConstraints = { ...IRON_LAWS, ...GUIDELINES, ...PROMPTS };
54
55
  const totalConstraints = Object.keys(allConstraints).length;
@@ -8,6 +8,7 @@ import chalk from 'chalk';
8
8
  import { execAsync } from '../../utils/exec';
9
9
  import { ReviewGate } from '../../gates/review';
10
10
  import { log, processIO, type CommandIO, type CommandResult } from '../command-contract';
11
+ import { reportGateDecision, reportGateError } from '../gate-command';
11
12
 
12
13
  export interface ReviewOptions {
13
14
  /** 项目路径 */
@@ -46,34 +47,27 @@ export async function review(
46
47
  const { stdout: branch } = await execAsync('git rev-parse --abbrev-ref HEAD', { cwd: projectPath });
47
48
  log(io, chalk.gray(`当前分支: ${branch.trim()}`));
48
49
 
49
- const result = await gate.check({ projectPath, projectId: 'default' });
50
-
51
- log(io);
52
- if (result.passed) {
53
- log(io, chalk.green('✅ 代码审查门控检查通过'));
54
- if (result.details) {
55
- log(io, chalk.gray(` 审批: ${result.details.approvals ?? 0}, 变更请求: ${result.details.changesRequested ?? 0}`));
56
- }
57
- } else {
58
- log(io, chalk.red('❌ 代码审查门控检查失败'));
59
- log(io, chalk.red(` ${result.message}`));
60
- if (result.details?.suggestion) {
61
- log(io, chalk.gray(` ${result.details.suggestion}`));
62
- }
63
- return { kind: 'fail', reason: `review gate denied: ${result.message}` };
64
- }
65
- return { kind: 'ok' };
66
- } catch (error: any) {
67
- log(io);
68
- log(io, chalk.red('❌ 代码审查门控检查出错'));
69
- log(io, chalk.red(` ${error.message}`));
70
-
71
- if (error.message.includes('not a git repository')) {
72
- log(io);
73
- log(io, chalk.gray('提示: 此命令需要在 Git 仓库中运行'));
74
- }
75
-
76
- return { kind: 'fail', reason: `review gate error: ${error.message}` };
50
+ const decision = await gate.evaluate({ projectPath });
51
+
52
+ return reportGateDecision(
53
+ io,
54
+ {
55
+ gateId: 'review',
56
+ label: '代码审查门控',
57
+ onPass: (r) =>
58
+ r.details
59
+ ? [chalk.gray(` 审批: ${r.details.approvals ?? 0}, 变更请求: ${r.details.changesRequested ?? 0}`)]
60
+ : [],
61
+ onFail: (r) => (r.details?.suggestion ? [chalk.gray(` ${r.details.suggestion}`)] : []),
62
+ },
63
+ decision
64
+ );
65
+ } catch (error) {
66
+ return reportGateError(io, 'review', '代码审查门控', error, (message) =>
67
+ message.includes('not a git repository')
68
+ ? ['', chalk.gray('提示: 此命令需要在 Git 仓库中运行')]
69
+ : []
70
+ );
77
71
  }
78
72
  }
79
73
 
@@ -0,0 +1,406 @@
1
+ /**
2
+ * 脚手架模板数据(harness#132)
3
+ *
4
+ * 受管文件的正文正本,纯数据 + 纯渲染,零 IO、零上色——落盘语义与文案在
5
+ * `scaffold.ts` 的 plan 里,本模块只回答「这个文件的内容是什么」。
6
+ *
7
+ * 刻意留在代码内而不落 `templates/` 目录:`templates/` 无运行时消费者
8
+ * (harness 自身不读它),发布完整性清单(`release/integrity.ts`)也不覆盖它。
9
+ */
10
+
11
+ import * as path from 'path';
12
+ import * as yaml from 'js-yaml';
13
+ import type { Checkpoint } from '../../types/checkpoint';
14
+ import type { CiPlatform } from '../../types/project-config';
15
+
16
+ /** Git pre-commit 片段(#103:打印片段与落盘 hook 的唯一正本) */
17
+ export const PRE_COMMIT_SNIPPET = `
18
+ echo "🔍 Running harness checks..."
19
+
20
+ STAGED=$(git diff --cached --name-only --diff-filter=ACMR 2>/dev/null || true)
21
+
22
+ # Harness 约束检查
23
+ npx @dommaker/harness check --staged
24
+ if [ $? -ne 0 ]; then
25
+ echo "❌ Iron law check failed"
26
+ exit 1
27
+ fi
28
+
29
+ # Plan coverage check (via PostEval)
30
+ if command -v npx > /dev/null 2>&1; then
31
+ PLAN_FILES=$(echo "$STAGED" | grep -E 'plans/.*\\.md$|\\.plan\\.md$' || true)
32
+ if [ -n "$PLAN_FILES" ]; then
33
+ echo "📋 Checking plan coverage..."
34
+ for plan in $PLAN_FILES; do
35
+ npx @dommaker/harness posteval-plan "$plan" || {
36
+ echo "🛑 Plan coverage incomplete. See above for missed items."
37
+ exit 1
38
+ }
39
+ done
40
+ fi
41
+ fi
42
+
43
+ echo "✅ All checks passed"
44
+ `;
45
+
46
+ /** 落盘的 pre-commit hook = shebang + 说明行 + 共享片段 */
47
+ export function renderPreCommitHook(): string {
48
+ return `#!/bin/sh
49
+ # Harness pre-commit hook
50
+ ${PRE_COMMIT_SNIPPET}`;
51
+ }
52
+
53
+ /**
54
+ * Git pre-push 片段(harness#144;#103:打印片段与落盘 hook 的唯一正本)
55
+ *
56
+ * 三道决定都写在这段正文里,不再由代码补:
57
+ * - **整仓全量**:`check` 不带 `--staged`,加一道 `validate`——它拦的是
58
+ * `git commit --no-verify` 绕过 pre-commit 的内容,重复是设计使然;
59
+ * - **不做增量**:不解析 pre-push 从 stdin 收到的 `<local_ref> <local_oid>
60
+ * <remote_ref> <remote_oid>` 清单,无论推什么整仓过一遍;子进程也不给它读;
61
+ * - **不内建逃生机制**:没有环境变量开关、没有超时、没有「慢则降级」,
62
+ * 唯一的口子是 git 原生 `git push --no-verify`。
63
+ */
64
+ export const PRE_PUSH_SNIPPET = `
65
+ echo "🔍 Running harness pre-push checks (whole repo)..."
66
+
67
+ # 分工:pre-commit 查暂存的(增量、快反馈),pre-push 查整仓的(全量、兜底)。
68
+ # 同一次改动跑两遍是设计使然——这道拦的是 git commit --no-verify 绕出去的内容。
69
+ # 本地 hook 只是自检与提醒,真正的门禁在服务端 CI;逃生口只有 git 原生 push --no-verify。
70
+ # 不解析 pre-push 从 stdin 收到的 ref 清单,子进程一律不给它读(< /dev/null)。
71
+ npx @dommaker/harness check < /dev/null
72
+ if [ $? -ne 0 ]; then
73
+ echo "❌ Iron law check failed"
74
+ exit 1
75
+ fi
76
+
77
+ npx @dommaker/harness validate < /dev/null
78
+ if [ $? -ne 0 ]; then
79
+ echo "❌ Validate failed"
80
+ exit 1
81
+ fi
82
+
83
+ echo "✅ All pre-push checks passed"
84
+ `;
85
+
86
+ /** 落盘的 pre-push hook = shebang + 说明行 + 共享片段 */
87
+ export function renderPrePushHook(): string {
88
+ return `#!/bin/sh
89
+ # Harness pre-push hook
90
+ ${PRE_PUSH_SNIPPET}`;
91
+ }
92
+
93
+ // ── GitLab CI(harness#143):与 GH 版对仗的接线形状 ──────────────────────
94
+
95
+ /**
96
+ * GitLab 任务的触发条件(决议 ⑥:用 `rules:` 不用过时的 `only:`)
97
+ *
98
+ * MR 事件 + main/master 分支 push,与 GH 版 `on:` 段一一对应。三个任务各自带一份
99
+ * ——GitLab 的 `default:` 不支持 `rules`,自建实例版本参差,不赌语法糖。
100
+ */
101
+ const GITLAB_RULES = ` rules:
102
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
103
+ - if: $CI_COMMIT_BRANCH == "main"
104
+ - if: $CI_COMMIT_BRANCH == "master"
105
+ `;
106
+
107
+ /** `.gitlab-ci.yml` 文件头:harness 只拥有其下的 `harness-*` 任务 */
108
+ const GITLAB_CI_HEADER = `# 由 harness init 生成 —— 以下 harness-* 任务是 harness 的 CI 接线
109
+ # 门禁真正生效还需在 GitLab 侧开分支保护:pipeline 成功才允许合并
110
+
111
+ image: node:20
112
+
113
+ stages:
114
+ - test
115
+
116
+ `;
117
+
118
+ /** GitLab harness-check 任务(`--print-snippets` 打印的 job 片段即此份) */
119
+ export const GITLAB_CI_SNIPPET = `harness-check:
120
+ stage: test
121
+ script:
122
+ - npm ci
123
+ - npx @dommaker/harness check
124
+ - npx @dommaker/harness validate
125
+ - npx @dommaker/harness passes-gate
126
+ ${GITLAB_RULES}`;
127
+
128
+ /** harness 拥有的 GitLab 任务全集(治理档在场时含治理任务)——落盘正文与冲突片段共用 */
129
+ export function renderGitLabCiJobs(governanceLevel?: string): string {
130
+ return governanceLevel
131
+ ? `${GITLAB_CI_SNIPPET}\n${renderGovernanceWorkflow(governanceLevel, 'gitlab')}`
132
+ : GITLAB_CI_SNIPPET;
133
+ }
134
+
135
+ /** `.gitlab-ci.yml` 落盘全文正本(= 文件头 + harness 拥有的任务) */
136
+ export function renderGitLabCiFile(governanceLevel?: string): string {
137
+ return `${GITLAB_CI_HEADER}${renderGitLabCiJobs(governanceLevel)}`;
138
+ }
139
+
140
+ /** harness-check.yml 全文(落盘正文,冲突时打印的也是这一份) */
141
+ export const HARNESS_CHECK_WORKFLOW = `name: Harness Check
142
+
143
+ on:
144
+ push:
145
+ branches: [main, master]
146
+ pull_request:
147
+ branches: [main, master]
148
+
149
+ jobs:
150
+ harness-check:
151
+ runs-on: ubuntu-latest
152
+
153
+ steps:
154
+ - uses: actions/checkout@v4
155
+
156
+ - name: Setup Node.js
157
+ uses: actions/setup-node@v4
158
+ with:
159
+ node-version: '20'
160
+
161
+ - name: Install dependencies
162
+ run: npm ci
163
+
164
+ - name: Run harness check
165
+ run: npx @dommaker/harness check
166
+
167
+ - name: Run harness validate
168
+ run: npx @dommaker/harness validate
169
+
170
+ - name: Run harness passes-gate
171
+ run: npx @dommaker/harness passes-gate
172
+ `;
173
+
174
+ /**
175
+ * GitHub Actions job 片段(`init --print-snippets` 的片段视图,harness#153)
176
+ *
177
+ * 由上面的落盘正本裁出 `jobs:` 段之后的一切,**不是第二份手抄文本**——它曾独立存在并
178
+ * 少掉 `validate` / `passes-gate` 两道门禁,照抄的用户拿到比同版本 `harness init` 弱一半
179
+ * 的 CI(#103 判据的第三种形态)。形状与 GitLab 侧对仗:打印的是正本的 job 段。
180
+ */
181
+ export const GITHUB_ACTIONS_SNIPPET = HARNESS_CHECK_WORKFLOW.slice(
182
+ HARNESS_CHECK_WORKFLOW.indexOf(' harness-check:'),
183
+ );
184
+
185
+ /**
186
+ * 治理 CI 面正文
187
+ *
188
+ * `minimal` 档不带 docs 新鲜度检查(其余档位带,且失败不阻断)。平台只改变接线形状,
189
+ * 三条命令与档位语义一致(harness#143):GitLab 侧的「失败不阻断」= `allow_failure: true`,
190
+ * 且因每个任务都是全新容器,docs 检查单列一个任务而非 GH 的一个 step。
191
+ */
192
+ export function renderGovernanceWorkflow(level: string, platform: CiPlatform): string {
193
+ if (platform === 'gitlab') {
194
+ const docsJob = level === 'minimal'
195
+ ? ''
196
+ : `
197
+ harness-docs-freshness:
198
+ stage: test
199
+ script:
200
+ - npm ci
201
+ - npx @dommaker/harness sync-docs --check
202
+ ${GITLAB_RULES} allow_failure: true
203
+ `;
204
+ return `harness-governance:
205
+ stage: test
206
+ script:
207
+ - npm ci
208
+ - npx @dommaker/harness check
209
+ - npx @dommaker/harness passes-gate
210
+ ${GITLAB_RULES}${docsJob}`;
211
+ }
212
+
213
+ const docsCheckStep = level !== 'minimal'
214
+ ? `
215
+ - name: Check docs freshness
216
+ run: npx @dommaker/harness sync-docs --check
217
+ continue-on-error: true`
218
+ : '';
219
+
220
+ return `name: Harness Governance
221
+
222
+ on:
223
+ push:
224
+ branches: [main, master]
225
+ pull_request:
226
+ branches: [main, master]
227
+
228
+ jobs:
229
+ governance:
230
+ runs-on: ubuntu-latest
231
+
232
+ steps:
233
+ - uses: actions/checkout@v4
234
+
235
+ - name: Setup Node.js
236
+ uses: actions/setup-node@v4
237
+ with:
238
+ node-version: '20'
239
+
240
+ - name: Install dependencies
241
+ run: npm ci
242
+
243
+ - name: Constraint check
244
+ run: npx @dommaker/harness check
245
+
246
+ - name: Quality gate
247
+ run: npx @dommaker/harness passes-gate
248
+ ${docsCheckStep}
249
+ `;
250
+ }
251
+
252
+ /** custom-constraints.yml 示例正文 */
253
+ export const CUSTOM_CONSTRAINTS_TEMPLATE = `# 自定义约束配置
254
+ #
255
+ # 此文件定义项目特定的约束,扩展或覆盖 harness 内置约束
256
+
257
+ # ========================================
258
+ # 自定义约束示例
259
+ # ========================================
260
+
261
+ custom_constraints:
262
+ # 示例 1:禁止 console.log
263
+ # my_project_no_console_log:
264
+ # id: my_project_no_console_log
265
+ # level: guideline
266
+ # rule: "NO CONSOLE.LOG IN PRODUCTION CODE"
267
+ # message: "生产代码禁止使用 console.log,请使用 logger 模块"
268
+ # trigger: ["code_implementation"]
269
+ # description: "使用项目统一的 logger 模块代替 console.log"
270
+
271
+ # 示例 2:禁止特定的导入
272
+ # my_project_no_moment_js:
273
+ # id: my_project_no_moment_js
274
+ # level: guideline
275
+ # rule: "NO MOMENT.JS IMPORTS"
276
+ # message: "禁止使用 moment.js,请使用 date-fns 或 dayjs"
277
+ # trigger: ["code_implementation"]
278
+
279
+ # 示例 3:要求特定的文件命名
280
+ # my_project_component_naming:
281
+ # id: my_project_component_naming
282
+ # level: tip
283
+ # rule: "REACT COMPONENTS SHOULD BE PASCAL CASE"
284
+ # message: "React 组件文件名应使用 PascalCase"
285
+ # trigger: ["file_creation"]
286
+ `;
287
+
288
+ /** CHANGELOG.md 正文(`format` 来自治理配置的 changelog.format) */
289
+ export function renderChangelog(format: string): string {
290
+ return format === 'keep-a-changelog'
291
+ ? `# Changelog
292
+
293
+ All notable changes to this project will be documented in this file.
294
+
295
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
296
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
297
+
298
+ ## [Unreleased]
299
+
300
+ ### Added
301
+ - Initial project setup with harness governance
302
+
303
+ ---
304
+
305
+ > 此文件可由 \`harness sync-docs\` 辅助维护
306
+ `
307
+ : `# Changelog
308
+
309
+ ## [Unreleased]
310
+
311
+ - Initial project setup with harness governance
312
+
313
+ ---
314
+
315
+ > 此文件可由 \`harness sync-docs\` 辅助维护
316
+ `;
317
+ }
318
+
319
+ /** 目录 CONTEXT.md 骨架正文(`dir` 是相对项目根的目录路径) */
320
+ export function renderContextDoc(dir: string): string {
321
+ const dirName = path.basename(dir);
322
+ return `# ${dirName}
323
+
324
+ > 此文件描述 ${dir} 目录的职责和上下文
325
+ > 请阅读本目录的源代码,然后填写以下各节。
326
+ > 如果使用 AI 编码助手,将本文件内容作为 prompt 请求它分析并填写。
327
+
328
+ ## 职责
329
+
330
+ <!-- 本目录的核心职责是什么 -->
331
+
332
+ ## 核心导出
333
+
334
+ <!-- 本目录对外暴露的主要模块/函数 -->
335
+
336
+ ## 依赖关系
337
+
338
+ <!-- 本目录依赖哪些其他模块,谁依赖本目录 -->
339
+
340
+ ## 注意事项
341
+
342
+ <!-- 开发时需要注意的约束或约定 -->
343
+ `;
344
+ }
345
+
346
+ /**
347
+ * 默认检查点列表
348
+ *
349
+ * 注:no-console 检查点已移除(工单 23/24)——CLI 产品 src/ 必然有合法 console 输出,
350
+ * 且旧配置 expected:'' 语义恒错;output_* 族修复为真正执行 config.command 后该检查会恒失败。
351
+ */
352
+ export const DEFAULT_CHECKPOINTS: Checkpoint[] = [
353
+ {
354
+ id: 'build-success',
355
+ name: '构建成功',
356
+ checks: [
357
+ {
358
+ id: 'build-command',
359
+ type: 'command_success',
360
+ config: { command: 'npm run build' },
361
+ message: '构建命令必须成功执行',
362
+ },
363
+ ],
364
+ },
365
+ {
366
+ id: 'test-pass',
367
+ name: '测试通过',
368
+ checks: [
369
+ {
370
+ id: 'test-command',
371
+ type: 'command_success',
372
+ config: { command: 'npm test' },
373
+ message: '测试命令必须成功执行',
374
+ },
375
+ ],
376
+ },
377
+ ];
378
+
379
+ /** 检查点文件的相对路径约定(validate 的缺省读取面与 init 的落盘面同一处) */
380
+ export const DEFAULT_CHECKPOINT_FILE = '.harness/checkpoints.yml';
381
+
382
+ /** checkpoints.yml 正文 */
383
+ export function renderCheckpoints(): string {
384
+ return yaml.dump({ checkpoints: DEFAULT_CHECKPOINTS }, { indent: 2 });
385
+ }
386
+
387
+ /** 默认 Resolutions(RKB — 约束 → 已知解法映射) */
388
+ const DEFAULT_RESOLUTIONS = {
389
+ no_fuzzy_completion_claim: {
390
+ title: 'commit message 缺少验证证据',
391
+ fix: '在 commit message body 中附上验证输出:\n`npx @dommaker/harness check --staged` | `npx @dommaker/harness validate` | `npm test -- --coverage`\n确认全部通过后重新 commit。',
392
+ },
393
+ capability_sync: {
394
+ title: '缺少 CAPABILITIES.md',
395
+ fix: '在项目根目录创建 CAPABILITIES.md,列出所有模块能力清单。运行 `npx @dommaker/harness sync-docs` 可自动生成模板。',
396
+ },
397
+ context_doc_sync: {
398
+ title: '关键目录缺少 CONTEXT.md',
399
+ fix: '在 required_dirs 目录下创建 CONTEXT.md。运行 `npx @dommaker/harness sync-docs` 可自动生成模板。',
400
+ },
401
+ };
402
+
403
+ /** resolutions.json 正文 */
404
+ export function renderResolutions(): string {
405
+ return JSON.stringify(DEFAULT_RESOLUTIONS, null, 2);
406
+ }