@dommaker/harness 1.3.0 → 1.5.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 (532) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +0 -2
  3. package/bin/harness.js +86 -32
  4. package/dist/cli/command-contract.d.ts +83 -0
  5. package/dist/cli/command-contract.d.ts.map +1 -0
  6. package/dist/cli/command-contract.js +66 -0
  7. package/dist/cli/command-contract.js.map +1 -0
  8. package/dist/cli/commands/acceptance.d.ts +3 -2
  9. package/dist/cli/commands/acceptance.d.ts.map +1 -1
  10. package/dist/cli/commands/acceptance.js +28 -24
  11. package/dist/cli/commands/acceptance.js.map +1 -1
  12. package/dist/cli/commands/analyze-sessions.d.ts +2 -1
  13. package/dist/cli/commands/analyze-sessions.d.ts.map +1 -1
  14. package/dist/cli/commands/analyze-sessions.js +25 -24
  15. package/dist/cli/commands/analyze-sessions.js.map +1 -1
  16. package/dist/cli/commands/check.d.ts +14 -2
  17. package/dist/cli/commands/check.d.ts.map +1 -1
  18. package/dist/cli/commands/check.js +104 -61
  19. package/dist/cli/commands/check.js.map +1 -1
  20. package/dist/cli/commands/command.d.ts +5 -1
  21. package/dist/cli/commands/command.d.ts.map +1 -1
  22. package/dist/cli/commands/command.js +26 -17
  23. package/dist/cli/commands/command.js.map +1 -1
  24. package/dist/cli/commands/constraints-report.d.ts +2 -1
  25. package/dist/cli/commands/constraints-report.d.ts.map +1 -1
  26. package/dist/cli/commands/constraints-report.js +37 -33
  27. package/dist/cli/commands/constraints-report.js.map +1 -1
  28. package/dist/cli/commands/constraints-retire.d.ts +6 -5
  29. package/dist/cli/commands/constraints-retire.d.ts.map +1 -1
  30. package/dist/cli/commands/constraints-retire.js +50 -52
  31. package/dist/cli/commands/constraints-retire.js.map +1 -1
  32. package/dist/cli/commands/constraints.d.ts +2 -1
  33. package/dist/cli/commands/constraints.d.ts.map +1 -1
  34. package/dist/cli/commands/constraints.js +10 -27
  35. package/dist/cli/commands/constraints.js.map +1 -1
  36. package/dist/cli/commands/contract.d.ts +3 -2
  37. package/dist/cli/commands/contract.d.ts.map +1 -1
  38. package/dist/cli/commands/contract.js +45 -42
  39. package/dist/cli/commands/contract.js.map +1 -1
  40. package/dist/cli/commands/definitions.d.ts +11 -11
  41. package/dist/cli/commands/definitions.d.ts.map +1 -1
  42. package/dist/cli/commands/definitions.js +27 -219
  43. package/dist/cli/commands/definitions.js.map +1 -1
  44. package/dist/cli/commands/failure.d.ts +5 -4
  45. package/dist/cli/commands/failure.d.ts.map +1 -1
  46. package/dist/cli/commands/failure.js +31 -25
  47. package/dist/cli/commands/failure.js.map +1 -1
  48. package/dist/cli/commands/init.d.ts +7 -5
  49. package/dist/cli/commands/init.d.ts.map +1 -1
  50. package/dist/cli/commands/init.js +147 -211
  51. package/dist/cli/commands/init.js.map +1 -1
  52. package/dist/cli/commands/knowledge.d.ts +17 -30
  53. package/dist/cli/commands/knowledge.d.ts.map +1 -1
  54. package/dist/cli/commands/knowledge.js +183 -273
  55. package/dist/cli/commands/knowledge.js.map +1 -1
  56. package/dist/cli/commands/passes-gate.d.ts +8 -2
  57. package/dist/cli/commands/passes-gate.d.ts.map +1 -1
  58. package/dist/cli/commands/passes-gate.js +44 -66
  59. package/dist/cli/commands/passes-gate.js.map +1 -1
  60. package/dist/cli/commands/performance.d.ts +2 -1
  61. package/dist/cli/commands/performance.d.ts.map +1 -1
  62. package/dist/cli/commands/performance.js +20 -18
  63. package/dist/cli/commands/performance.js.map +1 -1
  64. package/dist/cli/commands/posteval-plan.d.ts +5 -1
  65. package/dist/cli/commands/posteval-plan.d.ts.map +1 -1
  66. package/dist/cli/commands/posteval-plan.js +26 -15
  67. package/dist/cli/commands/posteval-plan.js.map +1 -1
  68. package/dist/cli/commands/release.d.ts +6 -1
  69. package/dist/cli/commands/release.d.ts.map +1 -1
  70. package/dist/cli/commands/release.js +69 -59
  71. package/dist/cli/commands/release.js.map +1 -1
  72. package/dist/cli/commands/report.d.ts +2 -1
  73. package/dist/cli/commands/report.d.ts.map +1 -1
  74. package/dist/cli/commands/report.js +9 -5
  75. package/dist/cli/commands/report.js.map +1 -1
  76. package/dist/cli/commands/review.d.ts +3 -2
  77. package/dist/cli/commands/review.d.ts.map +1 -1
  78. package/dist/cli/commands/review.js +33 -29
  79. package/dist/cli/commands/review.js.map +1 -1
  80. package/dist/cli/commands/sdd.d.ts +2 -1
  81. package/dist/cli/commands/sdd.d.ts.map +1 -1
  82. package/dist/cli/commands/sdd.js +7 -5
  83. package/dist/cli/commands/sdd.js.map +1 -1
  84. package/dist/cli/commands/security.d.ts +3 -2
  85. package/dist/cli/commands/security.d.ts.map +1 -1
  86. package/dist/cli/commands/security.js +29 -26
  87. package/dist/cli/commands/security.js.map +1 -1
  88. package/dist/cli/commands/spec-baseline-check.d.ts +2 -1
  89. package/dist/cli/commands/spec-baseline-check.d.ts.map +1 -1
  90. package/dist/cli/commands/spec-baseline-check.js +15 -11
  91. package/dist/cli/commands/spec-baseline-check.js.map +1 -1
  92. package/dist/cli/commands/spec.d.ts +7 -2
  93. package/dist/cli/commands/spec.d.ts.map +1 -1
  94. package/dist/cli/commands/spec.js +61 -51
  95. package/dist/cli/commands/spec.js.map +1 -1
  96. package/dist/cli/commands/status.d.ts +2 -1
  97. package/dist/cli/commands/status.d.ts.map +1 -1
  98. package/dist/cli/commands/status.js +57 -53
  99. package/dist/cli/commands/status.js.map +1 -1
  100. package/dist/cli/commands/sync-docs/agents-syncer.d.ts.map +1 -1
  101. package/dist/cli/commands/sync-docs/agents-syncer.js +5 -2
  102. package/dist/cli/commands/sync-docs/agents-syncer.js.map +1 -1
  103. package/dist/cli/commands/sync-docs/context-syncer.d.ts.map +1 -1
  104. package/dist/cli/commands/sync-docs/context-syncer.js +3 -2
  105. package/dist/cli/commands/sync-docs/context-syncer.js.map +1 -1
  106. package/dist/cli/commands/sync-docs/index.d.ts +2 -1
  107. package/dist/cli/commands/sync-docs/index.d.ts.map +1 -1
  108. package/dist/cli/commands/sync-docs/index.js +68 -88
  109. package/dist/cli/commands/sync-docs/index.js.map +1 -1
  110. package/dist/cli/commands/sync-docs/project-reader.d.ts +6 -1
  111. package/dist/cli/commands/sync-docs/project-reader.d.ts.map +1 -1
  112. package/dist/cli/commands/sync-docs/project-reader.js +14 -16
  113. package/dist/cli/commands/sync-docs/project-reader.js.map +1 -1
  114. package/dist/cli/commands/update-user-model.d.ts +9 -3
  115. package/dist/cli/commands/update-user-model.d.ts.map +1 -1
  116. package/dist/cli/commands/update-user-model.js +56 -61
  117. package/dist/cli/commands/update-user-model.js.map +1 -1
  118. package/dist/cli/commands/validate.d.ts +4 -3
  119. package/dist/cli/commands/validate.d.ts.map +1 -1
  120. package/dist/cli/commands/validate.js +28 -26
  121. package/dist/cli/commands/validate.js.map +1 -1
  122. package/dist/cli/session-mining/transcript.d.ts +7 -1
  123. package/dist/cli/session-mining/transcript.d.ts.map +1 -1
  124. package/dist/cli/session-mining/transcript.js +21 -14
  125. package/dist/cli/session-mining/transcript.js.map +1 -1
  126. package/dist/context/session-manager.d.ts.map +1 -1
  127. package/dist/context/session-manager.js +19 -32
  128. package/dist/context/session-manager.js.map +1 -1
  129. package/dist/core/constraints/agent-prompt-renderer.d.ts.map +1 -1
  130. package/dist/core/constraints/agent-prompt-renderer.js +1 -4
  131. package/dist/core/constraints/agent-prompt-renderer.js.map +1 -1
  132. package/dist/core/constraints/capabilities-parser.d.ts +24 -7
  133. package/dist/core/constraints/capabilities-parser.d.ts.map +1 -1
  134. package/dist/core/constraints/capabilities-parser.js +32 -28
  135. package/dist/core/constraints/capabilities-parser.js.map +1 -1
  136. package/dist/core/constraints/capabilities-reconcile.d.ts +67 -0
  137. package/dist/core/constraints/capabilities-reconcile.d.ts.map +1 -0
  138. package/dist/core/constraints/capabilities-reconcile.js +105 -0
  139. package/dist/core/constraints/capabilities-reconcile.js.map +1 -0
  140. package/dist/core/constraints/checker.d.ts +21 -43
  141. package/dist/core/constraints/checker.d.ts.map +1 -1
  142. package/dist/core/constraints/checker.js +68 -117
  143. package/dist/core/constraints/checker.js.map +1 -1
  144. package/dist/core/constraints/checkers/capability-sync.d.ts +20 -8
  145. package/dist/core/constraints/checkers/capability-sync.d.ts.map +1 -1
  146. package/dist/core/constraints/checkers/capability-sync.js +66 -77
  147. package/dist/core/constraints/checkers/capability-sync.js.map +1 -1
  148. package/dist/core/constraints/checkers/context-doc-sync.d.ts +4 -2
  149. package/dist/core/constraints/checkers/context-doc-sync.d.ts.map +1 -1
  150. package/dist/core/constraints/checkers/context-doc-sync.js +13 -22
  151. package/dist/core/constraints/checkers/context-doc-sync.js.map +1 -1
  152. package/dist/core/constraints/checkers/docs-freshness.d.ts.map +1 -1
  153. package/dist/core/constraints/checkers/docs-freshness.js +49 -66
  154. package/dist/core/constraints/checkers/docs-freshness.js.map +1 -1
  155. package/dist/core/constraints/checkers/governance-presence.d.ts +2 -2
  156. package/dist/core/constraints/checkers/governance-presence.d.ts.map +1 -1
  157. package/dist/core/constraints/checkers/governance-presence.js +7 -28
  158. package/dist/core/constraints/checkers/governance-presence.js.map +1 -1
  159. package/dist/core/constraints/checkers/index.d.ts +2 -2
  160. package/dist/core/constraints/checkers/index.d.ts.map +1 -1
  161. package/dist/core/constraints/checkers/index.js +2 -1
  162. package/dist/core/constraints/checkers/index.js.map +1 -1
  163. package/dist/core/constraints/checkers/no-test-simplification.d.ts.map +1 -1
  164. package/dist/core/constraints/checkers/no-test-simplification.js +4 -3
  165. package/dist/core/constraints/checkers/no-test-simplification.js.map +1 -1
  166. package/dist/core/constraints/checkers/types.d.ts +43 -4
  167. package/dist/core/constraints/checkers/types.d.ts.map +1 -1
  168. package/dist/core/constraints/checkers/types.js +33 -0
  169. package/dist/core/constraints/checkers/types.js.map +1 -1
  170. package/dist/core/constraints/context-builder.d.ts +15 -14
  171. package/dist/core/constraints/context-builder.d.ts.map +1 -1
  172. package/dist/core/constraints/context-builder.js +32 -96
  173. package/dist/core/constraints/context-builder.js.map +1 -1
  174. package/dist/core/constraints/doc-freshness/runner.d.ts.map +1 -1
  175. package/dist/core/constraints/doc-freshness/runner.js +2 -1
  176. package/dist/core/constraints/doc-freshness/runner.js.map +1 -1
  177. package/dist/core/constraints/git-evidence.d.ts +60 -0
  178. package/dist/core/constraints/git-evidence.d.ts.map +1 -0
  179. package/dist/core/constraints/git-evidence.js +88 -0
  180. package/dist/core/constraints/git-evidence.js.map +1 -0
  181. package/dist/core/constraints/injection-drift.d.ts +3 -20
  182. package/dist/core/constraints/injection-drift.d.ts.map +1 -1
  183. package/dist/core/constraints/injection-drift.js +10 -57
  184. package/dist/core/constraints/injection-drift.js.map +1 -1
  185. package/dist/core/constraints/injection-writer.d.ts +113 -0
  186. package/dist/core/constraints/injection-writer.d.ts.map +1 -0
  187. package/dist/core/constraints/injection-writer.js +228 -0
  188. package/dist/core/constraints/injection-writer.js.map +1 -0
  189. package/dist/core/constraints/usage-report.d.ts +22 -1
  190. package/dist/core/constraints/usage-report.d.ts.map +1 -1
  191. package/dist/core/constraints/usage-report.js +27 -20
  192. package/dist/core/constraints/usage-report.js.map +1 -1
  193. package/dist/core/index.d.ts +2 -2
  194. package/dist/core/index.d.ts.map +1 -1
  195. package/dist/core/index.js +4 -2
  196. package/dist/core/index.js.map +1 -1
  197. package/dist/core/project-config-loader.d.ts +32 -1
  198. package/dist/core/project-config-loader.d.ts.map +1 -1
  199. package/dist/core/project-config-loader.js +39 -9
  200. package/dist/core/project-config-loader.js.map +1 -1
  201. package/dist/core/validators/passes-gate.d.ts +15 -64
  202. package/dist/core/validators/passes-gate.d.ts.map +1 -1
  203. package/dist/core/validators/passes-gate.js +84 -222
  204. package/dist/core/validators/passes-gate.js.map +1 -1
  205. package/dist/core/validators/test-output.d.ts +58 -0
  206. package/dist/core/validators/test-output.d.ts.map +1 -0
  207. package/dist/core/validators/test-output.js +109 -0
  208. package/dist/core/validators/test-output.js.map +1 -0
  209. package/dist/failure/recorder.d.ts +6 -0
  210. package/dist/failure/recorder.d.ts.map +1 -1
  211. package/dist/failure/recorder.js +12 -8
  212. package/dist/failure/recorder.js.map +1 -1
  213. package/dist/gates/acceptance.d.ts +1 -48
  214. package/dist/gates/acceptance.d.ts.map +1 -1
  215. package/dist/gates/acceptance.js +6 -38
  216. package/dist/gates/acceptance.js.map +1 -1
  217. package/dist/gates/checker-gate.d.ts +2 -1
  218. package/dist/gates/checker-gate.d.ts.map +1 -1
  219. package/dist/gates/checker-gate.js +11 -13
  220. package/dist/gates/checker-gate.js.map +1 -1
  221. package/dist/gates/command.d.ts.map +1 -1
  222. package/dist/gates/command.js +10 -22
  223. package/dist/gates/command.js.map +1 -1
  224. package/dist/gates/contract.d.ts.map +1 -1
  225. package/dist/gates/contract.js +22 -61
  226. package/dist/gates/contract.js.map +1 -1
  227. package/dist/gates/performance.d.ts.map +1 -1
  228. package/dist/gates/performance.js +13 -31
  229. package/dist/gates/performance.js.map +1 -1
  230. package/dist/gates/review.d.ts.map +1 -1
  231. package/dist/gates/review.js +21 -53
  232. package/dist/gates/review.js.map +1 -1
  233. package/dist/gates/security.d.ts.map +1 -1
  234. package/dist/gates/security.js +14 -32
  235. package/dist/gates/security.js.map +1 -1
  236. package/dist/gates/types.d.ts +28 -5
  237. package/dist/gates/types.d.ts.map +1 -1
  238. package/dist/gates/types.js +38 -1
  239. package/dist/gates/types.js.map +1 -1
  240. package/dist/hooks/bootstrap.d.ts +2 -0
  241. package/dist/hooks/bootstrap.d.ts.map +1 -1
  242. package/dist/hooks/bootstrap.js +5 -2
  243. package/dist/hooks/bootstrap.js.map +1 -1
  244. package/dist/index.d.ts +1 -2
  245. package/dist/index.d.ts.map +1 -1
  246. package/dist/index.js.map +1 -1
  247. package/dist/knowledge/audit.d.ts +7 -2
  248. package/dist/knowledge/audit.d.ts.map +1 -1
  249. package/dist/knowledge/audit.js +59 -79
  250. package/dist/knowledge/audit.js.map +1 -1
  251. package/dist/knowledge/flywheel-metrics.d.ts +39 -0
  252. package/dist/knowledge/flywheel-metrics.d.ts.map +1 -0
  253. package/dist/knowledge/flywheel-metrics.js +47 -0
  254. package/dist/knowledge/flywheel-metrics.js.map +1 -0
  255. package/dist/knowledge/import.d.ts.map +1 -1
  256. package/dist/knowledge/import.js +4 -14
  257. package/dist/knowledge/import.js.map +1 -1
  258. package/dist/knowledge/index-generator.d.ts.map +1 -1
  259. package/dist/knowledge/index-generator.js +17 -14
  260. package/dist/knowledge/index-generator.js.map +1 -1
  261. package/dist/knowledge/ingest.d.ts.map +1 -1
  262. package/dist/knowledge/ingest.js +9 -4
  263. package/dist/knowledge/ingest.js.map +1 -1
  264. package/dist/knowledge/migration.d.ts.map +1 -1
  265. package/dist/knowledge/migration.js +11 -8
  266. package/dist/knowledge/migration.js.map +1 -1
  267. package/dist/knowledge/reference-tracker.d.ts.map +1 -1
  268. package/dist/knowledge/reference-tracker.js +12 -9
  269. package/dist/knowledge/reference-tracker.js.map +1 -1
  270. package/dist/knowledge/store.d.ts +15 -0
  271. package/dist/knowledge/store.d.ts.map +1 -1
  272. package/dist/knowledge/store.js +59 -10
  273. package/dist/knowledge/store.js.map +1 -1
  274. package/dist/monitoring/context-tracker.d.ts.map +1 -1
  275. package/dist/monitoring/context-tracker.js +11 -20
  276. package/dist/monitoring/context-tracker.js.map +1 -1
  277. package/dist/monitoring/index.d.ts +1 -1
  278. package/dist/monitoring/index.d.ts.map +1 -1
  279. package/dist/monitoring/index.js +1 -2
  280. package/dist/monitoring/index.js.map +1 -1
  281. package/dist/monitoring/trace-analyzer.d.ts +15 -0
  282. package/dist/monitoring/trace-analyzer.d.ts.map +1 -1
  283. package/dist/monitoring/trace-analyzer.js +19 -2
  284. package/dist/monitoring/trace-analyzer.js.map +1 -1
  285. package/dist/monitoring/traces.d.ts +21 -2
  286. package/dist/monitoring/traces.d.ts.map +1 -1
  287. package/dist/monitoring/traces.js +38 -29
  288. package/dist/monitoring/traces.js.map +1 -1
  289. package/dist/release/index.d.ts +2 -2
  290. package/dist/release/index.d.ts.map +1 -1
  291. package/dist/release/index.js +1 -5
  292. package/dist/release/index.js.map +1 -1
  293. package/dist/sdd/index-generator.js +10 -11
  294. package/dist/sdd/index-generator.js.map +1 -1
  295. package/dist/test-setup/project-fixture.d.ts +48 -0
  296. package/dist/test-setup/project-fixture.d.ts.map +1 -0
  297. package/dist/test-setup/project-fixture.js +106 -0
  298. package/dist/test-setup/project-fixture.js.map +1 -0
  299. package/dist/types/constraint.d.ts +8 -18
  300. package/dist/types/constraint.d.ts.map +1 -1
  301. package/dist/types/constraint.js +6 -1
  302. package/dist/types/constraint.js.map +1 -1
  303. package/dist/types/passes-gate.d.ts +10 -25
  304. package/dist/types/passes-gate.d.ts.map +1 -1
  305. package/dist/types/project-config.d.ts +1 -1
  306. package/dist/types/session.d.ts +6 -5
  307. package/dist/types/session.d.ts.map +1 -1
  308. package/dist/types/trace.d.ts +9 -0
  309. package/dist/types/trace.d.ts.map +1 -1
  310. package/dist/utils/exec.d.ts +10 -0
  311. package/dist/utils/exec.d.ts.map +1 -1
  312. package/dist/utils/exec.js +12 -0
  313. package/dist/utils/exec.js.map +1 -1
  314. package/dist/utils/file-walk.d.ts +9 -1
  315. package/dist/utils/file-walk.d.ts.map +1 -1
  316. package/dist/utils/file-walk.js +10 -1
  317. package/dist/utils/file-walk.js.map +1 -1
  318. package/dist/utils/frontmatter.d.ts +73 -0
  319. package/dist/utils/frontmatter.d.ts.map +1 -0
  320. package/dist/utils/frontmatter.js +141 -0
  321. package/dist/utils/frontmatter.js.map +1 -0
  322. package/dist/utils/jsonl.d.ts +92 -0
  323. package/dist/utils/jsonl.d.ts.map +1 -0
  324. package/dist/utils/jsonl.js +166 -0
  325. package/dist/utils/jsonl.js.map +1 -0
  326. package/dist/utils/package-version.d.ts +16 -0
  327. package/dist/utils/package-version.d.ts.map +1 -0
  328. package/dist/utils/package-version.js +63 -0
  329. package/dist/utils/package-version.js.map +1 -0
  330. package/package.json +1 -1
  331. package/src/CONTEXT.md +8 -2
  332. package/src/__tests__/acceptance-gate.test.ts +3 -1
  333. package/src/__tests__/checker-extra.test.ts +7 -1218
  334. package/src/__tests__/context-files-resolution.test.ts +116 -0
  335. package/src/__tests__/effective-constraints.test.ts +10 -13
  336. package/src/__tests__/exec.test.ts +35 -1
  337. package/src/__tests__/layering.test.ts +152 -0
  338. package/src/__tests__/passes-gate-extra.test.ts +0 -145
  339. package/src/__tests__/passes-gate.test.ts +130 -101
  340. package/src/__tests__/skip-semantics.test.ts +5 -9
  341. package/src/cli/__tests__/command-contract.test.ts +170 -0
  342. package/src/cli/command-contract.ts +108 -0
  343. package/src/cli/commands/CONTEXT.md +23 -8
  344. package/src/cli/commands/__tests__/acceptance.test.ts +40 -33
  345. package/src/cli/commands/__tests__/analyze-sessions.test.ts +35 -29
  346. package/src/cli/commands/__tests__/bin-exit-mapping.test.ts +107 -0
  347. package/src/cli/commands/__tests__/check-drift.test.ts +27 -34
  348. package/src/cli/commands/__tests__/check-skip-output.test.ts +21 -24
  349. package/src/cli/commands/__tests__/check.test.ts +448 -378
  350. package/src/cli/commands/__tests__/command.test.ts +85 -70
  351. package/src/cli/commands/__tests__/constraints-report.test.ts +100 -71
  352. package/src/cli/commands/__tests__/constraints-retire.test.ts +152 -95
  353. package/src/cli/commands/__tests__/contract.test.ts +27 -34
  354. package/src/cli/commands/__tests__/failure.test.ts +31 -34
  355. package/src/cli/commands/__tests__/init-injection.test.ts +58 -28
  356. package/src/cli/commands/__tests__/init.test.ts +77 -48
  357. package/src/cli/commands/__tests__/knowledge-flywheel-consistency.test.ts +108 -0
  358. package/src/cli/commands/__tests__/knowledge.test.ts +69 -43
  359. package/src/cli/commands/__tests__/passes-gate.test.ts +43 -45
  360. package/src/cli/commands/__tests__/performance.test.ts +22 -23
  361. package/src/cli/commands/__tests__/posteval-plan.test.ts +39 -38
  362. package/src/cli/commands/__tests__/project-path-anchoring.test.ts +157 -0
  363. package/src/cli/commands/__tests__/project-path-convention.test.ts +231 -0
  364. package/src/cli/commands/__tests__/registry.test.ts +75 -35
  365. package/src/cli/commands/__tests__/release.test.ts +209 -80
  366. package/src/cli/commands/__tests__/report-extra.test.ts +16 -16
  367. package/src/cli/commands/__tests__/report.test.ts +25 -25
  368. package/src/cli/commands/__tests__/review.test.ts +33 -31
  369. package/src/cli/commands/__tests__/security.test.ts +23 -27
  370. package/src/cli/commands/__tests__/spec-baseline-check.test.ts +20 -20
  371. package/src/cli/commands/__tests__/spec.test.ts +41 -29
  372. package/src/cli/commands/__tests__/status-extra.test.ts +18 -18
  373. package/src/cli/commands/__tests__/status-skipped-lines.test.ts +72 -0
  374. package/src/cli/commands/__tests__/status.test.ts +34 -34
  375. package/src/cli/commands/__tests__/sync-docs-agents.test.ts +77 -78
  376. package/src/cli/commands/__tests__/sync-docs.test.ts +72 -74
  377. package/src/cli/commands/__tests__/update-user-model.test.ts +97 -34
  378. package/src/cli/commands/__tests__/validate.test.ts +27 -29
  379. package/src/cli/commands/acceptance.ts +35 -24
  380. package/src/cli/commands/analyze-sessions.ts +25 -24
  381. package/src/cli/commands/check.ts +127 -66
  382. package/src/cli/commands/command.ts +30 -17
  383. package/src/cli/commands/constraints-report.ts +37 -34
  384. package/src/cli/commands/constraints-retire.ts +58 -55
  385. package/src/cli/commands/constraints.ts +10 -27
  386. package/src/cli/commands/contract.ts +51 -42
  387. package/src/cli/commands/definitions.ts +34 -227
  388. package/src/cli/commands/failure.ts +33 -26
  389. package/src/cli/commands/init.ts +166 -220
  390. package/src/cli/commands/knowledge.ts +192 -289
  391. package/src/cli/commands/passes-gate.ts +58 -68
  392. package/src/cli/commands/performance.ts +23 -18
  393. package/src/cli/commands/posteval-plan.ts +29 -15
  394. package/src/cli/commands/release.ts +70 -59
  395. package/src/cli/commands/report.ts +9 -5
  396. package/src/cli/commands/review.ts +39 -29
  397. package/src/cli/commands/sdd.ts +7 -5
  398. package/src/cli/commands/security.ts +35 -26
  399. package/src/cli/commands/spec-baseline-check.ts +16 -11
  400. package/src/cli/commands/spec.ts +66 -53
  401. package/src/cli/commands/status.ts +59 -53
  402. package/src/cli/commands/sync-docs/agents-syncer.ts +5 -2
  403. package/src/cli/commands/sync-docs/context-syncer.ts +3 -2
  404. package/src/cli/commands/sync-docs/index.ts +73 -100
  405. package/src/cli/commands/sync-docs/project-reader.ts +17 -18
  406. package/src/cli/commands/update-user-model.ts +64 -61
  407. package/src/cli/commands/validate.ts +31 -25
  408. package/src/cli/session-mining/__tests__/transcript.test.ts +118 -0
  409. package/src/cli/session-mining/transcript.ts +26 -8
  410. package/src/context/session-manager.ts +19 -33
  411. package/src/core/CONTEXT.md +10 -6
  412. package/src/core/constraints/__tests__/capabilities-reconcile.test.ts +200 -0
  413. package/src/core/constraints/__tests__/capability-counts.test.ts +94 -0
  414. package/src/core/constraints/__tests__/git-evidence.test.ts +208 -0
  415. package/src/core/constraints/__tests__/injection-drift.test.ts +3 -10
  416. package/src/core/constraints/__tests__/injection-writer.test.ts +231 -0
  417. package/src/core/constraints/__tests__/trace-injection.test.ts +71 -0
  418. package/src/core/constraints/__tests__/usage-report.test.ts +112 -0
  419. package/src/core/constraints/agent-prompt-renderer.ts +2 -6
  420. package/src/core/constraints/capabilities-parser.ts +53 -35
  421. package/src/core/constraints/capabilities-reconcile.ts +166 -0
  422. package/src/core/constraints/checker.ts +82 -133
  423. package/src/core/constraints/checkers/__tests__/capability-sync.test.ts +273 -0
  424. package/src/core/constraints/checkers/__tests__/check-outcome.test.ts +176 -0
  425. package/src/core/constraints/checkers/__tests__/context-doc-sync.test.ts +77 -0
  426. package/src/core/constraints/checkers/__tests__/docs-freshness.test.ts +126 -0
  427. package/src/{__tests__ → core/constraints/checkers/__tests__}/governance-presence.test.ts +83 -9
  428. package/src/core/constraints/checkers/__tests__/iron-flags.test.ts +50 -0
  429. package/src/core/constraints/checkers/__tests__/no-bypass-checkpoint.test.ts +76 -0
  430. package/src/{__tests__ → core/constraints/checkers/__tests__}/no-hardcoded-credentials.test.ts +4 -3
  431. package/src/core/constraints/checkers/__tests__/no-test-simplification.test.ts +58 -0
  432. package/src/core/constraints/checkers/__tests__/three-state-consistency.test.ts +153 -0
  433. package/src/core/constraints/checkers/capability-sync.ts +75 -96
  434. package/src/core/constraints/checkers/context-doc-sync.ts +15 -25
  435. package/src/core/constraints/checkers/docs-freshness.ts +54 -70
  436. package/src/core/constraints/checkers/governance-presence.ts +7 -25
  437. package/src/core/constraints/checkers/index.ts +9 -2
  438. package/src/core/constraints/checkers/no-test-simplification.ts +4 -3
  439. package/src/core/constraints/checkers/types.ts +60 -4
  440. package/src/core/constraints/context-builder.ts +39 -91
  441. package/src/core/constraints/doc-freshness/runner.ts +2 -1
  442. package/src/core/constraints/git-evidence.ts +120 -0
  443. package/src/core/constraints/injection-drift.ts +13 -60
  444. package/src/core/constraints/injection-writer.ts +212 -0
  445. package/src/core/constraints/usage-report.ts +36 -17
  446. package/src/core/index.ts +4 -2
  447. package/src/core/project-config-loader.ts +49 -9
  448. package/src/core/validators/__tests__/passes-gate.test.ts +2 -56
  449. package/src/core/validators/__tests__/test-output.test.ts +372 -0
  450. package/src/core/validators/passes-gate.ts +86 -248
  451. package/src/core/validators/test-output.ts +128 -0
  452. package/src/failure/__tests__/recorder.test.ts +168 -0
  453. package/src/failure/recorder.ts +12 -10
  454. package/src/gates/CONTEXT.md +7 -4
  455. package/src/gates/__tests__/acceptance-types-single-source.test.ts +68 -0
  456. package/src/gates/__tests__/acceptance.test.ts +4 -86
  457. package/src/gates/__tests__/checker-gate.test.ts +24 -0
  458. package/src/gates/__tests__/effective-gates.test.ts +3 -8
  459. package/src/gates/__tests__/test-verdict-consistency.test.ts +140 -0
  460. package/src/gates/acceptance.ts +19 -84
  461. package/src/gates/checker-gate.ts +12 -15
  462. package/src/gates/command.ts +10 -16
  463. package/src/gates/contract.ts +22 -61
  464. package/src/gates/performance.ts +10 -22
  465. package/src/gates/review.ts +21 -41
  466. package/src/gates/security.ts +10 -22
  467. package/src/gates/types.ts +70 -5
  468. package/src/hooks/CONTEXT.md +1 -1
  469. package/src/hooks/bootstrap.ts +5 -2
  470. package/src/index.ts +0 -4
  471. package/src/knowledge/CONTEXT.md +8 -3
  472. package/src/knowledge/__tests__/audit-labels.test.ts +44 -0
  473. package/src/knowledge/__tests__/flywheel-metrics.test.ts +135 -0
  474. package/src/knowledge/__tests__/import.test.ts +44 -0
  475. package/src/knowledge/__tests__/index-generator.test.ts +53 -0
  476. package/src/knowledge/__tests__/ingest.test.ts +85 -0
  477. package/src/knowledge/__tests__/migration.test.ts +47 -0
  478. package/src/knowledge/__tests__/reference-tracker.test.ts +16 -0
  479. package/src/knowledge/__tests__/store.test.ts +194 -0
  480. package/src/knowledge/audit.ts +67 -71
  481. package/src/knowledge/flywheel-metrics.ts +71 -0
  482. package/src/knowledge/import.ts +4 -18
  483. package/src/knowledge/index-generator.ts +19 -14
  484. package/src/knowledge/ingest.ts +9 -4
  485. package/src/knowledge/migration.ts +11 -8
  486. package/src/knowledge/reference-tracker.ts +12 -8
  487. package/src/knowledge/store.ts +64 -11
  488. package/src/monitoring/CONTEXT.md +8 -3
  489. package/src/monitoring/__tests__/skipped-lines-report.test.ts +178 -0
  490. package/src/monitoring/__tests__/traces.test.ts +57 -0
  491. package/src/monitoring/context-tracker.ts +11 -23
  492. package/src/monitoring/index.ts +1 -1
  493. package/src/monitoring/trace-analyzer.ts +21 -2
  494. package/src/monitoring/traces.ts +39 -36
  495. package/src/release/CONTEXT.md +1 -0
  496. package/src/release/__tests__/barrel.test.ts +60 -0
  497. package/src/release/index.ts +2 -13
  498. package/src/sdd/__tests__/index-generator.test.ts +71 -0
  499. package/src/sdd/index-generator.ts +9 -9
  500. package/src/test-setup/__tests__/project-fixture.test.ts +178 -0
  501. package/src/test-setup/project-fixture.ts +87 -0
  502. package/src/tools/CONTEXT.md +6 -0
  503. package/src/tools/__tests__/registry.test.ts +221 -0
  504. package/src/types/__tests__/types.test.ts +4 -5
  505. package/src/types/constraint.ts +16 -27
  506. package/src/types/passes-gate.ts +10 -30
  507. package/src/types/project-config.ts +1 -1
  508. package/src/types/session.ts +5 -5
  509. package/src/types/trace.ts +10 -0
  510. package/src/utils/__tests__/frontmatter.test.ts +206 -0
  511. package/src/utils/__tests__/jsonl-skip-disposition.test.ts +175 -0
  512. package/src/utils/__tests__/jsonl.test.ts +187 -0
  513. package/src/utils/__tests__/package-version.test.ts +97 -0
  514. package/src/utils/exec.ts +15 -0
  515. package/src/utils/file-walk.ts +11 -2
  516. package/src/utils/frontmatter.ts +121 -0
  517. package/src/utils/jsonl.ts +167 -0
  518. package/src/utils/package-version.ts +27 -0
  519. package/dist/cli/commands/doc-freshness-check.d.ts +0 -53
  520. package/dist/cli/commands/doc-freshness-check.d.ts.map +0 -1
  521. package/dist/cli/commands/doc-freshness-check.js +0 -352
  522. package/dist/cli/commands/doc-freshness-check.js.map +0 -1
  523. package/dist/types/index.d.ts +0 -14
  524. package/dist/types/index.d.ts.map +0 -1
  525. package/dist/types/index.js +0 -39
  526. package/dist/types/index.js.map +0 -1
  527. package/src/__tests__/long-running.test.ts +0 -17
  528. package/src/__tests__/passes-gate-extension.test.ts +0 -151
  529. package/src/cli/commands/__tests__/doc-freshness-check.test.ts +0 -168
  530. package/src/cli/commands/doc-freshness-check.ts +0 -386
  531. package/src/spec/CONTEXT.md +0 -11
  532. package/src/types/index.ts +0 -47
