@dommaker/harness 0.13.0 → 0.13.2

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 (420) hide show
  1. package/CHANGELOG.md +169 -0
  2. package/bin/harness-knowledge-capture.js +99 -0
  3. package/bin/harness-knowledge-check.js +149 -0
  4. package/bin/harness-knowledge-track.js +92 -0
  5. package/bin/harness-knowledge-track.sh +47 -0
  6. package/bin/harness-sensitive-check.sh +67 -0
  7. package/dist/cli/commands/init.js +34 -2
  8. package/dist/cli/commands/init.js.map +1 -1
  9. package/package.json +6 -3
  10. package/src/CONTEXT.md +34 -0
  11. package/src/__tests__/acceptance-gate.test.ts +364 -0
  12. package/src/__tests__/annotation-checker.test.ts +183 -0
  13. package/src/__tests__/architecture-engine.test.ts +619 -0
  14. package/src/__tests__/checker-extra.test.ts +1627 -0
  15. package/src/__tests__/checker.test.ts +1268 -0
  16. package/src/__tests__/checkpoint.test.ts +697 -0
  17. package/src/__tests__/clean-state-extra.test.ts +301 -0
  18. package/src/__tests__/clean-state.test.ts +169 -0
  19. package/src/__tests__/constraint-doctor.test.ts +410 -0
  20. package/src/__tests__/constraint-evolver.test.ts +404 -0
  21. package/src/__tests__/constraint-handler.test.ts +136 -0
  22. package/src/__tests__/context/progressive-loader.test.ts +131 -0
  23. package/src/__tests__/contract-gate.test.ts +321 -0
  24. package/src/__tests__/cross-project-checker.test.ts +318 -0
  25. package/src/__tests__/cso-validator.test.ts +205 -0
  26. package/src/__tests__/detect-source-roots.test.ts +98 -0
  27. package/src/__tests__/doctor-evolver.test.ts +381 -0
  28. package/src/__tests__/error-classifier.test.ts +304 -0
  29. package/src/__tests__/exec.test.ts +83 -0
  30. package/src/__tests__/extend-exceptions.test.ts +149 -0
  31. package/src/__tests__/failure-recorder.test.ts +335 -0
  32. package/src/__tests__/hooks-pipeline.test.ts +214 -0
  33. package/src/__tests__/interceptor.test.ts +89 -0
  34. package/src/__tests__/iron-laws.test.ts +246 -0
  35. package/src/__tests__/long-running.test.ts +17 -0
  36. package/src/__tests__/passes-gate-check.test.ts +138 -0
  37. package/src/__tests__/passes-gate-extension.test.ts +151 -0
  38. package/src/__tests__/passes-gate-extra.test.ts +238 -0
  39. package/src/__tests__/passes-gate.test.ts +231 -0
  40. package/src/__tests__/performance-analyzer.test.ts +501 -0
  41. package/src/__tests__/performance-collector.test.ts +276 -0
  42. package/src/__tests__/performance-gate.test.ts +74 -0
  43. package/src/__tests__/presets.test.ts +104 -0
  44. package/src/__tests__/project-config-loader-extra.test.ts +269 -0
  45. package/src/__tests__/project-config-loader.test.ts +127 -0
  46. package/src/__tests__/review-gate.test.ts +92 -0
  47. package/src/__tests__/security-gate.test.ts +100 -0
  48. package/src/__tests__/session-startup.test.ts +334 -0
  49. package/src/__tests__/spec-validator.test.ts +57 -0
  50. package/src/__tests__/token-budget.test.ts +252 -0
  51. package/src/__tests__/trace-analyzer-extra.test.ts +307 -0
  52. package/src/__tests__/trace-analyzer.test.ts +131 -0
  53. package/src/__tests__/trace-collector.test.ts +258 -0
  54. package/src/__tests__/traces.test.ts +347 -0
  55. package/src/agents/CONTEXT.md +21 -0
  56. package/src/agents/__tests__/lifecycle.test.ts +248 -0
  57. package/src/agents/index.ts +2 -0
  58. package/src/agents/lifecycle.ts +201 -0
  59. package/src/agents/types.ts +46 -0
  60. package/src/architecture/CONTEXT.md +22 -0
  61. package/src/architecture/constraint-engine.ts +356 -0
  62. package/src/architecture/cross-project-checker.ts +563 -0
  63. package/src/cli/commands/CONTEXT.md +24 -0
  64. package/src/cli/commands/__tests__/acceptance.test.ts +180 -0
  65. package/src/cli/commands/__tests__/check.test.ts +598 -0
  66. package/src/cli/commands/__tests__/command.test.ts +149 -0
  67. package/src/cli/commands/__tests__/contract.test.ts +151 -0
  68. package/src/cli/commands/__tests__/failure.test.ts +199 -0
  69. package/src/cli/commands/__tests__/flow.test.ts +343 -0
  70. package/src/cli/commands/__tests__/init.test.ts +306 -0
  71. package/src/cli/commands/__tests__/passes-gate.test.ts +256 -0
  72. package/src/cli/commands/__tests__/performance.test.ts +116 -0
  73. package/src/cli/commands/__tests__/posteval-plan.test.ts +201 -0
  74. package/src/cli/commands/__tests__/report-extra.test.ts +98 -0
  75. package/src/cli/commands/__tests__/report.test.ts +109 -0
  76. package/src/cli/commands/__tests__/review.test.ts +153 -0
  77. package/src/cli/commands/__tests__/security.test.ts +147 -0
  78. package/src/cli/commands/__tests__/spec.test.ts +193 -0
  79. package/src/cli/commands/__tests__/status-extra.test.ts +223 -0
  80. package/src/cli/commands/__tests__/status.test.ts +306 -0
  81. package/src/cli/commands/__tests__/sync-docs.test.ts +335 -0
  82. package/src/cli/commands/__tests__/validate.test.ts +139 -0
  83. package/src/cli/commands/acceptance.ts +111 -0
  84. package/src/cli/commands/analyze-sessions.ts +488 -0
  85. package/src/cli/commands/check.ts +441 -0
  86. package/src/cli/commands/command.ts +90 -0
  87. package/src/cli/commands/constraints.ts +86 -0
  88. package/src/cli/commands/contract.ts +168 -0
  89. package/src/cli/commands/failure.ts +117 -0
  90. package/src/cli/commands/flow.ts +275 -0
  91. package/src/cli/commands/index.ts +26 -0
  92. package/src/cli/commands/init.ts +832 -0
  93. package/src/cli/commands/knowledge.ts +391 -0
  94. package/src/cli/commands/passes-gate.ts +158 -0
  95. package/src/cli/commands/performance.ts +108 -0
  96. package/src/cli/commands/posteval-plan.ts +85 -0
  97. package/src/cli/commands/release.ts +159 -0
  98. package/src/cli/commands/report.ts +198 -0
  99. package/src/cli/commands/review.ts +118 -0
  100. package/src/cli/commands/security.ts +122 -0
  101. package/src/cli/commands/spec.ts +158 -0
  102. package/src/cli/commands/status.ts +169 -0
  103. package/src/cli/commands/sync-docs.ts +743 -0
  104. package/src/cli/commands/update-user-model.ts +527 -0
  105. package/src/cli/commands/validate.ts +222 -0
  106. package/src/constraints/__tests__/lifecycle-runner.test.ts +246 -0
  107. package/src/constraints/__tests__/registry.test.ts +196 -0
  108. package/src/constraints/index.ts +3 -0
  109. package/src/constraints/lifecycle-runner.ts +184 -0
  110. package/src/constraints/registry.ts +134 -0
  111. package/src/constraints/types.ts +59 -0
  112. package/src/context/CONTEXT.md +28 -0
  113. package/src/context/__tests__/compaction.test.ts +169 -0
  114. package/src/context/__tests__/file-budget.test.ts +142 -0
  115. package/src/context/__tests__/knowledge-injector.test.ts +148 -0
  116. package/src/context/__tests__/progressive-loader.test.ts +264 -0
  117. package/src/context/__tests__/session-manager.test.ts +300 -0
  118. package/src/context/__tests__/token-budget.test.ts +338 -0
  119. package/src/context/__tests__/token-pipeline.test.ts +178 -0
  120. package/src/context/__tests__/tool-output-budget.test.ts +95 -0
  121. package/src/context/compaction.ts +202 -0
  122. package/src/context/file-budget.ts +142 -0
  123. package/src/context/index.ts +15 -0
  124. package/src/context/knowledge-injector.ts +168 -0
  125. package/src/context/progressive-loader.ts +260 -0
  126. package/src/context/session-manager.ts +343 -0
  127. package/src/context/token-budget.ts +295 -0
  128. package/src/context/token-pipeline.ts +265 -0
  129. package/src/context/tool-output-budget.ts +178 -0
  130. package/src/context/types.ts +160 -0
  131. package/src/core/CONTEXT.md +26 -0
  132. package/src/core/constraints/__tests__/default-executors.test.ts +57 -0
  133. package/src/core/constraints/__tests__/interceptor.test.ts +251 -0
  134. package/src/core/constraints/__tests__/prompt-injection.test.ts +89 -0
  135. package/src/core/constraints/check-cache.ts +96 -0
  136. package/src/core/constraints/checker.ts +1169 -0
  137. package/src/core/constraints/default-executors.ts +92 -0
  138. package/src/core/constraints/definitions.ts +1119 -0
  139. package/src/core/constraints/doc-freshness/__tests__/runner.test.ts +551 -0
  140. package/src/core/constraints/doc-freshness/auto-fix.ts +69 -0
  141. package/src/core/constraints/doc-freshness/runner.ts +486 -0
  142. package/src/core/constraints/index.ts +78 -0
  143. package/src/core/constraints/interceptor.ts +220 -0
  144. package/src/core/constraints/prompt-injection.ts +73 -0
  145. package/src/core/index.ts +23 -0
  146. package/src/core/project-config-loader.ts +252 -0
  147. package/src/core/session/__tests__/startup.test.ts +281 -0
  148. package/src/core/session/clean-state.ts +178 -0
  149. package/src/core/session/index.ts +15 -0
  150. package/src/core/session/startup.ts +253 -0
  151. package/src/core/spec/__tests__/validator.test.ts +379 -0
  152. package/src/core/spec/index.ts +7 -0
  153. package/src/core/spec/validator.ts +383 -0
  154. package/src/core/validators/__tests__/passes-gate.test.ts +131 -0
  155. package/src/core/validators/checkpoint.ts +547 -0
  156. package/src/core/validators/cso.ts +124 -0
  157. package/src/core/validators/index.ts +25 -0
  158. package/src/core/validators/passes-gate.ts +613 -0
  159. package/src/dashboard/CONTEXT.md +21 -0
  160. package/src/dashboard/__tests__/data.test.ts +115 -0
  161. package/src/dashboard/__tests__/stats.test.ts +156 -0
  162. package/src/dashboard/data.ts +113 -0
  163. package/src/dashboard/index.ts +3 -0
  164. package/src/dashboard/stats.ts +127 -0
  165. package/src/dashboard/types.ts +113 -0
  166. package/src/evolution/CONTEXT.md +22 -0
  167. package/src/evolution/__tests__/auto-evolve.test.ts +320 -0
  168. package/src/evolution/auto-evolve.ts +98 -0
  169. package/src/evolution/index.ts +1 -0
  170. package/src/failure/CONTEXT.md +24 -0
  171. package/src/failure/classifier.ts +156 -0
  172. package/src/failure/constraint-handler.ts +173 -0
  173. package/src/failure/index.ts +35 -0
  174. package/src/failure/recorder.ts +201 -0
  175. package/src/failure/types.ts +165 -0
  176. package/src/gates/CONTEXT.md +27 -0
  177. package/src/gates/__tests__/acceptance.test.ts +608 -0
  178. package/src/gates/__tests__/command.test.ts +206 -0
  179. package/src/gates/__tests__/performance.test.ts +381 -0
  180. package/src/gates/__tests__/review.test.ts +302 -0
  181. package/src/gates/__tests__/security.test.ts +332 -0
  182. package/src/gates/acceptance.ts +493 -0
  183. package/src/gates/command.ts +444 -0
  184. package/src/gates/contract.ts +260 -0
  185. package/src/gates/index.ts +67 -0
  186. package/src/gates/performance.ts +359 -0
  187. package/src/gates/review.ts +169 -0
  188. package/src/gates/security.ts +244 -0
  189. package/src/gates/types.ts +159 -0
  190. package/src/governance/CONTEXT.md +22 -0
  191. package/src/governance/__tests__/executor.test.ts +249 -0
  192. package/src/governance/executor.ts +229 -0
  193. package/src/governance/index.ts +13 -0
  194. package/src/governance/types.ts +53 -0
  195. package/src/hooks/CONTEXT.md +23 -0
  196. package/src/hooks/__tests__/bootstrap.test.ts +184 -0
  197. package/src/hooks/bootstrap.ts +144 -0
  198. package/src/hooks/index.ts +15 -0
  199. package/src/hooks/pipeline.ts +157 -0
  200. package/src/hooks/registry.ts +88 -0
  201. package/src/hooks/types.ts +80 -0
  202. package/src/index.ts +198 -0
  203. package/src/knowledge/CONTEXT.md +29 -0
  204. package/src/knowledge/__tests__/doctor.test.ts +272 -0
  205. package/src/knowledge/__tests__/import.test.ts +376 -0
  206. package/src/knowledge/__tests__/ingest.test.ts +125 -0
  207. package/src/knowledge/__tests__/lifecycle-hooks.test.ts +137 -0
  208. package/src/knowledge/__tests__/lifecycle.test.ts +248 -0
  209. package/src/knowledge/__tests__/lint.test.ts +401 -0
  210. package/src/knowledge/__tests__/query.test.ts +185 -0
  211. package/src/knowledge/__tests__/reference-tracker.test.ts +129 -0
  212. package/src/knowledge/__tests__/store.test.ts +238 -0
  213. package/src/knowledge/doctor.ts +104 -0
  214. package/src/knowledge/import.ts +505 -0
  215. package/src/knowledge/index.ts +16 -0
  216. package/src/knowledge/ingest.ts +126 -0
  217. package/src/knowledge/lifecycle-hooks.ts +199 -0
  218. package/src/knowledge/lifecycle.ts +175 -0
  219. package/src/knowledge/lint.ts +360 -0
  220. package/src/knowledge/query.ts +150 -0
  221. package/src/knowledge/reference-tracker.ts +99 -0
  222. package/src/knowledge/store.ts +264 -0
  223. package/src/knowledge/types.ts +139 -0
  224. package/src/llm/CONTEXT.md +21 -0
  225. package/src/llm/__tests__/adapter.test.ts +172 -0
  226. package/src/llm/adapter.ts +149 -0
  227. package/src/llm/index.ts +2 -0
  228. package/src/llm/types.ts +81 -0
  229. package/src/monitoring/CONTEXT.md +29 -0
  230. package/src/monitoring/__tests__/context-tracker.test.ts +172 -0
  231. package/src/monitoring/__tests__/knowledge-doctor.test.ts +276 -0
  232. package/src/monitoring/__tests__/knowledge-evolver.test.ts +365 -0
  233. package/src/monitoring/__tests__/performance-analyzer.test.ts +137 -0
  234. package/src/monitoring/__tests__/performance-collector.test.ts +332 -0
  235. package/src/monitoring/__tests__/traces.test.ts +190 -0
  236. package/src/monitoring/constraint-doctor.ts +499 -0
  237. package/src/monitoring/constraint-evolver.ts +573 -0
  238. package/src/monitoring/context-tracker.ts +148 -0
  239. package/src/monitoring/index.ts +23 -0
  240. package/src/monitoring/knowledge-doctor.ts +323 -0
  241. package/src/monitoring/knowledge-evolver.ts +289 -0
  242. package/src/monitoring/performance-analyzer.ts +450 -0
  243. package/src/monitoring/performance-collector.ts +348 -0
  244. package/src/monitoring/trace-analyzer.ts +470 -0
  245. package/src/monitoring/traces.ts +339 -0
  246. package/src/presets/__tests__/standard.test.ts +104 -0
  247. package/src/presets/index.ts +16 -0
  248. package/src/presets/standard.ts +163 -0
  249. package/src/safety/CONTEXT.md +23 -0
  250. package/src/safety/__tests__/input-guardrail.test.ts +105 -0
  251. package/src/safety/__tests__/output-guardrail.test.ts +108 -0
  252. package/src/safety/__tests__/sandbox.test.ts +158 -0
  253. package/src/safety/__tests__/tool-guardrail.test.ts +127 -0
  254. package/src/safety/index.ts +5 -0
  255. package/src/safety/input-guardrail.ts +133 -0
  256. package/src/safety/output-guardrail.ts +174 -0
  257. package/src/safety/sandbox.ts +148 -0
  258. package/src/safety/tool-guardrail.ts +176 -0
  259. package/src/safety/types.ts +124 -0
  260. package/src/spec/CONTEXT.md +19 -0
  261. package/src/spec/__tests__/annotation-checker.test.ts +289 -0
  262. package/src/spec/annotation-checker.ts +342 -0
  263. package/src/tools/CONTEXT.md +25 -0
  264. package/src/tools/__tests__/loader.test.ts +252 -0
  265. package/src/tools/__tests__/registry.test.ts +157 -0
  266. package/src/tools/core/__tests__/core.test.ts +122 -0
  267. package/src/tools/core/index.ts +201 -0
  268. package/src/tools/core/package.json +7 -0
  269. package/src/tools/core/pnpm-lock.yaml +232 -0
  270. package/src/tools/definitions/core/code/fingerprint.sh +273 -0
  271. package/src/tools/definitions/core/code/fingerprint.yml +72 -0
  272. package/src/tools/definitions/core/code/parse.yml +68 -0
  273. package/src/tools/definitions/core/code/register-language.sh +475 -0
  274. package/src/tools/definitions/core/code/register-language.yml +74 -0
  275. package/src/tools/definitions/core/docker/build.yml +73 -0
  276. package/src/tools/definitions/core/docker/run.yml +81 -0
  277. package/src/tools/definitions/core/file/copy.yml +88 -0
  278. package/src/tools/definitions/core/file/read.yml +69 -0
  279. package/src/tools/definitions/core/file/write.yml +75 -0
  280. package/src/tools/definitions/core/git/branch.yml +61 -0
  281. package/src/tools/definitions/core/git/cleanup-worktree.yml +50 -0
  282. package/src/tools/definitions/core/git/clone.yml +69 -0
  283. package/src/tools/definitions/core/git/commit.yml +65 -0
  284. package/src/tools/definitions/core/git/push.yml +79 -0
  285. package/src/tools/definitions/core/git/worktree.yml +96 -0
  286. package/src/tools/definitions/core/notification/notify.sh +152 -0
  287. package/src/tools/definitions/core/notification/notify.yml +60 -0
  288. package/src/tools/definitions/core/npm/build.yml +75 -0
  289. package/src/tools/definitions/core/npm/install.yml +58 -0
  290. package/src/tools/definitions/core/npm/test.yml +75 -0
  291. package/src/tools/definitions/core/validation/check-reuse.yml +170 -0
  292. package/src/tools/definitions/core/validation/validate-handlers.yml +118 -0
  293. package/src/tools/definitions/core/validation/validate-readme-stats.yml +155 -0
  294. package/src/tools/definitions/core/validation/validate-yaml-syntax.yml +134 -0
  295. package/src/tools/definitions/ext/browser/browser-automate.sh +255 -0
  296. package/src/tools/definitions/ext/browser/browser-automate.yml +166 -0
  297. package/src/tools/definitions/ext/browser/browser-close.sh +104 -0
  298. package/src/tools/definitions/ext/browser/browser-close.yml +55 -0
  299. package/src/tools/definitions/ext/browser/browser-mcp-debug.sh +682 -0
  300. package/src/tools/definitions/ext/browser/browser-mcp-debug.yml +167 -0
  301. package/src/tools/definitions/ext/browser/browser-start.sh +101 -0
  302. package/src/tools/definitions/ext/browser/browser-start.yml +62 -0
  303. package/src/tools/definitions/registry.json +795 -0
  304. package/src/tools/definitions/std/README.md +350 -0
  305. package/src/tools/definitions/std/analysis/analyze-codebase.yml +72 -0
  306. package/src/tools/definitions/std/analysis/analyze-diff.yml +182 -0
  307. package/src/tools/definitions/std/analysis/analyze-git-diff.yml +70 -0
  308. package/src/tools/definitions/std/analysis/analyze-impact.yml +78 -0
  309. package/src/tools/definitions/std/analysis/analyze-requirements.yml +105 -0
  310. package/src/tools/definitions/std/analysis/brainstorm-options.yml +106 -0
  311. package/src/tools/definitions/std/analysis/build-graph.yml +154 -0
  312. package/src/tools/definitions/std/analysis/clarify-requirements.yml +90 -0
  313. package/src/tools/definitions/std/analysis/detect-context.yml +109 -0
  314. package/src/tools/definitions/std/analysis/detect-layers.yml +125 -0
  315. package/src/tools/definitions/std/analysis/generate-tour.yml +102 -0
  316. package/src/tools/definitions/std/analysis/search-enhance.yml +105 -0
  317. package/src/tools/definitions/std/backlog/add.yml +51 -0
  318. package/src/tools/definitions/std/backlog/decide.yml +39 -0
  319. package/src/tools/definitions/std/backlog/github-sync.yml +161 -0
  320. package/src/tools/definitions/std/backlog/list.yml +53 -0
  321. package/src/tools/definitions/std/backlog/load.yml +46 -0
  322. package/src/tools/definitions/std/backlog/resolve.yml +37 -0
  323. package/src/tools/definitions/std/backlog/update.yml +42 -0
  324. package/src/tools/definitions/std/bugfix/diagnose.yml +68 -0
  325. package/src/tools/definitions/std/bugfix/fix.yml +66 -0
  326. package/src/tools/definitions/std/bugfix/verify.yml +69 -0
  327. package/src/tools/definitions/std/constraint/check-decomposition.yml +103 -0
  328. package/src/tools/definitions/std/constraint/check-feature-list.yml +77 -0
  329. package/src/tools/definitions/std/constraint/check-progress.yml +97 -0
  330. package/src/tools/definitions/std/constraint/generate-report.yml +147 -0
  331. package/src/tools/definitions/std/deploy/commit-push.yml +33 -0
  332. package/src/tools/definitions/std/deploy/deploy-backend.yml +37 -0
  333. package/src/tools/definitions/std/deploy/deploy-frontend.yml +37 -0
  334. package/src/tools/definitions/std/deploy/rollback.yml +148 -0
  335. package/src/tools/definitions/std/design/analyze-architecture-impact.yml +113 -0
  336. package/src/tools/definitions/std/design/design-api.yml +55 -0
  337. package/src/tools/definitions/std/design/design-architecture.yml +97 -0
  338. package/src/tools/definitions/std/design/design-db.yml +81 -0
  339. package/src/tools/definitions/std/design/generate-spec.yml +182 -0
  340. package/src/tools/definitions/std/development/develop-api.yml +85 -0
  341. package/src/tools/definitions/std/development/develop-backend.yml +88 -0
  342. package/src/tools/definitions/std/development/develop-frontend.yml +87 -0
  343. package/src/tools/definitions/std/development/develop-shared-types.yml +74 -0
  344. package/src/tools/definitions/std/development/develop-task.yml +122 -0
  345. package/src/tools/definitions/std/development/develop-tests.yml +76 -0
  346. package/src/tools/definitions/std/development/execute-batch.yml +152 -0
  347. package/src/tools/definitions/std/development/fix-issues.yml +100 -0
  348. package/src/tools/definitions/std/development/implement-task.yml +124 -0
  349. package/src/tools/definitions/std/development/review-fix-cycle.yml +232 -0
  350. package/src/tools/definitions/std/evolution/implement.yml +125 -0
  351. package/src/tools/definitions/std/evolution/prioritize.yml +112 -0
  352. package/src/tools/definitions/std/evolution/report-gap.yml +166 -0
  353. package/src/tools/definitions/std/file/read.yml +21 -0
  354. package/src/tools/definitions/std/governance/aggregate-opinions.sh +201 -0
  355. package/src/tools/definitions/std/governance/aggregate-opinions.yml +79 -0
  356. package/src/tools/definitions/std/governance/audit-task.yml +178 -0
  357. package/src/tools/definitions/std/governance/cast-vote.yml +129 -0
  358. package/src/tools/definitions/std/governance/collect-issues.yml +16 -0
  359. package/src/tools/definitions/std/governance/create-signed-document.yml +23 -0
  360. package/src/tools/definitions/std/governance/create-voting-session.yml +101 -0
  361. package/src/tools/definitions/std/governance/define-stance.sh +243 -0
  362. package/src/tools/definitions/std/governance/define-stance.yml +82 -0
  363. package/src/tools/definitions/std/governance/generate-review-report.yml +23 -0
  364. package/src/tools/definitions/std/governance/impeach.yml +179 -0
  365. package/src/tools/definitions/std/governance/multi-stance-review.yml +154 -0
  366. package/src/tools/definitions/std/governance/prepare-artifact.yml +20 -0
  367. package/src/tools/definitions/std/governance/review-spec-approval.yml +262 -0
  368. package/src/tools/definitions/std/governance/rollback.yml +186 -0
  369. package/src/tools/definitions/std/governance/stance-review.yml +149 -0
  370. package/src/tools/definitions/std/governance/track-effect.yml +199 -0
  371. package/src/tools/definitions/std/governance/vote-tally.yml +144 -0
  372. package/src/tools/definitions/std/patch/execute.yml +51 -0
  373. package/src/tools/definitions/std/planning/generate-tasks.yml +36 -0
  374. package/src/tools/definitions/std/planning/load-tasks.yml +44 -0
  375. package/src/tools/definitions/std/planning/split-batch.yml +481 -0
  376. package/src/tools/definitions/std/planning/split-tasks.yml +359 -0
  377. package/src/tools/definitions/std/planning/update-tasks.yml +51 -0
  378. package/src/tools/definitions/std/planning/validate-tasks.yml +46 -0
  379. package/src/tools/definitions/std/project/decide-next-workflow.yml +38 -0
  380. package/src/tools/definitions/std/project/load-state.yml +31 -0
  381. package/src/tools/definitions/std/project/save-state.yml +32 -0
  382. package/src/tools/definitions/std/quality/check-quality.yml +241 -0
  383. package/src/tools/definitions/std/quality/debug-systematic.yml +163 -0
  384. package/src/tools/definitions/std/quality/handle-feedback.yml +108 -0
  385. package/src/tools/definitions/std/quality/review-code.yml +128 -0
  386. package/src/tools/definitions/std/quality/review-spec.yml +140 -0
  387. package/src/tools/definitions/std/quality/review-task.yml +190 -0
  388. package/src/tools/definitions/std/quality/run-tests.yml +80 -0
  389. package/src/tools/definitions/std/quick/analyze.yml +56 -0
  390. package/src/tools/definitions/std/quick/implement.yml +67 -0
  391. package/src/tools/definitions/std/quick/verify.yml +71 -0
  392. package/src/tools/definitions/std/verification/verify_completion.yml +113 -0
  393. package/src/tools/definitions/std/verification/wait-condition.yml +107 -0
  394. package/src/tools/index.ts +5 -0
  395. package/src/tools/loader.ts +216 -0
  396. package/src/tools/paths.ts +15 -0
  397. package/src/tools/registry.ts +128 -0
  398. package/src/tools/types.ts +46 -0
  399. package/src/types/__tests__/types.test.ts +86 -0
  400. package/src/types/checkpoint.ts +174 -0
  401. package/src/types/constraint.ts +335 -0
  402. package/src/types/cso.ts +37 -0
  403. package/src/types/enforcement.ts +48 -0
  404. package/src/types/index.ts +59 -0
  405. package/src/types/iron-law.ts +50 -0
  406. package/src/types/passes-gate.ts +185 -0
  407. package/src/types/performance.ts +295 -0
  408. package/src/types/project-config.ts +251 -0
  409. package/src/types/session.ts +132 -0
  410. package/src/types/spec.ts +91 -0
  411. package/src/types/trace.ts +228 -0
  412. package/src/utils/detect-source-roots.ts +114 -0
  413. package/src/utils/exec.ts +61 -0
  414. package/src/verification/CONTEXT.md +23 -0
  415. package/src/verification/__tests__/loop.test.ts +303 -0
  416. package/src/verification/__tests__/rules-based.test.ts +240 -0
  417. package/src/verification/index.ts +3 -0
  418. package/src/verification/loop.ts +137 -0
  419. package/src/verification/rules-based.ts +153 -0
  420. package/src/verification/types.ts +81 -0
