@dommaker/harness 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (549) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/bin/harness.js +17 -1
  3. package/dist/agents/index.d.ts +6 -2
  4. package/dist/agents/index.d.ts.map +1 -1
  5. package/dist/agents/index.js +6 -16
  6. package/dist/agents/index.js.map +1 -1
  7. package/dist/cli/commands/__tests__/gate-decision.d.ts +18 -0
  8. package/dist/cli/commands/__tests__/gate-decision.d.ts.map +1 -0
  9. package/dist/cli/commands/__tests__/gate-decision.js +26 -0
  10. package/dist/cli/commands/__tests__/gate-decision.js.map +1 -0
  11. package/dist/cli/commands/acceptance.d.ts.map +1 -1
  12. package/dist/cli/commands/acceptance.js +17 -28
  13. package/dist/cli/commands/acceptance.js.map +1 -1
  14. package/dist/cli/commands/check.d.ts +11 -3
  15. package/dist/cli/commands/check.d.ts.map +1 -1
  16. package/dist/cli/commands/check.js +26 -11
  17. package/dist/cli/commands/check.js.map +1 -1
  18. package/dist/cli/commands/command.d.ts +0 -1
  19. package/dist/cli/commands/command.d.ts.map +1 -1
  20. package/dist/cli/commands/command.js +8 -6
  21. package/dist/cli/commands/command.js.map +1 -1
  22. package/dist/cli/commands/constraints-retire.d.ts.map +1 -1
  23. package/dist/cli/commands/constraints-retire.js +36 -57
  24. package/dist/cli/commands/constraints-retire.js.map +1 -1
  25. package/dist/cli/commands/contract.d.ts.map +1 -1
  26. package/dist/cli/commands/contract.js +36 -42
  27. package/dist/cli/commands/contract.js.map +1 -1
  28. package/dist/cli/commands/definitions.d.ts +2 -0
  29. package/dist/cli/commands/definitions.d.ts.map +1 -1
  30. package/dist/cli/commands/definitions.js +11 -6
  31. package/dist/cli/commands/definitions.js.map +1 -1
  32. package/dist/cli/commands/failure.d.ts.map +1 -1
  33. package/dist/cli/commands/failure.js +16 -2
  34. package/dist/cli/commands/failure.js.map +1 -1
  35. package/dist/cli/commands/init.d.ts +14 -8
  36. package/dist/cli/commands/init.d.ts.map +1 -1
  37. package/dist/cli/commands/init.js +172 -364
  38. package/dist/cli/commands/init.js.map +1 -1
  39. package/dist/cli/commands/knowledge-view.d.ts +90 -0
  40. package/dist/cli/commands/knowledge-view.d.ts.map +1 -0
  41. package/dist/cli/commands/knowledge-view.js +198 -0
  42. package/dist/cli/commands/knowledge-view.js.map +1 -0
  43. package/dist/cli/commands/knowledge.d.ts +137 -52
  44. package/dist/cli/commands/knowledge.d.ts.map +1 -1
  45. package/dist/cli/commands/knowledge.js +534 -400
  46. package/dist/cli/commands/knowledge.js.map +1 -1
  47. package/dist/cli/commands/passes-gate.d.ts +4 -1
  48. package/dist/cli/commands/passes-gate.d.ts.map +1 -1
  49. package/dist/cli/commands/passes-gate.js +11 -2
  50. package/dist/cli/commands/passes-gate.js.map +1 -1
  51. package/dist/cli/commands/performance.d.ts.map +1 -1
  52. package/dist/cli/commands/performance.js +19 -31
  53. package/dist/cli/commands/performance.js.map +1 -1
  54. package/dist/cli/commands/report.d.ts.map +1 -1
  55. package/dist/cli/commands/report.js +2 -1
  56. package/dist/cli/commands/report.js.map +1 -1
  57. package/dist/cli/commands/review.d.ts.map +1 -1
  58. package/dist/cli/commands/review.js +13 -25
  59. package/dist/cli/commands/review.js.map +1 -1
  60. package/dist/cli/commands/scaffold-templates.d.ts +73 -0
  61. package/dist/cli/commands/scaffold-templates.d.ts.map +1 -0
  62. package/dist/cli/commands/scaffold-templates.js +424 -0
  63. package/dist/cli/commands/scaffold-templates.js.map +1 -0
  64. package/dist/cli/commands/scaffold.d.ts +105 -0
  65. package/dist/cli/commands/scaffold.d.ts.map +1 -0
  66. package/dist/cli/commands/scaffold.js +263 -0
  67. package/dist/cli/commands/scaffold.js.map +1 -0
  68. package/dist/cli/commands/security.d.ts.map +1 -1
  69. package/dist/cli/commands/security.js +22 -24
  70. package/dist/cli/commands/security.js.map +1 -1
  71. package/dist/cli/commands/spec-baseline-check.d.ts +43 -0
  72. package/dist/cli/commands/spec-baseline-check.d.ts.map +1 -1
  73. package/dist/cli/commands/spec-baseline-check.js +109 -34
  74. package/dist/cli/commands/spec-baseline-check.js.map +1 -1
  75. package/dist/cli/commands/sync-docs/context-syncer.d.ts +21 -2
  76. package/dist/cli/commands/sync-docs/context-syncer.d.ts.map +1 -1
  77. package/dist/cli/commands/sync-docs/context-syncer.js +112 -28
  78. package/dist/cli/commands/sync-docs/context-syncer.js.map +1 -1
  79. package/dist/cli/commands/sync-docs/index.d.ts +1 -1
  80. package/dist/cli/commands/sync-docs/index.d.ts.map +1 -1
  81. package/dist/cli/commands/sync-docs/index.js +86 -27
  82. package/dist/cli/commands/sync-docs/index.js.map +1 -1
  83. package/dist/cli/commands/sync-docs/project-reader.d.ts +24 -1
  84. package/dist/cli/commands/sync-docs/project-reader.d.ts.map +1 -1
  85. package/dist/cli/commands/sync-docs/project-reader.js +33 -7
  86. package/dist/cli/commands/sync-docs/project-reader.js.map +1 -1
  87. package/dist/cli/commands/validate.d.ts +0 -16
  88. package/dist/cli/commands/validate.d.ts.map +1 -1
  89. package/dist/cli/commands/validate.js +2 -97
  90. package/dist/cli/commands/validate.js.map +1 -1
  91. package/dist/cli/gate-command.d.ts +37 -0
  92. package/dist/cli/gate-command.d.ts.map +1 -0
  93. package/dist/cli/gate-command.js +64 -0
  94. package/dist/cli/gate-command.js.map +1 -0
  95. package/dist/completion-checkers/index.d.ts +1 -1
  96. package/dist/completion-checkers/index.d.ts.map +1 -1
  97. package/dist/completion-checkers/index.js +0 -15
  98. package/dist/completion-checkers/index.js.map +1 -1
  99. package/dist/context/knowledge-injector.d.ts +4 -2
  100. package/dist/context/knowledge-injector.d.ts.map +1 -1
  101. package/dist/context/knowledge-injector.js +13 -6
  102. package/dist/context/knowledge-injector.js.map +1 -1
  103. package/dist/core/constraints/agent-prompt-renderer.js +2 -2
  104. package/dist/core/constraints/agent-prompt-renderer.js.map +1 -1
  105. package/dist/core/constraints/capabilities-reconcile.d.ts +20 -0
  106. package/dist/core/constraints/capabilities-reconcile.d.ts.map +1 -1
  107. package/dist/core/constraints/capabilities-reconcile.js +26 -4
  108. package/dist/core/constraints/capabilities-reconcile.js.map +1 -1
  109. package/dist/core/constraints/check-cache.d.ts +1 -1
  110. package/dist/core/constraints/check-cache.js +1 -1
  111. package/dist/core/constraints/checker.d.ts +8 -3
  112. package/dist/core/constraints/checker.d.ts.map +1 -1
  113. package/dist/core/constraints/checker.js +30 -19
  114. package/dist/core/constraints/checker.js.map +1 -1
  115. package/dist/core/constraints/checkers/capability-sync.d.ts +3 -1
  116. package/dist/core/constraints/checkers/capability-sync.d.ts.map +1 -1
  117. package/dist/core/constraints/checkers/capability-sync.js +17 -24
  118. package/dist/core/constraints/checkers/capability-sync.js.map +1 -1
  119. package/dist/core/constraints/checkers/context-doc-sync.d.ts +1 -1
  120. package/dist/core/constraints/checkers/context-doc-sync.d.ts.map +1 -1
  121. package/dist/core/constraints/checkers/context-doc-sync.js +9 -6
  122. package/dist/core/constraints/checkers/context-doc-sync.js.map +1 -1
  123. package/dist/core/constraints/checkers/docs-freshness.d.ts.map +1 -1
  124. package/dist/core/constraints/checkers/docs-freshness.js +24 -30
  125. package/dist/core/constraints/checkers/docs-freshness.js.map +1 -1
  126. package/dist/core/constraints/checkers/governance-presence.d.ts.map +1 -1
  127. package/dist/core/constraints/checkers/governance-presence.js +10 -4
  128. package/dist/core/constraints/checkers/governance-presence.js.map +1 -1
  129. package/dist/core/constraints/checkers/types.d.ts +10 -6
  130. package/dist/core/constraints/checkers/types.d.ts.map +1 -1
  131. package/dist/core/constraints/checkers/types.js +7 -3
  132. package/dist/core/constraints/checkers/types.js.map +1 -1
  133. package/dist/core/constraints/context-builder.d.ts +11 -10
  134. package/dist/core/constraints/context-builder.d.ts.map +1 -1
  135. package/dist/core/constraints/context-builder.js +31 -27
  136. package/dist/core/constraints/context-builder.js.map +1 -1
  137. package/dist/core/constraints/context-reconcile.d.ts +75 -0
  138. package/dist/core/constraints/context-reconcile.d.ts.map +1 -0
  139. package/dist/core/constraints/context-reconcile.js +161 -0
  140. package/dist/core/constraints/context-reconcile.js.map +1 -0
  141. package/dist/core/constraints/doc-freshness/runner.d.ts +7 -0
  142. package/dist/core/constraints/doc-freshness/runner.d.ts.map +1 -1
  143. package/dist/core/constraints/doc-freshness/runner.js +8 -3
  144. package/dist/core/constraints/doc-freshness/runner.js.map +1 -1
  145. package/dist/core/constraints/git-evidence.js +1 -1
  146. package/dist/core/constraints/git-evidence.js.map +1 -1
  147. package/dist/core/constraints/injection-drift.d.ts +7 -2
  148. package/dist/core/constraints/injection-drift.d.ts.map +1 -1
  149. package/dist/core/constraints/injection-drift.js +13 -7
  150. package/dist/core/constraints/injection-drift.js.map +1 -1
  151. package/dist/core/constraints/run-env.d.ts +92 -0
  152. package/dist/core/constraints/run-env.d.ts.map +1 -0
  153. package/dist/core/constraints/run-env.js +175 -0
  154. package/dist/core/constraints/run-env.js.map +1 -0
  155. package/dist/core/constraints/triggers.d.ts +22 -0
  156. package/dist/core/constraints/triggers.d.ts.map +1 -0
  157. package/dist/core/constraints/triggers.js +31 -0
  158. package/dist/core/constraints/triggers.js.map +1 -0
  159. package/dist/core/effective-constraints.d.ts +13 -4
  160. package/dist/core/effective-constraints.d.ts.map +1 -1
  161. package/dist/core/effective-constraints.js +16 -6
  162. package/dist/core/effective-constraints.js.map +1 -1
  163. package/dist/core/effective-set.d.ts +8 -15
  164. package/dist/core/effective-set.d.ts.map +1 -1
  165. package/dist/core/effective-set.js +7 -12
  166. package/dist/core/effective-set.js.map +1 -1
  167. package/dist/core/index.d.ts +1 -0
  168. package/dist/core/index.d.ts.map +1 -1
  169. package/dist/core/index.js.map +1 -1
  170. package/dist/core/project-config-loader.d.ts +39 -17
  171. package/dist/core/project-config-loader.d.ts.map +1 -1
  172. package/dist/core/project-config-loader.js +51 -122
  173. package/dist/core/project-config-loader.js.map +1 -1
  174. package/dist/core/validators/check-handlers/http.d.ts +2 -2
  175. package/dist/core/validators/check-handlers/http.d.ts.map +1 -1
  176. package/dist/core/validators/check-handlers/http.js +12 -7
  177. package/dist/core/validators/check-handlers/http.js.map +1 -1
  178. package/dist/failure/classifier.d.ts +1 -1
  179. package/dist/failure/classifier.d.ts.map +1 -1
  180. package/dist/failure/classifier.js +8 -8
  181. package/dist/failure/classifier.js.map +1 -1
  182. package/dist/failure/index.d.ts +2 -1
  183. package/dist/failure/index.d.ts.map +1 -1
  184. package/dist/failure/index.js +9 -17
  185. package/dist/failure/index.js.map +1 -1
  186. package/dist/failure/recorder.d.ts +1 -1
  187. package/dist/failure/recorder.d.ts.map +1 -1
  188. package/dist/gates/checker-gate.d.ts +2 -1
  189. package/dist/gates/checker-gate.d.ts.map +1 -1
  190. package/dist/gates/checker-gate.js +3 -2
  191. package/dist/gates/checker-gate.js.map +1 -1
  192. package/dist/gates/command.d.ts +10 -4
  193. package/dist/gates/command.d.ts.map +1 -1
  194. package/dist/gates/command.js +36 -62
  195. package/dist/gates/command.js.map +1 -1
  196. package/dist/gates/contract.d.ts.map +1 -1
  197. package/dist/gates/contract.js +0 -4
  198. package/dist/gates/contract.js.map +1 -1
  199. package/dist/gates/definitions.d.ts +2 -1
  200. package/dist/gates/definitions.d.ts.map +1 -1
  201. package/dist/gates/definitions.js +6 -5
  202. package/dist/gates/definitions.js.map +1 -1
  203. package/dist/gates/index.d.ts +0 -4
  204. package/dist/gates/index.d.ts.map +1 -1
  205. package/dist/gates/index.js +1 -6
  206. package/dist/gates/index.js.map +1 -1
  207. package/dist/gates/performance.d.ts.map +1 -1
  208. package/dist/gates/performance.js +0 -4
  209. package/dist/gates/performance.js.map +1 -1
  210. package/dist/gates/runner.d.ts +1 -1
  211. package/dist/gates/runner.js +1 -1
  212. package/dist/gates/security.d.ts +1 -1
  213. package/dist/gates/security.d.ts.map +1 -1
  214. package/dist/gates/security.js +5 -6
  215. package/dist/gates/security.js.map +1 -1
  216. package/dist/gates/types.d.ts +14 -17
  217. package/dist/gates/types.d.ts.map +1 -1
  218. package/dist/gates/types.js.map +1 -1
  219. package/dist/hooks/bootstrap.d.ts +6 -4
  220. package/dist/hooks/bootstrap.d.ts.map +1 -1
  221. package/dist/hooks/bootstrap.js +25 -13
  222. package/dist/hooks/bootstrap.js.map +1 -1
  223. package/dist/hooks/config.d.ts +6 -2
  224. package/dist/hooks/config.d.ts.map +1 -1
  225. package/dist/hooks/config.js +5 -1
  226. package/dist/hooks/config.js.map +1 -1
  227. package/dist/hooks/index.d.ts +1 -1
  228. package/dist/hooks/index.d.ts.map +1 -1
  229. package/dist/hooks/index.js +0 -15
  230. package/dist/hooks/index.js.map +1 -1
  231. package/dist/hooks/pipeline.d.ts.map +1 -1
  232. package/dist/hooks/pipeline.js +2 -4
  233. package/dist/hooks/pipeline.js.map +1 -1
  234. package/dist/hooks/registry.d.ts +11 -8
  235. package/dist/hooks/registry.d.ts.map +1 -1
  236. package/dist/hooks/registry.js +22 -7
  237. package/dist/hooks/registry.js.map +1 -1
  238. package/dist/hooks/types.d.ts +23 -7
  239. package/dist/hooks/types.d.ts.map +1 -1
  240. package/dist/index.d.ts +3 -3
  241. package/dist/index.d.ts.map +1 -1
  242. package/dist/index.js +3 -4
  243. package/dist/index.js.map +1 -1
  244. package/dist/knowledge/audit-scoring.d.ts +87 -0
  245. package/dist/knowledge/audit-scoring.d.ts.map +1 -0
  246. package/dist/knowledge/audit-scoring.js +470 -0
  247. package/dist/knowledge/audit-scoring.js.map +1 -0
  248. package/dist/knowledge/audit.d.ts +11 -59
  249. package/dist/knowledge/audit.d.ts.map +1 -1
  250. package/dist/knowledge/audit.js +47 -522
  251. package/dist/knowledge/audit.js.map +1 -1
  252. package/dist/knowledge/import.d.ts.map +1 -1
  253. package/dist/knowledge/import.js +2 -0
  254. package/dist/knowledge/import.js.map +1 -1
  255. package/dist/knowledge/index-generator.d.ts.map +1 -1
  256. package/dist/knowledge/index-generator.js +4 -5
  257. package/dist/knowledge/index-generator.js.map +1 -1
  258. package/dist/knowledge/index.d.ts +3 -2
  259. package/dist/knowledge/index.d.ts.map +1 -1
  260. package/dist/knowledge/index.js +3 -16
  261. package/dist/knowledge/index.js.map +1 -1
  262. package/dist/knowledge/ingest.js +1 -1
  263. package/dist/knowledge/ingest.js.map +1 -1
  264. package/dist/knowledge/lifecycle.d.ts.map +1 -1
  265. package/dist/knowledge/lifecycle.js +4 -2
  266. package/dist/knowledge/lifecycle.js.map +1 -1
  267. package/dist/knowledge/migration.d.ts +3 -0
  268. package/dist/knowledge/migration.d.ts.map +1 -1
  269. package/dist/knowledge/migration.js +8 -2
  270. package/dist/knowledge/migration.js.map +1 -1
  271. package/dist/knowledge/query.d.ts +6 -0
  272. package/dist/knowledge/query.d.ts.map +1 -1
  273. package/dist/knowledge/query.js +8 -2
  274. package/dist/knowledge/query.js.map +1 -1
  275. package/dist/knowledge/reference-tracker.d.ts.map +1 -1
  276. package/dist/knowledge/reference-tracker.js +4 -6
  277. package/dist/knowledge/reference-tracker.js.map +1 -1
  278. package/dist/knowledge/store.d.ts +22 -16
  279. package/dist/knowledge/store.d.ts.map +1 -1
  280. package/dist/knowledge/store.js +53 -12
  281. package/dist/knowledge/store.js.map +1 -1
  282. package/dist/knowledge/tree-walker.d.ts +19 -0
  283. package/dist/knowledge/tree-walker.d.ts.map +1 -0
  284. package/dist/knowledge/tree-walker.js +30 -0
  285. package/dist/knowledge/tree-walker.js.map +1 -0
  286. package/dist/knowledge/types.d.ts +16 -0
  287. package/dist/knowledge/types.d.ts.map +1 -1
  288. package/dist/monitoring/traces.d.ts +5 -3
  289. package/dist/monitoring/traces.d.ts.map +1 -1
  290. package/dist/monitoring/traces.js +19 -5
  291. package/dist/monitoring/traces.js.map +1 -1
  292. package/dist/test-setup/jsonl-fake-fs.d.ts +30 -0
  293. package/dist/test-setup/jsonl-fake-fs.d.ts.map +1 -0
  294. package/dist/test-setup/jsonl-fake-fs.js +49 -0
  295. package/dist/test-setup/jsonl-fake-fs.js.map +1 -0
  296. package/dist/tools/index.d.ts +4 -1
  297. package/dist/tools/index.d.ts.map +1 -1
  298. package/dist/tools/index.js +7 -15
  299. package/dist/tools/index.js.map +1 -1
  300. package/dist/types/checkpoint.d.ts +5 -0
  301. package/dist/types/checkpoint.d.ts.map +1 -1
  302. package/dist/types/project-config.d.ts +18 -0
  303. package/dist/types/project-config.d.ts.map +1 -1
  304. package/dist/types/trace.d.ts +13 -4
  305. package/dist/types/trace.d.ts.map +1 -1
  306. package/dist/types/trace.js +4 -3
  307. package/dist/types/trace.js.map +1 -1
  308. package/dist/utils/exec.d.ts +4 -27
  309. package/dist/utils/exec.d.ts.map +1 -1
  310. package/dist/utils/exec.js +4 -94
  311. package/dist/utils/exec.js.map +1 -1
  312. package/dist/utils/jsonl.d.ts +17 -7
  313. package/dist/utils/jsonl.d.ts.map +1 -1
  314. package/dist/utils/jsonl.js +144 -17
  315. package/dist/utils/jsonl.js.map +1 -1
  316. package/dist/utils/numeric-flag.d.ts +44 -0
  317. package/dist/utils/numeric-flag.d.ts.map +1 -0
  318. package/dist/utils/numeric-flag.js +62 -0
  319. package/dist/utils/numeric-flag.js.map +1 -0
  320. package/package.json +1 -1
  321. package/src/CONTEXT.md +5 -2
  322. package/src/__tests__/acceptance-gate.test.ts +7 -4
  323. package/src/__tests__/checker-extra.test.ts +3 -2
  324. package/src/__tests__/checker.test.ts +4 -3
  325. package/src/__tests__/checkpoint.test.ts +26 -9
  326. package/src/__tests__/context-files-resolution.test.ts +29 -15
  327. package/src/__tests__/contract-gate.test.ts +19 -40
  328. package/src/__tests__/error-classifier.test.ts +1 -1
  329. package/src/__tests__/exec.test.ts +45 -107
  330. package/src/__tests__/failure-recorder.test.ts +7 -5
  331. package/src/__tests__/hooks-pipeline.test.ts +34 -47
  332. package/src/__tests__/layering.test.ts +217 -25
  333. package/src/__tests__/passes-gate.test.ts +9 -4
  334. package/src/__tests__/performance-gate.test.ts +3 -15
  335. package/src/__tests__/project-config-loader-extra.test.ts +31 -57
  336. package/src/__tests__/project-config-loader.test.ts +6 -3
  337. package/src/__tests__/public-exports.test.ts +0 -1
  338. package/src/__tests__/public-type-surface.test.ts +5 -4
  339. package/src/__tests__/public-value-surface.test.ts +182 -0
  340. package/src/__tests__/review-gate.test.ts +4 -6
  341. package/src/__tests__/security-gate.test.ts +5 -20
  342. package/src/__tests__/skip-semantics.test.ts +5 -3
  343. package/src/__tests__/spec-validator.test.ts +3 -2
  344. package/src/__tests__/sub-barrels-explicit.test.ts +87 -0
  345. package/src/__tests__/test-fixture-hygiene.test.ts +53 -0
  346. package/src/__tests__/trace-analyzer-extra.test.ts +5 -3
  347. package/src/__tests__/trace-analyzer.test.ts +5 -3
  348. package/src/__tests__/trace-collector.test.ts +5 -3
  349. package/src/agents/index.ts +13 -2
  350. package/src/cli/__tests__/gate-command.test.ts +162 -0
  351. package/src/cli/commands/CONTEXT.md +29 -5
  352. package/src/cli/commands/__tests__/acceptance.test.ts +24 -25
  353. package/src/cli/commands/__tests__/bin-exit-mapping.test.ts +15 -0
  354. package/src/cli/commands/__tests__/check-drift.test.ts +42 -1
  355. package/src/cli/commands/__tests__/check-read-count.test.ts +167 -0
  356. package/src/cli/commands/__tests__/check-skip-output.test.ts +4 -1
  357. package/src/cli/commands/__tests__/check.test.ts +43 -36
  358. package/src/cli/commands/__tests__/command-gate-dead-options.test.ts +60 -0
  359. package/src/cli/commands/__tests__/command.test.ts +33 -17
  360. package/src/cli/commands/__tests__/constraints-retire.test.ts +52 -0
  361. package/src/cli/commands/__tests__/context-syncer.test.ts +141 -0
  362. package/src/cli/commands/__tests__/contract.test.ts +20 -20
  363. package/src/cli/commands/__tests__/failure.test.ts +5 -4
  364. package/src/cli/commands/__tests__/gate-decision.ts +30 -0
  365. package/src/cli/commands/__tests__/init-dead-options.test.ts +50 -0
  366. package/src/cli/commands/__tests__/init-governance-io.test.ts +139 -0
  367. package/src/cli/commands/__tests__/init-injection.test.ts +3 -3
  368. package/src/cli/commands/__tests__/init-ondisk.test.ts +867 -0
  369. package/src/cli/commands/__tests__/init.test.ts +82 -6
  370. package/src/cli/commands/__tests__/knowledge-audit-threshold.test.ts +146 -0
  371. package/src/cli/commands/__tests__/knowledge-flywheel-consistency.test.ts +1 -1
  372. package/src/cli/commands/__tests__/knowledge-tone-mapping.test.ts +244 -0
  373. package/src/cli/commands/__tests__/knowledge-view.test.ts +839 -0
  374. package/src/cli/commands/__tests__/knowledge.test.ts +33 -15
  375. package/src/cli/commands/__tests__/numeric-flag-assembly.test.ts +368 -0
  376. package/src/cli/commands/__tests__/performance.test.ts +19 -21
  377. package/src/cli/commands/__tests__/posteval-plan.test.ts +5 -3
  378. package/src/cli/commands/__tests__/pre-push-hook.test.ts +181 -0
  379. package/src/cli/commands/__tests__/project-path-anchoring.test.ts +95 -2
  380. package/src/cli/commands/__tests__/project-path-convention.test.ts +103 -25
  381. package/src/cli/commands/__tests__/registry.test.ts +2 -0
  382. package/src/cli/commands/__tests__/report.test.ts +23 -1
  383. package/src/cli/commands/__tests__/review.test.ts +10 -17
  384. package/src/cli/commands/__tests__/scaffold.test.ts +505 -0
  385. package/src/cli/commands/__tests__/security-default-scan.test.ts +75 -0
  386. package/src/cli/commands/__tests__/security.test.ts +21 -24
  387. package/src/cli/commands/__tests__/spec-baseline-check.test.ts +3 -2
  388. package/src/cli/commands/__tests__/spec-baseline-index-cap.test.ts +131 -0
  389. package/src/cli/commands/__tests__/spec-baseline-read-count.test.ts +325 -0
  390. package/src/cli/commands/__tests__/sync-docs-agents.test.ts +19 -4
  391. package/src/cli/commands/__tests__/sync-docs-context-drift.test.ts +232 -0
  392. package/src/cli/commands/__tests__/sync-docs-module-order.test.ts +111 -0
  393. package/src/cli/commands/__tests__/sync-docs-read-count.test.ts +192 -0
  394. package/src/cli/commands/__tests__/sync-docs.test.ts +3 -2
  395. package/src/cli/commands/__tests__/validate.test.ts +1 -48
  396. package/src/cli/commands/acceptance.ts +24 -29
  397. package/src/cli/commands/check.ts +40 -17
  398. package/src/cli/commands/command.ts +9 -8
  399. package/src/cli/commands/constraints-retire.ts +57 -70
  400. package/src/cli/commands/contract.ts +44 -47
  401. package/src/cli/commands/definitions.ts +12 -6
  402. package/src/cli/commands/failure.ts +16 -3
  403. package/src/cli/commands/init.ts +242 -389
  404. package/src/cli/commands/knowledge-view.ts +224 -0
  405. package/src/cli/commands/knowledge.ts +643 -448
  406. package/src/cli/commands/passes-gate.ts +12 -3
  407. package/src/cli/commands/performance.ts +31 -38
  408. package/src/cli/commands/report.ts +3 -2
  409. package/src/cli/commands/review.ts +22 -28
  410. package/src/cli/commands/scaffold-templates.ts +406 -0
  411. package/src/cli/commands/scaffold.ts +302 -0
  412. package/src/cli/commands/security.ts +27 -23
  413. package/src/cli/commands/spec-baseline-check.ts +158 -33
  414. package/src/cli/commands/sync-docs/__tests__/context-export-surface.test.ts +102 -0
  415. package/src/cli/commands/sync-docs/__tests__/module-descriptions.test.ts +196 -0
  416. package/src/cli/commands/sync-docs/context-syncer.ts +137 -31
  417. package/src/cli/commands/sync-docs/index.ts +103 -28
  418. package/src/cli/commands/sync-docs/project-reader.ts +51 -7
  419. package/src/cli/commands/validate.ts +1 -104
  420. package/src/cli/gate-command.ts +87 -0
  421. package/src/completion-checkers/index.ts +10 -1
  422. package/src/context/CONTEXT.md +2 -1
  423. package/src/context/__tests__/knowledge-injector.test.ts +27 -0
  424. package/src/context/__tests__/session-manager.test.ts +19 -12
  425. package/src/context/knowledge-injector.ts +14 -7
  426. package/src/core/CONTEXT.md +10 -7
  427. package/src/core/__tests__/effective-set.test.ts +36 -60
  428. package/src/core/constraints/__tests__/context-reconcile.test.ts +246 -0
  429. package/src/core/constraints/__tests__/run-env.test.ts +377 -0
  430. package/src/core/constraints/__tests__/triggers.test.ts +70 -0
  431. package/src/core/constraints/agent-prompt-renderer.ts +1 -1
  432. package/src/core/constraints/capabilities-reconcile.ts +28 -4
  433. package/src/core/constraints/check-cache.ts +1 -1
  434. package/src/core/constraints/checker.ts +30 -14
  435. package/src/core/constraints/checkers/__tests__/context-doc-sync.test.ts +8 -3
  436. package/src/core/constraints/checkers/__tests__/governance-presence.test.ts +16 -7
  437. package/src/core/constraints/checkers/__tests__/no-hardcoded-credentials.test.ts +2 -1
  438. package/src/core/constraints/checkers/capability-sync.ts +27 -28
  439. package/src/core/constraints/checkers/context-doc-sync.ts +9 -7
  440. package/src/core/constraints/checkers/docs-freshness.ts +28 -33
  441. package/src/core/constraints/checkers/governance-presence.ts +10 -6
  442. package/src/core/constraints/checkers/types.ts +14 -8
  443. package/src/core/constraints/context-builder.ts +35 -26
  444. package/src/core/constraints/context-reconcile.ts +200 -0
  445. package/src/core/constraints/doc-freshness/__tests__/runner.test.ts +25 -0
  446. package/src/core/constraints/doc-freshness/runner.ts +18 -4
  447. package/src/core/constraints/git-evidence.ts +1 -1
  448. package/src/core/constraints/injection-drift.ts +19 -8
  449. package/src/core/constraints/run-env.ts +207 -0
  450. package/src/core/constraints/triggers.ts +33 -0
  451. package/src/core/effective-constraints.ts +17 -6
  452. package/src/core/effective-set.ts +8 -24
  453. package/src/core/index.ts +2 -0
  454. package/src/core/project-config-loader.ts +54 -102
  455. package/src/core/validators/__tests__/http-retry-sleep.test.ts +231 -0
  456. package/src/core/validators/check-handlers/http.ts +18 -7
  457. package/src/failure/CONTEXT.md +2 -1
  458. package/src/failure/classifier.ts +2 -2
  459. package/src/failure/index.ts +14 -2
  460. package/src/failure/recorder.ts +1 -1
  461. package/src/gates/CONTEXT.md +13 -7
  462. package/src/gates/__tests__/checker-gate.test.ts +1 -1
  463. package/src/gates/__tests__/command-single-predicate.test.ts +135 -0
  464. package/src/gates/__tests__/command.test.ts +8 -15
  465. package/src/gates/__tests__/contract.test.ts +5 -5
  466. package/src/gates/__tests__/gate-interface.test.ts +0 -17
  467. package/src/gates/__tests__/performance.test.ts +0 -13
  468. package/src/gates/__tests__/review.test.ts +0 -1
  469. package/src/gates/__tests__/runner.test.ts +1 -1
  470. package/src/gates/__tests__/security-default-scan.test.ts +97 -0
  471. package/src/gates/__tests__/security.test.ts +0 -13
  472. package/src/gates/checker-gate.ts +3 -2
  473. package/src/gates/command.ts +51 -74
  474. package/src/gates/contract.ts +0 -5
  475. package/src/gates/definitions.ts +6 -5
  476. package/src/gates/index.ts +0 -5
  477. package/src/gates/performance.ts +1 -6
  478. package/src/gates/runner.ts +1 -1
  479. package/src/gates/security.ts +9 -11
  480. package/src/gates/types.ts +20 -23
  481. package/src/hooks/CONTEXT.md +10 -9
  482. package/src/hooks/__tests__/bootstrap.test.ts +29 -6
  483. package/src/hooks/__tests__/pipeline.test.ts +28 -17
  484. package/src/hooks/__tests__/registry.test.ts +51 -3
  485. package/src/hooks/bootstrap.ts +35 -15
  486. package/src/hooks/config.ts +6 -2
  487. package/src/hooks/index.ts +10 -1
  488. package/src/hooks/pipeline.ts +4 -6
  489. package/src/hooks/registry.ts +31 -12
  490. package/src/hooks/types.ts +24 -7
  491. package/src/index.ts +1 -2
  492. package/src/knowledge/CONTEXT.md +14 -7
  493. package/src/knowledge/__tests__/audit-labels.test.ts +8 -5
  494. package/src/knowledge/__tests__/audit-scoring.test.ts +230 -0
  495. package/src/knowledge/__tests__/audit-write-count.test.ts +131 -0
  496. package/src/knowledge/__tests__/audit.test.ts +291 -208
  497. package/src/knowledge/__tests__/doctor.test.ts +3 -2
  498. package/src/knowledge/__tests__/ingest.test.ts +3 -2
  499. package/src/knowledge/__tests__/lifecycle.test.ts +57 -2
  500. package/src/knowledge/__tests__/migration.test.ts +35 -6
  501. package/src/knowledge/__tests__/query.test.ts +3 -2
  502. package/src/knowledge/__tests__/reference-tracker.test.ts +23 -2
  503. package/src/knowledge/__tests__/store.test.ts +149 -4
  504. package/src/knowledge/__tests__/tree-walker.test.ts +132 -0
  505. package/src/knowledge/audit-scoring.ts +589 -0
  506. package/src/knowledge/audit.ts +55 -599
  507. package/src/knowledge/import.ts +2 -0
  508. package/src/knowledge/index-generator.ts +4 -6
  509. package/src/knowledge/index.ts +27 -2
  510. package/src/knowledge/ingest.ts +1 -1
  511. package/src/knowledge/lifecycle.ts +5 -2
  512. package/src/knowledge/migration.ts +8 -2
  513. package/src/knowledge/query.ts +8 -1
  514. package/src/knowledge/reference-tracker.ts +5 -7
  515. package/src/knowledge/store.ts +75 -16
  516. package/src/knowledge/tree-walker.ts +29 -0
  517. package/src/knowledge/types.ts +19 -0
  518. package/src/monitoring/CONTEXT.md +5 -2
  519. package/src/monitoring/__tests__/context-tracker.test.ts +16 -8
  520. package/src/monitoring/__tests__/trace-file-anchoring.test.ts +80 -0
  521. package/src/monitoring/traces.ts +19 -5
  522. package/src/release/CONTEXT.md +1 -1
  523. package/src/release/__tests__/integrity.test.ts +21 -12
  524. package/src/test-setup/__tests__/jsonl-fake-fs.test.ts +98 -0
  525. package/src/test-setup/jsonl-fake-fs.ts +59 -0
  526. package/src/tools/index.ts +5 -1
  527. package/src/types/checkpoint.ts +6 -0
  528. package/src/types/project-config.ts +21 -0
  529. package/src/types/trace.ts +14 -4
  530. package/src/utils/__tests__/file-walk.test.ts +3 -2
  531. package/src/utils/__tests__/jsonl-bounded-read.test.ts +106 -0
  532. package/src/utils/__tests__/jsonl-skip-disposition.test.ts +10 -6
  533. package/src/utils/__tests__/jsonl.test.ts +61 -14
  534. package/src/utils/__tests__/numeric-flag.test.ts +80 -0
  535. package/src/utils/__tests__/package-version.test.ts +2 -2
  536. package/src/utils/exec.ts +4 -64
  537. package/src/utils/jsonl.ts +159 -20
  538. package/src/utils/numeric-flag.ts +64 -0
  539. package/dist/failure/types.d.ts +0 -9
  540. package/dist/failure/types.d.ts.map +0 -1
  541. package/dist/failure/types.js +0 -25
  542. package/dist/failure/types.js.map +0 -1
  543. package/dist/gates/effective-gates.d.ts +0 -30
  544. package/dist/gates/effective-gates.d.ts.map +0 -1
  545. package/dist/gates/effective-gates.js +0 -81
  546. package/dist/gates/effective-gates.js.map +0 -1
  547. package/src/failure/types.ts +0 -9
  548. package/src/gates/__tests__/effective-gates.test.ts +0 -77
  549. package/src/gates/effective-gates.ts +0 -99