@@ -47,14 +47,16 @@ exports.setupAgentsMdConstraints = setupAgentsMdConstraints;
47
47
  exports.setupClaudeMdConstraints = setupClaudeMdConstraints;
48
48
  exports.setupGovernanceConstraints = setupGovernanceConstraints;
49
49
  const chalk_1 = __importDefault(require("chalk"));
50
- const fs_1 = require("fs");
51
50
  const fs = __importStar(require("fs/promises"));
52
51
  const path = __importStar(require("path"));
53
52
  const yaml = __importStar(require("js-yaml"));
54
53
  const validate_1 = require("./validate");
55
54
  const detect_source_roots_1 = require("../../utils/detect-source-roots");
55
+ const package_version_1 = require("../../utils/package-version");
56
56
  const effective_constraints_1 = require("../../core/effective-constraints");
57
57
  const injection_renderer_1 = require("../../core/constraints/injection-renderer");
58
+ const injection_writer_1 = require("../../core/constraints/injection-writer");
59
+ const command_contract_1 = require("../command-contract");
58
60
  /**
59
61
  * 默认配置
60
62
  *
@@ -85,7 +87,7 @@ const PRESETS = {
85
87
  },
86
88
  };
87
89
  /**
88
- * 治理预设
90
+ * 治理预设(形状 = 写入 config.yml 的 governance 段,直接用类型正本)
89
91
  */