@@ -0,0 +1,276 @@
1
+ import { KnowledgeDoctor } from '../knowledge-doctor';
2
+ import type { KnowledgeEntry, LintIssue } from '../../knowledge/types';
3
+
4
+ function makeEntry(overrides: Partial<KnowledgeEntry> = {}): KnowledgeEntry {
5
+ return {
6
+ id: 'entry-1',
7
+ type: 'guideline',
8
+ title: 'Test Entry',
9
+ content: 'content',
10
+ maturity: 'draft',
11
+ layer: 'team',
12
+ created: '2025-01-01T00:00:00Z',
13
+ lastReferenced: new Date().toISOString(),
14
+ contributors: ['user-1'],
15
+ projects: ['proj-1'],
16
+ tags: ['test'],
17
+ applicablePhases: ['implementation'],
18
+ sourceReferences: [],
19
+ referencedBy: ['ref-1'],
20
+ ...overrides,
21
+ };
22
+ }
23
+
24
+ describe('KnowledgeDoctor', () => {
25
+ describe('基础诊断', () => {
26
+ it('空知识库返回满分', () => {
27
+ const doctor = new KnowledgeDoctor();
28
+ const report = doctor.diagnose([]);
29
+ expect(report.healthScore).toBe(100);
30
+ expect(report.totalEntries).toBe(0);
31
+ expect(report.diagnoses).toHaveLength(0);
32
+ });
33
+
34
+ it('健康条目不产生诊断', () => {
35
+ const doctor = new KnowledgeDoctor();
36
+ const entry = makeEntry({ maturity: 'verified', referencedBy: ['r1', 'r2', 'r3'], projects: ['p1'] });
37
+ const report = doctor.diagnose([entry]);
38
+ // 可能有 low_reference 诊断,但不会有 orphan/outdated/decay
39
+ const criticalDiags = report.diagnoses.filter(d => d.type === 'orphan' || d.type === 'outdated' || d.type === 'decay');
40
+ expect(criticalDiags).toHaveLength(0);
41
+ });
42
+ });
43
+
44
+ describe('孤儿检测', () => {
45
+ it('检测无引用、无贡献者、无项目的 draft 条目', () => {
46
+ const doctor = new KnowledgeDoctor();
47
+ const orphan = makeEntry({
48
+ id: 'orphan-1',
49
+ maturity: 'draft',
50
+ referencedBy: [],
51
+ contributors: [],
52
+ projects: [],
53
+ });
54
+ const report = doctor.diagnose([orphan]);
55
+ const orphanDiags = report.diagnoses.filter(d => d.type === 'orphan');
56
+ expect(orphanDiags).toHaveLength(1);
57
+ expect(orphanDiags[0].entryId).toBe('orphan-1');
58
+ expect(orphanDiags[0].severity).toBe('low');
59
+ });
60
+
61
+ it('archived 条目不检测为孤儿', () => {
62
+ const doctor = new KnowledgeDoctor();
63
+ const archived = makeEntry({
64
+ maturity: 'archived',
65
+ referencedBy: [],
66
+ contributors: [],
67
+ projects: [],
68
+ });
69
+ const report = doctor.diagnose([archived]);
70
+ expect(report.diagnoses.filter(d => d.type === 'orphan')).toHaveLength(0);
71
+ });
72
+
73
+ it('有引用的 draft 条目不检测为孤儿', () => {
74
+ const doctor = new KnowledgeDoctor();
75
+ const entry = makeEntry({ maturity: 'draft', referencedBy: ['r1'], contributors: [], projects: [] });
76
+ const report = doctor.diagnose([entry]);
77
+ expect(report.diagnoses.filter(d => d.type === 'orphan')).toHaveLength(0);
78
+ });
79
+ });
80
+
81
+ describe('过时检测', () => {
82
+ it('检测超过阈值天数未引用的 draft 条目', () => {
83
+ const doctor = new KnowledgeDoctor({ outdatedDays: 30 });
84
+ const old = makeEntry({
85
+ id: 'old-1',
86
+ maturity: 'draft',
87
+ lastReferenced: '2020-01-01T00:00:00Z',
88
+ });
89
+ const report = doctor.diagnose([old]);
90
+ const outdated = report.diagnoses.filter(d => d.type === 'outdated');
91
+ expect(outdated).toHaveLength(1);
92
+ expect(outdated[0].entryId).toBe('old-1');
93
+ });
94
+
95
+ it('verified/proven 条目不检测为过时', () => {
96
+ const doctor = new KnowledgeDoctor({ outdatedDays: 1 });
97
+ const entry = makeEntry({
98
+ maturity: 'verified',
99
+ lastReferenced: '2020-01-01T00:00:00Z',
100
+ });
101
+ const report = doctor.diagnose([entry]);
102
+ expect(report.diagnoses.filter(d => d.type === 'outdated')).toHaveLength(0);
103
+ });
104
+ });
105
+
106
+ describe('衰减检测', () => {
107
+ it('检测长期未引用的 proven 条目', () => {
108
+ const doctor = new KnowledgeDoctor({ decayWarningDays: 30 });
109
+ const entry = makeEntry({
110
+ id: 'decay-1',
111
+ maturity: 'proven',
112
+ lastReferenced: '2020-01-01T00:00:00Z',
113
+ });
114
+ const report = doctor.diagnose([entry]);
115
+ const decay = report.diagnoses.filter(d => d.type === 'decay');
116
+ expect(decay).toHaveLength(1);
117
+ expect(decay[0].severity).toBe('high');
118
+ });
119
+
120
+ it('检测长期未引用的 verified 条目(medium severity)', () => {
121
+ const doctor = new KnowledgeDoctor({ decayWarningDays: 30 });
122
+ const entry = makeEntry({
123
+ maturity: 'verified',
124
+ lastReferenced: '2020-01-01T00:00:00Z',
125
+ });
126
+ const report = doctor.diagnose([entry]);
127
+ const decay = report.diagnoses.filter(d => d.type === 'decay');
128
+ expect(decay).toHaveLength(1);
129
+ expect(decay[0].severity).toBe('medium');
130
+ });
131
+
132
+ it('draft 条目不检测衰减', () => {
133
+ const doctor = new KnowledgeDoctor({ decayWarningDays: 1 });
134
+ const entry = makeEntry({
135
+ maturity: 'draft',
136
+ lastReferenced: '2020-01-01T00:00:00Z',
137
+ });
138
+ const report = doctor.diagnose([entry]);
139
+ expect(report.diagnoses.filter(d => d.type === 'decay')).toHaveLength(0);
140
+ });
141
+ });
142
+
143
+ describe('低引用检测', () => {
144
+ it('检测引用次数低于阈值的非 draft 条目', () => {
145
+ const doctor = new KnowledgeDoctor({ lowReferenceThreshold: 5 });
146
+ const entry = makeEntry({
147
+ maturity: 'verified',
148
+ referencedBy: ['r1'],
149
+ });
150
+ const report = doctor.diagnose([entry]);
151
+ const lowRef = report.diagnoses.filter(d => d.type === 'low_reference');
152
+ expect(lowRef).toHaveLength(1);
153
+ expect(lowRef[0].severity).toBe('low');
154
+ });
155
+
156
+ it('archived 和 draft 条目不检测低引用', () => {
157
+ const doctor = new KnowledgeDoctor({ lowReferenceThreshold: 100 });
158
+ const archived = makeEntry({ id: 'a1', maturity: 'archived', referencedBy: [] });
159
+ const draft = makeEntry({ id: 'd1', maturity: 'draft', referencedBy: [] });
160
+ const report = doctor.diagnose([archived, draft]);
161
+ expect(report.diagnoses.filter(d => d.type === 'low_reference')).toHaveLength(0);
162
+ });
163
+ });
164
+
165
+ describe('Lint issues 转换', () => {
166
+ it('将 LintIssue 转换为诊断', () => {
167
+ const doctor = new KnowledgeDoctor();
168
+ const issue: LintIssue = {
169
+ type: 'orphan',
170
+ entryId: 'e1',
171
+ severity: 'medium',
172
+ description: 'Orphan entry',
173
+ suggestion: 'Archive it',
174
+ };
175
+ const report = doctor.diagnose([], [issue]);
176
+ expect(report.diagnoses).toHaveLength(1);
177
+ expect(report.diagnoses[0].type).toBe('orphan');
178
+ expect(report.diagnoses[0].severity).toBe('medium');
179
+ expect(report.diagnoses[0].recommendations).toContain('Archive it');
180
+ });
181
+
182
+ it('覆盖所有 LintIssue 类型的根因和影响推断', () => {
183
+ const doctor = new KnowledgeDoctor();
184
+ const types: LintIssue['type'][] = ['contradiction', 'outdated', 'duplicate', 'index_inconsistent'];
185
+ for (const type of types) {
186
+ const issue: LintIssue = { type, severity: 'low', description: `test ${type}`, suggestion: 'fix' };
187
+ const report = doctor.diagnose([], [issue]);
188
+ const diag = report.diagnoses.find(d => d.type === type);
189
+ expect(diag).toBeDefined();
190
+ expect(diag!.rootCause).toBeTruthy();
191
+ expect(diag!.impact).toBeTruthy();
192
+ }
193
+ });
194
+
195
+ it('未知 LintIssue 类型使用默认根因和影响', () => {
196
+ const doctor = new KnowledgeDoctor();
197
+ const issue = { type: 'unknown_type', severity: 'low', description: 'unknown', suggestion: 'fix' } as unknown as LintIssue;
198
+ const report = doctor.diagnose([], [issue]);
199
+ expect(report.diagnoses[0].rootCause).toBe('未知原因');
200
+ expect(report.diagnoses[0].impact).toBe('未知影响');
201
+ });
202
+ });
203
+
204
+ describe('健康分数', () => {
205
+ it('无问题时返回 100', () => {
206
+ const doctor = new KnowledgeDoctor();
207
+ const entry = makeEntry({ maturity: 'verified', referencedBy: ['r1', 'r2', 'r3'], projects: ['p1', 'p2'] });
208
+ const report = doctor.diagnose([entry]);
209
+ expect(report.healthScore).toBe(100);
210
+ });
211
+
212
+ it('有问题时扣分', () => {
213
+ const doctor = new KnowledgeDoctor({ decayWarningDays: 1, lowReferenceThreshold: 100 });
214
+ const entry = makeEntry({
215
+ maturity: 'proven',
216
+ lastReferenced: '2020-01-01T00:00:00Z',
217
+ referencedBy: ['r1'],
218
+ projects: ['p1'],
219
+ });
220
+ const report = doctor.diagnose([entry]);
221
+ expect(report.healthScore).toBeLessThan(100);
222
+ });
223
+
224
+ it('critical 严重度扣 10 分', () => {
225
+ const doctor = new KnowledgeDoctor();
226
+ const issue: LintIssue = { type: 'contradiction', severity: 'high', entryId: 'e1', description: 'critical issue', suggestion: 'fix' };
227
+ // 直接构造 critical 诊断来测试 calculateHealthScore 的 critical 分支
228
+ // LintIssue severity 只有 low/medium/high,所以通过 checkDecay 的 high 来测试
229
+ const entry = makeEntry({ maturity: 'proven', lastReferenced: '2020-01-01T00:00:00Z' });
230
+ const report = doctor.diagnose([entry]);
231
+ const decayDiag = report.diagnoses.find(d => d.type === 'decay');
232
+ expect(decayDiag).toBeDefined();
233
+ expect(decayDiag!.severity).toBe('high');
234
+ });
235
+ });
236
+
237
+ describe('报告生成', () => {
238
+ it('生成 Markdown 报告', () => {
239
+ const doctor = new KnowledgeDoctor();
240
+ const report = doctor.diagnose([makeEntry()]);
241
+ const md = doctor.generateReport(report);
242
+ expect(md).toContain('# 知识库健康报告');
243
+ expect(md).toContain('健康分数');
244
+ expect(md).toContain('## 问题统计');
245
+ });
246
+
247
+ it('有诊断时生成详情', () => {
248
+ const doctor = new KnowledgeDoctor({ decayWarningDays: 1 });
249
+ const entry = makeEntry({
250
+ maturity: 'proven',
251
+ lastReferenced: '2020-01-01T00:00:00Z',
252
+ });
253
+ const report = doctor.diagnose([entry]);
254
+ const md = doctor.generateReport(report);
255
+ expect(md).toContain('## 诊断详情');
256
+ expect(md).toContain('衰减预警');
257
+ });
258
+ });
259
+
260
+ describe('配置', () => {
261
+ it('使用默认配置', () => {
262
+ const doctor = new KnowledgeDoctor();
263
+ // 默认 lowReferenceThreshold=2
264
+ const entry = makeEntry({ maturity: 'verified', referencedBy: ['r1'] });
265
+ const report = doctor.diagnose([entry]);
266
+ expect(report.diagnoses.filter(d => d.type === 'low_reference')).toHaveLength(1);
267
+ });
268
+
269
+ it('自定义配置覆盖默认值', () => {
270
+ const doctor = new KnowledgeDoctor({ lowReferenceThreshold: 0 });
271
+ const entry = makeEntry({ maturity: 'verified', referencedBy: [] });
272
+ const report = doctor.diagnose([entry]);
273
+ expect(report.diagnoses.filter(d => d.type === 'low_reference')).toHaveLength(0);
274
+ });
275
+ });
276
+ });
@@ -0,0 +1,365 @@
1
+ import { KnowledgeEvolver } from '../knowledge-evolver';
2
+ import type { KnowledgeDiagnosis } from '../knowledge-doctor';
3
+ import type { KnowledgeEntry } from '../../knowledge/types';
4
+
5
+ function makeEntry(overrides: Partial<KnowledgeEntry> = {}): KnowledgeEntry {
6
+ return {
7
+ id: 'entry-1',
8
+ type: 'guideline',
9
+ title: 'Test Entry',
10
+ content: 'content',
11
+ maturity: 'draft',
12
+ layer: 'team',
13
+ created: '2025-01-01T00:00:00Z',
14
+ lastReferenced: new Date().toISOString(),
15
+ contributors: ['user-1'],
16
+ projects: ['proj-1'],
17
+ tags: ['test'],
18
+ applicablePhases: ['implementation'],
19
+ sourceReferences: [],
20
+ referencedBy: ['ref-1'],
21
+ ...overrides,
22
+ };
23
+ }
24
+
25
+ describe('KnowledgeEvolver', () => {
26
+ describe('升级提案', () => {
27
+ it('draft 有引用时提议升级为 verified', () => {
28
+ const evolver = new KnowledgeEvolver();
29
+ const entry = makeEntry({ maturity: 'draft', referencedBy: ['r1'] });
30
+ const proposals = evolver.generateProposals([entry]);
31
+ const promote = proposals.filter(p => p.action === 'promote');
32
+ expect(promote).toHaveLength(1);
33
+ expect(promote[0].targetMaturity).toBe('verified');
34
+ expect(promote[0].risk).toBe('low');
35
+ expect(promote[0].autoApprovable).toBe(true);
36
+ });
37
+
38
+ it('draft 无引用时不提议升级', () => {
39
+ const evolver = new KnowledgeEvolver();
40
+ const entry = makeEntry({ maturity: 'draft', referencedBy: [] });
41
+ const proposals = evolver.generateProposals([entry]);
42
+ expect(proposals.filter(p => p.action === 'promote')).toHaveLength(0);
43
+ });
44
+
45
+ it('verified 有足够项目验证时提议升级为 proven', () => {
46
+ const evolver = new KnowledgeEvolver({ promoteThreshold: 2 });
47
+ const entry = makeEntry({ maturity: 'verified', projects: ['p1', 'p2'] });
48
+ const proposals = evolver.generateProposals([entry]);
49
+ const promote = proposals.filter(p => p.action === 'promote');
50
+ expect(promote).toHaveLength(1);
51
+ expect(promote[0].targetMaturity).toBe('proven');
52
+ });
53
+
54
+ it('verified 项目数不足时不提议升级', () => {
55
+ const evolver = new KnowledgeEvolver({ promoteThreshold: 5 });
56
+ const entry = makeEntry({ maturity: 'verified', projects: ['p1'] });
57
+ const proposals = evolver.generateProposals([entry]);
58
+ expect(proposals.filter(p => p.action === 'promote')).toHaveLength(0);
59
+ });
60
+
61
+ it('proven 不会提议升级(已到顶)', () => {
62
+ const evolver = new KnowledgeEvolver();
63
+ const entry = makeEntry({ maturity: 'proven', referencedBy: ['r1', 'r2'], projects: ['p1', 'p2'] });
64
+ const proposals = evolver.generateProposals([entry]);
65
+ expect(proposals.filter(p => p.action === 'promote')).toHaveLength(0);
66
+ });
67
+ });
68
+
69
+ describe('降级提案', () => {
70
+ it('长期未引用的 verified 提议降级', () => {
71
+ const evolver = new KnowledgeEvolver({ demoteDays: 30 });
72
+ const entry = makeEntry({
73
+ maturity: 'verified',
74
+ lastReferenced: '2020-01-01T00:00:00Z',
75
+ });
76
+ const proposals = evolver.generateProposals([entry]);
77
+ const demote = proposals.filter(p => p.action === 'demote');
78
+ expect(demote).toHaveLength(1);
79
+ expect(demote[0].targetMaturity).toBe('draft');
80
+ });
81
+
82
+ it('长期未引用的 proven 提议降级为 verified', () => {
83
+ const evolver = new KnowledgeEvolver({ demoteDays: 30 });
84
+ const entry = makeEntry({
85
+ maturity: 'proven',
86
+ lastReferenced: '2020-01-01T00:00:00Z',
87
+ });
88
+ const proposals = evolver.generateProposals([entry]);
89
+ const demote = proposals.filter(p => p.action === 'demote');
90
+ expect(demote).toHaveLength(1);
91
+ expect(demote[0].targetMaturity).toBe('verified');
92
+ });
93
+
94
+ it('draft 不会提议降级(已到底)', () => {
95
+ const evolver = new KnowledgeEvolver({ demoteDays: 1 });
96
+ const entry = makeEntry({
97
+ maturity: 'draft',
98
+ lastReferenced: '2020-01-01T00:00:00Z',
99
+ });
100
+ const proposals = evolver.generateProposals([entry]);
101
+ expect(proposals.filter(p => p.action === 'demote')).toHaveLength(0);
102
+ });
103
+
104
+ it('近期有引用的不提议降级', () => {
105
+ const evolver = new KnowledgeEvolver({ demoteDays: 180 });
106
+ const entry = makeEntry({ maturity: 'verified' });
107
+ const proposals = evolver.generateProposals([entry]);
108
+ expect(proposals.filter(p => p.action === 'demote')).toHaveLength(0);
109
+ });
110
+ });
111
+
112
+ describe('archived 条目', () => {
113
+ it('跳过 archived 条目', () => {
114
+ const evolver = new KnowledgeEvolver();
115
+ const entry = makeEntry({ maturity: 'archived' });
116
+ const proposals = evolver.generateProposals([entry]);
117
+ expect(proposals).toHaveLength(0);
118
+ });
119
+ });
120
+
121
+ describe('矛盾诊断 → freeze 提案', () => {
122
+ it('从矛盾诊断生成 freeze 提案', () => {
123
+ const evolver = new KnowledgeEvolver();
124
+ const entry = makeEntry({ id: 'e1', maturity: 'verified' });
125
+ const diagnosis: KnowledgeDiagnosis = {
126
+ id: 'd1',
127
+ type: 'contradiction',
128
+ severity: 'high',
129
+ entryId: 'e1',
130
+ title: 'Contradiction',
131
+ description: 'Conflicting entries',
132
+ rootCause: 'Same tag different maturity',
133
+ impact: 'Confusion',
134
+ recommendations: ['Freeze'],
135
+ timestamp: new Date().toISOString(),
136
+ };
137
+ const proposals = evolver.generateProposals([entry], [diagnosis]);
138
+ const freeze = proposals.filter(p => p.action === 'freeze');
139
+ expect(freeze).toHaveLength(1);
140
+ expect(freeze[0].risk).toBe('medium');
141
+ expect(freeze[0].autoApprovable).toBe(false);
142
+ });
143
+
144
+ it('无 entryId 的矛盾诊断不生成提案', () => {
145
+ const evolver = new KnowledgeEvolver();
146
+ const diagnosis: KnowledgeDiagnosis = {
147
+ id: 'd1',
148
+ type: 'contradiction',
149
+ severity: 'high',
150
+ title: 'Contradiction',
151
+ description: 'Conflicting entries',
152
+ rootCause: 'Unknown',
153
+ impact: 'Unknown',
154
+ recommendations: [],
155
+ timestamp: new Date().toISOString(),
156
+ };
157
+ const proposals = evolver.generateProposals([], [diagnosis]);
158
+ expect(proposals).toHaveLength(0);
159
+ });
160
+ });
161
+
162
+ describe('审核', () => {
163
+ it('低风险自动通过提案自动批准', () => {
164
+ const evolver = new KnowledgeEvolver();
165
+ const entry = makeEntry({ maturity: 'draft', referencedBy: ['r1'] });
166
+ const proposals = evolver.generateProposals([entry]);
167
+ const result = evolver.review(proposals[0]);
168
+ expect(result.approved).toBe(true);
169
+ });
170
+
171
+ it('proven 直接归档被拒绝', () => {
172
+ const evolver = new KnowledgeEvolver();
173
+ const proposal = {
174
+ id: 'p1',
175
+ entryId: 'e1',
176
+ action: 'archive' as const,
177
+ currentMaturity: 'proven' as const,
178
+ targetMaturity: 'archived' as const,
179
+ reason: 'test',
180
+ evidence: [],
181
+ risk: 'low' as const,
182
+ autoApprovable: true,
183
+ status: 'pending' as const,
184
+ createdAt: new Date().toISOString(),
185
+ };
186
+ const result = evolver.review(proposal);
187
+ expect(result.approved).toBe(false);
188
+ expect(result.reason).toContain('proven');
189
+ });
190
+
191
+ it('高风险升级被拒绝', () => {
192
+ const evolver = new KnowledgeEvolver();
193
+ const proposal = {
194
+ id: 'p1',
195
+ entryId: 'e1',
196
+ action: 'promote' as const,
197
+ currentMaturity: 'draft' as const,
198
+ targetMaturity: 'verified' as const,
199
+ reason: 'test',
200
+ evidence: [],
201
+ risk: 'high' as const,
202
+ autoApprovable: false,
203
+ status: 'pending' as const,
204
+ createdAt: new Date().toISOString(),
205
+ };
206
+ const result = evolver.review(proposal);
207
+ expect(result.approved).toBe(false);
208
+ expect(result.reason).toContain('高风险');
209
+ });
210
+
211
+ it('中等风险提案通过审核', () => {
212
+ const evolver = new KnowledgeEvolver();
213
+ const proposal = {
214
+ id: 'p1',
215
+ entryId: 'e1',
216
+ action: 'freeze' as const,
217
+ currentMaturity: 'verified' as const,
218
+ targetMaturity: 'verified' as const,
219
+ reason: 'test',
220
+ evidence: [],
221
+ risk: 'medium' as const,
222
+ autoApprovable: false,
223
+ status: 'pending' as const,
224
+ createdAt: new Date().toISOString(),
225
+ };
226
+ const result = evolver.review(proposal);
227
+ expect(result.approved).toBe(true);
228
+ expect(result.reason).toBe('提案通过审核');
229
+ });
230
+ });
231
+
232
+ describe('执行提案', () => {
233
+ it('无 store 时返回 false', () => {
234
+ const evolver = new KnowledgeEvolver();
235
+ const proposal = {
236
+ id: 'p1',
237
+ entryId: 'e1',
238
+ action: 'promote' as const,
239
+ currentMaturity: 'draft' as const,
240
+ targetMaturity: 'verified' as const,
241
+ reason: 'test',
242
+ evidence: [],
243
+ risk: 'low' as const,
244
+ autoApprovable: true,
245
+ status: 'approved' as const,
246
+ createdAt: new Date().toISOString(),
247
+ };
248
+ expect(evolver.implement(proposal)).toBe(false);
249
+ });
250
+
251
+ it('非 approved 状态返回 false', () => {
252
+ const evolver = new KnowledgeEvolver();
253
+ const proposal = {
254
+ id: 'p1',
255
+ entryId: 'e1',
256
+ action: 'promote' as const,
257
+ currentMaturity: 'draft' as const,
258
+ targetMaturity: 'verified' as const,
259
+ reason: 'test',
260
+ evidence: [],
261
+ risk: 'low' as const,
262
+ autoApprovable: true,
263
+ status: 'pending' as const,
264
+ createdAt: new Date().toISOString(),
265
+ };
266
+ expect(evolver.implement(proposal)).toBe(false);
267
+ });
268
+
269
+ it('store 中不存在条目时返回 false', () => {
270
+ const mockStore = { get: () => undefined, update: jest.fn() };
271
+ const evolver = new KnowledgeEvolver({}, mockStore as any);
272
+ const proposal = {
273
+ id: 'p1', entryId: 'e1', action: 'promote' as const,
274
+ currentMaturity: 'draft' as const, targetMaturity: 'verified' as const,
275
+ reason: 'test', evidence: [], risk: 'low' as const,
276
+ autoApprovable: true, status: 'approved' as const,
277
+ createdAt: new Date().toISOString(),
278
+ };
279
+ expect(evolver.implement(proposal)).toBe(false);
280
+ });
281
+
282
+ it('archive 操作执行成功', () => {
283
+ const mockStore = { get: () => makeEntry(), update: jest.fn() };
284
+ const evolver = new KnowledgeEvolver({}, mockStore as any);
285
+ const proposal = {
286
+ id: 'p1', entryId: 'entry-1', action: 'archive' as const,
287
+ currentMaturity: 'draft' as const, targetMaturity: 'archived' as const,
288
+ reason: 'test', evidence: [], risk: 'low' as const,
289
+ autoApprovable: true, status: 'approved' as const,
290
+ createdAt: new Date().toISOString(),
291
+ };
292
+ expect(evolver.implement(proposal)).toBe(true);
293
+ expect(mockStore.update).toHaveBeenCalledWith('entry-1', { maturity: 'archived' });
294
+ expect(proposal.status).toBe('implemented');
295
+ });
296
+
297
+ it('freeze 操作不调用 update', () => {
298
+ const mockStore = { get: () => makeEntry(), update: jest.fn() };
299
+ const evolver = new KnowledgeEvolver({}, mockStore as any);
300
+ const proposal = {
301
+ id: 'p1', entryId: 'entry-1', action: 'freeze' as const,
302
+ currentMaturity: 'verified' as const, targetMaturity: 'verified' as const,
303
+ reason: 'test', evidence: [], risk: 'medium' as const,
304
+ autoApprovable: false, status: 'approved' as const,
305
+ createdAt: new Date().toISOString(),
306
+ };
307
+ expect(evolver.implement(proposal)).toBe(true);
308
+ expect(mockStore.update).not.toHaveBeenCalled();
309
+ expect(proposal.status).toBe('implemented');
310
+ });
311
+
312
+ it('未知 action 返回 false', () => {
313
+ const mockStore = { get: () => makeEntry(), update: jest.fn() };
314
+ const evolver = new KnowledgeEvolver({}, mockStore as any);
315
+ const proposal = {
316
+ id: 'p1', entryId: 'entry-1', action: 'merge' as const,
317
+ currentMaturity: 'draft' as const, targetMaturity: 'verified' as const,
318
+ reason: 'test', evidence: [], risk: 'low' as const,
319
+ autoApprovable: true, status: 'approved' as const,
320
+ createdAt: new Date().toISOString(),
321
+ };
322
+ expect(evolver.implement(proposal)).toBe(false);
323
+ });
324
+ });
325
+
326
+ describe('批量处理', () => {
327
+ it('processProposals 审核并生成报告', () => {
328
+ const evolver = new KnowledgeEvolver();
329
+ const entry = makeEntry({ maturity: 'draft', referencedBy: ['r1'] });
330
+ const proposals = evolver.generateProposals([entry]);
331
+ const report = evolver.processProposals(proposals);
332
+ expect(report.proposals.length).toBeGreaterThan(0);
333
+ expect(report.proposals[0].status).toBe('approved');
334
+ expect(report.summary).toBeDefined();
335
+ });
336
+
337
+ it('processProposals 拒绝高风险提案', () => {
338
+ const evolver = new KnowledgeEvolver();
339
+ const proposal = {
340
+ id: 'p1', entryId: 'e1', action: 'promote' as const,
341
+ currentMaturity: 'draft' as const, targetMaturity: 'verified' as const,
342
+ reason: 'test', evidence: [], risk: 'high' as const,
343
+ autoApprovable: false, status: 'pending' as const,
344
+ createdAt: new Date().toISOString(),
345
+ };
346
+ const report = evolver.processProposals([proposal]);
347
+ expect(report.proposals[0].status).toBe('rejected');
348
+ });
349
+
350
+ it('autoImplement 模式自动执行低风险提案', () => {
351
+ const mockStore = {
352
+ get: (id: string) => makeEntry({ id, maturity: 'draft' }),
353
+ update: jest.fn(),
354
+ };
355
+ const evolver = new KnowledgeEvolver({ autoImplement: true }, mockStore as any);
356
+ const entry = makeEntry({ maturity: 'draft', referencedBy: ['r1'] });
357
+ const proposals = evolver.generateProposals([entry]);
358
+ const report = evolver.processProposals(proposals);
359
+ const promote = report.proposals.find(p => p.action === 'promote');
360
+ if (promote?.autoApprovable) {
361
+ expect(promote.status).toBe('implemented');
362
+ }
363
+ });
364
+ });
365
+ });