@dommaker/harness 1.2.3 → 1.4.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 (550) hide show
  1. package/CHANGELOG.md +15 -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 +76 -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 +30 -215
  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 +33 -26
  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 +21 -15
  53. package/dist/cli/commands/knowledge.d.ts.map +1 -1
  54. package/dist/cli/commands/knowledge.js +237 -199
  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 +73 -77
  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 +31 -16
  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 +2 -1
  115. package/dist/cli/commands/update-user-model.d.ts.map +1 -1
  116. package/dist/cli/commands/update-user-model.js +31 -45
  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/completion-checkers/index.d.ts +3 -3
  127. package/dist/completion-checkers/index.js +3 -3
  128. package/dist/completion-checkers/phase-format.d.ts +1 -1
  129. package/dist/completion-checkers/phase-format.js +2 -2
  130. package/dist/completion-checkers/phase-format.js.map +1 -1
  131. package/dist/completion-checkers/tdd-chain.d.ts +1 -1
  132. package/dist/completion-checkers/tdd-chain.js +2 -2
  133. package/dist/completion-checkers/tdd-chain.js.map +1 -1
  134. package/dist/completion-checkers/types.d.ts +5 -5
  135. package/dist/completion-checkers/types.d.ts.map +1 -1
  136. package/dist/completion-checkers/types.js +2 -2
  137. package/dist/context/session-manager.d.ts.map +1 -1
  138. package/dist/context/session-manager.js +19 -32
  139. package/dist/context/session-manager.js.map +1 -1
  140. package/dist/core/constraints/agent-prompt-renderer.d.ts.map +1 -1
  141. package/dist/core/constraints/agent-prompt-renderer.js +1 -4
  142. package/dist/core/constraints/agent-prompt-renderer.js.map +1 -1
  143. package/dist/core/constraints/capabilities-parser.d.ts +24 -7
  144. package/dist/core/constraints/capabilities-parser.d.ts.map +1 -1
  145. package/dist/core/constraints/capabilities-parser.js +32 -28
  146. package/dist/core/constraints/capabilities-parser.js.map +1 -1
  147. package/dist/core/constraints/capabilities-reconcile.d.ts +67 -0
  148. package/dist/core/constraints/capabilities-reconcile.d.ts.map +1 -0
  149. package/dist/core/constraints/capabilities-reconcile.js +105 -0
  150. package/dist/core/constraints/capabilities-reconcile.js.map +1 -0
  151. package/dist/core/constraints/checker.d.ts +21 -43
  152. package/dist/core/constraints/checker.d.ts.map +1 -1
  153. package/dist/core/constraints/checker.js +64 -115
  154. package/dist/core/constraints/checker.js.map +1 -1
  155. package/dist/core/constraints/checkers/capability-sync.d.ts +4 -3
  156. package/dist/core/constraints/checkers/capability-sync.d.ts.map +1 -1
  157. package/dist/core/constraints/checkers/capability-sync.js +29 -69
  158. package/dist/core/constraints/checkers/capability-sync.js.map +1 -1
  159. package/dist/core/constraints/checkers/context-doc-sync.d.ts +4 -2
  160. package/dist/core/constraints/checkers/context-doc-sync.d.ts.map +1 -1
  161. package/dist/core/constraints/checkers/context-doc-sync.js +13 -22
  162. package/dist/core/constraints/checkers/context-doc-sync.js.map +1 -1
  163. package/dist/core/constraints/checkers/docs-freshness.d.ts.map +1 -1
  164. package/dist/core/constraints/checkers/docs-freshness.js +37 -63
  165. package/dist/core/constraints/checkers/docs-freshness.js.map +1 -1
  166. package/dist/core/constraints/checkers/governance-presence.d.ts +2 -2
  167. package/dist/core/constraints/checkers/governance-presence.d.ts.map +1 -1
  168. package/dist/core/constraints/checkers/governance-presence.js +7 -28
  169. package/dist/core/constraints/checkers/governance-presence.js.map +1 -1
  170. package/dist/core/constraints/checkers/no-test-simplification.d.ts.map +1 -1
  171. package/dist/core/constraints/checkers/no-test-simplification.js +4 -3
  172. package/dist/core/constraints/checkers/no-test-simplification.js.map +1 -1
  173. package/dist/core/constraints/checkers/types.d.ts +2 -2
  174. package/dist/core/constraints/context-builder.d.ts +15 -14
  175. package/dist/core/constraints/context-builder.d.ts.map +1 -1
  176. package/dist/core/constraints/context-builder.js +32 -96
  177. package/dist/core/constraints/context-builder.js.map +1 -1
  178. package/dist/core/constraints/doc-freshness/runner.d.ts.map +1 -1
  179. package/dist/core/constraints/doc-freshness/runner.js +2 -1
  180. package/dist/core/constraints/doc-freshness/runner.js.map +1 -1
  181. package/dist/core/constraints/git-evidence.d.ts +60 -0
  182. package/dist/core/constraints/git-evidence.d.ts.map +1 -0
  183. package/dist/core/constraints/git-evidence.js +88 -0
  184. package/dist/core/constraints/git-evidence.js.map +1 -0
  185. package/dist/core/constraints/injection-drift.d.ts +3 -20
  186. package/dist/core/constraints/injection-drift.d.ts.map +1 -1
  187. package/dist/core/constraints/injection-drift.js +10 -57
  188. package/dist/core/constraints/injection-drift.js.map +1 -1
  189. package/dist/core/constraints/injection-writer.d.ts +113 -0
  190. package/dist/core/constraints/injection-writer.d.ts.map +1 -0
  191. package/dist/core/constraints/injection-writer.js +228 -0
  192. package/dist/core/constraints/injection-writer.js.map +1 -0
  193. package/dist/core/constraints/usage-report.d.ts +22 -1
  194. package/dist/core/constraints/usage-report.d.ts.map +1 -1
  195. package/dist/core/constraints/usage-report.js +27 -20
  196. package/dist/core/constraints/usage-report.js.map +1 -1
  197. package/dist/core/index.d.ts +2 -2
  198. package/dist/core/index.d.ts.map +1 -1
  199. package/dist/core/index.js +4 -2
  200. package/dist/core/index.js.map +1 -1
  201. package/dist/core/project-config-loader.d.ts +32 -1
  202. package/dist/core/project-config-loader.d.ts.map +1 -1
  203. package/dist/core/project-config-loader.js +39 -9
  204. package/dist/core/project-config-loader.js.map +1 -1
  205. package/dist/core/validators/passes-gate.d.ts +15 -64
  206. package/dist/core/validators/passes-gate.d.ts.map +1 -1
  207. package/dist/core/validators/passes-gate.js +84 -222
  208. package/dist/core/validators/passes-gate.js.map +1 -1
  209. package/dist/core/validators/test-output.d.ts +58 -0
  210. package/dist/core/validators/test-output.d.ts.map +1 -0
  211. package/dist/core/validators/test-output.js +109 -0
  212. package/dist/core/validators/test-output.js.map +1 -0
  213. package/dist/failure/recorder.d.ts +7 -1
  214. package/dist/failure/recorder.d.ts.map +1 -1
  215. package/dist/failure/recorder.js +13 -9
  216. package/dist/failure/recorder.js.map +1 -1
  217. package/dist/gates/acceptance.d.ts +1 -48
  218. package/dist/gates/acceptance.d.ts.map +1 -1
  219. package/dist/gates/acceptance.js +6 -38
  220. package/dist/gates/acceptance.js.map +1 -1
  221. package/dist/gates/checker-gate.d.ts.map +1 -1
  222. package/dist/gates/checker-gate.js +6 -11
  223. package/dist/gates/checker-gate.js.map +1 -1
  224. package/dist/gates/command.d.ts.map +1 -1
  225. package/dist/gates/command.js +10 -22
  226. package/dist/gates/command.js.map +1 -1
  227. package/dist/gates/contract.d.ts.map +1 -1
  228. package/dist/gates/contract.js +22 -61
  229. package/dist/gates/contract.js.map +1 -1
  230. package/dist/gates/performance.d.ts.map +1 -1
  231. package/dist/gates/performance.js +13 -31
  232. package/dist/gates/performance.js.map +1 -1
  233. package/dist/gates/review.d.ts.map +1 -1
  234. package/dist/gates/review.js +21 -53
  235. package/dist/gates/review.js.map +1 -1
  236. package/dist/gates/security.d.ts.map +1 -1
  237. package/dist/gates/security.js +14 -32
  238. package/dist/gates/security.js.map +1 -1
  239. package/dist/gates/types.d.ts +28 -5
  240. package/dist/gates/types.d.ts.map +1 -1
  241. package/dist/gates/types.js +38 -1
  242. package/dist/gates/types.js.map +1 -1
  243. package/dist/hooks/bootstrap.d.ts +2 -0
  244. package/dist/hooks/bootstrap.d.ts.map +1 -1
  245. package/dist/hooks/bootstrap.js +5 -2
  246. package/dist/hooks/bootstrap.js.map +1 -1
  247. package/dist/index.d.ts +4 -3
  248. package/dist/index.d.ts.map +1 -1
  249. package/dist/index.js +13 -4
  250. package/dist/index.js.map +1 -1
  251. package/dist/knowledge/audit.d.ts +7 -2
  252. package/dist/knowledge/audit.d.ts.map +1 -1
  253. package/dist/knowledge/audit.js +59 -79
  254. package/dist/knowledge/audit.js.map +1 -1
  255. package/dist/knowledge/flywheel-metrics.d.ts +39 -0
  256. package/dist/knowledge/flywheel-metrics.d.ts.map +1 -0
  257. package/dist/knowledge/flywheel-metrics.js +47 -0
  258. package/dist/knowledge/flywheel-metrics.js.map +1 -0
  259. package/dist/knowledge/import.d.ts.map +1 -1
  260. package/dist/knowledge/import.js +4 -14
  261. package/dist/knowledge/import.js.map +1 -1
  262. package/dist/knowledge/index-generator.d.ts.map +1 -1
  263. package/dist/knowledge/index-generator.js +18 -15
  264. package/dist/knowledge/index-generator.js.map +1 -1
  265. package/dist/knowledge/ingest.d.ts.map +1 -1
  266. package/dist/knowledge/ingest.js +9 -4
  267. package/dist/knowledge/ingest.js.map +1 -1
  268. package/dist/knowledge/migration.d.ts.map +1 -1
  269. package/dist/knowledge/migration.js +11 -8
  270. package/dist/knowledge/migration.js.map +1 -1
  271. package/dist/knowledge/reference-tracker.d.ts.map +1 -1
  272. package/dist/knowledge/reference-tracker.js +12 -9
  273. package/dist/knowledge/reference-tracker.js.map +1 -1
  274. package/dist/knowledge/store.d.ts +15 -0
  275. package/dist/knowledge/store.d.ts.map +1 -1
  276. package/dist/knowledge/store.js +59 -10
  277. package/dist/knowledge/store.js.map +1 -1
  278. package/dist/monitoring/context-tracker.d.ts.map +1 -1
  279. package/dist/monitoring/context-tracker.js +11 -20
  280. package/dist/monitoring/context-tracker.js.map +1 -1
  281. package/dist/monitoring/index.d.ts +1 -1
  282. package/dist/monitoring/index.d.ts.map +1 -1
  283. package/dist/monitoring/index.js +1 -2
  284. package/dist/monitoring/index.js.map +1 -1
  285. package/dist/monitoring/trace-analyzer.d.ts +15 -0
  286. package/dist/monitoring/trace-analyzer.d.ts.map +1 -1
  287. package/dist/monitoring/trace-analyzer.js +19 -2
  288. package/dist/monitoring/trace-analyzer.js.map +1 -1
  289. package/dist/monitoring/traces.d.ts +21 -2
  290. package/dist/monitoring/traces.d.ts.map +1 -1
  291. package/dist/monitoring/traces.js +38 -29
  292. package/dist/monitoring/traces.js.map +1 -1
  293. package/dist/release/index.d.ts +3 -0
  294. package/dist/release/index.d.ts.map +1 -0
  295. package/dist/release/index.js +7 -0
  296. package/dist/release/index.js.map +1 -0
  297. package/dist/release/integrity.d.ts +65 -0
  298. package/dist/release/integrity.d.ts.map +1 -0
  299. package/dist/release/integrity.js +151 -0
  300. package/dist/release/integrity.js.map +1 -0
  301. package/dist/sdd/index-generator.js +10 -11
  302. package/dist/sdd/index-generator.js.map +1 -1
  303. package/dist/test-setup/project-fixture.d.ts +48 -0
  304. package/dist/test-setup/project-fixture.d.ts.map +1 -0
  305. package/dist/test-setup/project-fixture.js +106 -0
  306. package/dist/test-setup/project-fixture.js.map +1 -0
  307. package/dist/types/constraint.d.ts +0 -18
  308. package/dist/types/constraint.d.ts.map +1 -1
  309. package/dist/types/constraint.js.map +1 -1
  310. package/dist/types/failure.d.ts +7 -0
  311. package/dist/types/failure.d.ts.map +1 -1
  312. package/dist/types/failure.js +8 -1
  313. package/dist/types/failure.js.map +1 -1
  314. package/dist/types/passes-gate.d.ts +10 -25
  315. package/dist/types/passes-gate.d.ts.map +1 -1
  316. package/dist/types/project-config.d.ts +1 -1
  317. package/dist/types/session.d.ts +6 -5
  318. package/dist/types/session.d.ts.map +1 -1
  319. package/dist/utils/exec.d.ts +10 -0
  320. package/dist/utils/exec.d.ts.map +1 -1
  321. package/dist/utils/exec.js +12 -0
  322. package/dist/utils/exec.js.map +1 -1
  323. package/dist/utils/file-walk.d.ts +9 -1
  324. package/dist/utils/file-walk.d.ts.map +1 -1
  325. package/dist/utils/file-walk.js +10 -1
  326. package/dist/utils/file-walk.js.map +1 -1
  327. package/dist/utils/frontmatter.d.ts +73 -0
  328. package/dist/utils/frontmatter.d.ts.map +1 -0
  329. package/dist/utils/frontmatter.js +141 -0
  330. package/dist/utils/frontmatter.js.map +1 -0
  331. package/dist/utils/jsonl.d.ts +92 -0
  332. package/dist/utils/jsonl.d.ts.map +1 -0
  333. package/dist/utils/jsonl.js +166 -0
  334. package/dist/utils/jsonl.js.map +1 -0
  335. package/dist/utils/package-version.d.ts +16 -0
  336. package/dist/utils/package-version.d.ts.map +1 -0
  337. package/dist/utils/package-version.js +63 -0
  338. package/dist/utils/package-version.js.map +1 -0
  339. package/package.json +1 -1
  340. package/src/CONTEXT.md +7 -2
  341. package/src/__tests__/acceptance-gate.test.ts +3 -1
  342. package/src/__tests__/checker-extra.test.ts +7 -1218
  343. package/src/__tests__/context-files-resolution.test.ts +116 -0
  344. package/src/__tests__/effective-constraints.test.ts +10 -13
  345. package/src/__tests__/exec.test.ts +35 -1
  346. package/src/__tests__/failure-recorder.test.ts +9 -0
  347. package/src/__tests__/layering.test.ts +152 -0
  348. package/src/__tests__/passes-gate-extra.test.ts +0 -145
  349. package/src/__tests__/passes-gate.test.ts +142 -106
  350. package/src/__tests__/public-exports.test.ts +3 -0
  351. package/src/__tests__/skip-semantics.test.ts +5 -9
  352. package/src/cli/__tests__/command-contract.test.ts +170 -0
  353. package/src/cli/command-contract.ts +108 -0
  354. package/src/cli/commands/CONTEXT.md +22 -7
  355. package/src/cli/commands/__tests__/acceptance.test.ts +40 -33
  356. package/src/cli/commands/__tests__/analyze-sessions.test.ts +35 -29
  357. package/src/cli/commands/__tests__/bin-exit-mapping.test.ts +101 -0
  358. package/src/cli/commands/__tests__/check-drift.test.ts +27 -34
  359. package/src/cli/commands/__tests__/check-skip-output.test.ts +21 -24
  360. package/src/cli/commands/__tests__/check.test.ts +378 -382
  361. package/src/cli/commands/__tests__/command.test.ts +85 -70
  362. package/src/cli/commands/__tests__/constraints-report.test.ts +100 -71
  363. package/src/cli/commands/__tests__/constraints-retire.test.ts +152 -95
  364. package/src/cli/commands/__tests__/contract.test.ts +27 -34
  365. package/src/cli/commands/__tests__/failure.test.ts +31 -34
  366. package/src/cli/commands/__tests__/init-injection.test.ts +58 -28
  367. package/src/cli/commands/__tests__/init.test.ts +77 -48
  368. package/src/cli/commands/__tests__/knowledge-flywheel-consistency.test.ts +108 -0
  369. package/src/cli/commands/__tests__/knowledge.test.ts +96 -38
  370. package/src/cli/commands/__tests__/passes-gate.test.ts +43 -45
  371. package/src/cli/commands/__tests__/performance.test.ts +22 -23
  372. package/src/cli/commands/__tests__/posteval-plan.test.ts +39 -38
  373. package/src/cli/commands/__tests__/project-path-anchoring.test.ts +157 -0
  374. package/src/cli/commands/__tests__/project-path-convention.test.ts +169 -0
  375. package/src/cli/commands/__tests__/registry.test.ts +69 -35
  376. package/src/cli/commands/__tests__/release.test.ts +224 -74
  377. package/src/cli/commands/__tests__/report-extra.test.ts +16 -16
  378. package/src/cli/commands/__tests__/report.test.ts +25 -25
  379. package/src/cli/commands/__tests__/review.test.ts +33 -31
  380. package/src/cli/commands/__tests__/security.test.ts +23 -27
  381. package/src/cli/commands/__tests__/spec-baseline-check.test.ts +20 -20
  382. package/src/cli/commands/__tests__/spec.test.ts +41 -29
  383. package/src/cli/commands/__tests__/status-extra.test.ts +18 -18
  384. package/src/cli/commands/__tests__/status-skipped-lines.test.ts +72 -0
  385. package/src/cli/commands/__tests__/status.test.ts +34 -34
  386. package/src/cli/commands/__tests__/sync-docs-agents.test.ts +108 -86
  387. package/src/cli/commands/__tests__/sync-docs.test.ts +72 -74
  388. package/src/cli/commands/__tests__/update-user-model.test.ts +62 -33
  389. package/src/cli/commands/__tests__/validate.test.ts +27 -29
  390. package/src/cli/commands/acceptance.ts +35 -24
  391. package/src/cli/commands/analyze-sessions.ts +25 -24
  392. package/src/cli/commands/check.ts +88 -65
  393. package/src/cli/commands/command.ts +30 -17
  394. package/src/cli/commands/constraints-report.ts +37 -34
  395. package/src/cli/commands/constraints-retire.ts +58 -55
  396. package/src/cli/commands/constraints.ts +10 -27
  397. package/src/cli/commands/contract.ts +51 -42
  398. package/src/cli/commands/definitions.ts +37 -223
  399. package/src/cli/commands/failure.ts +35 -27
  400. package/src/cli/commands/init.ts +166 -220
  401. package/src/cli/commands/knowledge.ts +250 -203
  402. package/src/cli/commands/passes-gate.ts +58 -68
  403. package/src/cli/commands/performance.ts +23 -18
  404. package/src/cli/commands/posteval-plan.ts +29 -15
  405. package/src/cli/commands/release.ts +75 -78
  406. package/src/cli/commands/report.ts +9 -5
  407. package/src/cli/commands/review.ts +39 -29
  408. package/src/cli/commands/sdd.ts +7 -5
  409. package/src/cli/commands/security.ts +35 -26
  410. package/src/cli/commands/spec-baseline-check.ts +16 -11
  411. package/src/cli/commands/spec.ts +66 -53
  412. package/src/cli/commands/status.ts +59 -53
  413. package/src/cli/commands/sync-docs/agents-syncer.ts +31 -15
  414. package/src/cli/commands/sync-docs/context-syncer.ts +3 -2
  415. package/src/cli/commands/sync-docs/index.ts +73 -100
  416. package/src/cli/commands/sync-docs/project-reader.ts +17 -18
  417. package/src/cli/commands/update-user-model.ts +33 -45
  418. package/src/cli/commands/validate.ts +31 -25
  419. package/src/cli/session-mining/__tests__/transcript.test.ts +118 -0
  420. package/src/cli/session-mining/transcript.ts +26 -8
  421. package/src/completion-checkers/CONTEXT.md +1 -1
  422. package/src/completion-checkers/__tests__/contract-presence.test.ts +1 -1
  423. package/src/completion-checkers/__tests__/phase-format.test.ts +1 -1
  424. package/src/completion-checkers/__tests__/tdd-chain.test.ts +2 -2
  425. package/src/completion-checkers/index.ts +3 -3
  426. package/src/completion-checkers/phase-format.ts +2 -2
  427. package/src/completion-checkers/tdd-chain.ts +2 -2
  428. package/src/completion-checkers/types.ts +5 -5
  429. package/src/context/session-manager.ts +19 -33
  430. package/src/core/CONTEXT.md +9 -6
  431. package/src/core/constraints/__tests__/capabilities-reconcile.test.ts +200 -0
  432. package/src/core/constraints/__tests__/capability-counts.test.ts +94 -0
  433. package/src/core/constraints/__tests__/git-evidence.test.ts +208 -0
  434. package/src/core/constraints/__tests__/injection-drift.test.ts +3 -10
  435. package/src/core/constraints/__tests__/injection-writer.test.ts +231 -0
  436. package/src/core/constraints/__tests__/trace-injection.test.ts +71 -0
  437. package/src/core/constraints/__tests__/usage-report.test.ts +112 -0
  438. package/src/core/constraints/agent-prompt-renderer.ts +2 -6
  439. package/src/core/constraints/capabilities-parser.ts +53 -35
  440. package/src/core/constraints/capabilities-reconcile.ts +166 -0
  441. package/src/core/constraints/checker.ts +75 -130
  442. package/src/core/constraints/checkers/__tests__/capability-sync.test.ts +214 -0
  443. package/src/core/constraints/checkers/__tests__/context-doc-sync.test.ts +77 -0
  444. package/src/core/constraints/checkers/__tests__/docs-freshness.test.ts +117 -0
  445. package/src/{__tests__ → core/constraints/checkers/__tests__}/governance-presence.test.ts +83 -9
  446. package/src/core/constraints/checkers/__tests__/iron-flags.test.ts +50 -0
  447. package/src/core/constraints/checkers/__tests__/no-bypass-checkpoint.test.ts +76 -0
  448. package/src/{__tests__ → core/constraints/checkers/__tests__}/no-hardcoded-credentials.test.ts +4 -3
  449. package/src/core/constraints/checkers/__tests__/no-test-simplification.test.ts +58 -0
  450. package/src/core/constraints/checkers/__tests__/three-state-consistency.test.ts +145 -0
  451. package/src/core/constraints/checkers/capability-sync.ts +29 -88
  452. package/src/core/constraints/checkers/context-doc-sync.ts +15 -25
  453. package/src/core/constraints/checkers/docs-freshness.ts +40 -69
  454. package/src/core/constraints/checkers/governance-presence.ts +7 -25
  455. package/src/core/constraints/checkers/no-test-simplification.ts +4 -3
  456. package/src/core/constraints/checkers/types.ts +2 -2
  457. package/src/core/constraints/context-builder.ts +39 -91
  458. package/src/core/constraints/doc-freshness/runner.ts +2 -1
  459. package/src/core/constraints/git-evidence.ts +120 -0
  460. package/src/core/constraints/injection-drift.ts +13 -60
  461. package/src/core/constraints/injection-writer.ts +212 -0
  462. package/src/core/constraints/usage-report.ts +36 -17
  463. package/src/core/index.ts +4 -2
  464. package/src/core/project-config-loader.ts +49 -9
  465. package/src/core/validators/__tests__/passes-gate.test.ts +2 -56
  466. package/src/core/validators/__tests__/test-output.test.ts +372 -0
  467. package/src/core/validators/passes-gate.ts +86 -248
  468. package/src/core/validators/test-output.ts +128 -0
  469. package/src/failure/__tests__/recorder.test.ts +168 -0
  470. package/src/failure/recorder.ts +13 -11
  471. package/src/gates/CONTEXT.md +6 -3
  472. package/src/gates/__tests__/acceptance-types-single-source.test.ts +68 -0
  473. package/src/gates/__tests__/acceptance.test.ts +4 -86
  474. package/src/gates/__tests__/effective-gates.test.ts +3 -8
  475. package/src/gates/__tests__/test-verdict-consistency.test.ts +140 -0
  476. package/src/gates/acceptance.ts +19 -84
  477. package/src/gates/checker-gate.ts +8 -7
  478. package/src/gates/command.ts +10 -16
  479. package/src/gates/contract.ts +22 -61
  480. package/src/gates/performance.ts +10 -22
  481. package/src/gates/review.ts +21 -41
  482. package/src/gates/security.ts +10 -22
  483. package/src/gates/types.ts +70 -5
  484. package/src/hooks/CONTEXT.md +1 -1
  485. package/src/hooks/bootstrap.ts +5 -2
  486. package/src/index.ts +11 -6
  487. package/src/knowledge/CONTEXT.md +8 -3
  488. package/src/knowledge/__tests__/audit-labels.test.ts +44 -0
  489. package/src/knowledge/__tests__/flywheel-metrics.test.ts +135 -0
  490. package/src/knowledge/__tests__/import.test.ts +44 -0
  491. package/src/knowledge/__tests__/index-generator.test.ts +55 -2
  492. package/src/knowledge/__tests__/ingest.test.ts +85 -0
  493. package/src/knowledge/__tests__/migration.test.ts +47 -0
  494. package/src/knowledge/__tests__/reference-tracker.test.ts +16 -0
  495. package/src/knowledge/__tests__/store.test.ts +194 -0
  496. package/src/knowledge/audit.ts +67 -71
  497. package/src/knowledge/flywheel-metrics.ts +71 -0
  498. package/src/knowledge/import.ts +4 -18
  499. package/src/knowledge/index-generator.ts +20 -15
  500. package/src/knowledge/ingest.ts +9 -4
  501. package/src/knowledge/migration.ts +11 -8
  502. package/src/knowledge/reference-tracker.ts +12 -8
  503. package/src/knowledge/store.ts +64 -11
  504. package/src/monitoring/CONTEXT.md +8 -3
  505. package/src/monitoring/__tests__/skipped-lines-report.test.ts +178 -0
  506. package/src/monitoring/__tests__/traces.test.ts +57 -0
  507. package/src/monitoring/context-tracker.ts +11 -23
  508. package/src/monitoring/index.ts +1 -1
  509. package/src/monitoring/trace-analyzer.ts +21 -2
  510. package/src/monitoring/traces.ts +39 -36
  511. package/src/release/CONTEXT.md +24 -0
  512. package/src/release/__tests__/barrel.test.ts +60 -0
  513. package/src/release/__tests__/integrity.test.ts +157 -0
  514. package/src/release/index.ts +2 -0
  515. package/src/release/integrity.ts +141 -0
  516. package/src/sdd/__tests__/index-generator.test.ts +71 -0
  517. package/src/sdd/index-generator.ts +9 -9
  518. package/src/test-setup/__tests__/project-fixture.test.ts +178 -0
  519. package/src/test-setup/project-fixture.ts +87 -0
  520. package/src/tools/CONTEXT.md +6 -0
  521. package/src/tools/__tests__/registry.test.ts +221 -0
  522. package/src/types/__tests__/types.test.ts +4 -5
  523. package/src/types/constraint.ts +0 -25
  524. package/src/types/failure.ts +8 -0
  525. package/src/types/passes-gate.ts +10 -30
  526. package/src/types/project-config.ts +1 -1
  527. package/src/types/session.ts +5 -5
  528. package/src/utils/__tests__/frontmatter.test.ts +206 -0
  529. package/src/utils/__tests__/jsonl-skip-disposition.test.ts +175 -0
  530. package/src/utils/__tests__/jsonl.test.ts +187 -0
  531. package/src/utils/__tests__/package-version.test.ts +97 -0
  532. package/src/utils/exec.ts +15 -0
  533. package/src/utils/file-walk.ts +11 -2
  534. package/src/utils/frontmatter.ts +121 -0
  535. package/src/utils/jsonl.ts +167 -0
  536. package/src/utils/package-version.ts +27 -0
  537. package/dist/cli/commands/doc-freshness-check.d.ts +0 -53
  538. package/dist/cli/commands/doc-freshness-check.d.ts.map +0 -1
  539. package/dist/cli/commands/doc-freshness-check.js +0 -352
  540. package/dist/cli/commands/doc-freshness-check.js.map +0 -1
  541. package/dist/types/index.d.ts +0 -14
  542. package/dist/types/index.d.ts.map +0 -1
  543. package/dist/types/index.js +0 -39
  544. package/dist/types/index.js.map +0 -1
  545. package/src/__tests__/long-running.test.ts +0 -17
  546. package/src/__tests__/passes-gate-extension.test.ts +0 -151
  547. package/src/cli/commands/__tests__/doc-freshness-check.test.ts +0 -168
  548. package/src/cli/commands/doc-freshness-check.ts +0 -386
  549. package/src/spec/CONTEXT.md +0 -11
  550. package/src/types/index.ts +0 -47