90
92
  const GOVERNANCE_PRESETS = {
91
93
  minimal: {
@@ -152,97 +154,91 @@ const GOVERNANCE_PRESETS = {
152
154
  /**
153
155
  * 初始化项目
154
156
  */
155
- async function init(options) {
157
+ async function init(options, io = command_contract_1.processIO) {
156
158
  // 只输出代码片段
157
159
  if (options.printSnippets) {
158
- printSnippets();
159
- return;
160
+ printSnippets(io);
161
+ return { kind: 'ok' };
160
162
  }
161
- console.log(chalk_1.default.blue('🚀 初始化 harness 配置...'));
163
+ (0, command_contract_1.log)(io, chalk_1.default.blue('🚀 初始化 harness 配置...'));
162
164
  const projectPath = options.projectPath || process.cwd();
163
165
  const configDir = path.join(projectPath, '.harness');
164
166
  // 创建配置目录
165
167
  await fs.mkdir(configDir, { recursive: true });
166
- console.log(chalk_1.default.gray(`配置目录: ${configDir}`));
168
+ (0, command_contract_1.log)(io, chalk_1.default.gray(`配置目录: ${configDir}`));
167
169
  // 选择预设
168
170
  const preset = PRESETS[options.preset];
169
- console.log(chalk_1.default.gray(`预设: ${options.preset}`));
171
+ (0, command_contract_1.log)(io, chalk_1.default.gray(`预设: ${options.preset}`));
170
172
  // 合并治理配置
171
173
  const configData = { ...preset };
172
174
  if (options.governance) {
173
175
  configData.governance = GOVERNANCE_PRESETS[options.governance];
174
- console.log(chalk_1.default.gray(`治理级别: ${options.governance}`));
176
+ (0, command_contract_1.log)(io, chalk_1.default.gray(`治理级别: ${options.governance}`));
175
177
  }
176
178
  // 写入 harness 版本
177
- const pkgVersion = getPackageVersion();
179
+ const pkgVersion = (0, package_version_1.getHarnessPackageVersion)();
178
180
  configData.harness = { version: pkgVersion };
179
181
  // 写入配置文件(harness 管理的配置,始终重新生成)
180
182
  const configPath = path.join(configDir, 'config.yml');
181
183
  const configContent = yaml.dump(configData, { indent: 2 });
182
184
  await fs.writeFile(configPath, configContent, 'utf-8');
183
- console.log(chalk_1.default.green(`✅ 已创建配置文件: ${configPath} (v${pkgVersion})`));
185
+ (0, command_contract_1.log)(io, chalk_1.default.green(`✅ 已创建配置文件: ${configPath} (v${pkgVersion})`));
184
186
  // 创建检查点示例
185
- await (0, validate_1.createExampleCheckpoint)(projectPath);
187
+ await (0, validate_1.createExampleCheckpoint)(projectPath, io);
186
188
  // 创建 Resolutions(RKB 狗粮 — 约束 → 已知解法映射)
187
- await (0, validate_1.createExampleResolutions)(projectPath);
189
+ await (0, validate_1.createExampleResolutions)(projectPath, io);
188
190
  // 创建自定义约束示例
189
- await createCustomConstraintsExample(projectPath);
191
+ await createCustomConstraintsExample(projectPath, io);
190
192
  // CAPABILITIES.md / CHANGELOG.md 由 sync-docs(AI 治理)管理,init 不创建
191
193
  // 创建 Git hooks
192
194
  if (options.gitHooks !== false) {
193
- await setupGitHooks(projectPath);
195
+ await setupGitHooks(projectPath, io);
194
196
  }
195
197
  // 创建 GitHub Actions
196
198
  if (options.githubActions !== false) {
197
- await setupGitHubActions(projectPath);
199
+ await setupGitHubActions(projectPath, io);
198
200
  }
199
201
  // 治理相关文件生成
200
202
  if (options.governance) {
201
- await setupGovernance(projectPath, options.governance);
202
- }
203
- console.log();
204
- console.log(chalk_1.default.green('✅ harness 初始化完成!'));
205
- console.log();
206
- console.log(chalk_1.default.gray('下一步:'));
207
- console.log(chalk_1.default.gray(' 1. 编辑 .harness/config.yml 自定义配置'));
208
- console.log(chalk_1.default.gray(' 2. 编辑 .harness/custom-constraints.yml 添加项目约束'));
209
- console.log(chalk_1.default.gray(' 3. 正常开发,每次 git commit 会自动检查约束'));
210
- console.log(chalk_1.default.gray(' 4. 运行 harness status 查看状态'));
211
- console.log();
212
- console.log(chalk_1.default.blue('💡 提示: 使用 harness init --print-snippets 查看配置代码片段'));
213
- }
214
- /**
215
- * 获取 harness 包版本
216
- */
217
- function getPackageVersion() {
218
- try {
219
- // eslint-disable-next-line @typescript-eslint/no-var-requires
220
- return require('../../../package.json').version;
221
- }
222
- catch {
223
- return 'unknown';
224
- }
203
+ await setupGovernance(projectPath, options.governance, io);
204
+ }
205
+ (0, command_contract_1.log)(io);
206
+ (0, command_contract_1.log)(io, chalk_1.default.green('✅ harness 初始化完成!'));
207
+ (0, command_contract_1.log)(io);
208
+ (0, command_contract_1.log)(io, chalk_1.default.gray('下一步:'));
209
+ (0, command_contract_1.log)(io, chalk_1.default.gray(' 1. 编辑 .harness/config.yml 自定义配置'));
210
+ (0, command_contract_1.log)(io, chalk_1.default.gray(' 2. 编辑 .harness/custom-constraints.yml 添加项目约束'));
211
+ (0, command_contract_1.log)(io, chalk_1.default.gray(' 3. 正常开发,每次 git commit 会自动检查约束'));
212
+ (0, command_contract_1.log)(io, chalk_1.default.gray(' 4. 运行 harness status 查看状态'));
213
+ (0, command_contract_1.log)(io);
214
+ (0, command_contract_1.log)(io, chalk_1.default.blue('💡 提示: 使用 harness init --print-snippets 查看配置代码片段'));
215
+ return { kind: 'ok' };
225
216
  }
226
217
  /**
227
218
  * 输出代码片段
228
219
  */
229
- function printSnippets() {
230
- console.log(chalk_1.default.blue('📄 Harness 配置代码片段'));
231
- console.log();
232
- console.log(chalk_1.default.yellow('Git pre-commit hook:'));
233
- console.log(chalk_1.default.gray('添加到 .git/hooks/pre-commit'));
234
- console.log();
235
- console.log(chalk_1.default.cyan(PRE_COMMIT_SNIPPET));
236
- console.log(chalk_1.default.yellow('GitHub Actions:'));
237
- console.log(chalk_1.default.gray('添加到 .github/workflows/*.yml 的 jobs 中'));
238
- console.log();
239
- console.log(chalk_1.default.cyan(GITHUB_ACTIONS_SNIPPET));
240
- console.log(chalk_1.default.blue('💡 提示: 运行 npx @dommaker/harness init 自动创建配置文件'));
220
+ function printSnippets(io) {
221
+ (0, command_contract_1.log)(io, chalk_1.default.blue('📄 Harness 配置代码片段'));
222
+ (0, command_contract_1.log)(io);
223
+ (0, command_contract_1.log)(io, chalk_1.default.yellow('Git pre-commit hook:'));
224
+ (0, command_contract_1.log)(io, chalk_1.default.gray('添加到 .git/hooks/pre-commit'));
225
+ (0, command_contract_1.log)(io);
226
+ (0, command_contract_1.log)(io, chalk_1.default.cyan(PRE_COMMIT_SNIPPET));
227
+ (0, command_contract_1.log)(io, chalk_1.default.yellow('GitHub Actions:'));
228
+ (0, command_contract_1.log)(io, chalk_1.default.gray('添加到 .github/workflows/*.yml 的 jobs 中'));
229
+ (0, command_contract_1.log)(io);
230
+ (0, command_contract_1.log)(io, chalk_1.default.cyan(GITHUB_ACTIONS_SNIPPET));
231
+ (0, command_contract_1.log)(io, chalk_1.default.blue('💡 提示: 运行 npx @dommaker/harness init 自动创建配置文件'));
241
232
  }
242
233
  /**
243
- * Git pre-commit 代码片段
234
+ * Git pre-commit 代码片段(#103:打印片段与落盘 hook 的唯一正本;
235
+ * 落盘 hook = `#!/bin/sh` 头 + 本常量,改钩子只改这里)
244
236
  */
245
237
  const PRE_COMMIT_SNIPPET = `
238
+ echo "🔍 Running harness checks..."
239
+
240
+ STAGED=$(git diff --cached --name-only --diff-filter=ACMR 2>/dev/null || true)
241
+
246
242
  # Harness 约束检查
247
243
  npx @dommaker/harness check --staged
248
244
  if [ $? -ne 0 ]; then
@@ -251,7 +247,6 @@ if [ $? -ne 0 ]; then
251
247
  fi
252
248
 
253
249
  # Plan coverage check (via PostEval)
254
- STAGED=$(git diff --cached --name-only --diff-filter=ACMR 2>/dev/null || true)
255
250
  if command -v npx > /dev/null 2>&1; then
256
251
  PLAN_FILES=$(echo "$STAGED" | grep -E 'plans/.*\\.md$|\\.plan\\.md$' || true)
257
252
  if [ -n "$PLAN_FILES" ]; then
@@ -264,6 +259,8 @@ if command -v npx > /dev/null 2>&1; then
264
259
  done
265
260
  fi
266
261
  fi
262
+
263
+ echo "✅ All checks passed"
267
264
  `;
268
265
  /**
269
266
  * GitHub Actions 代码片段
@@ -282,7 +279,7 @@ const GITHUB_ACTIONS_SNIPPET = `
282
279
  /**
283
280
  * 设置 Git hooks
284
281
  */
285
- async function setupGitHooks(projectPath) {
282
+ async function setupGitHooks(projectPath, io) {
286
283
  const gitDir = path.join(projectPath, '.git');
287
284
  const hooksDir = path.join(gitDir, 'hooks');
288
285
  const preCommitPath = path.join(hooksDir, 'pre-commit');
@@ -290,8 +287,8 @@ async function setupGitHooks(projectPath) {
290
287
  await fs.access(gitDir);
291
288
  }
292
289
  catch {
293
- console.log(chalk_1.default.yellow('⚠️ 未检测到 Git 仓库,跳过 Git hooks'));
294
- console.log(chalk_1.default.gray('💡 初始化 Git 后可运行 npx @dommaker/harness init --print-snippets 查看配置'));
290
+ (0, command_contract_1.log)(io, chalk_1.default.yellow('⚠️ 未检测到 Git 仓库,跳过 Git hooks'));
291
+ (0, command_contract_1.log)(io, chalk_1.default.gray('💡 初始化 Git 后可运行 npx @dommaker/harness init --print-snippets 查看配置'));
295
292
  return;
296
293
  }
297
294
  await fs.mkdir(hooksDir, { recursive: true });
@@ -299,65 +296,38 @@ async function setupGitHooks(projectPath) {
299
296
  try {
300
297
  await fs.access(preCommitPath);
301
298
  // 已存在,输出代码片段
302
- console.log(chalk_1.default.yellow('⚠️ .git/hooks/pre-commit 已存在'));
303
- console.log(chalk_1.default.gray('💡 请手动添加以下内容到文件末尾:'));
304
- console.log();
305
- console.log(chalk_1.default.cyan(PRE_COMMIT_SNIPPET));
299
+ (0, command_contract_1.log)(io, chalk_1.default.yellow('⚠️ .git/hooks/pre-commit 已存在'));
300
+ (0, command_contract_1.log)(io, chalk_1.default.gray('💡 请手动添加以下内容到文件末尾:'));
301
+ (0, command_contract_1.log)(io);
302
+ (0, command_contract_1.log)(io, chalk_1.default.cyan(PRE_COMMIT_SNIPPET));
306
303
  }
307
304
  catch {
308
- // 不存在,创建文件
305
+ // 不存在,创建文件:shebang 头 + 共享片段(#103 同源,无第二份文本)
309
306
  const preCommitContent = `#!/bin/sh
310
307
  # Harness pre-commit hook
311
-
312
- echo "🔍 Running harness checks..."
313
-
314
- STAGED=$(git diff --cached --name-only --diff-filter=ACMR 2>/dev/null || true)
315
-
316
- # 铁律检查
317
- npx @dommaker/harness check --staged
318
- if [ $? -ne 0 ]; then
319
- echo "❌ Iron law check failed"
320
- exit 1
321
- fi
322
-
323
- # Plan coverage check (via PostEval)
324
- if command -v npx > /dev/null 2>&1; then
325
- PLAN_FILES=$(echo "$STAGED" | grep -E 'plans/.*\\.md$|\\.plan\\.md$' || true)
326
- if [ -n "$PLAN_FILES" ]; then
327
- echo "📋 Checking plan coverage..."
328
- for plan in $PLAN_FILES; do
329
- npx @dommaker/harness posteval-plan "$plan" || {
330
- echo "🛑 Plan coverage incomplete. See above for missed items."
331
- exit 1
332
- }
333
- done
334
- fi
335
- fi
336
-
337
- echo "✅ All checks passed"
338
- `;
308
+ ${PRE_COMMIT_SNIPPET}`;
339
309
  await fs.writeFile(preCommitPath, preCommitContent, 'utf-8');
340
310
  await fs.chmod(preCommitPath, 0o755);
341
- console.log(chalk_1.default.green(`✅ 已创建 .git/hooks/pre-commit`));
311
+ (0, command_contract_1.log)(io, chalk_1.default.green(`✅ 已创建 .git/hooks/pre-commit`));
342
312
  }
343
313
  }
344
314
  /**
345
315
  * 设置 GitHub Actions
346
316
  */
347
- async function setupGitHubActions(projectPath) {
317
+ async function setupGitHubActions(projectPath, io) {
348
318
  const workflowsDir = path.join(projectPath, '.github', 'workflows');
349
319
  const workflowPath = path.join(workflowsDir, 'harness-check.yml');
350
320
  // 检查是否已有 CI 配置
351
321
  const existingFiles = await findCiWorkflows(workflowsDir);
352
322
  if (existingFiles.length > 0) {
353
323
  // 已有 CI 配置,输出代码片段
354
- console.log(chalk_1.default.yellow('⚠️ 检测到已存在的 CI 配置:'));
324
+ (0, command_contract_1.log)(io, chalk_1.default.yellow('⚠️ 检测到已存在的 CI 配置:'));
355
325
  existingFiles.forEach(f => {
356
- console.log(chalk_1.default.gray(` - .github/workflows/${f}`));
326
+ (0, command_contract_1.log)(io, chalk_1.default.gray(` - .github/workflows/${f}`));
357
327
  });
358
- console.log(chalk_1.default.gray('💡 请手动添加以下内容到 jobs 中:'));
359
- console.log();
360
- console.log(chalk_1.default.cyan(GITHUB_ACTIONS_SNIPPET));
328
+ (0, command_contract_1.log)(io, chalk_1.default.gray('💡 请手动添加以下内容到 jobs 中:'));
329
+ (0, command_contract_1.log)(io);
330
+ (0, command_contract_1.log)(io, chalk_1.default.cyan(GITHUB_ACTIONS_SNIPPET));
361
331
  return;
362
332
  }
363
333
  // 没有现有 CI 配置,创建文件
@@ -395,7 +365,7 @@ jobs:
395
365
  run: npx @dommaker/harness passes-gate
396
366
  `;
397
367
  await fs.writeFile(workflowPath, workflowContent, 'utf-8');
398
- console.log(chalk_1.default.green(`✅ 已创建 .github/workflows/harness-check.yml`));
368
+ (0, command_contract_1.log)(io, chalk_1.default.green(`✅ 已创建 .github/workflows/harness-check.yml`));
399
369
  }
400
370
  /**
401
371
  * 查找已存在的 CI 工作流文件
@@ -414,13 +384,13 @@ async function findCiWorkflows(workflowsDir) {
414
384
  /**
415
385
  * 创建自定义约束示例
416
386
  */
417
- async function createCustomConstraintsExample(projectPath) {
387
+ async function createCustomConstraintsExample(projectPath, io) {
418
388
  const configDir = path.join(projectPath, '.harness');
419
389
  const customConstraintsPath = path.join(configDir, 'custom-constraints.yml');
420
390
  // 如果已存在,不覆盖
421
391
  try {
422
392
  await fs.access(customConstraintsPath);
423
- console.log(chalk_1.default.gray(`custom-constraints.yml 已存在`));
393
+ (0, command_contract_1.log)(io, chalk_1.default.gray(`custom-constraints.yml 已存在`));
424
394
  return;
425
395
  }
426
396
  catch {
@@ -461,7 +431,7 @@ custom_constraints:
461
431
  # trigger: ["file_creation"]
462
432
  `;
463
433
  await fs.writeFile(customConstraintsPath, content, 'utf-8');
464
- console.log(chalk_1.default.green(`✅ 已创建自定义约束示例: custom-constraints.yml`));
434
+ (0, command_contract_1.log)(io, chalk_1.default.green(`✅ 已创建自定义约束示例: custom-constraints.yml`));
465
435
  }
466
436
  /**
467
437
  * Output Style 段标记(ADR-0001:init 只写标记区间内,标记外只读)
@@ -492,7 +462,7 @@ function renderOutputStyleSection() {
492
462
  * - 无标记且 `## Output Style` 段为用户自写(特征串不匹配):跳过并提示,不重复追加
493
463
  * - 完全没有该段:在文件顶部插入标记版
494
464
  */
495
- async function setupClaudeMdOutputStyle(projectPath) {
465
+ async function setupClaudeMdOutputStyle(projectPath, io = command_contract_1.processIO) {
496
466
  const claudeMdPath = path.join(projectPath, 'CLAUDE.md');
497
467
  let content;
498
468
  try {
@@ -503,19 +473,19 @@ async function setupClaudeMdOutputStyle(projectPath) {
503
473
  return;
504
474
  }
505
475
  const section = renderOutputStyleSection();
506
- const startIdx = content.indexOf(OUTPUT_STYLE_START);
507
- const endIdx = content.indexOf(OUTPUT_STYLE_END);
508
- if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
509
- // 替换标记间内容(标记本身也替换,保持最新文本)。
510
- // 尾部换行规范化:标记后恰好保留一个换行分隔,保证重复运行幂等。
511
- const after = content.slice(endIdx + OUTPUT_STYLE_END.length).replace(/^\n+/, '');
512
- const newContent = content.slice(0, startIdx) + section + (after ? '\n' + after : '');
513
- if (newContent !== content) {
514
- await fs.writeFile(claudeMdPath, newContent, 'utf-8');
515
- console.log(chalk_1.default.green('✅ 已更新 CLAUDE.md Output Style 段'));
476
+ const write = (0, injection_writer_1.replaceStandaloneRange)(content, OUTPUT_STYLE_START, OUTPUT_STYLE_END, section);
477
+ if (write.kind === 'updated') {
478
+ // 尾部换行规范化在 writer 内(幂等)。
479
+ if (write.content !== content) {
480
+ await fs.writeFile(claudeMdPath, write.content, 'utf-8');
481
+ (0, command_contract_1.log)(io, chalk_1.default.green('✅ 已更新 CLAUDE.md Output Style 段'));
516
482
  }
517
483
  return;
518
484
  }
485
+ if (write.kind === 'half') {
486
+ (0, command_contract_1.log)(io, chalk_1.default.yellow('⚠️ CLAUDE.md 中 HARNESS_OUTPUT_STYLE 标记残缺(单边或乱序),跳过 Output Style 注入,请人工修复'));
487
+ return;
488
+ }
519
489
  // 检测旧版无标记 `## Output Style` 段
520
490
  const legacyMatch = /^## Output Style[ \t]*$/m.exec(content);
521
491
  if (legacyMatch) {
@@ -526,7 +496,7 @@ async function setupClaudeMdOutputStyle(projectPath) {
526
496
  const legacySection = content.slice(sectionStart, sectionEnd);
527
497
  if (!legacySection.includes(LEGACY_OUTPUT_STYLE_FINGERPRINT)) {
528
498
  // 用户自写的同名 section:不动,也不追加(避免重复)
529
- console.log(chalk_1.default.yellow('⚠️ CLAUDE.md 已存在自定义 "## Output Style" 段,跳过 harness Output Style 注入'));
499
+ (0, command_contract_1.log)(io, chalk_1.default.yellow('⚠️ CLAUDE.md 已存在自定义 "## Output Style" 段,跳过 harness Output Style 注入'));
530
500
  return;
531
501
  }
532
502
  // 旧版 harness 写入:原位置换为标记版
@@ -534,12 +504,12 @@ async function setupClaudeMdOutputStyle(projectPath) {
534
504
  const after = content.slice(sectionEnd);
535
505
  const newContent = before + section + (after.length > 0 ? '\n' + after : '');
536
506
  await fs.writeFile(claudeMdPath, newContent, 'utf-8');
537
- console.log(chalk_1.default.green('✅ 已将 CLAUDE.md Output Style 段迁移为标记化管理'));
507
+ (0, command_contract_1.log)(io, chalk_1.default.green('✅ 已将 CLAUDE.md Output Style 段迁移为标记化管理'));
538
508
  return;
539
509
  }
540
510
  // 完全没有该段:插入文件顶部
541
511
  await fs.writeFile(claudeMdPath, section + '\n' + content, 'utf-8');
542
- console.log(chalk_1.default.green('✅ 已在 CLAUDE.md 顶部写入 Output Style 段'));
512
+ (0, command_contract_1.log)(io, chalk_1.default.green('✅ 已在 CLAUDE.md 顶部写入 Output Style 段'));
543
513
  }
544
514
  /**
545
515
  * 治理契约 PRESERVE 段标记(studio #302,ADR 2026-08-21 落点模型:
@@ -556,14 +526,14 @@ const GOVERNANCE_PRESERVE_END = '<!-- /PRESERVE:governance -->';
556
526
  * 有标记则只替换标记区间,段内其余手写内容(治理契约引言/流程/纪律等)原样保留;
557
527
  * 无标记(纯手写段)则在段尾追加注入段,不动手写内容
558
528
  * - 无该段:在文件末尾追加
559
- * - 段标记残缺(只有单边标记):不写入,告警交由人工修复(防二次损坏)
529
+ * - 段标记残缺(外层或段内 HARNESS_CONSTRAINTS 单边/乱序):不写入,告警交由人工修复(防二次损坏)
560
530
  */
561
- async function setupAgentsMdConstraints(projectPath) {
531
+ async function setupAgentsMdConstraints(projectPath, io = command_contract_1.processIO) {
562
532
  const agentsMdPath = path.join(projectPath, 'AGENTS.md');
563
- const version = getPackageVersion();
533
+ const version = (0, package_version_1.getHarnessPackageVersion)();
564
534
  const constraints = (0, effective_constraints_1.getEffectiveConstraints)(projectPath);
565
535
  const bodyOnly = (0, injection_renderer_1.renderConstraintsSection)(constraints, version);
566
- const block = `${GOVERNANCE_PRESERVE_BEGIN}\n## Governance Rules\n${bodyOnly}${GOVERNANCE_PRESERVE_END}\n`;
536
+ const block = `${GOVERNANCE_PRESERVE_BEGIN}\n${injection_writer_1.GOVERNANCE_HEADING}\n${bodyOnly}${GOVERNANCE_PRESERVE_END}\n`;
567
537
  let existingContent = null;
568
538
  try {
569
539
  existingContent = await fs.readFile(agentsMdPath, 'utf-8');
@@ -580,51 +550,36 @@ async function setupAgentsMdConstraints(projectPath) {
580
550
  block,
581
551
  ].join('\n');
582
552
  await fs.writeFile(agentsMdPath, skeleton, 'utf-8');
583
- console.log(chalk_1.default.green(`✅ 已创建 AGENTS.md 并写入治理契约 PRESERVE:governance 段 (v${version})`));
553
+ (0, command_contract_1.log)(io, chalk_1.default.green(`✅ 已创建 AGENTS.md 并写入治理契约 PRESERVE:governance 段 (v${version})`));
554
+ return;
555
+ }
556
+ const preserve = (0, injection_writer_1.cutMarkerBlock)(existingContent, GOVERNANCE_PRESERVE_BEGIN, GOVERNANCE_PRESERVE_END);
557
+ if (preserve === 'half') {
558
+ (0, command_contract_1.log)(io, chalk_1.default.yellow('⚠️ AGENTS.md 中 PRESERVE:governance 标记残缺(只有单边),跳过治理契约写入,请人工修复'));
584
559
  return;
585
560
  }
586
- const startIdx = existingContent.indexOf(GOVERNANCE_PRESERVE_BEGIN);
587
- const endIdx = existingContent.indexOf(GOVERNANCE_PRESERVE_END);
588
- if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
561
+ if (preserve !== 'absent') {
589
562
  // 段内机器管理的只有 HARNESS_CONSTRAINTS 标记区间;其余手写内容原样保留
590
- const before = existingContent.slice(0, startIdx);
591
- const blockContent = existingContent.slice(startIdx + GOVERNANCE_PRESERVE_BEGIN.length, endIdx);
592
- const after = existingContent.slice(endIdx + GOVERNANCE_PRESERVE_END.length).replace(/^\n+/, '');
593
- const csIdx = blockContent.indexOf(injection_renderer_1.CONSTRAINTS_START_MARKER);
594
- const ceIdx = blockContent.indexOf(injection_renderer_1.CONSTRAINTS_END_MARKER);
595
- let newBlockContent;
596
- if (csIdx !== -1 && ceIdx !== -1 && ceIdx > csIdx) {
597
- // 只替换标记区间。bodyOnly 自带结尾换行,故剥掉尾部恰好一个前导换行
598
- // (END 标记行的行尾换行),其余手写内容逐字保留,保证幂等。
599
- newBlockContent =
600
- blockContent.slice(0, csIdx) +
601
- bodyOnly +
602
- blockContent.slice(ceIdx + injection_renderer_1.CONSTRAINTS_END_MARKER.length).replace(/^\n/, '');
603
- }
604
- else {
605
- // 纯手写段(无约束标记):段尾追加注入段,手写内容不动
606
- newBlockContent = blockContent.trimEnd() + '\n\n## Governance Rules\n' + bodyOnly;
563
+ const inner = (0, injection_writer_1.replaceEnclosedRange)(preserve.inner, injection_renderer_1.CONSTRAINTS_START_MARKER, injection_renderer_1.CONSTRAINTS_END_MARKER, bodyOnly);
564
+ if (inner.kind === 'half') {
565
+ (0, command_contract_1.log)(io, chalk_1.default.yellow('⚠️ AGENTS.md PRESERVE:governance 段内 HARNESS_CONSTRAINTS 标记残缺(单边或乱序),跳过治理契约写入,请人工修复'));
566
+ return;
607
567
  }
608
- const newContent = before +
609
- GOVERNANCE_PRESERVE_BEGIN +
610
- newBlockContent +
611
- GOVERNANCE_PRESERVE_END +
612
- '\n' +
613
- (after ? '\n' + after : '');
614
- if (newContent !== existingContent) {
615
- await fs.writeFile(agentsMdPath, newContent, 'utf-8');
616
- console.log(chalk_1.default.green(`✅ 已更新 AGENTS.md 治理契约 PRESERVE:governance 段 (v${version})`));
568
+ const newInner = inner.kind === 'updated'
569
+ ? inner.content
570
+ : // 纯手写段(无约束标记):段尾追加注入段,手写内容不动
571
+ preserve.inner.trimEnd() + '\n\n' + injection_writer_1.GOVERNANCE_HEADING + '\n' + bodyOnly;
572
+ const write = (0, injection_writer_1.replaceStandaloneRange)(existingContent, GOVERNANCE_PRESERVE_BEGIN, GOVERNANCE_PRESERVE_END, GOVERNANCE_PRESERVE_BEGIN + newInner + GOVERNANCE_PRESERVE_END + '\n');
573
+ if (write.kind === 'updated' && write.content !== existingContent) {
574
+ await fs.writeFile(agentsMdPath, write.content, 'utf-8');
575
+ (0, command_contract_1.log)(io, chalk_1.default.green(`✅ 已更新 AGENTS.md 治理契约 PRESERVE:governance 段 (v${version})`));
617
576
  }
618
577
  return;
619
578
  }
620
- if (startIdx !== -1 || endIdx !== -1) {
621
- console.log(chalk_1.default.yellow('⚠️ AGENTS.md 中 PRESERVE:governance 标记残缺(只有单边),跳过治理契约写入,请人工修复'));
622
- return;
623
- }
624
579
  // 无该段:文件末尾追加
625
580
  const newContent = existingContent.trimEnd() + '\n\n' + block;
626
581
  await fs.writeFile(agentsMdPath, newContent, 'utf-8');
627
- console.log(chalk_1.default.green(`✅ 已追加治理契约 PRESERVE:governance 段到 AGENTS.md (v${version})`));
582
+ (0, command_contract_1.log)(io, chalk_1.default.green(`✅ 已追加治理契约 PRESERVE:governance 段到 AGENTS.md (v${version})`));
628
583
  }
629
584
  /**
630
585
  * 在 CLAUDE.md 中写入/更新 Governance Rules 约束段(旧落点模型,向后兼容保留)
@@ -636,22 +591,13 @@ async function setupAgentsMdConstraints(projectPath) {
636
591
  * - 如果存在 HARNESS_CONSTRAINTS_START/END 标记,替换标记间内容
637
592
  * - 如果不存在标记,在文件末尾追加约束段
638
593
  */
639
- async function setupClaudeMdConstraints(projectPath) {
594
+ async function setupClaudeMdConstraints(projectPath, io = command_contract_1.processIO) {
640
595
  const claudeMdPath = path.join(projectPath, 'CLAUDE.md');
641
- // 读取 harness 版本
642
- let version = 'unknown';
643
- try {
644
- const pkgPath = path.join(__dirname, '../../../package.json');
645
- const pkg = JSON.parse((0, fs_1.readFileSync)(pkgPath, 'utf-8'));
646
- version = pkg.version;
647
- }
648
- catch {
649
- // fallback to 'unknown'
650
- }
596
+ const version = (0, package_version_1.getHarnessPackageVersion)();
651
597
  // 生效约束集 → 渲染期望段(纯函数,与写文件分离)
652
598
  const constraints = (0, effective_constraints_1.getEffectiveConstraints)(projectPath);
653
599
  const bodyOnly = (0, injection_renderer_1.renderConstraintsSection)(constraints, version);
654
- const fullSection = '## Governance Rules\n' + bodyOnly;
600
+ const fullSection = injection_writer_1.GOVERNANCE_HEADING + '\n' + bodyOnly;
655
601
  // 检查 CLAUDE.md 是否存在
656
602
  let existingContent;
657
603
  let fileExists = false;
@@ -665,93 +611,83 @@ async function setupClaudeMdConstraints(projectPath) {
665
611
  if (!fileExists) {
666
612
  // 创建新文件
667
613
  await fs.writeFile(claudeMdPath, fullSection, 'utf-8');
668
- console.log(chalk_1.default.green(`✅ 已创建 CLAUDE.md 并写入治理约束 (v${version})`));
614
+ (0, command_contract_1.log)(io, chalk_1.default.green(`✅ 已创建 CLAUDE.md 并写入治理约束 (v${version})`));
669
615
  return;
670
616
  }
671
- const startIdx = existingContent.indexOf(injection_renderer_1.CONSTRAINTS_START_MARKER);
672
- const endIdx = existingContent.indexOf(injection_renderer_1.CONSTRAINTS_END_MARKER);
673
- if (startIdx !== -1 && endIdx !== -1) {
674
- // 替换标记间内容(标记本身也替换,保持包括最新版本号)。
675
- // 尾部换行规范化:标记后恰好保留一个换行分隔,保证重复运行幂等。
676
- const before = existingContent.slice(0, startIdx);
677
- const after = existingContent.slice(endIdx + injection_renderer_1.CONSTRAINTS_END_MARKER.length).replace(/^\n+/, '');
678
- const newContent = before + bodyOnly + (after ? '\n' + after : '');
679
- await fs.writeFile(claudeMdPath, newContent, 'utf-8');
680
- console.log(chalk_1.default.green(`✅ 已更新 CLAUDE.md 治理约束 (v${version})`));
617
+ const write = (0, injection_writer_1.replaceStandaloneRange)(existingContent, injection_renderer_1.CONSTRAINTS_START_MARKER, injection_renderer_1.CONSTRAINTS_END_MARKER, bodyOnly);
618
+ if (write.kind === 'updated') {
619
+ // 替换标记区间含标记本身(保持包括最新版本号),尾部换行规范化在 writer
620
+ await fs.writeFile(claudeMdPath, write.content, 'utf-8');
621
+ (0, command_contract_1.log)(io, chalk_1.default.green(`✅ 已更新 CLAUDE.md 治理约束 (v${version})`));
622
+ }
623
+ else if (write.kind === 'half') {
624
+ (0, command_contract_1.log)(io, chalk_1.default.yellow('⚠️ CLAUDE.md HARNESS_CONSTRAINTS 标记残缺(单边或乱序),跳过治理约束注入,请人工修复'));
681
625
  }
682
626
  else {
683
627
  // 在文件末尾追加完整段
684
628
  const newContent = existingContent.trimEnd() + '\n\n' + fullSection;
685
629
  await fs.writeFile(claudeMdPath, newContent, 'utf-8');
686
- console.log(chalk_1.default.green(`✅ 已追加治理约束到 CLAUDE.md (v${version})`));
630
+ (0, command_contract_1.log)(io, chalk_1.default.green(`✅ 已追加治理约束到 CLAUDE.md (v${version})`));
687
631
  }
688
632
  }
689
633
  /**
690
634
  * 治理约束段写入落点路由(studio #302,ADR 2026-08-21 落点模型)
691
635
  *
636
+ * 判定收口在 core/constraints/injection-writer resolveGovernanceLanding:
692
637
  * - 旧模型仓(CLAUDE.md 已有 HARNESS_CONSTRAINTS 标记或 `## Governance Rules` 块):
693
638
  * 继续写 CLAUDE.md——init 幂等重跑不破坏既有仓,不制造双份约束正本
694
639
  * - 其余(新仓初始化):写 AGENTS.md PRESERVE:governance 段(入库公共面正本)
695
640
  */
696
641
  async function setupGovernanceConstraints(projectPath) {
697
- let claudeContent = null;
698
- try {
699
- claudeContent = await fs.readFile(path.join(projectPath, 'CLAUDE.md'), 'utf-8');
700
- }
701
- catch {
702
- // CLAUDE.md 不存在 → 新仓
703
- }
704
- if (claudeContent !== null &&
705
- (claudeContent.includes(injection_renderer_1.CONSTRAINTS_START_MARKER) || /^##\s+Governance Rules/m.test(claudeContent))) {
706
- return setupClaudeMdConstraints(projectPath);
707
- }
708
- return setupAgentsMdConstraints(projectPath);
642
+ const { target } = (0, injection_writer_1.resolveGovernanceLanding)(projectPath);
643
+ return target === 'claude-md'
644
+ ? setupClaudeMdConstraints(projectPath)
645
+ : setupAgentsMdConstraints(projectPath);
709
646
  }
710
647
  /**
711
648
  * 设置治理相关文件
712
649
  */
713
- async function setupGovernance(projectPath, level) {
650
+ async function setupGovernance(projectPath, level, io) {
714
651
  const governance = GOVERNANCE_PRESETS[level];
715
652
  if (!governance)
716
653
  return;
717
- console.log();
718
- console.log(chalk_1.default.blue('📋 设置治理文件...'));
654
+ (0, command_contract_1.log)(io);
655
+ (0, command_contract_1.log)(io, chalk_1.default.blue('📋 设置治理文件...'));
719
656
  // 1. 生成 CHANGELOG.md
720
- await createChangelog(projectPath, governance);
657
+ await createChangelog(projectPath, governance, io);
721
658
  // 2. 在 CLAUDE.md 中写入 Output Style 段(仅在不存在时创建)
722
659
  await setupClaudeMdOutputStyle(projectPath);
723
660
  // 3. 写入/更新 Governance Rules 约束段(新仓 → AGENTS.md PRESERVE:governance;
724
661
  // 旧模型仓 → CLAUDE.md,落点路由见 setupGovernanceConstraints)
725
662
  await setupGovernanceConstraints(projectPath);
726
- // 4. 生成 CONTEXT.md 文件
663
+ // 4. 生成 CONTEXT.md 文件(预设形状即 GovernanceConfig,无需再 cast)
727
664
  const contextConfig = governance.context_files;
728
665
  if (contextConfig?.enabled) {
729
- let requiredDirs = contextConfig.required_dirs || [];
666
+ let requiredDirs = contextConfig.required_dirs ?? [];
730
667
  if (requiredDirs.length === 0) {
731
668
  requiredDirs = (0, detect_source_roots_1.detectSourceRoots)(projectPath);
732
669
  }
733
670
  for (const dir of requiredDirs) {
734
- await createContextMd(projectPath, dir);
671
+ await createContextMd(projectPath, dir, io);
735
672
  }
736
673
  }
737
674
  // 4. 生成治理 CI workflow
738
- await setupGovernanceWorkflow(projectPath, level);
675
+ await setupGovernanceWorkflow(projectPath, level, io);
739
676
  }
740
677
  /**
741
678
  * 创建 CHANGELOG.md
742
679
  */
743
- async function createChangelog(projectPath, governance) {
680
+ async function createChangelog(projectPath, governance, io) {
744
681
  const changelogPath = path.join(projectPath, 'CHANGELOG.md');
745
682
  try {
746
683
  await fs.access(changelogPath);
747
- console.log(chalk_1.default.gray(`CHANGELOG.md 已存在`));
684
+ (0, command_contract_1.log)(io, chalk_1.default.gray(`CHANGELOG.md 已存在`));
748
685
  return;
749
686
  }
750
687
  catch {
751
688
  // 文件不存在,创建
752
689
  }
753
- const changelogConfig = governance.changelog;
754
- const format = changelogConfig?.format || 'keep-a-changelog';
690
+ const format = governance.changelog?.format || 'keep-a-changelog';
755
691
  let content;
756
692
  if (format === 'keep-a-changelog') {
757
693
  content = `# Changelog
@@ -784,16 +720,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
784
720
  `;
785
721
  }
786
722
  await fs.writeFile(changelogPath, content, 'utf-8');
787
- console.log(chalk_1.default.green(`✅ 已创建 CHANGELOG.md`));
723
+ (0, command_contract_1.log)(io, chalk_1.default.green(`✅ 已创建 CHANGELOG.md`));
788
724
  }
789
725
  /**
790
726
  * 在指定目录创建 CONTEXT.md
791
727
  */
792
- async function createContextMd(projectPath, dir) {
728
+ async function createContextMd(projectPath, dir, io) {
793
729
  const contextPath = path.join(projectPath, dir, 'CONTEXT.md');
794
730
  try {
795
731
  await fs.access(contextPath);
796
- console.log(chalk_1.default.gray(`${dir}/CONTEXT.md 已存在`));
732
+ (0, command_contract_1.log)(io, chalk_1.default.gray(`${dir}/CONTEXT.md 已存在`));
797
733
  return;
798
734
  }
799
735
  catch {
@@ -805,7 +741,7 @@ async function createContextMd(projectPath, dir) {
805
741
  await fs.access(dirPath);
806
742
  }
807
743
  catch {
808
- console.log(chalk_1.default.yellow(`⚠️ 目录 ${dir} 不存在,跳过 CONTEXT.md`));
744
+ (0, command_contract_1.log)(io, chalk_1.default.yellow(`⚠️ 目录 ${dir} 不存在,跳过 CONTEXT.md`));
809
745
  return;
810
746
  }
811
747
  const dirName = path.basename(dir);
@@ -830,7 +766,7 @@ async function createContextMd(projectPath, dir) {
830
766
  <!-- 开发时需要注意的约束或约定 -->
831
767
  `;
832
768
  await fs.writeFile(contextPath, content, 'utf-8');
833
- console.log(chalk_1.default.green(`✅ 已创建 ${dir}/CONTEXT.md`));
769
+ (0, command_contract_1.log)(io, chalk_1.default.green(`✅ 已创建 ${dir}/CONTEXT.md`));
834
770
  }
835
771
  /**
836
772
  * 检测已有 workflow 是否已覆盖 harness 治理命令
@@ -854,13 +790,13 @@ async function findGovernanceCoverage(workflowsDir) {
854
790
  /**
855
791
  * 设置治理 CI workflow
856
792
  */
857
- async function setupGovernanceWorkflow(projectPath, level) {
793
+ async function setupGovernanceWorkflow(projectPath, level, io) {
858
794
  const workflowsDir = path.join(projectPath, '.github', 'workflows');
859
795
  const workflowPath = path.join(workflowsDir, 'harness-governance.yml');
860
796
  // 检查是否已存在
861
797
  try {
862
798
  await fs.access(workflowPath);
863
- console.log(chalk_1.default.gray(`harness-governance.yml 已存在`));
799
+ (0, command_contract_1.log)(io, chalk_1.default.gray(`harness-governance.yml 已存在`));
864
800
  return;
865
801
  }
866
802
  catch {
@@ -869,7 +805,7 @@ async function setupGovernanceWorkflow(projectPath, level) {
869
805
  // 能力检测:已有 workflow 已跑 harness 治理命令时跳过,避免重复 CI 面
870
806
  const coveredBy = await findGovernanceCoverage(workflowsDir);
871
807
  if (coveredBy) {
872
- console.log(chalk_1.default.gray(`治理检查已由 ${coveredBy} 覆盖,跳过创建 harness-governance.yml`));
808
+ (0, command_contract_1.log)(io, chalk_1.default.gray(`治理检查已由 ${coveredBy} 覆盖,跳过创建 harness-governance.yml`));
873
809
  return;
874
810
  }
875
811
  await fs.mkdir(workflowsDir, { recursive: true });
@@ -910,6 +846,6 @@ jobs:
910
846
  ${docsCheckStep}
911
847
  `;
912
848
  await fs.writeFile(workflowPath, workflowContent, 'utf-8');
913
- console.log(chalk_1.default.green(`✅ 已创建 .github/workflows/harness-governance.yml`));
849
+ (0, command_contract_1.log)(io, chalk_1.default.green(`✅ 已创建 .github/workflows/harness-governance.yml`));
914
850
  }
915
851
  //# sourceMappingURL=init.js.map