@@ -4,16 +4,26 @@
4
4
  * block/warn 行为是 studio safeCallHook 语义在管线侧的无损承载面:
5
5
  * - 'block':hook 失败 → passed=false、blockedBy 记名、停止执行后续 hook
6
6
  * - 'warn':hook 失败 → 记录警告、继续执行后续 hook、passed 不受影响
7
- * - 'ignore'/未声明:静默跳过(历史行为保留)
7
+ *
8
+ * #159 起 `enabled` / `errorStrategy` 的唯一声明点是 HookConfig:
9
+ * HookDefinition 不再携带这两个字段,有效值在注册环节由配置表填充。
8
10
  */
9
11
 
10
12
  import { HookPipeline } from '../pipeline';
11
13
  import { HookRegistry } from '../registry';
12
- import type { HookDefinition } from '../types';
14
+ import type { HookConfig, HookDefinition } from '../types';
15
+
16
+ function makeConfig(name: string, overrides: Partial<HookConfig> = {}): HookConfig {
17
+ return { name, enabled: true, errorStrategy: 'warn', ...overrides };
18
+ }
13
19
 
14
- function makeRegistry(hooks: HookDefinition[]): { registry: HookRegistry; pipeline: HookPipeline } {
20
+ function makeRegistry(
21
+ entries: Array<{ hook: HookDefinition; config?: Partial<HookConfig> }>
22
+ ): { registry: HookRegistry; pipeline: HookPipeline } {
15
23
  const registry = new HookRegistry();
16
- registry.registerAll(hooks);
24
+ for (const { hook, config } of entries) {
25
+ registry.register(hook, makeConfig(hook.name, config));
26
+ }
17
27
  return { registry, pipeline: new HookPipeline(registry) };
18
28
  }
19
29
 
@@ -21,8 +31,8 @@ describe('HookPipeline errorStrategy 语义', () => {
21
31
  it('block:失败阻断管线(passed=false、blockedBy 记名、停止后续 hook)', async () => {
22
32
  const second = jest.fn().mockResolvedValue({ passed: true });
23
33
  const { pipeline } = makeRegistry([
24
- { name: 'first', phase: 'before', errorStrategy: 'block', execute: async () => ({ passed: false, error: 'boom' }) },
25
- { name: 'second', phase: 'before', execute: second },
34
+ { hook: { name: 'first', phase: 'before', execute: async () => ({ passed: false, error: 'boom' }) }, config: { errorStrategy: 'block' } },
35
+ { hook: { name: 'second', phase: 'before', execute: second } },
26
36
  ]);
27
37
 
28
38
  const result = await pipeline.run('before', {});
@@ -35,8 +45,8 @@ describe('HookPipeline errorStrategy 语义', () => {
35
45
  it('warn:失败记录警告并继续(passed 不受影响、后续 hook 照常执行)', async () => {
36
46
  const second = jest.fn().mockResolvedValue({ passed: true });
37
47
  const { pipeline } = makeRegistry([
38
- { name: 'first', phase: 'before', errorStrategy: 'warn', execute: async () => ({ passed: false, error: 'soft' }) },
39
- { name: 'second', phase: 'before', execute: second },
48
+ { hook: { name: 'first', phase: 'before', execute: async () => ({ passed: false, error: 'soft' }) }, config: { errorStrategy: 'warn' } },
49
+ { hook: { name: 'second', phase: 'before', execute: second } },
40
50
  ]);
41
51
 
42
52
  const result = await pipeline.run('before', {});
@@ -50,8 +60,8 @@ describe('HookPipeline errorStrategy 语义', () => {
50
60
  it('block 失败停在当前 phase,不改变其它 phase 的 hook', async () => {
51
61
  const afterHook = jest.fn().mockResolvedValue({ passed: true });
52
62
  const { pipeline } = makeRegistry([
53
- { name: 'blocker', phase: 'before', errorStrategy: 'block', execute: async () => ({ passed: false }) },
54
- { name: 'afterHook', phase: 'after', execute: afterHook },
63
+ { hook: { name: 'blocker', phase: 'before', execute: async () => ({ passed: false }) }, config: { errorStrategy: 'block' } },
64
+ { hook: { name: 'afterHook', phase: 'after', execute: afterHook } },
55
65
  ]);
56
66
 
57
67
  const before = await pipeline.run('before', {});
@@ -62,18 +72,19 @@ describe('HookPipeline errorStrategy 语义', () => {
62
72
  expect(afterHook).toHaveBeenCalled();
63
73
  });
64
74
 
65
- it('未声明 errorStrategy:静默跳过(历史行为保留)', async () => {
66
- const second = jest.fn().mockResolvedValue({ passed: true });
75
+ it('配置 enabled:false 的 hook 不进入管线执行(配置表是唯一声明点)', async () => {
76
+ const disabledHook = jest.fn().mockResolvedValue({ passed: true });
77
+ const enabledHook = jest.fn().mockResolvedValue({ passed: true });
67
78
  const { pipeline } = makeRegistry([
68
- { name: 'first', phase: 'before', execute: async () => ({ passed: false }) },
69
- { name: 'second', phase: 'before', execute: second },
79
+ { hook: { name: 'disabled', phase: 'before', execute: disabledHook }, config: { enabled: false } },
80
+ { hook: { name: 'enabled', phase: 'before', execute: enabledHook } },
70
81
  ]);
71
82
 
72
83
  const result = await pipeline.run('before', {});
73
84
 
74
85
  expect(result.passed).toBe(true);
75
- expect(result.blockedBy).toEqual([]);
76
- expect(result.warnings).toEqual([]);
77
- expect(second).toHaveBeenCalled();
86
+ expect(disabledHook).not.toHaveBeenCalled();
87
+ expect(enabledHook).toHaveBeenCalled();
88
+ expect(result.records.map(r => r.hookName)).toEqual(['enabled']);
78
89
  });
79
90
  });
@@ -2,6 +2,10 @@
2
2
  * Hook 注册表闭环双向校验测试(H5,复制 checker 闭环模式)
3
3
  *
4
4
  * 两个失败方向 + 重复声明/注册都必须抛错;闭环通过时不抛错。
5
+ *
6
+ * #159 起注册即配对:`register(hook, config)` 以 HookConfig 填充有效
7
+ * `enabled` / `errorStrategy`——配置表是这两个语义的唯一声明点,
8
+ * HookDefinition 类型上不再存在同名字段(矛盾在构造上不可能出现)。
5
9
  */
6
10
 
7
11
  import { assertHookRegistryClosed, HookRegistry } from '../registry';
@@ -15,8 +19,8 @@ function makeHook(name: string): HookDefinition {
15
19
  };
16
20
  }
17
21
 
18
- function makeConfig(name: string): HookConfig {
19
- return { name, enabled: true, errorStrategy: 'block' };
22
+ function makeConfig(name: string, overrides: Partial<HookConfig> = {}): HookConfig {
23
+ return { name, enabled: true, errorStrategy: 'block', ...overrides };
20
24
  }
21
25
 
22
26
  describe('assertHookRegistryClosed', () => {
@@ -60,8 +64,52 @@ describe('assertHookRegistryClosed', () => {
60
64
 
61
65
  it('与 HookRegistry.listAll 组合可用(consumer 注册点用法)', () => {
62
66
  const registry = new HookRegistry();
63
- registry.registerAll([makeHook('beforeAgentExecute')]);
67
+ registry.registerAll([makeHook('beforeAgentExecute')], [makeConfig('beforeAgentExecute')]);
64
68
  expect(() => assertHookRegistryClosed([makeConfig('beforeAgentExecute')], registry.listAll()))
65
69
  .not.toThrow();
66
70
  });
67
71
  });
72
+
73
+ describe('HookRegistry 注册即配对(#159 配置表唯一化)', () => {
74
+ it('register 以 HookConfig 填充有效 enabled / errorStrategy', () => {
75
+ const registry = new HookRegistry();
76
+ registry.register(makeHook('a'), makeConfig('a', { enabled: false, errorStrategy: 'block' }));
77
+
78
+ const effective = registry.get('a');
79
+ expect(effective?.enabled).toBe(false);
80
+ expect(effective?.errorStrategy).toBe('block');
81
+ // 配置 enabled:false → 不进 enabled 列表
82
+ expect(registry.getEnabled('before')).toEqual([]);
83
+ });
84
+
85
+ it('register 定义与配置名称不一致 → 抛错', () => {
86
+ const registry = new HookRegistry();
87
+ expect(() => registry.register(makeHook('a'), makeConfig('b'))).toThrow(/名称不一致/);
88
+ });
89
+
90
+ it('registerAll 有实现缺配置声明 → 抛错', () => {
91
+ const registry = new HookRegistry();
92
+ expect(() =>
93
+ registry.registerAll([makeHook('a'), makeHook('orphan')], [makeConfig('a')])
94
+ ).toThrow(/hook "orphan" 没有对应的 HookConfig 声明/);
95
+ });
96
+
97
+ it('HookDefinition 类型上不再存在 enabled / errorStrategy(编译期钉)', () => {
98
+ const withStrategy: HookDefinition = {
99
+ name: 'x',
100
+ phase: 'before',
101
+ // @ts-expect-error HookDefinition 不再存在 errorStrategy 字段(#159)
102
+ errorStrategy: 'block',
103
+ execute: async () => ({ passed: true }),
104
+ };
105
+ const withEnabled: HookDefinition = {
106
+ name: 'y',
107
+ phase: 'before',
108
+ // @ts-expect-error HookDefinition 不再存在 enabled 字段(#159)
109
+ enabled: false,
110
+ execute: async () => ({ passed: true }),
111
+ };
112
+ expect(withStrategy.name).toBe('x');
113
+ expect(withEnabled.name).toBe('y');
114
+ });
115
+ });
@@ -11,17 +11,18 @@
11
11
  * // harness.checker, harness.config, harness.hooks, harness.sessions
12
12
  * ```
13
13
  *
14
- * checker 的 trace 记录器在此接线(harness#88:core 不上行依赖 monitoring)。
14
+ * checker 的 trace 记录器在此接线(harness#88:core 不上行依赖 monitoring),
15
+ * 且锚在本函数收到的 projectPath 上(#139:落点跟根走,不落调用方 cwd)。
15
16
  */
16
17
 
17
18
  import { ConstraintChecker } from '../core/constraints/checker';
18
19
  import { SessionManager } from '../context/session-manager';
19
20
  import { ProjectConfigLoader } from '../core/project-config-loader';
20
- import { getTraceCollector } from '../monitoring/traces';
21
+ import { TraceCollector } from '../monitoring/traces';
21
22
  import { HookRegistry } from './registry';
22
23
  import { HookPipeline } from './pipeline';
23
24
  import type { MergedConstraintsConfig } from '../types/project-config';
24
- import type { HookDefinition } from './types';
25
+ import type { HookConfig, HookDefinition } from './types';
25
26
 
26
27
  /**
27
28
  * 异步加载项目配置(S9:异步 I/O)
@@ -30,8 +31,8 @@ async function loadConfigAsync(projectPath: string): Promise<{
30
31
  config: ReturnType<ProjectConfigLoader['getConfig']>;
31
32
  mergedConstraints: MergedConstraintsConfig;
32
33
  }> {
33
- // config.yml 解析经 loadRawProjectConfig 进程级 memoize(工单 16),
34
- // 此处不再重复读取文件
34
+ // config.yml 的读取只有 loadRawProjectConfig 这一条路(ADR-0023 决策 2 撤销进程级
35
+ // 缓存后,每次调用读当下内容),此处不重复读文件
35
36
  const loader = new ProjectConfigLoader(projectPath);
36
37
  loader.load();
37
38
 
@@ -59,15 +60,36 @@ export interface HarnessBootstrap {
59
60
  mergedConstraints: MergedConstraintsConfig;
60
61
  }
61
62
 
63
+ /**
64
+ * 注册初始 hook(定义必须配对配置声明表——#159 起 HookConfig 是
65
+ * enabled / errorStrategy 的唯一声明点,缺表即抛错)
66
+ */
67
+ function registerInitialHooks(
68
+ hooks: HookRegistry,
69
+ hookDefinitions: HookDefinition[] | undefined,
70
+ hookConfigs: HookConfig[] | undefined
71
+ ): void {
72
+ if (!hookDefinitions || hookDefinitions.length === 0) return;
73
+ if (!hookConfigs) {
74
+ throw new Error(
75
+ '[harness] bootstrap 失败:注册 hook 定义必须同时提供 HookConfig 声明表' +
76
+ '(enabled / errorStrategy 的唯一声明点)。'
77
+ );
78
+ }
79
+ hooks.registerAll(hookDefinitions, hookConfigs);
80
+ }
81
+
62
82
  /**
63
83
  * 初始化 harness 运行环境(异步,不阻塞事件循环)
64
84
  *
65
85
  * @param projectPath 项目根路径
66
86
  * @param hookDefinitions 可选,初始化时注册的 hook
87
+ * @param hookConfigs 可选,与 hookDefinitions 配对的配置声明表(注册定义时必填)
67
88
  */
68
89
  export async function bootstrapHarness(
69
90
  projectPath?: string,
70
- hookDefinitions?: HookDefinition[]
91
+ hookDefinitions?: HookDefinition[],
92
+ hookConfigs?: HookConfig[]
71
93
  ): Promise<HarnessBootstrap> {
72
94
  const resolvedPath = projectPath || process.cwd();
73
95
 
@@ -75,16 +97,15 @@ export async function bootstrapHarness(
75
97
  const { mergedConstraints } = await loadConfigAsync(resolvedPath);
76
98
 
77
99
  // 2. 初始化核心组件
78
- const checker = new ConstraintChecker(getTraceCollector());
100
+ // trace 记录器锚根构造(#139):本函数本就收 projectPath,落点必须跟着根走
101
+ const checker = new ConstraintChecker(new TraceCollector({ projectPath: resolvedPath }));
79
102
 
80
103
  const sessions = new SessionManager(resolvedPath);
81
104
  const hooks = new HookRegistry();
82
105
  const pipeline = new HookPipeline(hooks);
83
106
 
84
107
  // 3. 注册初始 hook
85
- if (hookDefinitions) {
86
- hooks.registerAll(hookDefinitions);
87
- }
108
+ registerInitialHooks(hooks, hookDefinitions, hookConfigs);
88
109
 
89
110
  return {
90
111
  checker,
@@ -103,7 +124,8 @@ export async function bootstrapHarness(
103
124
  */
104
125
  export function bootstrapHarnessSync(
105
126
  projectPath?: string,
106
- hookDefinitions?: HookDefinition[]
127
+ hookDefinitions?: HookDefinition[],
128
+ hookConfigs?: HookConfig[]
107
129
  ): HarnessBootstrap {
108
130
  const resolvedPath = projectPath || process.cwd();
109
131
 
@@ -111,15 +133,13 @@ export function bootstrapHarnessSync(
111
133
  loader.load();
112
134
  const mergedConstraints = loader.mergeConstraints();
113
135
 
114
- const checker = new ConstraintChecker(getTraceCollector());
136
+ const checker = new ConstraintChecker(new TraceCollector({ projectPath: resolvedPath }));
115
137
 
116
138
  const sessions = new SessionManager(resolvedPath);
117
139
  const hooks = new HookRegistry();
118
140
  const pipeline = new HookPipeline(hooks);
119
141
 
120
- if (hookDefinitions) {
121
- hooks.registerAll(hookDefinitions);
122
- }
142
+ registerInitialHooks(hooks, hookDefinitions, hookConfigs);
123
143
 
124
144
  return {
125
145
  checker,
@@ -2,7 +2,7 @@
2
2
  * Hook 配置归一(G7)
3
3
  *
4
4
  * studio 侧 per-hook 运行时配置(`blocking: boolean`)与 harness 侧
5
- * `HookDefinition.errorStrategy` 双轨归一:以 errorStrategy 为唯一真相,
5
+ * `HookConfig.errorStrategy` 双轨归一:以 errorStrategy 为唯一真相,
6
6
  * `blocking` → errorStrategy 为无损映射。
7
7
  *
8
8
  * 映射语义(确认于 H5):
@@ -12,6 +12,10 @@
12
12
  * (管线结果 warnings 记名,passed 不受影响)——对应 studio safeCallHook
13
13
  * console.warn 继续
14
14
  *
15
+ * #159 起 `HookConfig` 是 `enabled` / `errorStrategy` 的唯一声明点:
16
+ * HookDefinition 不再携带这两个字段,注册环节以配置表填充有效值,
17
+ * 有效策略集合收敛为 'block' | 'warn'(原 'ignore' 退出有效面)。
18
+ *
15
19
  * studio 侧随动(studio #150 A4):hooks/config.ts 删 DEFAULTS/safeCallHook,
16
20
  * blocking→errorStrategy 无损映射进 toHookDef;HARNESS_HOOK_DISABLE 保留 studio。
17
21
  */
@@ -24,6 +28,6 @@ import type { HookErrorStrategy } from './types';
24
28
  * @param blocking studio 侧「失败是否阻断」语义
25
29
  * @returns 'block'(阻断)| 'warn'(警告继续)
26
30
  */
27
- export function toErrorStrategy(blocking: boolean): Extract<HookErrorStrategy, 'block' | 'warn'> {
31
+ export function toErrorStrategy(blocking: boolean): HookErrorStrategy {
28
32
  return blocking ? 'block' : 'warn';
29
33
  }
@@ -5,7 +5,16 @@
5
5
  * 无业务逻辑,consumer 自行定义 hook 名称和语义。
6
6
  */
7
7
 
8
- export * from './types';
8
+ export type {
9
+ HookPhase,
10
+ HookErrorStrategy,
11
+ HookConfig,
12
+ HookDefinition,
13
+ EffectiveHook,
14
+ HookResult,
15
+ HookExecutionRecord,
16
+ PipelineResult,
17
+ } from './types';
9
18
  export { HookRegistry, assertHookRegistryClosed } from './registry';
10
19
  export { HookPipeline } from './pipeline';
11
20
  export { toErrorStrategy } from './config';
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import type {
9
- HookDefinition,
9
+ EffectiveHook,
10
10
  HookPhase,
11
11
  HookExecutionRecord,
12
12
  PipelineResult,
@@ -47,10 +47,8 @@ export class HookPipeline<C = unknown> {
47
47
  blockedBy.push(hook.name);
48
48
  break; // blocking hook 失败,停止执行后续 hook
49
49
  }
50
- if (hook.errorStrategy === 'warn') {
51
- warnings.push(hook.name);
52
- }
53
- // 'ignore' 策略静默跳过
50
+ // 'warn':记录警告继续(有效集合仅 block/warn,策略由 HookConfig 必填声明)
51
+ warnings.push(hook.name);
54
52
  }
55
53
  }
56
54
 
@@ -111,7 +109,7 @@ export class HookPipeline<C = unknown> {
111
109
  * 执行单个 hook(带采样和错误隔离)
112
110
  */
113
111
  private async executeOne(
114
- hook: HookDefinition<C, unknown>,
112
+ hook: EffectiveHook<C, unknown>,
115
113
  context: C
116
114
  ): Promise<HookExecutionRecord> {
117
115
  const startedAt = Date.now();
@@ -4,7 +4,7 @@
4
4
  * 纯簿记,无执行逻辑。线程不安全(Node.js 单线程)。
5
5
  */
6
6
 
7
- import type { HookConfig, HookDefinition, HookPhase } from './types';
7
+ import type { EffectiveHook, HookConfig, HookDefinition, HookPhase } from './types';
8
8
 
9
9
  /**
10
10
  * 注册表闭环双向校验(H5,复制 checker 闭环模式)
@@ -66,21 +66,40 @@ export function assertHookRegistryClosed<C = unknown, R = unknown>(
66
66
  }
67
67
 
68
68
  export class HookRegistry<C = unknown, R = unknown> {
69
- private hooks: Map<string, HookDefinition<C, R>> = new Map();
69
+ private hooks: Map<string, EffectiveHook<C, R>> = new Map();
70
70
 
71
71
  /**
72
72
  * 注册 hook(同名覆盖)
73
+ *
74
+ * 有效 `enabled` / `errorStrategy` 由 HookConfig 填充——配置表是这两个
75
+ * 语义的唯一声明点(#159),定义与配置名称不一致即抛错。
73
76
  */
74
- register(hook: HookDefinition<C, R>): void {
75
- this.hooks.set(hook.name, { ...hook });
77
+ register(hook: HookDefinition<C, R>, config: HookConfig): void {
78
+ if (hook.name !== config.name) {
79
+ throw new Error(
80
+ `[harness] hook 注册失败:定义 "${hook.name}" 与配置 "${config.name}" 名称不一致。`
81
+ );
82
+ }
83
+ this.hooks.set(hook.name, {
84
+ ...hook,
85
+ enabled: config.enabled,
86
+ errorStrategy: config.errorStrategy,
87
+ });
76
88
  }
77
89
 
78
90
  /**
79
- * 批量注册
91
+ * 批量注册(按 name 配对配置;有实现缺配置声明即抛错)
80
92
  */
81
- registerAll(hooks: HookDefinition<C, R>[]): void {
93
+ registerAll(hooks: HookDefinition<C, R>[], configs: readonly HookConfig[]): void {
94
+ const configByName = new Map(configs.map(c => [c.name, c]));
82
95
  for (const hook of hooks) {
83
- this.register(hook);
96
+ const config = configByName.get(hook.name);
97
+ if (!config) {
98
+ throw new Error(
99
+ `[harness] hook 注册失败:hook "${hook.name}" 没有对应的 HookConfig 声明。`
100
+ );
101
+ }
102
+ this.register(hook, config);
84
103
  }
85
104
  }
86
105
 
@@ -92,18 +111,18 @@ export class HookRegistry<C = unknown, R = unknown> {
92
111
  }
93
112
 
94
113
  /**
95
- * 获取单个 hook
114
+ * 获取单个 hook(含有效 enabled / errorStrategy)
96
115
  */
97
- get(name: string): HookDefinition<C, R> | undefined {
116
+ get(name: string): EffectiveHook<C, R> | undefined {
98
117
  return this.hooks.get(name);
99
118
  }
100
119
 
101
120
  /**
102
121
  * 获取指定时机、已启用的 hook,按优先级排序
103
122
  */
104
- getEnabled(phase: HookPhase): HookDefinition<C, R>[] {
123
+ getEnabled(phase: HookPhase): EffectiveHook<C, R>[] {
105
124
  return Array.from(this.hooks.values())
106
- .filter(h => h.phase === phase && h.enabled !== false)
125
+ .filter(h => h.phase === phase && h.enabled)
107
126
  .sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));
108
127
  }
109
128
 
@@ -117,7 +136,7 @@ export class HookRegistry<C = unknown, R = unknown> {
117
136
  /**
118
137
  * 列出所有 hook(含禁用)
119
138
  */
120
- listAll(): HookDefinition<C, R>[] {
139
+ listAll(): EffectiveHook<C, R>[] {
121
140
  return Array.from(this.hooks.values());
122
141
  }
123
142
 
@@ -11,9 +11,12 @@
11
11
  export type HookPhase = 'before' | 'after' | 'around';
12
12
 
13
13
  /**
14
- * Hook 错误处理策略
14
+ * Hook 错误处理策略(有效集合:'block' | 'warn')
15
+ *
16
+ * #159 起原 'ignore' 退出有效面:策略的唯一声明点是 HookConfig(必填),
17
+ * 不存在「未声明 strategy」的运行时形态。
15
18
  */
16
- export type HookErrorStrategy = 'block' | 'warn' | 'ignore';
19
+ export type HookErrorStrategy = 'block' | 'warn';
17
20
 
18
21
  /**
19
22
  * Hook 配置(G7 归一后形状:consumer 侧的 per-hook 声明表)
@@ -22,6 +25,10 @@ export type HookErrorStrategy = 'block' | 'warn' | 'ignore';
22
25
  * - 声明(HookConfig)是「定义」侧:引用未注册实现 → 抛错
23
26
  * - 注册(HookDefinition)是「实现」侧:注册无对应声明 → 抛错
24
27
  *
28
+ * #159 起本表是 `enabled` / `errorStrategy` 的**唯一声明点**:
29
+ * HookDefinition 不再携带这两个字段,有效值在注册环节由本表填充
30
+ * (见 EffectiveHook),声明与实现两处值矛盾在构造上不可能出现。
31
+ *
25
32
  * 对应 studio 侧 per-hook 运行时配置(hooks/config.ts 的 DEFAULTS)语义:
26
33
  * blocking:true ↔ errorStrategy 'block'(失败阻断管线),
27
34
  * blocking:false ↔ errorStrategy 'warn'(记录警告继续)——无损映射见
@@ -33,13 +40,14 @@ export interface HookConfig {
33
40
  /** 是否启用(false 时不进入管线) */
34
41
  enabled: boolean;
35
42
  /** 错误策略:block=失败阻断管线,warn=记录警告继续 */
36
- errorStrategy: 'block' | 'warn';
43
+ errorStrategy: HookErrorStrategy;
37
44
  }
38
45
 
39
46
  /**
40
47
  * Hook 定义
41
48
  *
42
49
  * Consumer 自行选择 name(如 'beforeAgentExecute'),harness 只提供管线。
50
+ * `enabled` / `errorStrategy` 不在此处声明——唯一声明点是 HookConfig(#159)。
43
51
  */
44
52
  export interface HookDefinition<C = unknown, R = unknown> {
45
53
  /** Hook 唯一名称(consumer 定义语义) */
@@ -48,16 +56,25 @@ export interface HookDefinition<C = unknown, R = unknown> {
48
56
  phase: HookPhase;
49
57
  /** 优先级(越小越先执行,默认 100) */
50
58
  priority?: number;
51
- /** 错误策略:block=阻断管线, warn=记录警告继续, ignore=静默跳过 */
52
- errorStrategy?: HookErrorStrategy;
53
59
  /** 采样率 0-1(1=100% 执行,0.1=10% 采样) */
54
60
  sampleRate?: number;
55
- /** 是否启用 */
56
- enabled?: boolean;
57
61
  /** Hook 执行函数 */
58
62
  execute: (context: C) => Promise<HookResult<R>>;
59
63
  }
60
64
 
65
+ /**
66
+ * 有效 hook = HookDefinition + 注册环节由 HookConfig 填充的有效值
67
+ *
68
+ * 管线与注册表的判定(启用过滤、block/warn 分派)只读本类型,
69
+ * 值来源单一(HookConfig),不存在第二声明点。
70
+ */
71
+ export interface EffectiveHook<C = unknown, R = unknown> extends HookDefinition<C, R> {
72
+ /** 是否启用(来自 HookConfig.enabled) */
73
+ enabled: boolean;
74
+ /** 错误策略(来自 HookConfig.errorStrategy) */
75
+ errorStrategy: HookErrorStrategy;
76
+ }
77
+
61
78
  /**
62
79
  * Hook 执行结果
63
80
  */
package/src/index.ts CHANGED
@@ -152,7 +152,6 @@ export {
152
152
  registeredGateCount,
153
153
  assertGateRegistryClosed,
154
154
  runGates,
155
- getEffectiveGates,
156
155
  createCheckerGate,
157
156
  } from './gates';
158
157
  export type {
@@ -163,7 +162,6 @@ export type {
163
162
  GateDecisionStatus,
164
163
  GateDefinition,
165
164
  GateRunResult,
166
- GatesConfig,
167
165
  PerformanceThresholds,
168
166
  ReviewGateConfig,
169
167
  SecurityGateConfig,
@@ -357,6 +355,7 @@ export {
357
355
  export type {
358
356
  HookDefinition,
359
357
  HookConfig,
358
+ EffectiveHook,
360
359
  HookErrorStrategy,
361
360
  HookExecutionRecord,
362
361
  HookPhase,
@@ -17,13 +17,16 @@
17
17
  - 所有模式支持 `decayAt` 硬过期
18
18
 
19
19
  ## 核心导出
20
- - `KnowledgeStore` 知识条目 CRUD + 结构化存储;`saveAll()` 批量写入(循环内只更新内存索引、结束一次 writeIndex,harness#107)
20
+ - `KnowledgeStore`(类型面)/ `FileKnowledgeStore`(`store.ts`,barrel 与包根交出的**值**符号——store 的文件系统实现,构造收 `{ baseDir }`;仓内构造点两处:`cli/commands/knowledge-view.ts` 的 `openKnowledgeStore()`(knowledge 各子命令的取数口)与 `cli/commands/constraints-retire.ts` 的退役沉淀写入)— 知识条目 CRUD + 结构化存储;`saveAll()` 全量批量写入(循环内只更新内存索引、结束一次 writeIndex,harness#107)、`applyAll()` 按 id 部分更新的批量出口(`update(id, partial)` 的批量形,语义含未知 id 逐条跳过与空批零读写,harness#134)、`getConsumptionStats()` 读 `.consumption-stats.json` 的当日消费计数(打分核心唯一的消费统计取数口,harness#134
21
21
  - `KnowledgeQuery` — 语义搜索 + 类型/标签过滤 + `queryByMode()` + `consume(taskContext)`;`query()` 是 budget 截断管线(仅用于 prompt 注入),`search()` 是全语料文本搜索(先匹配→排序→limit,交互搜索专用,勿用 query() 代替)
22
- - `KnowledgeLifecycle` — per-mode 生命周期管理
22
+ - `KnowledgeLifecycle` — per-mode 生命周期管理;缺省阈值常量 `DEFAULT_DECAY_CONFIG`(`provenDecayMonths: 12` / `verifiedDecayMonths: 6` / `draftDecayMonths: 3` / `autoPromoteSources: []`,正本 `types.ts`)经构造器 `{...DEFAULT_DECAY_CONFIG, ...config}` 合并,barrel 与包根一并交出
23
+ - `extractCodeStructure(dir)`(`primitives/code-structure.ts`,配 `CodeStructure`/`DeclarationInfo`/`ImportInfo` 三类型对外)— 目录代码结构提取;仓内零调用方,是留给下游的公开面
23
24
  - `KnowledgeIngest` — 知识摄取引擎(含 ingest gate 质量门)+ `ingestExternal()` 外部内容摄入
24
25
  - `sanitizeExternalContent` — 外部内容安全清洗(过滤注入模式 + 长度限制)
25
- - `migrateKnowledgeEntries` — AS-021 迁移工具(为现有条目添加 consumptionMode/origin
26
- - `KnowledgeAudit` — 7 维度质量审计引擎。per-entry 规则记录带 `scope: 'active' | 'all'`(active = 不判定 archived 条目);人口过滤由 `ruleDetail()` 统一执行,规则内禁止再写 `entry.maturity === 'archived'` 早返回。规则中文 label 正本在规则定义的 `label` 字段(harness#109,ADR-0002 定义即注册),`AUDIT_RULE_LABELS` 派生导出、与 `AuditRuleName` 编译期闭环,CLI 展示层直接消费、禁止另建 label 表
26
+ - `migrateKnowledgeEntries` — AS-021 迁移工具(为现有条目添加 consumptionMode/origin);条目人口按 `tree-walker` 口径判定,`_index.md` 等树生成物不计入 `total`/`errors`(harness#134 修此前假阳性)
27
+ - `KnowledgeAudit` — 7 维度质量审计**引擎**:构造收 `KnowledgeStore`(与 lint / doctor / query / lifecycle / ingest 同形,harness#134——此前收目录并自建 store,致使打分判定无法脱离文件系统测试)+ 可选阈值形参(三个数值槽显式传 NaN/±Infinity/负数时构造期抛 `TypeError`(message 含槽名与实参),不放行到打分层静默关掉 short-content/stale-entry/promotion-blocked 三条判定;未传/显式 `undefined` 走缺省、显式 `0` 合法按 0 生效,harness#163)。职责只剩装配:取条目、经 store 取环境数据、把整批修复动作交 `store.applyAll()`。per-entry 规则记录带 `scope: 'active' | 'all'`(active = 不判定 archived 条目);人口过滤由 `ruleDetail()` 统一执行,规则内禁止再写 `entry.maturity === 'archived'` 早返回。规则中文 label 正本在规则定义的 `label` 字段(harness#109,ADR-0002 定义即注册),`AUDIT_RULE_LABELS` 派生导出、与 `AuditRuleName` 编译期闭环,CLI 展示层直接消费、禁止另建 label 表
28
+ - `audit-scoring`(**值面**不进导出面;类型面是例外——`AuditRuleName`/`AuditAction`/`AuditIssue`/`AuditReport`/`AuditOptions` 经 `index.ts` 再导出并上包根,ADR-0003 显式清单)— D1–D7 打分**纯模块**(harness#134):规则表、`scanEntries()` / `summarizeIssues()` / `computeDimensions()` / `calculateHealthScore()`,零 fs——环境数据(消费统计、快照存活)由调用方经 store 取好喂入。审计判定的唯一正本在此,可脱离合建目录测试
29
+ - `tree-walker`(包内,不进导出面)— 知识树排除口径单点(harness#134):`isEntryFile()` / `isInfraDir()` / `INDEX_MD_FILE` / `SNAPSHOTS_DIR`,由 store 顶层扫描、migration 顶层扫描、index-generator 递归扫描三处共同消费
27
30
  - `flywheel-metrics`(包内,不进导出面)— 知识飞轮指标唯一实现:`evaluateFlywheel(env)` 出 canonical 比例、`genuineRefs()` 出 synthetic 过滤口径,audit D6 / `knowledge stats` / `knowledge health` 三处共消费(ADR-0013)
28
31
  - `ReferenceTracker` — 知识引用关系图谱
29
32
  - `KnowledgeLinter` — 知识质量检查(完整性/一致性/时效性)
@@ -31,19 +34,22 @@
31
34
  - `KnowledgeHealthScorer` — 知识健康评分(doctor.ts)
32
35
 
33
36
  ## 依赖关系
34
- - 依赖 `src/types/` 知识相关类型
37
+ - 知识类型正本在**本模块** `src/knowledge/types.ts`(`KnowledgeEntry`/`MaturityLevel`/`ConsumptionMode`/`KnowledgeOrigin`/`DecayConfig`…);本目录对 `src/types/` **零 import**——旧条目「依赖 `src/types/` 知识相关类型」不实(harness#142 逐条核对)
35
38
  - 依赖 `src/utils/frontmatter` — markdown frontmatter 解析/序列化的唯一正本(harness#89:store、migration、index-generator、ingest 共用同一套语法判定,不再各写正则)
36
39
  - 不依赖 `src/context/`(原 `lifecycle-hooks.ts` 是唯一 import `context/types` 的文件,已随 ADR-0022 删除),也不依赖 monitoring——知识健康评分由本目录 doctor.ts 的 KnowledgeHealthScorer 承载
37
40
  - 被 `src/cli/commands/knowledge.ts` CLI 消费(含 `migrate` 子命令)
38
41
 
39
42
  ## 约定
40
- - 知识条目文件的 frontmatter 语法只由 `src/utils/frontmatter` 定义(harness#89):缺头/空 meta = `absent`(合法输入,按非条目静默处理);未闭合/YAML 非法 = `malformed`(必须显式上报后按消费方语义恢复——migration 落 `errors`、store 与 index-generator 打一行 stderr 后跳过或走 best-effort),禁止静默丢条目;canonical 字段序是 `store.toFrontmatter` 的私有策略,`join` 只管包裹格式
43
+ - 知识条目文件的 frontmatter 语法只由 `src/utils/frontmatter` 定义(harness#89):缺头/空 meta = `absent`(合法输入,按非条目静默处理、不上报——migration 对 `absent` 不计 `errors`、不迁移,只计 `skipped` 保证 `total` 计数闭环,harness#161 对齐 #89 裁决 2);未闭合/YAML 非法 = `malformed`(必须显式上报后按消费方语义恢复——migration 落 `errors`、store 与 index-generator 打一行 stderr 后跳过或走 best-effort),禁止静默丢条目;canonical 字段序是 `store.toFrontmatter` 的私有策略,`join` 只管包裹格式
44
+ - **知识树的排除口径只有一个正本 `tree-walker`**(harness#134):`_index.md`(索引生成物)、`.snapshots`、`.archive` / `archived`、`resolutions` 是树基建、不是条目人口。store 与 migration 的顶层扫描、index-generator 的递归扫描三处都走它;新增 walker 禁止另立排除清单。统一的是**排除口径**不是遍历深度(store/migration 顶层、index-generator 递归)。例外须原地记名理由:`import.ts` 的 docs 扫描吃的是**项目文档树**,本口径在它那里没有对应物
45
+ - **循环内禁止逐条 `store.update()`**(harness#134):`update()` 的形状是 get→save、`save()` 每次全量重写 index.json,N 条修复 = N 次全量重写。批量形是 `applyAll(id → partial)`;一次 `audit --fix`、一轮 `runDecayCycle()`、一次 `updateReferencedBy()` 各只重写一次索引,计数闸见 `audit-write-count.test.ts` 与 `lifecycle.test.ts` / `reference-tracker.test.ts` 的 stringify 计数项
46
+ - **审计判定脱离文件系统可测**(harness#134):规则表与 D1–D7 打分住 `audit-scoring.ts`,零 fs(源形状闸钉在 `audit-scoring.test.ts`);引擎 `audit.ts` 只做 store 装配,环境数据经 `store.getConsumptionStats()` / `getSurvivalRate()` 取好喂入
41
47
  - 知识条目有明确的生命周期状态(按 consumptionMode 分化)
42
48
  - 约束退役(`harness constraints retire`,人确认)时写入 KnowledgeStore:规则原文 + 退役原因 + 历史统计
43
49
  - Linter 检查完整性/一致性/时效性三个维度
44
50
  - Audit 7 维度评分:D1结构 D2内容 D3去重 D4成熟度 D5新鲜度 D6飞轮 D7增量存活
45
51
  - Ingest gate: ingestEntry() 先经 audit.validate() 检查,reject 不入库
46
- - 外部内容三层防御:ingest sanitization + retrieval marking + prompt constraint
52
+ - 外部内容三层防御:ingest sanitization + retrieval marking + prompt constraint。第二层 marking 已接线(harness#161):标记正本是 `knowledge/query.ts` 的 `EXTERNAL_SOURCE_MARKER` 常量(`[External Source — verify before acting]`),`KnowledgeQuery.formatForPrompt()` 与注入路径 `context/knowledge-injector.ts` 的 `formatEntry()`/`formatEntrySummary()` 共用同一常量——`origin === 'external'` 条目注入 prompt 时带来源前缀,注入 source 的 metadata 带 `origin`。第三层(prompt constraint)在本仓不可核(属 studio/agent 侧提示词),未核不改
47
53
  - 消费饱和度替代固定 TTL 用于 signal 过期判断
48
54
  - **飞轮指标只有一个实现**(ADR-0013):`refCoverage` / `avgRefs` / `consumptionHitRate` 一律出自 `flywheel-metrics.evaluateFlywheel()`,canonical 分子 = `genuineRefs()` 过滤后的真实消费引用(`search|test-agent|prompt-inject|monitor|analyst|...:<date>` 自动化按天记账键不算消费,`unknown:` 注入键算消费)。audit D6 / `knowledge stats` / `knowledge health` 只在展示层做单位与字段名映射(百分比取整、一位小数、`avgRefs`→`avgRefCount`),人口筛选留在各调用方。新增消费方禁止自行数 `referencedBy.length`。
49
55
 
@@ -53,3 +59,4 @@
53
59
  - `MaturityLevel` 包含 6 个值: draft/verified/proven/archived/active/deprecated
54
60
  - `excludeArchived` 同时排除 archived 和 deprecated
55
61
  - 仍有两处按**原始** `referencedBy.length` 判定,不属飞轮指标、ADR-0013 明确列为范围外:`lifecycle.ts` 的 signal 饱和 / reference 激活(退役阈值调整另票)、`knowledge health` 的 D1「verified 零引用」线索提示(逐条 issue 线索,非聚合分子)
62
+ - #134 收口后仍在的逐条写点(同型问题,本票裁决点名的循环之外,需要时另票):`lint.ts` 的三处 autoFix `store.update()`、`lifecycle.recordReference()`(逐事件调用,返回更新后条目并触发回调,批量化会改它的契约)、`ingest.mergeEntries()`;`store.list()` 每条一次 `findFile()` 线性扫索引的 O(N²) 按 #134 裁决**未动**,待把知识树实际规模重新量一次再判是否单开票
@@ -1,15 +1,18 @@
1
1
  /**
2
2
  * 审计规则 label 闭环测试(架构评审 A6,#109)
3
3
  *
4
- * label 正本在 audit.ts 规则定义上(定义即注册),AUDIT_RULE_LABELS 派生自规则表。
5
- * 新增规则无 label → 编译期/本测试期即失败,CLI 不再静默回落英文键名。
4
+ * label 正本在规则定义上(定义即注册,#134 后随规则表住在 audit-scoring.ts),
5
+ * AUDIT_RULE_LABELS 派生自规则表。新增规则无 label → 编译期/本测试期即失败,
6
+ * CLI 不再静默回落英文键名。
6
7
  */
7
8
 
8
9
  import * as fs from 'fs';
9
10
  import * as os from 'os';
10
11
  import * as path from 'path';
11
- import { KnowledgeAudit, AUDIT_RULE_LABELS } from '../audit';
12
- import type { AuditRuleName } from '../audit';
12
+ import { KnowledgeAudit } from '../audit';
13
+ import { AUDIT_RULE_LABELS } from '../audit-scoring';
14
+ import type { AuditRuleName } from '../audit-scoring';
15
+ import { FileKnowledgeStore } from '../store';
13
16
 
14
17
  function makeTmpDir(): string {
15
18
  return fs.mkdtempSync(path.join(os.tmpdir(), 'audit-labels-test-'));
@@ -27,7 +30,7 @@ describe('AUDIT_RULE_LABELS', () => {
27
30
  });
28
31
 
29
32
  it('应与运行期 summary 的规则键集完全一致(双向闭环)', () => {
30
- const report = new KnowledgeAudit({ baseDir: tmpDir }).run();
33
+ const report = new KnowledgeAudit(new FileKnowledgeStore({ baseDir: tmpDir })).run();
31
34
  const summaryKeys = Object.keys(report.summary).sort();
32
35
  const labelKeys = (Object.keys(AUDIT_RULE_LABELS) as AuditRuleName[]).sort();
33
36
  expect(labelKeys).toEqual(summaryKeys);