@@ -0,0 +1,97 @@
1
+ /**
2
+ * getHarnessPackageVersion 正本测试(#102,架构评审 A3)
3
+ *
4
+ * 钉住三件事:
5
+ * 1. 读的是 harness 包自身的 package.json(与真实版本一致)
6
+ * 2. cwd 兜底已删除:cwd 是装着 harness 的消费者项目时,绝不误读消费者版本
7
+ * 3. 仓内不再有第二份「harness 自身 package.json」版本读取(防回潮扫描)
8
+ */
9
+
10
+ import * as fs from 'fs';
11
+ import * as path from 'path';
12
+ import { getHarnessPackageVersion } from '../package-version';
13
+
14
+ const REAL_VERSION = JSON.parse(
15
+ fs.readFileSync(path.join(__dirname, '..', '..', '..', 'package.json'), 'utf-8')
16
+ ).version as string;
17
+
18
+ describe('getHarnessPackageVersion', () => {
19
+ it('返回 harness 包真实版本(与包根 package.json 一致)', () => {
20
+ expect(getHarnessPackageVersion()).toBe(REAL_VERSION);
21
+ });
22
+
23
+ it('cwd 是消费者项目时仍读 harness 版本,不误读消费者 package.json', () => {
24
+ const consumerDir = path.join(process.cwd(), 'temp-test-pkg-version-consumer');
25
+ fs.mkdirSync(consumerDir, { recursive: true });
26
+ fs.writeFileSync(
27
+ path.join(consumerDir, 'package.json'),
28
+ JSON.stringify({ name: 'consumer-app', version: '9.9.9' })
29
+ );
30
+ const prevCwd = process.cwd();
31
+ try {
32
+ process.chdir(consumerDir);
33
+ expect(getHarnessPackageVersion()).toBe(REAL_VERSION);
34
+ } finally {
35
+ process.chdir(prevCwd);
36
+ fs.rmSync(consumerDir, { recursive: true, force: true });
37
+ }
38
+ });
39
+
40
+ it('package.json 读取失败(缺失/损坏)时返回 unknown', () => {
41
+ jest.isolateModules(() => {
42
+ jest.doMock('fs', () => ({
43
+ ...jest.requireActual('fs'),
44
+ readFileSync: () => { throw new Error('ENOENT'); },
45
+ }));
46
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
47
+ const fresh = require('../package-version') as typeof import('../package-version');
48
+ expect(fresh.getHarnessPackageVersion()).toBe('unknown');
49
+ jest.dontMock('fs');
50
+ });
51
+ });
52
+
53
+ it('package.json 无 version 字段时返回 unknown', () => {
54
+ jest.isolateModules(() => {
55
+ jest.doMock('fs', () => ({
56
+ ...jest.requireActual('fs'),
57
+ readFileSync: () => JSON.stringify({ name: '@dommaker/harness' }),
58
+ }));
59
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
60
+ const fresh = require('../package-version') as typeof import('../package-version');
61
+ expect(fresh.getHarnessPackageVersion()).toBe('unknown');
62
+ jest.dontMock('fs');
63
+ });
64
+ });
65
+ });
66
+
67
+ describe('版本读取正本收口(防回潮扫描)', () => {
68
+ function collectTsFiles(dir: string): string[] {
69
+ const out: string[] = [];
70
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
71
+ const full = path.join(dir, entry.name);
72
+ if (entry.isDirectory()) {
73
+ if (entry.name === '__tests__') continue;
74
+ out.push(...collectTsFiles(full));
75
+ } else if (entry.name.endsWith('.ts')) {
76
+ out.push(full);
77
+ }
78
+ }
79
+ return out;
80
+ }
81
+
82
+ it('src/ 内只有 utils/package-version.ts 读取 harness 自身 package.json', () => {
83
+ const srcRoot = path.join(__dirname, '..', '..');
84
+ const canonical = path.join(srcRoot, 'utils', 'package-version.ts');
85
+ // harness 自身清单的三类历史读法:__dirname 相对 / require / cwd 兜底
86
+ const selfPkgReadRe = /(__dirname[^\n]*package\.json|require\(['"][^'"]*package\.json['"]\)|process\.cwd\(\)[^\n]*package\.json)/;
87
+ const offenders: string[] = [];
88
+ for (const file of collectTsFiles(srcRoot)) {
89
+ if (file === canonical) continue;
90
+ const hits = fs.readFileSync(file, 'utf-8')
91
+ .split('\n')
92
+ .filter(line => selfPkgReadRe.test(line));
93
+ if (hits.length > 0) offenders.push(`${file}: ${hits.join(' | ')}`);
94
+ }
95
+ expect(offenders).toEqual([]);
96
+ });
97
+ });
package/src/utils/exec.ts CHANGED
@@ -53,6 +53,21 @@ export function normalizeTriggers<T>(
53
53
  return Array.isArray(value) ? value : [value];
54
54
  }
55
55
 
56
+ /**
57
+ * 判断约束是否匹配当前操作集合(#105:trigger 匹配语义单一来源)
58
+ *
59
+ * 语义 = normalizeTriggers(undefined → [] 不匹配任何操作)+ 交集判定,
60
+ * 任一 operation 命中任一 trigger 即匹配。checker 与 prompt 渲染共用本函数,
61
+ * 禁止就地重写。
62
+ */
63
+ export function matchesTrigger<T>(
64
+ constraint: { trigger: T | T[] | undefined },
65
+ operations: T[]
66
+ ): boolean {
67
+ const triggers = normalizeTriggers(constraint.trigger);
68
+ return operations.some(op => triggers.includes(op));
69
+ }
70
+
56
71
  /**
57
72
  * 异步延迟
58
73
  */
@@ -50,12 +50,21 @@ export function walkFiles(root: string, options: FileWalkOptions = {}): string[]
50
50
  return results;
51
51
  }
52
52
 
53
+ /**
54
+ * 目录遍历默认跳过名单:依赖 / 旁测目录 / 构建产物。
55
+ *
56
+ * 遍历跳过口径的正本——chain 式判断(sync-docs 的 readdir 循环)与
57
+ * findTsSourceFiles 的 skipDirs 默认值同源,禁止再各处手抄三段 `===`。
58
+ * 各调用方自有的更广名单(如 AGENTS.md 目录表跳过 build/out/coverage)不并入。
59
+ */
60
+ export const DEFAULT_SKIP_DIRS = ['node_modules', '__tests__', 'dist'];
61
+
53
62
  export interface TsSourceWalkOptions {
54
63
  /** 是否跳过 barrel 文件 index.ts,默认 false */
55
64
  skipIndex?: boolean;
56
65
  /** 是否同时收集 .tsx 文件,默认 false(只收集 .ts) */
57
66
  includeTsx?: boolean;
58
- /** 跳过的目录名,默认 node_modules/__tests__/dist */
67
+ /** 跳过的目录名,默认 DEFAULT_SKIP_DIRS */
59
68
  skipDirs?: string[];
60
69
  /** 是否跳过 `.` 开头的条目,默认 false */
61
70
  skipHidden?: boolean;
@@ -86,7 +95,7 @@ export function findTsSourceFiles(root: string, options: TsSourceWalkOptions = {
86
95
  const {
87
96
  skipIndex = false,
88
97
  includeTsx = false,
89
- skipDirs = ['node_modules', '__tests__', 'dist'],
98
+ skipDirs = DEFAULT_SKIP_DIRS,
90
99
  skipHidden = false,
91
100
  } = options;
92
101
 
@@ -0,0 +1,121 @@
1
+ /**
2
+ * markdown frontmatter 解析/序列化正本(harness#89,架构评审 2026-09-02 候选10)
3
+ *
4
+ * `---\n<yaml>\n---\n<body>` 这一种语法此前在 knowledge 域 5 个文件里手写了 7 遍,
5
+ * 失败语义三派并存(store 静默丢条目 / migration 记 errors / index-generator 走
6
+ * best-effort / sdd 不要求闭合行完整 / ingest 只 strip 会把正文 `---` 误吞)。
7
+ * 语法与失败走法在此一处定义,仓内不允许存在第二份副本。
8
+ *
9
+ * 语法(唯一解释):
10
+ * - 开界:偏移 0 处必须正好是一行 `---`(前面有空白行则不算 frontmatter)
11
+ * - 闭界:其后第一个**独立成行**的 `---`(`---x`、`----`、缩进 `---` 均不作闭合)
12
+ * - body:闭合行之后全部内容,紧随的一个空行被吃掉(与 join 的 `---\n\n` 包裹严格对称,
13
+ * 保证已落盘条目 load→save 字节稳定)
14
+ * - meta:闭合前的行经 YAML 解析,必须是 mapping
15
+ * - CRLF 文件不按 frontmatter 处理(与收口前各消费方一致,本 module 不新增解释)
16
+ *
17
+ * 三种畸形输入的走法(裁决 2,用例固定在 utils/__tests__/frontmatter.test.ts):
18
+ * - 缺 frontmatter(无开界)→ 'absent'
19
+ * - 空 meta(闭合前只有空白,含零宽块)→ 'absent'——零宽元数据块不承载信息,
20
+ * 与「没有 frontmatter」同走一支,消费方按无元数据路径处理(store 视为非条目、
21
+ * index-generator 走 best-effort),无需上报
22
+ * - 未闭合(有开无闭 / 闭合行不完整)→ 'malformed' + reason 'unterminated'
23
+ * - meta 不是合法 YAML mapping(语法错、显式 null、标量或数组)→ 'malformed' + reason 'invalid-yaml'
24
+ *
25
+ * 消费方统一口径(裁决 2:不允许两派并存):'malformed' 两支必须**显式上报**,
26
+ * 禁止静默丢数据;恢复动作按消费方语义选择并在代码里写明——
27
+ * 有结构化报告面的写报告(migration → result.errors),
28
+ * 纯扫描型的打一行 stderr(前缀 `[harness]`,与 failure/recorder.ts 的坏行告警同构)
29
+ * 后跳过或走 best-effort。'absent' 是合法输入,不上报。
30
+ *
31
+ * 序列化(裁决 3:收格式不收字段排序策略):join 只负责包裹与 YAML dump 参数
32
+ * (lineWidth 120,与收口前 store/migration 逐字一致);canonical 字段序是 store 的
33
+ * 私有策略,留在 store.toFrontmatter。
34
+ *
35
+ * 机械核查(期望命中数,均已实测):
36
+ * grep -rnE '/\^---' src --include='*.ts' | grep -v __tests__
37
+ * → 期望 0 处:手写开界正则归零
38
+ * grep -rn "'---'" src --include='*.ts' | grep -v __tests__
39
+ * → 期望 1 处:本文件 DELIMITER
40
+ * grep -rn "yaml.load(metaText)\|yaml.dump(meta," src --include='*.ts' | grep -v __tests__
41
+ * → 期望 2 处:本文件 split 的 load + join 的 dump
42
+ * 豁免清单(不属 frontmatter,不改):markdown 生成物里的 `---` 分隔线与表格分隔行
43
+ * (init / sync-docs / report / constraints-report 模板)、doc-freshness 的章节定位正则
44
+ * (`\n---` 是章节边界)、config.yml 与 checkpoint/tasks/progress 的 yaml.dump(单 YAML/JSON 文档)。
45
+ */
46
+
47
+ import * as yaml from 'js-yaml';
48
+
49
+ /** frontmatter 界符(整行) */
50
+ const DELIMITER = '---';
51
+
52
+ /** 与收口前 store/migration 逐字一致的 YAML dump 行宽 */
53
+ const DUMP_LINE_WIDTH = 120;
54
+
55
+ /** 'malformed' 的两支:消费方必须逐支显式处理(口径见文件头) */
56
+ export type FrontmatterMalformedReason = 'unterminated' | 'invalid-yaml';
57
+
58
+ /** frontmatter 元数据(已由 split 保证是 YAML mapping) */
59
+ export type FrontmatterMeta = Record<string, unknown>;
60
+
61
+ export type FrontmatterSplit =
62
+ | { state: 'ok'; meta: FrontmatterMeta; body: string }
63
+ | { state: 'absent' }
64
+ | { state: 'malformed'; reason: FrontmatterMalformedReason; detail: string };
65
+
66
+ /**
67
+ * 解析 markdown 的 YAML frontmatter。
68
+ *
69
+ * 不抛:三种畸形输入与 YAML 非法都体现在返回值 state/reason 上,由消费方按口径处置。
70
+ */
71
+ export function splitFrontmatter(raw: string): FrontmatterSplit {
72
+ const lines = raw.split('\n');
73
+ if (lines[0] !== DELIMITER) return { state: 'absent' };
74
+
75
+ const closeIndex = lines.indexOf(DELIMITER, 1);
76
+ if (closeIndex === -1) {
77
+ return {
78
+ state: 'malformed',
79
+ reason: 'unterminated',
80
+ detail: `开界之后缺少独立成行的 ${DELIMITER} 闭合行`,
81
+ };
82
+ }
83
+
84
+ const metaLines = lines.slice(1, closeIndex);
85
+ if (metaLines.every(line => line.trim().length === 0)) return { state: 'absent' };
86
+
87
+ const metaText = metaLines.join('\n');
88
+ let parsed: unknown;
89
+ try {
90
+ parsed = yaml.load(metaText);
91
+ } catch (error) {
92
+ return {
93
+ state: 'malformed',
94
+ reason: 'invalid-yaml',
95
+ // js-yaml 的 message 带多行代码片段,detail 只取首行描述——消费方要嵌进单行报告/stderr
96
+ detail: (error instanceof Error ? error.message : String(error)).split('\n')[0],
97
+ };
98
+ }
99
+
100
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
101
+ return {
102
+ state: 'malformed',
103
+ reason: 'invalid-yaml',
104
+ detail: `frontmatter 必须是 YAML mapping,实际是 ${Array.isArray(parsed) ? 'array' : typeof parsed}`,
105
+ };
106
+ }
107
+
108
+ let bodyStart = closeIndex + 1;
109
+ if (lines[bodyStart] === '') bodyStart++;
110
+
111
+ return { state: 'ok', meta: parsed as FrontmatterMeta, body: lines.slice(bodyStart).join('\n') };
112
+ }
113
+
114
+ /**
115
+ * 序列化为 `---\n<yaml>---\n\n<body>`(包裹格式与收口前 store/migration 逐字一致)。
116
+ *
117
+ * meta 的键序由调用方决定(store 保 canonical 序);本函数只做包裹与 dump 参数。
118
+ */
119
+ export function joinFrontmatter(meta: FrontmatterMeta, body: string): string {
120
+ return `${DELIMITER}\n${yaml.dump(meta, { lineWidth: DUMP_LINE_WIDTH })}${DELIMITER}\n\n${body}`;
121
+ }
@@ -0,0 +1,167 @@
1
+ /**
2
+ * append-only JSONL 日志读写正本(harness#82,架构评审 2026-09-02 候选3)
3
+ *
4
+ * 全仓 append-only JSONL(traces.log / failures.log / context-tracker.log /
5
+ * references.jsonl / sessions/<id>/events.jsonl / 外部 transcript .jsonl)的
6
+ * exists → read → split → parse → filter 读链与 ensureDir + append 写链
7
+ * 收口于此,仓内不允许存在第二份副本。
8
+ *
9
+ * 坏行策略(harness#82 裁决 1):读入口 policy 为显式必填参数,类型层面无缺省,
10
+ * 每个调用点必须逐一声明 'skip' | 'throw'——既不让「静默丢数据」成为框架缺省,
11
+ * 也不反转既有容错调用点的语义。坏行指非空但 JSON.parse 失败的行
12
+ * (半写入截断、手工编辑、磁盘满等)。
13
+ *
14
+ * tail / head:只解析尾部 / 头部 N 个非空行(文件仍全量读取,parse 才是大头),
15
+ * 供「只看最近 K 条」的调用点避免全量 parse(check 等热路径)。
16
+ * countJsonlLines 供纯计数消费方(完全不 parse)。
17
+ *
18
+ * 计数去向(harness#100):本模块是坏行计数的唯一正本,但正本≠终点——凡以 'skip'
19
+ * 策略读,调用点必须把 skippedLines 带到该消费面的用户可见输出(CLI 走 stderr,
20
+ * 结构化输出与 API 走字段),或显式记名豁免并写明理由。机器可检面:
21
+ * `src/utils/__tests__/jsonl-skip-disposition.test.ts`(冻结站点集合 + 要求每个读点
22
+ * 上方声明 `计数去向:`)。
23
+ *
24
+ * 豁免清单与机械核查(期望命中数):
25
+ * grep -rnE "JSON\.parse\((line|trimmed|l)\b" src --include='*.ts' | grep -v __tests__
26
+ * → 期望 1 处:本文件 readJsonl(读链正本本体)
27
+ * grep -rn "map(JSON.parse" src --include='*.ts' | grep -v __tests__
28
+ * → 期望 0 处
29
+ * __tests__ 下的坏行 fixture 不在核查范围。
30
+ * 其余裁决豁免:readIfExists(injection-writer,string|null 形态不同,#82 裁决 3);
31
+ * FailureRecorder 轮换链(文件生命周期不变量,裁决 2);
32
+ * 单 JSON 文档读取(package.json / .state.json / checkpoint.json / summary 等非 JSONL)。
33
+ */
34
+
35
+ import * as fs from 'fs';
36
+ import * as path from 'path';
37
+
38
+ /**
39
+ * 坏行策略
40
+ *
41
+ * - 'skip':跳过损坏行,继续解析;skippedLines 计数
42
+ * - 'throw':损坏行直接上抛(沿用原抛语义的调用点显式选择)
43
+ */
44
+ export type JsonlBadLinePolicy = 'skip' | 'throw';
45
+
46
+ export interface JsonlReadResult<T> {
47
+ records: T[];
48
+ /**
49
+ * 被跳过的坏行数('throw' 策略下恒为 0)
50
+ *
51
+ * 拿到它不等于告知:skip 读点必须把它带到消费面的用户可见输出或记名豁免(harness#100)
52
+ */
53
+ skippedLines: number;
54
+ }
55
+
56
+ export interface JsonlReadOptions {
57
+ /** 只解析最后 N 个非空行(尾部读取) */
58
+ tail?: number;
59
+ /** 只解析前 N 个非空行(头部读取) */
60
+ head?: number;
61
+ }
62
+
63
+ /** exists → read → split → filter 空行的公共前缀(正本唯一一份) */
64
+ function readNonEmptyLines(filePath: string): string[] {
65
+ if (!fs.existsSync(filePath)) return [];
66
+ return fs
67
+ .readFileSync(filePath, 'utf-8')
68
+ .split('\n')
69
+ .filter(line => line.trim().length > 0);
70
+ }
71
+
72
+ /**
73
+ * 读取 JSONL 文件:exists → read → split → parse → filter(正本读链)
74
+ *
75
+ * policy 必填无缺省(裁决 1);缺文件返回空结果,不抛。
76
+ */
77
+ export function readJsonl<T>(
78
+ filePath: string,
79
+ policy: JsonlBadLinePolicy,
80
+ options?: JsonlReadOptions
81
+ ): JsonlReadResult<T> {
82
+ let lines = readNonEmptyLines(filePath);
83
+ if (options?.head !== undefined) {
84
+ lines = options.head > 0 ? lines.slice(0, options.head) : [];
85
+ }
86
+ if (options?.tail !== undefined) {
87
+ lines = options.tail > 0 ? lines.slice(-options.tail) : [];
88
+ }
89
+
90
+ const records: T[] = [];
91
+ let skippedLines = 0;
92
+ for (const line of lines) {
93
+ try {
94
+ records.push(JSON.parse(line) as T);
95
+ } catch (error) {
96
+ if (policy === 'throw') throw error;
97
+ skippedLines++;
98
+ }
99
+ }
100
+ return { records, skippedLines };
101
+ }
102
+
103
+ /**
104
+ * 统计非空行数(含坏行,完全不 parse)
105
+ *
106
+ * 供只关心记录条数的调用点(如 check 智能提示)避免全量 parse;
107
+ * 缺文件返回 0。
108
+ */
109
+ export function countJsonlLines(filePath: string): number {
110
+ return readNonEmptyLines(filePath).length;
111
+ }
112
+
113
+ export interface JsonlEndsResult<T> {
114
+ /** 原始非空行数(合法 + 坏行),与 records.length + skippedLines 同口径 */
115
+ totalLines: number;
116
+ /** 自首向尾第一条合法记录;无合法记录为 undefined */
117
+ first?: T;
118
+ /** 自尾向首第一条合法记录;无合法记录为 undefined */
119
+ last?: T;
120
+ }
121
+
122
+ /**
123
+ * 只取首尾:首/末条合法记录 + 原始行数,parse 停在两端首个合法行
124
+ *
125
+ * 供只要「总数 + 首末记录」的调用点(如 TraceCollector.getStats)避免全量
126
+ * parse;行文本仍整读(10MB 级文本读廉价,JSON.parse 才是成本)。坏行策略
127
+ * 同 readJsonl:'skip' 跳过继续找,'throw' 遇坏行上抛。缺文件返回
128
+ * { totalLines: 0 }。
129
+ */
130
+ export function readJsonlEnds<T>(filePath: string, policy: JsonlBadLinePolicy): JsonlEndsResult<T> {
131
+ const lines = readNonEmptyLines(filePath);
132
+
133
+ let first: T | undefined;
134
+ for (let i = 0; i < lines.length; i++) {
135
+ try {
136
+ first = JSON.parse(lines[i]) as T;
137
+ break;
138
+ } catch (error) {
139
+ if (policy === 'throw') throw error;
140
+ }
141
+ }
142
+
143
+ let last: T | undefined;
144
+ for (let i = lines.length - 1; i >= 0; i--) {
145
+ try {
146
+ last = JSON.parse(lines[i]) as T;
147
+ break;
148
+ } catch (error) {
149
+ if (policy === 'throw') throw error;
150
+ }
151
+ }
152
+
153
+ return { totalLines: lines.length, first, last };
154
+ }
155
+
156
+ /**
157
+ * 追加一条 JSONL 记录:ensureDir + append(正本写链)
158
+ *
159
+ * 目录不存在时递归创建;value 序列化为单行 JSON + 换行。
160
+ */
161
+ export function appendJsonl(filePath: string, value: unknown): void {
162
+ const dir = path.dirname(filePath);
163
+ if (!fs.existsSync(dir)) {
164
+ fs.mkdirSync(dir, { recursive: true });
165
+ }
166
+ fs.appendFileSync(filePath, JSON.stringify(value) + '\n', 'utf-8');
167
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * harness 包版本读取正本(#102,架构评审 A3)
3
+ *
4
+ * 「harness 包版本」此前散在四处五种写法(constraints.ts 带 cwd 兜底、init.ts
5
+ * require 与内联各一份、injection-drift.ts / constraints-retire.ts __dirname
6
+ * 相对路径)。其中 cwd 兜底在 harness 装进消费者 node_modules 且相对路径失败时
7
+ * 会读到**消费者自己的版本号**——这是本模块要消灭的 bug。语义在此一处定义:
8
+ *
9
+ * - 只读本模块自身的 package.json(__dirname 相对;src 与 dist 目录深度一致,
10
+ * 两种加载方式命中同一份清单);
11
+ * - 无 cwd 兜底——cwd 的 package.json 是消费者项目的,不是 harness 的;
12
+ * - 清单缺失/损坏/无 version 字段 → 'unknown'(沿用收口前各处一致语义)。
13
+ */
14
+
15
+ import * as fs from 'fs';
16
+ import * as path from 'path';
17
+
18
+ /** 读取 harness 包版本;读不到(缺失/损坏/无 version 字段)返回 'unknown' */
19
+ export function getHarnessPackageVersion(): string {
20
+ try {
21
+ const pkgPath = path.join(__dirname, '..', '..', 'package.json');
22
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
23
+ return typeof pkg.version === 'string' && pkg.version ? pkg.version : 'unknown';
24
+ } catch {
25
+ return 'unknown';
26
+ }
27
+ }
@@ -1,53 +0,0 @@
1
- /**
2
- * harness doc-freshness-check 命令
3
- *
4
- * 从文档中提取可验证的声明(claims),与代码/文件系统对照,输出差异。
5
- * 纯代码操作,零 LLM 调用。
6
- */
7
- export interface DocFreshnessCheckOptions {
8
- /** 输出 JSON 格式 */
9
- format?: 'json' | 'table';
10
- /** 变更文件列表(逗号分隔),用于聚焦检查 */
11
- changedFiles?: string;
12
- /** 项目路径 */
13
- projectPath?: string;
14
- }
15
- /** 声明类型 */
16
- export type ClaimType = 'numeric' | 'list' | 'status' | 'narrative';
17
- /** 单条声明 */
18
- export interface Claim {
19
- /** 原始文本片段 */
20
- text: string;
21
- /** 声明类型 */
22
- type: ClaimType;
23
- /** 行号 */
24
- line: number;
25
- }
26
- /** 验证结果 */
27
- export interface ClaimResult {
28
- /** 原始声明 */
29
- claim: string;
30
- /** 声明类型 */
31
- type: ClaimType;
32
- /** 文档中的期望值 */
33
- expected: string;
34
- /** 实际值 */
35
- actual: string;
36
- /** 来源文件 */
37
- file: string;
38
- /** 是否匹配 */
39
- match: boolean;
40
- }
41
- /**
42
- * 从 markdown 内容提取 claims
43
- */
44
- export declare function extractClaims(content: string, filePath: string): ClaimResult[];
45
- /**
46
- * 验证所有 claims
47
- */
48
- export declare function verifyClaims(claims: ClaimResult[], projectPath: string): ClaimResult[];
49
- /**
50
- * doc-freshness-check CLI 命令
51
- */
52
- export declare function docFreshnessCheck(docPath: string, options?: DocFreshnessCheckOptions): Promise<void>;
53
- //# sourceMappingURL=doc-freshness-check.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"doc-freshness-check.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/doc-freshness-check.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,MAAM,WAAW,wBAAwB;IACvC,iBAAiB;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,0BAA0B;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,WAAW;AACX,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEpE,WAAW;AACX,MAAM,WAAW,KAAK;IACpB,aAAa;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW;IACX,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS;IACT,IAAI,EAAE,MAAM,CAAC;CACd;AAED,WAAW;AACX,MAAM,WAAW,WAAW;IAC1B,WAAW;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW;IACX,IAAI,EAAE,SAAS,CAAC;IAChB,cAAc;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU;IACV,MAAM,EAAE,MAAM,CAAC;IACf,WAAW;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW;IACX,KAAK,EAAE,OAAO,CAAC;CAChB;AA4BD;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE,CA6D9E;AAyHD;;GAEG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,WAAW,EAAE,EACrB,WAAW,EAAE,MAAM,GAClB,WAAW,EAAE,CAaf;AAuDD;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,IAAI,CAAC,CA4Cf"}