akm-cli 0.9.16 → 0.9.17-alpha.10

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 (403) hide show
  1. package/CHANGELOG.md +2101 -0
  2. package/STABILITY.md +11 -10
  3. package/dist/akm +124 -193
  4. package/dist/akm-migrate +38 -19
  5. package/dist/assets/hints/cli-hints-full.md +6 -7
  6. package/dist/assets/improve-strategies/catchup.json +0 -3
  7. package/dist/assets/improve-strategies/consolidate.json +0 -1
  8. package/dist/assets/improve-strategies/default.json +1 -2
  9. package/dist/assets/improve-strategies/proactive-maintenance.json +1 -2
  10. package/dist/assets/improve-strategies/quick.json +1 -2
  11. package/dist/assets/improve-strategies/reflect-distill.json +1 -2
  12. package/dist/assets/improve-strategies/thorough.json +0 -3
  13. package/dist/assets/prompts/consolidate-pair.md +20 -0
  14. package/dist/assets/prompts/consolidate-system.md +4 -11
  15. package/dist/assets/prompts/retrieval-relevance-judge.md +6 -0
  16. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +20 -20
  17. package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -2
  18. package/dist/assets/templates/html/health.html +3 -5
  19. package/dist/cli/retired-commands.js +1 -1
  20. package/dist/cli/shared.js +6 -2
  21. package/dist/cli/unknown-flags.js +24 -1
  22. package/dist/cli.js +68 -10
  23. package/dist/commands/agent/agent-dispatch.js +1 -1
  24. package/dist/commands/command/command-execution.js +24 -62
  25. package/dist/commands/feedback-cli.js +0 -1
  26. package/dist/commands/health/accept-rate.js +6 -0
  27. package/dist/commands/health/archive-usage.js +92 -0
  28. package/dist/commands/health/checks.js +83 -74
  29. package/dist/commands/health/config-skew.js +38 -0
  30. package/dist/commands/health/data-dir-usage.js +25 -13
  31. package/dist/commands/health/egress.js +54 -0
  32. package/dist/commands/health/html-report.js +1 -42
  33. package/dist/commands/health/improve-metrics.js +136 -591
  34. package/dist/commands/health/md-report.js +1 -6
  35. package/dist/commands/health/plugin-staleness.js +53 -3
  36. package/dist/commands/health/renderers.js +12 -4
  37. package/dist/commands/health/report-view-model.js +14 -120
  38. package/dist/commands/health/types-improve.js +4 -19
  39. package/dist/commands/health/windows.js +64 -74
  40. package/dist/commands/health.js +145 -143
  41. package/dist/commands/improve/consolidate/chunking.js +26 -117
  42. package/dist/commands/improve/consolidate/continuity-check.js +137 -0
  43. package/dist/commands/improve/consolidate/pair-pass.js +791 -0
  44. package/dist/commands/improve/consolidate/sanitize.js +54 -149
  45. package/dist/commands/improve/consolidate.js +589 -1127
  46. package/dist/commands/improve/content-hash.js +16 -24
  47. package/dist/commands/improve/distill/content-repair.js +18 -100
  48. package/dist/commands/improve/distill-guards.js +20 -81
  49. package/dist/commands/improve/distill-promotion-policy.js +23 -243
  50. package/dist/commands/improve/distill.js +608 -1041
  51. package/dist/commands/improve/eligibility.js +126 -390
  52. package/dist/commands/improve/execution.js +8 -10
  53. package/dist/commands/improve/extract-prompt.js +1 -2
  54. package/dist/commands/improve/extract.js +487 -1046
  55. package/dist/commands/improve/feedback-valence.js +0 -25
  56. package/dist/commands/improve/improve-cli.js +75 -169
  57. package/dist/commands/improve/improve-result-file.js +10 -66
  58. package/dist/commands/improve/improve-strategies.js +52 -4
  59. package/dist/commands/improve/improve-usage-report.js +18 -64
  60. package/dist/commands/improve/improve.js +480 -1074
  61. package/dist/commands/improve/ledger.js +119 -0
  62. package/dist/commands/improve/locks.js +2 -8
  63. package/dist/commands/improve/loop-stages.js +415 -1073
  64. package/dist/commands/improve/memory/derived-ref.js +12 -77
  65. package/dist/commands/improve/memory/memory-belief.js +16 -118
  66. package/dist/commands/improve/memory/memory-improve.js +266 -14
  67. package/dist/commands/improve/outcome-loop.js +28 -156
  68. package/dist/commands/improve/planner.js +5 -15
  69. package/dist/commands/improve/preparation.js +779 -2319
  70. package/dist/commands/improve/proactive-maintenance.js +34 -101
  71. package/dist/commands/improve/reflect-noise.js +104 -280
  72. package/dist/commands/improve/reflect.js +642 -1353
  73. package/dist/commands/improve/retrieval-gate.js +127 -0
  74. package/dist/commands/improve/retrieval-scope.js +92 -0
  75. package/dist/commands/improve/salience.js +41 -240
  76. package/dist/commands/improve/session-asset.js +19 -100
  77. package/dist/commands/improve/stage.js +322 -0
  78. package/dist/commands/lint/base-linter.js +37 -15
  79. package/dist/commands/proposal/drain.js +261 -578
  80. package/dist/commands/proposal/proposal-cli.js +19 -20
  81. package/dist/commands/proposal/proposal-types.js +31 -24
  82. package/dist/commands/proposal/proposal.js +38 -8
  83. package/dist/commands/proposal/propose.js +134 -160
  84. package/dist/commands/proposal/repository.js +1097 -1394
  85. package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
  86. package/dist/commands/proposal/validators/proposal-validators.js +1 -1
  87. package/dist/commands/proposal/validators/proposals.js +22 -89
  88. package/dist/commands/read/curate.js +105 -462
  89. package/dist/commands/read/knowledge.js +3 -2
  90. package/dist/commands/read/search-cli.js +16 -33
  91. package/dist/commands/read/search.js +17 -23
  92. package/dist/commands/read/show.js +57 -108
  93. package/dist/commands/sources/bundle-cli.js +25 -2
  94. package/dist/commands/sources/bundle-config-ops.js +4 -0
  95. package/dist/commands/sources/dangerous-env-audit.js +1 -2
  96. package/dist/commands/sources/info.js +127 -29
  97. package/dist/commands/sources/installed-stashes.js +197 -746
  98. package/dist/commands/sources/schema-repair.js +98 -129
  99. package/dist/commands/sources/source-add.js +62 -12
  100. package/dist/commands/sources/source-manage.js +9 -2
  101. package/dist/commands/sources/stash-cli.js +24 -4
  102. package/dist/commands/tasks/explain.js +10 -13
  103. package/dist/commands/tasks/tasks-cli.js +12 -13
  104. package/dist/commands/tasks/tasks.js +350 -936
  105. package/dist/commands/tasks/validate.js +26 -24
  106. package/dist/commands/workflow/plan.js +22 -29
  107. package/dist/commands/workflow-cli.js +4 -4
  108. package/dist/core/adapter/adapters/akm-adapter.js +2 -1
  109. package/dist/core/adapter/adapters/akm-lint.js +2 -3
  110. package/dist/core/adapter/adapters/akm-metadata.js +42 -12
  111. package/dist/core/adapter/adapters/akm-task-adapter.js +29 -8
  112. package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
  113. package/dist/core/adapter/execution-source.js +17 -29
  114. package/dist/core/asset/asset-placement.js +4 -13
  115. package/dist/core/asset/frontmatter.js +106 -1
  116. package/dist/core/asset/resolve-ref.js +1 -1
  117. package/dist/core/bundle-id.js +42 -5
  118. package/dist/core/bundle-rename.js +285 -0
  119. package/dist/core/config/config-io.js +1 -2
  120. package/dist/core/config/config-schema.js +9 -34
  121. package/dist/core/config/config-walker.js +1 -1
  122. package/dist/core/config/config.js +184 -111
  123. package/dist/core/config/engine-semantics.js +0 -2
  124. package/dist/core/config/legacy-source-shape-shim.js +38 -9
  125. package/dist/core/config/schema/embedding.js +20 -5
  126. package/dist/core/config/schema/engines.js +5 -0
  127. package/dist/core/config/schema/execution.js +1 -1
  128. package/dist/core/config/schema/experimental.js +1 -1
  129. package/dist/core/config/schema/improve-processes.js +54 -125
  130. package/dist/core/config/schema/improve.js +4 -42
  131. package/dist/core/config/schema/index-config.js +9 -48
  132. package/dist/core/config/schema/scheduler.js +12 -12
  133. package/dist/core/config/schema/search.js +6 -22
  134. package/dist/core/env-secret-ref.js +0 -1
  135. package/dist/core/errors.js +8 -9
  136. package/dist/core/file-change.js +13 -5
  137. package/dist/core/file-lock.js +76 -173
  138. package/dist/core/improve-result.js +35 -7
  139. package/dist/core/improve-types.js +0 -1
  140. package/dist/core/logs-db.js +2 -2
  141. package/dist/core/loopback.js +7 -12
  142. package/dist/core/non-task-input.js +20 -0
  143. package/dist/core/parse.js +13 -16
  144. package/dist/core/paths.js +0 -24
  145. package/dist/core/redaction.js +109 -2
  146. package/dist/core/run-lock.js +2 -5
  147. package/dist/core/spawn-env.js +1 -1
  148. package/dist/core/state/migrations.js +123 -61
  149. package/dist/core/state-db-scope.js +2 -4
  150. package/dist/core/state-db.js +126 -692
  151. package/dist/core/time.js +0 -20
  152. package/dist/core/type-presentation.js +1 -9
  153. package/dist/core/write-source.js +294 -1005
  154. package/dist/execution/input-contract.js +1 -1
  155. package/dist/execution/resolved-request.js +135 -689
  156. package/dist/execution/source.js +63 -257
  157. package/dist/execution/target-ref.js +1 -1
  158. package/dist/indexer/bundle-identity-guard.js +2 -2
  159. package/dist/indexer/db/llm-cache.js +2 -2
  160. package/dist/indexer/ensure-index.js +77 -73
  161. package/dist/indexer/index-rebuild-lock.js +3 -11
  162. package/dist/indexer/index-writer-lock.js +8 -17
  163. package/dist/indexer/index-written-assets.js +141 -154
  164. package/dist/indexer/indexer.js +400 -1124
  165. package/dist/indexer/links/declared-links.js +90 -0
  166. package/dist/indexer/materialize-embeddings.js +60 -397
  167. package/dist/indexer/passes/memory-inference.js +96 -90
  168. package/dist/indexer/passes/metadata.js +132 -219
  169. package/dist/indexer/read-preflight.js +0 -7
  170. package/dist/indexer/scan/doc-to-entry.js +2 -3
  171. package/dist/indexer/scan/drain-dir.js +1 -1
  172. package/dist/indexer/search/db-search.js +190 -590
  173. package/dist/indexer/search/fts-query.js +30 -41
  174. package/dist/indexer/search/ranking.js +28 -154
  175. package/dist/indexer/search/search-attribution.js +12 -32
  176. package/dist/indexer/search/search-fields.js +11 -15
  177. package/dist/indexer/search/search-hit-enrichers.js +54 -85
  178. package/dist/indexer/search/search-source.js +1 -4
  179. package/dist/indexer/usage/usage-events.js +36 -7
  180. package/dist/indexer/walk/walker.js +3 -4
  181. package/dist/integrations/agent/engine-fallback.js +23 -40
  182. package/dist/integrations/agent/engine-resolution.js +93 -183
  183. package/dist/integrations/agent/execution.js +507 -0
  184. package/dist/integrations/agent/model-map.js +28 -156
  185. package/dist/integrations/agent/request-lowering.js +66 -141
  186. package/dist/integrations/agent/runner-dispatch.js +143 -321
  187. package/dist/integrations/agent/runner.js +54 -14
  188. package/dist/integrations/lockfile.js +53 -101
  189. package/dist/llm/client.js +18 -6
  190. package/dist/llm/embedders/deterministic.js +2 -3
  191. package/dist/llm/embedders/profile.js +71 -0
  192. package/dist/llm/embedders/remote.js +11 -17
  193. package/dist/llm/feature-gate.js +0 -8
  194. package/dist/llm/index-passes.js +3 -5
  195. package/dist/llm/memory-infer.js +1 -2
  196. package/dist/llm/structured-call.js +5 -24
  197. package/dist/output/generic-render.js +23 -11
  198. package/dist/output/html-render.js +13 -10
  199. package/dist/output/render-registry.js +3 -32
  200. package/dist/output/shapes/helpers.js +25 -38
  201. package/dist/output/shapes/passthrough.js +1 -9
  202. package/dist/{indexer/graph/graph-types.js → output/text/bundle-rename.js} +4 -1
  203. package/dist/output/text/command-format.js +69 -31
  204. package/dist/output/text/helpers.js +1 -1
  205. package/dist/output/text/migrate.js +5 -14
  206. package/dist/output/text/proposal-format.js +48 -3
  207. package/dist/output/text/show-format.js +13 -17
  208. package/dist/output/text/workflow-format.js +0 -32
  209. package/dist/output/text.js +2 -0
  210. package/dist/registry/factory.js +4 -19
  211. package/dist/registry/network.js +66 -220
  212. package/dist/registry/providers/index.js +0 -2
  213. package/dist/registry/providers/skills-sh.js +3 -14
  214. package/dist/registry/providers/static-index.js +24 -26
  215. package/dist/registry/resolve.js +55 -131
  216. package/dist/scripts/akm-migrate-node.js +42948 -92369
  217. package/dist/scripts/akm-migrate.js +42935 -92354
  218. package/dist/setup/registry-stash-loader.js +4 -13
  219. package/dist/setup/semantic-assets.js +3 -44
  220. package/dist/setup/setup.js +1 -1
  221. package/dist/setup/steps/connection.js +5 -6
  222. package/dist/setup/steps/platforms.js +2 -2
  223. package/dist/setup/steps/tasks.js +25 -15
  224. package/dist/sources/provider-factory.js +17 -18
  225. package/dist/sources/providers/filesystem.js +2 -3
  226. package/dist/sources/providers/git-install.js +7 -1
  227. package/dist/sources/providers/git-provider.js +0 -3
  228. package/dist/sources/providers/git-stash.js +83 -21
  229. package/dist/sources/providers/npm.js +2 -4
  230. package/dist/sources/providers/provider-utils.js +5 -10
  231. package/dist/sources/providers/website.js +0 -2
  232. package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
  233. package/dist/sources/website-url.js +2 -2
  234. package/dist/storage/database.js +9 -35
  235. package/dist/storage/repositories/improve-ledger-repository.js +209 -0
  236. package/dist/storage/repositories/index-connection.js +39 -72
  237. package/dist/storage/repositories/index-entries-repository.js +131 -129
  238. package/dist/storage/repositories/index-entry-mapper.js +1 -2
  239. package/dist/storage/repositories/index-entry-schema.js +101 -268
  240. package/dist/storage/repositories/index-fts-repository.js +86 -256
  241. package/dist/storage/repositories/index-links-repository.js +143 -0
  242. package/dist/storage/repositories/index-llm-cache-repository.js +7 -9
  243. package/dist/storage/repositories/index-meta-repository.js +6 -4
  244. package/dist/storage/repositories/index-schema.js +257 -325
  245. package/dist/storage/repositories/index-utility-repository.js +8 -29
  246. package/dist/storage/repositories/index-vec-repository.js +133 -414
  247. package/dist/storage/repositories/outcome-repository.js +2 -1
  248. package/dist/storage/repositories/proposals-repository.js +104 -1
  249. package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
  250. package/dist/storage/repositories/salience-repository.js +1 -19
  251. package/dist/storage/repositories/task-history-repository.js +26 -4
  252. package/dist/storage/repositories/workflow-runs-repository.js +53 -244
  253. package/dist/storage/sqlite-migrations.js +136 -0
  254. package/dist/storage/sqlite-pragmas.js +11 -9
  255. package/dist/storage/sqlite-transaction.js +170 -0
  256. package/dist/storage/state-db-integrity.js +130 -0
  257. package/dist/tasks/activation-config.js +134 -62
  258. package/dist/tasks/backends/cron.js +191 -302
  259. package/dist/tasks/backends/exec-utils.js +2 -5
  260. package/dist/tasks/backends/launchd.js +141 -748
  261. package/dist/tasks/backends/schtasks.js +119 -623
  262. package/dist/tasks/prepare/prepare-support.js +5 -15
  263. package/dist/tasks/prepare/prepare.js +0 -2
  264. package/dist/tasks/resolve-akm-bin.js +20 -79
  265. package/dist/tasks/run/attempt-lifecycle.js +0 -1
  266. package/dist/tasks/run/load-task.js +1 -1
  267. package/dist/tasks/scheduler-binding.js +20 -238
  268. package/dist/tasks/scheduler-invocation.js +136 -244
  269. package/dist/tasks/scheduler-lock.js +53 -0
  270. package/dist/tasks/scheduler-sync.js +368 -679
  271. package/dist/tasks/source/parse-task-source.js +55 -9
  272. package/dist/tasks/source/task-source-v3-frozen.js +3 -4
  273. package/dist/tasks/source/task-to-v4.js +464 -88
  274. package/dist/workflows/authoring/authoring.js +3 -12
  275. package/dist/workflows/compile.js +211 -0
  276. package/dist/workflows/concurrency-policy.js +13 -74
  277. package/dist/workflows/exec/child-invocation.js +3 -17
  278. package/dist/workflows/exec/child-workflow.js +32 -141
  279. package/dist/workflows/exec/dispatch-redaction.js +13 -53
  280. package/dist/workflows/exec/environment.js +98 -0
  281. package/dist/workflows/exec/exec-unit.js +33 -140
  282. package/dist/workflows/exec/frozen-judge.js +7 -59
  283. package/dist/workflows/exec/native-executor.js +82 -341
  284. package/dist/workflows/exec/param-secrets.js +29 -47
  285. package/dist/workflows/exec/run-workflow.js +154 -387
  286. package/dist/workflows/exec/scheduler.js +9 -36
  287. package/dist/workflows/exec/step-work.js +127 -430
  288. package/dist/workflows/exec/unit-dispatch.js +11 -63
  289. package/dist/workflows/exec/unit-writer.js +8 -52
  290. package/dist/workflows/exec/worktree.js +39 -273
  291. package/dist/workflows/freeze/child-output-references.js +4 -15
  292. package/dist/workflows/freeze/environment.js +99 -92
  293. package/dist/workflows/freeze/freeze.js +172 -0
  294. package/dist/workflows/freeze/step-values.js +19 -21
  295. package/dist/workflows/freeze/targets/child-workflow.js +23 -92
  296. package/dist/workflows/freeze/targets/command.js +10 -33
  297. package/dist/workflows/freeze/targets/script.js +5 -12
  298. package/dist/workflows/freeze/targets/shell.js +3 -6
  299. package/dist/workflows/freeze/targets/task.js +25 -80
  300. package/dist/workflows/freeze/task-bindings.js +20 -67
  301. package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
  302. package/dist/workflows/ir/params.js +6 -51
  303. package/dist/workflows/ir/plan-hash.js +2 -34
  304. package/dist/workflows/parser.js +140 -43
  305. package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
  306. package/dist/workflows/renderer.js +36 -69
  307. package/dist/workflows/resource-limits.js +12 -120
  308. package/dist/workflows/runtime/agent-identity.js +8 -40
  309. package/dist/workflows/runtime/run-outputs.js +3 -6
  310. package/dist/workflows/runtime/run-plan.js +316 -0
  311. package/dist/workflows/runtime/runs.js +48 -200
  312. package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
  313. package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
  314. package/dist/workflows/validate-summary.js +2 -7
  315. package/docs/integration/bundling-akm.md +49 -42
  316. package/docs/migration/README.md +1 -0
  317. package/docs/migration/release-notes/0.9.17.md +43 -0
  318. package/docs/migration/v0.9.1-to-v0.9.2.md +23 -7
  319. package/docs/reference/cli.md +232 -135
  320. package/docs/reference/configuration.md +71 -57
  321. package/docs/reference/data-and-telemetry.md +20 -21
  322. package/docs/reference/tasks.md +105 -39
  323. package/docs/reference/workflow-schema.md +14 -18
  324. package/docs/reference/workflows.md +6 -9
  325. package/package.json +1 -1
  326. package/schemas/akm-config.json +115 -738
  327. package/schemas/akm-workflow.json +1 -0
  328. package/dist/assets/improve-strategies/graph-refresh.json +0 -15
  329. package/dist/assets/prompts/contradiction-judge.md +0 -33
  330. package/dist/assets/prompts/graph-extract-system.md +0 -1
  331. package/dist/assets/prompts/graph-extract-user-prompt.md +0 -35
  332. package/dist/assets/prompts/metadata-enhance-system.md +0 -1
  333. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +0 -4
  334. package/dist/commands/health/advisories.js +0 -150
  335. package/dist/commands/health/metrics.js +0 -329
  336. package/dist/commands/health/surfaces.js +0 -102
  337. package/dist/commands/improve/anti-collapse.js +0 -83
  338. package/dist/commands/improve/collapse-detector.js +0 -432
  339. package/dist/commands/improve/consolidate/eligibility.js +0 -48
  340. package/dist/commands/improve/consolidate/merge.js +0 -149
  341. package/dist/commands/improve/distill/promote-memory.js +0 -291
  342. package/dist/commands/improve/distill/quality-gate.js +0 -337
  343. package/dist/commands/improve/eval-cases.js +0 -52
  344. package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
  345. package/dist/commands/improve/proposal-envelope.js +0 -31
  346. package/dist/commands/improve/run-context.js +0 -123
  347. package/dist/commands/improve/shared.js +0 -31
  348. package/dist/commands/improve/source-identity.js +0 -28
  349. package/dist/commands/improve/triage.js +0 -96
  350. package/dist/commands/proposal/drain-policies.js +0 -151
  351. package/dist/commands/sources/update-transaction.js +0 -220
  352. package/dist/core/action-contributors.js +0 -28
  353. package/dist/core/config/config-version-shim.js +0 -101
  354. package/dist/core/fs-txn.js +0 -405
  355. package/dist/core/lexical-score.js +0 -25
  356. package/dist/core/maintenance-barrier.js +0 -167
  357. package/dist/execution/executable-identity.js +0 -105
  358. package/dist/execution/guarded-source.js +0 -427
  359. package/dist/indexer/db/graph-db.js +0 -444
  360. package/dist/indexer/graph/graph-boost.js +0 -427
  361. package/dist/indexer/graph/graph-dedup.js +0 -95
  362. package/dist/indexer/graph/graph-extraction.js +0 -1108
  363. package/dist/indexer/search/name-match.js +0 -35
  364. package/dist/indexer/search/ranking-contributors.js +0 -515
  365. package/dist/indexer/search/ranking-types.js +0 -4
  366. package/dist/indexer/walk/project-context.js +0 -192
  367. package/dist/integrations/agent/execution-cascade.js +0 -566
  368. package/dist/integrations/agent/execution-definitions.js +0 -202
  369. package/dist/integrations/agent/execution-lowering.js +0 -841
  370. package/dist/integrations/agent/execution-preparation.js +0 -98
  371. package/dist/integrations/agent/inline-execution.js +0 -74
  372. package/dist/llm/graph-extract.js +0 -728
  373. package/dist/llm/metadata-enhance.js +0 -96
  374. package/dist/registry/create-provider-registry.js +0 -29
  375. package/dist/registry/pinned-request-helper.js +0 -247
  376. package/dist/registry/pinned-transport.js +0 -717
  377. package/dist/sources/providers/index.js +0 -14
  378. package/dist/storage/engines/sqlite-migrations.js +0 -271
  379. package/dist/storage/repositories/canaries-repository.js +0 -107
  380. package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
  381. package/dist/storage/repositories/registry-cache.js +0 -113
  382. package/dist/tasks/scheduler-sync-preview.js +0 -52
  383. package/dist/tasks/source/task-to-v3.js +0 -507
  384. package/dist/workflows/freeze/resolve-steps.js +0 -86
  385. package/dist/workflows/freeze/source-freeze.js +0 -64
  386. package/dist/workflows/ir/compile.js +0 -321
  387. package/dist/workflows/ir/environment-v4.js +0 -330
  388. package/dist/workflows/ir/freeze-v4.js +0 -153
  389. package/dist/workflows/ir/schema-v4.js +0 -745
  390. package/dist/workflows/ir/schema.js +0 -354
  391. package/dist/workflows/program/schema.js +0 -77
  392. package/dist/workflows/runtime/checkin.js +0 -57
  393. package/dist/workflows/runtime/plan-classifier.js +0 -196
  394. package/dist/workflows/runtime/unit-checkin.js +0 -45
  395. package/dist/workflows/runtime/unit-phases.js +0 -20
  396. package/dist/workflows/schema.js +0 -4
  397. package/dist/workflows/source-ir/compile.js +0 -200
  398. package/dist/workflows/source-ir/program.js +0 -50
  399. package/dist/workflows/source-ir/result.js +0 -26
  400. package/dist/workflows/source-ir/schema.js +0 -786
  401. package/dist/workflows/source-ir/triggers.js +0 -79
  402. package/dist/workflows/source-ir/uses.js +0 -40
  403. package/dist/workflows/validator.js +0 -60
@@ -20,7 +20,7 @@ function renderTable(headers, rows) {
20
20
  *
21
21
  * Columns: ts | ok | actions | refl_ok/fail/cd/skip |
22
22
  * distill_q/llm-fail/qrej/cfg/skip | cons_proc/promo/merge/del |
23
- * mem_cons/written/skip | graph_f/e/r | orphans | lint_f/fl
23
+ * mem_cons/written/skip | orphans | lint_f/fl
24
24
  */
25
25
  export function renderRunsDetailMd(runs) {
26
26
  const headers = [
@@ -32,7 +32,6 @@ export function renderRunsDetailMd(runs) {
32
32
  "distill_q/llm-fail/judge/validator/cfg/skip",
33
33
  "cons_proc/promo/merge/del",
34
34
  "mem_cons/written/skip",
35
- "graph_f/e/r",
36
35
  "orphans",
37
36
  "lint_f/fl",
38
37
  "result_status",
@@ -50,7 +49,6 @@ export function renderRunsDetailMd(runs) {
50
49
  r.actions.distill.skipped +
51
50
  r.actions.memoryPrune +
52
51
  r.actions.memoryInference +
53
- r.actions.graphExtraction +
54
52
  r.actions.error;
55
53
  return [
56
54
  r.startedAt,
@@ -61,7 +59,6 @@ export function renderRunsDetailMd(runs) {
61
59
  `${r.actions.distill.queued}/${r.actions.distill.llmFailed}/${r.actions.distill.judgeRejected}/${r.actions.distill.validatorRejected}/${r.actions.distill.configDisabled}/${r.actions.distill.skipped}`,
62
60
  `${r.consolidation.processed}/${r.consolidation.promoted}/${r.consolidation.merged}/${r.consolidation.deleted}`,
63
61
  `${r.memoryInference.considered}/${r.memoryInference.written}/${r.memoryInference.skippedNoFacts}`,
64
- `${r.graphExtraction.extractedFiles}/${r.graphExtraction.entities}/${r.graphExtraction.relations}`,
65
62
  String(r.orphansPurged),
66
63
  `${r.lintFixed}/${r.lintFlagged}`,
67
64
  r.resultStatus ?? "valid",
@@ -81,8 +78,6 @@ export function renderWindowCompareMd(windows, deltas) {
81
78
  const badIfPositive = new Set([
82
79
  "improve.actions.reflect.failed",
83
80
  "improve.actions.distill.llmFailed",
84
- "improve.graphExtraction.failures",
85
- "improve.graphExtraction.nonArrayBatchFailures",
86
81
  "improve.wallTime.medianMs",
87
82
  "improve.wallTime.p95Ms",
88
83
  "improve.memoryInference.skippedNoFacts",
@@ -63,6 +63,46 @@ import { isExactSemver, isSemverRange, maxSatisfying, satisfiesRange } from "../
63
63
  function claudePluginsDir() {
64
64
  return process.env.AKM_CLAUDE_PLUGINS_DIR ?? path.join(os.homedir(), ".claude", "plugins");
65
65
  }
66
+ /**
67
+ * Root of OpenCode's package cache, same override pattern as
68
+ * {@link claudePluginsDir} (`AKM_OPENCODE_CACHE_DIR` for tests).
69
+ * The OpenCode plugin (`akm-opencode`) bundles its own `akm-cli` under
70
+ * `packages/akm-opencode/node_modules/akm-cli` and runs it in-process,
71
+ * sharing the host's databases with every other akm install — its version
72
+ * lag matters the same way a stale Claude plugin's does.
73
+ */
74
+ function opencodeCacheDir() {
75
+ return process.env.AKM_OPENCODE_CACHE_DIR ?? path.join(os.homedir(), ".cache", "opencode");
76
+ }
77
+ /**
78
+ * Read the OpenCode plugin's bundled `akm-cli` version from its
79
+ * `package.json` — never executed, just parsed, mirroring
80
+ * {@link detectInstalledPlugins}'s manifest read. `undefined` when the
81
+ * OpenCode plugin, or its bundled akm-cli, is not installed.
82
+ */
83
+ function detectOpencodeBundledAkmVersion(cacheRoot) {
84
+ const pkgPath = path.join(cacheRoot, "packages", "akm-opencode", "node_modules", "akm-cli", "package.json");
85
+ try {
86
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
87
+ return typeof pkg.version === "string" ? pkg.version : undefined;
88
+ }
89
+ catch {
90
+ return undefined;
91
+ }
92
+ }
93
+ function buildOpencodeBundledAdvisory(bundledVersion, cliVersion) {
94
+ const stale = bundledVersion !== cliVersion;
95
+ return {
96
+ name: "opencode-plugin-version",
97
+ kind: "deterministic",
98
+ status: stale ? "warn" : "pass",
99
+ confidence: "high",
100
+ message: stale
101
+ ? `OpenCode's bundled akm-cli is v${bundledVersion}, but the running CLI is v${cliVersion} — it shares the same databases in-process; update the OpenCode plugin.`
102
+ : `OpenCode's bundled akm-cli matches the running v${cliVersion}.`,
103
+ evidence: { bundledVersion, cliVersion },
104
+ };
105
+ }
66
106
  /**
67
107
  * Scan `<pluginsRoot>/cache/<marketplace>/akm/<version>/` for every
68
108
  * `akm` plugin cache entry, picking the highest cached version per
@@ -165,14 +205,24 @@ const realListRemoteTags = (marketplaceDir) => {
165
205
  return [...new Set(tags)];
166
206
  };
167
207
  /**
168
- * Build one `plugin-version` advisory per detected `akm` harness plugin.
169
- * Returns `[]` when no plugin is installed — the benign, common case.
208
+ * Build one `plugin-version` advisory per detected `akm` harness plugin,
209
+ * plus one `opencode-plugin-version` advisory when the
210
+ * OpenCode plugin's bundled `akm-cli` is found — it shares the host's
211
+ * databases in-process, so its lag matters the same way a stale Claude
212
+ * plugin's does. Returns `[]` when neither is installed — the benign,
213
+ * common case.
170
214
  */
171
215
  export function collectPluginStalenessAdvisories(options) {
172
216
  const pluginsRoot = options.pluginsRoot ?? claudePluginsDir();
173
217
  const listRemoteTags = options.listRemoteTags ?? realListRemoteTags;
174
218
  const plugins = detectInstalledPlugins(pluginsRoot);
175
- return plugins.map((plugin) => buildAdvisory(plugin, options.cliVersion, pluginsRoot, listRemoteTags));
219
+ const results = plugins.map((plugin) => buildAdvisory(plugin, options.cliVersion, pluginsRoot, listRemoteTags));
220
+ const opencodeCacheRoot = options.opencodeCacheRoot ?? opencodeCacheDir();
221
+ const bundledVersion = detectOpencodeBundledAkmVersion(opencodeCacheRoot);
222
+ if (bundledVersion !== undefined) {
223
+ results.push(buildOpencodeBundledAdvisory(bundledVersion, options.cliVersion));
224
+ }
225
+ return results;
176
226
  }
177
227
  function buildAdvisory(plugin, cliVersion, pluginsRoot, listRemoteTags) {
178
228
  const pluginRef = `${plugin.pluginName}@${plugin.marketplace}`;
@@ -2,7 +2,7 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  /**
5
- * `akm health` document renderers, registered rather than intercepted (D7).
5
+ * `akm health` document renderers.
6
6
  *
7
7
  * Both handlers are **pure functions of the shaped result**. Everything the
8
8
  * rich report needs — per-run rows, window-compare deltas, the pending
@@ -13,12 +13,19 @@
13
13
  * renderer to call order and made the command branch on the output format to
14
14
  * know when to bind it. Putting the data in the envelope removed both.
15
15
  *
16
+ * The Markdown renderer registers into the shared per-command registry (D7,
17
+ * `../../output/render-registry.ts`) alongside every other command's `--format
18
+ * md` renderer. The HTML renderer does not: `health` was, and remains, the
19
+ * only command with a bespoke HTML report, so `cli/shared.ts` calls
20
+ * {@link renderHealthHtml} directly instead of going through a registry with
21
+ * exactly one possible registrant.
22
+ *
16
23
  * Returning `null` falls through to the generic renderer, so a result without
17
24
  * the report dataset still renders — generically — instead of erroring or
18
25
  * emitting an empty table.
19
26
  */
20
27
  import { renderHtml, resolveTemplatePath } from "../../output/html-render.js";
21
- import { registerHtmlRenderer, registerMdRenderer } from "../../output/render-registry.js";
28
+ import { registerMdRenderer } from "../../output/render-registry.js";
22
29
  import { buildHealthHtmlReplacements } from "./html-report.js";
23
30
  import { renderRunsDetailMd, renderWindowCompareMd } from "./md-report.js";
24
31
  function isHealthResult(value) {
@@ -34,7 +41,8 @@ registerMdRenderer("health", (result) => {
34
41
  return renderRunsDetailMd(result.runs);
35
42
  return null;
36
43
  });
37
- registerHtmlRenderer("health", (result) => {
44
+ /** `--format html` renderer for `akm health`, called directly from `cli/shared.ts`. */
45
+ export function renderHealthHtml(result) {
38
46
  if (!isHealthResult(result) || !result.report)
39
47
  return null;
40
48
  return renderHtml(resolveTemplatePath("health"), buildHealthHtmlReplacements(result, {
@@ -44,4 +52,4 @@ registerHtmlRenderer("health", (result) => {
44
52
  proposals: result.report.pendingProposals,
45
53
  deltas: result.deltas,
46
54
  }));
47
- });
55
+ }
@@ -64,11 +64,9 @@ function coercePct(raw) {
64
64
  function reshapeRun(r) {
65
65
  const cons = r.consolidation;
66
66
  const mi = r.memoryInference;
67
- const ge = r.graphExtraction;
68
67
  const wall = r.wallTimeMs || 0;
69
68
  const consMs = cons.durationMs || 0;
70
69
  const miMs = mi.durationMs || 0;
71
- const geMs = ge.durationMs || 0;
72
70
  return {
73
71
  id: r.id,
74
72
  resultStatus: r.resultStatus ?? "valid",
@@ -79,31 +77,15 @@ function reshapeRun(r) {
79
77
  completedAt: r.completedAt,
80
78
  wallTimeMs: wall,
81
79
  ok: r.ok,
82
- mode: r.scope.mode,
83
80
  consDurationMs: consMs,
84
81
  miDurationMs: miMs,
85
- geDurationMs: geMs,
86
- otherMs: Math.max(0, wall - consMs - miMs - geMs),
87
- consRan: cons.ran,
82
+ otherMs: Math.max(0, wall - consMs - miMs),
88
83
  promoted: cons.promoted,
89
84
  merged: cons.merged,
90
85
  deleted: cons.deleted,
91
86
  contradicted: cons.contradicted,
92
87
  judgedNoAction: cons.judgedNoAction,
93
- processed: cons.processed,
94
- failedChunks: cons.failedChunks,
95
- totalChunks: cons.totalChunks,
96
88
  miWritten: mi.written,
97
- miConsidered: mi.considered,
98
- miYieldRate: mi.yieldRate,
99
- miCacheHits: mi.cacheHits,
100
- geEntities: ge.entities,
101
- geRelations: ge.relations,
102
- geCacheHitRate: ge.cacheHitRate,
103
- geFailures: ge.failures,
104
- distillSkipped: r.actions.distill.skipped,
105
- distillQueued: r.actions.distill.queued,
106
- distillLlmFailed: r.actions.distill.llmFailed,
107
89
  distillByReason: r.actions.distill.skippedByReason,
108
90
  reflectOk: r.actions.reflect.ok,
109
91
  reflectFailed: r.actions.reflect.failed,
@@ -111,9 +93,6 @@ function reshapeRun(r) {
111
93
  eligible: r.memorySummary.eligible,
112
94
  lintFlagged: r.lintFlagged,
113
95
  lintFixed: r.lintFixed,
114
- reflectsWithErrorContext: r.reflectsWithErrorContext,
115
- orphansPurged: r.orphansPurged,
116
- evalCasesWritten: r.evalCasesWritten,
117
96
  };
118
97
  }
119
98
  function compareRuns(a, b) {
@@ -136,16 +115,11 @@ function classify(deltas, metricKeys, lowerIsBetter = false) {
136
115
  }
137
116
  function buildTrend(deltas) {
138
117
  const decisionQuality = classify(deltas, ["improve.memoryInference.yieldRate", "improve.consolidation.promoted"]);
139
- const outputVolume = classify(deltas, [
140
- "improve.consolidation.promoted",
141
- "improve.memoryInference.written",
142
- "improve.sessionExtraction.proposalsCreated",
143
- ]);
144
- const failures = classify(deltas, ["improve.graphExtraction.failures"], true);
118
+ const outputVolume = classify(deltas, ["improve.consolidation.promoted", "improve.memoryInference.written"]);
145
119
  const latency = classify(deltas, ["improve.wallTime.medianMs", "improve.wallTime.p95Ms"], true);
146
- const score = [decisionQuality, outputVolume, failures, latency].reduce((acc, d) => acc + (d === "up" ? 1 : d === "down" ? -1 : 0), 0);
120
+ const score = [decisionQuality, outputVolume, latency].reduce((acc, d) => acc + (d === "up" ? 1 : d === "down" ? -1 : 0), 0);
147
121
  const overall = score >= 1 ? "improving" : score <= -1 ? "degrading" : "mixed";
148
- return { decisionQuality, outputVolume, failures, latency, overall };
122
+ return { decisionQuality, outputVolume, latency, overall };
149
123
  }
150
124
  function readSemSearch(advisories) {
151
125
  const check = advisories.find((a) => a.name === "semantic-search-runtime");
@@ -204,21 +178,8 @@ function buildAggregatesPhase(result, runsPhase) {
204
178
  const improve = result.improve;
205
179
  const cons = improve.consolidation;
206
180
  const mi = improve.memoryInference;
207
- const ge = improve.graphExtraction;
208
181
  const wallTime = improve.wallTime;
209
- // WS-5: perf telemetry, coverage, and degradation metrics.
210
- const perf = improve.perfTelemetry ?? {
211
- dedupPoolSize: 0,
212
- llmPoolSize: 0,
213
- embedMs: 0,
214
- embedCacheHits: 0,
215
- embedCacheMisses: 0,
216
- overBudgetRuns: 0,
217
- runsWithTelemetry: 0,
218
- };
219
182
  const coverage = improve.coverage;
220
- const degradation = improve.degradation;
221
- const minting = improve.enrichmentMinting;
222
183
  // #576: real per-stage LLM token/time accounting (replaces the GPU-time
223
184
  // proxy). Optional-guarded so reports built from older health JSON without
224
185
  // the aggregate still render.
@@ -241,12 +202,8 @@ function buildAggregatesPhase(result, runsPhase) {
241
202
  return {
242
203
  consolidation: cons,
243
204
  memoryInference: mi,
244
- graphExtraction: ge,
245
205
  wallTime,
246
- perf,
247
206
  coverage,
248
- degradation,
249
- minting,
250
207
  llm,
251
208
  memorySummary: improve.memorySummary,
252
209
  includedResultRows: improve.resultRows?.included ?? totalRuns,
@@ -344,7 +301,7 @@ function groupProposalsBySource(proposals) {
344
301
  }
345
302
  /** Summary table rows: the base metric set + the WS-5 coverage/minting/perf/degradation extensions, when present. */
346
303
  function buildSummaryRows(aggregates, trend) {
347
- const { consolidation: cons, graphExtraction: ge, wallTime, llm, coverage, minting, perf, degradation } = aggregates;
304
+ const { consolidation: cons, wallTime, llm, coverage } = aggregates;
348
305
  const summaryRows = [
349
306
  ["Task fail rate", aggregates.taskFailRate, "flat"],
350
307
  ["Agent fail rate", aggregates.agentFailRate, "flat"],
@@ -367,8 +324,6 @@ function buildSummaryRows(aggregates, trend) {
367
324
  "Candidates reviewed but intentionally left unchanged (the 'judgedNoAction' field).",
368
325
  ],
369
326
  ["Chunk failure", aggregates.chunkFail, "flat"],
370
- ["Graph entities", num(ge.entities), "up"],
371
- ["Graph relations", num(ge.relations), "up"],
372
327
  [
373
328
  "Stash derived",
374
329
  num(aggregates.memorySummary.derived),
@@ -389,80 +344,19 @@ function buildSummaryRows(aggregates, trend) {
389
344
  "Tokens spent on model reasoning/thinking, billed separately from prompt and completion.",
390
345
  ],
391
346
  ["LLM wall time", fmtMs(llm.totalDurationMs), trend.latency],
392
- ];
393
- // WS-5: denominator-fixed coverage rows (only when we have real data).
394
- if (coverage && !Number.isNaN(coverage.rate)) {
395
- summaryRows.push([
396
- "Coverage rate",
397
- pct(coverage.rate, 1),
398
- "flat",
399
- "Distinct accepted refs / total stash assets (denominator-fixed). Shows what fraction of the corpus has been touched.",
400
- ], [
401
- "Eligible fraction",
402
- pct(coverage.eligibleFraction, 1),
403
- "flat",
404
- "Eligible assets / total stash assets. Fraction the improve pipeline actively considers.",
405
- ], [
347
+ [
406
348
  "Coverage accepted",
407
349
  num(coverage.acceptedProposals),
408
350
  "flat",
409
- "Total accepted proposals in the window (raw volume — includes repeated rewrites of the same asset).",
410
- ], [
411
- "Churn ratio",
412
- Number.isFinite(coverage.churnRatio) ? num(coverage.churnRatio) : "—",
413
- Number.isFinite(coverage.churnRatio) && coverage.churnRatio > 1.5 ? "down" : "flat",
414
- "Accepted proposals / distinct refs touched. >1.5 = the loop is repeatedly rewriting the same assets (churn, not coverage).",
415
- ]);
416
- }
417
- // Enrichment-vs-minting policy rollup (reporting-only).
418
- if (minting && Number.isFinite(minting.share)) {
419
- summaryRows.push([
420
- "Enrichment-lane minted share",
421
- pct(minting.share, 1),
422
- minting.share > 0.05 ? "down" : "flat",
423
- `New assets minted by enrichment lanes / their accepted total (${minting.minted} minted vs ${minting.updated} updated). Enrichment lanes are ratified to edit existing assets only; WARN >5%, FAIL >15%.`,
424
- ]);
425
- }
426
- // WS-5: perf telemetry rows (only when at least one run reported telemetry).
427
- if (perf.runsWithTelemetry > 0) {
428
- const embedCacheTotal = perf.embedCacheHits + perf.embedCacheMisses;
429
- const embedCacheHitRate = embedCacheTotal > 0 ? pct(perf.embedCacheHits / embedCacheTotal, 1) : "—";
430
- summaryRows.push([
431
- "Embed cache hit rate",
432
- embedCacheHitRate,
433
- "flat",
434
- "Fraction of embedding lookups served from cache (>95% is healthy). Aggregated across WS-5 runs.",
435
- ], [
436
- "Embed wall time",
437
- fmtMs(perf.embedMs),
438
- "flat",
439
- "Cumulative embedding wall-clock time across consolidation runs in the window.",
440
- ], [
441
- "Dedup pool size",
442
- num(perf.dedupPoolSize),
443
- "flat",
444
- "Memory pool size after incremental narrowing, before the limit cap. WS-5 perf telemetry.",
445
- ], [
446
- "Over-budget consolidation runs",
447
- String(perf.overBudgetRuns),
448
- perf.overBudgetRuns > 0 ? "down" : "flat",
449
- "Runs where consolidation alone exceeded the total run budget (estimatedBudgetFractionUsed > 1.0).",
450
- ]);
451
- }
452
- // WS-5: degradation metrics rows.
453
- if (degradation) {
454
- summaryRows.push([
455
- "Corpus diversity (Gini)",
456
- num(degradation.corpusCentroidDistance),
457
- degradation.entrenchmentFlagged || degradation.salienceUniformityFlagged ? "down" : "flat",
458
- `Gini coefficient of positive retrieval_salience values across ${degradation.retrievalSalienceSampleSize} resolvable assets. Two-tailed: >0.35 = entrenchment risk; <0.08 = collapsed toward uniform.`,
459
- ], [
460
- "Merge fidelity contradiction rate",
461
- pct(degradation.mergeFidelityContradictionRate, 1),
351
+ "Accepted proposals in the window (raw volume — includes repeated rewrites of the same asset).",
352
+ ],
353
+ [
354
+ "Distinct assets touched",
355
+ num(coverage.distinctRefs),
462
356
  "flat",
463
- "Fraction of consolidated proposals that involved a contradiction, from consolidation result envelopes.",
464
- ]);
465
- }
357
+ "Distinct assets touched by accepted proposals in the window.",
358
+ ],
359
+ ];
466
360
  return summaryRows;
467
361
  }
468
362
  /**
@@ -2,28 +2,13 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  /**
5
- * Lanes ratified as ENRICHMENT-ONLY: they may propose edits to existing
6
- * assets (metadata, relations, content refresh) but must not mint new ones.
7
- * New-asset generation belongs to the signal-gated minting lanes
8
- * (extract/distill/memory-inference).
9
- */
10
- export const ENRICHMENT_LANES = ["proactive", "high-salience", "signal-delta"];
11
- /** Minted share of enrichment-lane accepts that triggers a WARN advisory. */
12
- export const ENRICHMENT_MINTED_WARN_SHARE = 0.05;
13
- /** Minted share of enrichment-lane accepts that triggers a FAIL advisory. */
14
- export const ENRICHMENT_MINTED_FAIL_SHARE = 0.15;
15
- /**
16
- * Cron task failure rate at or above which the `task-fail-rate` health advisory
17
- * warns. 0.05 (5%) is the SAME threshold the HTML report already applies as its
18
- * fail-rate pass/warn cutoff (`failOk = taskFailRate < 0.05` in
19
- * src/commands/health/html-report.ts) — this constant makes it the single
20
- * source so the advisory and the rendered badge cannot drift.
5
+ * Cron task failure rate at or above which the `task-fail-rate` advisory
6
+ * warns; also the HTML report's fail-rate badge cutoff, so the two cannot drift.
21
7
  */
22
8
  export const TASK_FAIL_RATE_WARN = 0.05;
23
9
  /**
24
10
  * Minimum task_history rows a single task_id needs in the window before its
25
- * per-task fail rate feeds the `task-fail-rate` advisory's "worst single
26
- * task" signal. Guards against a rarely-run task (e.g. 1 failure out of 1
27
- * run) reading as a 100% fail rate off a single noisy sample.
11
+ * own fail rate feeds `task-fail-rate` — a task run once and failed once is
12
+ * not a 100% signal.
28
13
  */
29
14
  export const MIN_ROWS_FOR_WORST_TASK_FAIL_RATE = 5;
@@ -3,17 +3,14 @@
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  /**
5
5
  * Window handling for `akm health`: `--window-compare` / `--windows` parsing,
6
- * per-window metric assembly, log-backing partition, and delta computation.
6
+ * per-window metric assembly, and delta computation between two windows.
7
7
  */
8
- import fs from "node:fs";
9
8
  import { UsageError } from "../../core/errors.js";
10
9
  import { readEvents } from "../../core/events.js";
11
- import { buildTaskRunId, getLoggedRunIds } from "../../core/logs-db.js";
12
10
  import { DURATION_UNITS, parseDuration } from "../../core/time.js";
13
11
  import { queryTaskHistory } from "../../storage/repositories/task-history-repository.js";
14
- import { buildImproveSkipSummary, computeWallTimeStats, countAgentFailureReasons, isAgentTaskHistoryRow, roundRate, summarizeImproveCompleted, summarizeImproveRuns, taskFailureDetail, } from "./improve-metrics.js";
12
+ import { buildImproveSkipSummary, computeWallTimeStats, computeWindowProposalCoverage, countAgentFailureReasons, isAgentTaskHistoryRow, roundRate, summarizeImproveRuns, taskFailureDetail, } from "./improve-metrics.js";
15
13
  import { readLlmUsageAggregate } from "./llm-usage.js";
16
- import { computeDegradationMetrics, computeDenominatorFixedCoverage } from "./metrics.js";
17
14
  import { buildPerRunSummaries } from "./task-runs.js";
18
15
  import { ACTIVE_RUN_WARN_MS, IMPROVE_COMPLETED_EVENT, } from "./types.js";
19
16
  /**
@@ -71,28 +68,29 @@ export function parseWindowSpec(raw) {
71
68
  ...(fields.until ? { until: fields.until } : {}),
72
69
  };
73
70
  }
74
- /** Hard-coded list of "interesting" metric paths for window-compare deltas. */
71
+ /**
72
+ * Metric paths diffed between the earliest and latest window (`deltas` in the
73
+ * JSON result; the delta column of `--format md`). Paths are relative to a
74
+ * {@link WindowResult}.
75
+ */
75
76
  export const INTERESTING_DELTA_PATHS = [
76
77
  "improve.actions.reflect.failed",
77
- "improve.actions.reflect.guardRejected",
78
- "improve.actions.distill.llmFailed",
79
78
  "improve.actions.distill.queued",
80
- "improve.actions.distill.deferred",
79
+ "improve.actions.distill.llmFailed",
81
80
  "improve.consolidation.promoted",
82
81
  "improve.memoryInference.written",
83
82
  "improve.memoryInference.yieldRate",
84
83
  "improve.memoryInference.skippedNoFacts",
85
- "improve.memoryInference.htmlErrorCount",
86
- "improve.graphExtraction.cacheHitRate",
87
- "improve.graphExtraction.failures",
88
- "improve.graphExtraction.htmlErrors",
89
- "improve.graphExtraction.nonArrayBatchFailures",
90
- "improve.sessionExtraction.sessionsScanned",
91
- "improve.sessionExtraction.proposalsCreated",
92
84
  "improve.autoAccept.promoted",
93
85
  "improve.autoAccept.validationFailed",
86
+ "improve.coverage.acceptedProposals",
87
+ "improve.coverage.distinctRefs",
94
88
  "improve.wallTime.medianMs",
95
89
  "improve.wallTime.p95Ms",
90
+ "metrics.llmUsage.calls",
91
+ "metrics.llmUsage.totalTokens",
92
+ "metrics.llmUsage.totalDurationMs",
93
+ "metrics.llmUsage.failures",
96
94
  ];
97
95
  export function readNumericPath(obj, path) {
98
96
  const parts = path.split(".");
@@ -123,74 +121,66 @@ export function computeDeltas(first, last) {
123
121
  return out;
124
122
  }
125
123
  /**
126
- * Partition task_history rows into "should have a log" (non-null log_path) and
127
- * "log is actually backed". A run counts as backed when logs.db holds rows for
128
- * its run_id (#579 — the DB is the primary record); rows written before logs.db
129
- * existed fall back to the transitional on-disk file check. `logsDb` may be
130
- * undefined when logs.db could not be opened — then only the file check runs.
124
+ * Task-history-derived rates, shared by the main health path
125
+ * (`health.ts`'s `gatherTaskHistoryPhase`) and {@link buildWindowMetrics}
126
+ * below — previously computed twice with the only difference being whether
127
+ * the caller had already bounded `taskRows` by an `until`. Pure projection of
128
+ * already-queried rows; callers own the `since`/`until` query.
131
129
  */
132
- export function partitionLogBackedRows(taskRows, logsDb) {
133
- const withLogs = taskRows.filter((row) => row.log_path !== null);
134
- const loggedRunIds = logsDb
135
- ? getLoggedRunIds(logsDb, withLogs.map((row) => buildTaskRunId(row.task_id, row.started_at)))
136
- : new Set();
137
- const backed = withLogs.filter((row) => loggedRunIds.has(buildTaskRunId(row.task_id, row.started_at)) ||
138
- (row.log_path !== null && fs.existsSync(row.log_path)));
139
- return { withLogs, backed };
140
- }
141
- export function buildWindowMetrics(db, stateDbPath, since, until, now = () => Date.now(), logsDb) {
142
- const taskRows = queryTaskHistory(db, { since }).filter((row) => {
143
- const startMs = new Date(row.started_at).getTime();
144
- const untilMs = new Date(until).getTime();
145
- return !Number.isFinite(untilMs) || startMs < untilMs;
146
- });
147
- const { withLogs: taskRowsWithLogs, backed: existingLogRows } = partitionLogBackedRows(taskRows, logsDb);
130
+ export function computeTaskWindowRates(taskRows, now) {
148
131
  const failedTaskRows = taskRows.filter((row) => row.status === "failed");
149
132
  const activeRows = taskRows.filter((row) => row.status === "active" && row.completed_at === null);
150
- const stuckActiveRuns = activeRows.filter((row) => now() - new Date(row.started_at).getTime() > ACTIVE_RUN_WARN_MS).length;
133
+ const stuckActiveRows = activeRows.filter((row) => now() - new Date(row.started_at).getTime() > ACTIVE_RUN_WARN_MS);
151
134
  const agentRows = taskRows.filter((row) => isAgentTaskHistoryRow(row));
152
135
  const agentFailures = agentRows.filter((row) => {
153
136
  const detail = taskFailureDetail(row);
154
137
  return typeof detail?.reason === "string" && detail.reason.length > 0;
155
138
  });
156
- const logBackingRate = taskRowsWithLogs.length === 0 ? 1 : existingLogRows.length / taskRowsWithLogs.length;
157
- const taskFailRate = taskRows.length === 0 ? 0 : failedTaskRows.length / taskRows.length;
158
- const agentFailureRate = agentRows.length === 0 ? 0 : agentFailures.length / agentRows.length;
159
- const agentFailureReasonCounts = countAgentFailureReasons(agentFailures);
160
- const improveInvoked = readEvents({ since, type: "improve_invoked" }, { dbPath: stateDbPath }).events.filter((event) => new Date(event.ts ?? since).getTime() < new Date(until).getTime()).length;
161
- const improveCompletedEvents = readEvents({ since, type: IMPROVE_COMPLETED_EVENT }, { dbPath: stateDbPath }).events.filter((event) => new Date(event.ts ?? since).getTime() < new Date(until).getTime());
162
- const improveSkippedEvents = readEvents({ since, type: "improve_skipped" }, { dbPath: stateDbPath }).events.filter((event) => new Date(event.ts ?? since).getTime() < new Date(until).getTime());
163
- const eventsMetrics = summarizeImproveCompleted(improveCompletedEvents);
164
- const { metrics: improveSummary, runCount } = summarizeImproveRuns(db, since, until);
165
- improveSummary.invoked = improveInvoked;
166
- improveSummary.completed = eventsMetrics.completed;
167
- const skipSummary = buildImproveSkipSummary(improveSkippedEvents);
168
- improveSummary.skipped = skipSummary.skipped;
169
- improveSummary.skipReasons = skipSummary.skipReasons;
170
- // Preserve the per-phase aggregation computed by summarizeImproveRuns and
171
- // derive top-level wall times from the same improve-runs window so counts
172
- // and percentiles stay aligned with per-run reporting.
139
+ return {
140
+ taskFailRate: taskRows.length === 0 ? 0 : failedTaskRows.length / taskRows.length,
141
+ agentFailureRate: agentRows.length === 0 ? 0 : agentFailures.length / agentRows.length,
142
+ agentFailureReasonCounts: countAgentFailureReasons(agentFailures),
143
+ stuckActiveRuns: stuckActiveRows.length,
144
+ stuckActiveRows,
145
+ };
146
+ }
147
+ /**
148
+ * Improve-pipeline window summary, shared by the main health path
149
+ * (`health.ts`) and {@link buildWindowMetrics} below: events-derived
150
+ * invoked/completed/skipped counts, the `result_json` aggregate, wall-time
151
+ * stats from the same per-run rows, and accepted-proposal coverage, all over
152
+ * one `[since, until)`.
153
+ */
154
+ export function buildImproveWindowSummary(db, stateDbPath, since, until) {
155
+ const untilMs = new Date(until).getTime();
156
+ const eventsBeforeUntil = (type) => readEvents({ since, type }, { dbPath: stateDbPath }).events.filter((event) => new Date(event.ts ?? since).getTime() < untilMs);
157
+ const { metrics: improve, runCount } = summarizeImproveRuns(db, since, until);
158
+ improve.invoked = eventsBeforeUntil("improve_invoked").length;
159
+ improve.completed = eventsBeforeUntil(IMPROVE_COMPLETED_EVENT).length;
160
+ const skipSummary = buildImproveSkipSummary(eventsBeforeUntil("improve_skipped"));
161
+ improve.skipped = skipSummary.skipped;
162
+ improve.skipReasons = skipSummary.skipReasons;
163
+ // Wall times come from the same improve-runs window as the per-run
164
+ // reporting so counts and percentiles stay aligned with it.
173
165
  const perRunSummaries = buildPerRunSummaries(db, since, until);
174
- const wallTimes = perRunSummaries.map((run) => run.wallTimeMs).filter((ms) => Number.isFinite(ms) && ms > 0);
175
- improveSummary.wallTime = computeWallTimeStats(wallTimes, improveSummary.wallTime.byPhase);
176
- // WS-5: Compute denominator-fixed coverage from the most recent run's
177
- // memorySummary (totalAssets = eligible + derived — the fixed denominator).
178
- const totalAssets = improveSummary.memorySummary.eligible + improveSummary.memorySummary.derived;
179
- improveSummary.coverage = computeDenominatorFixedCoverage(db, totalAssets, improveSummary.memorySummary.eligible, since, until);
180
- // WS-5: Compute per-run degradation metrics (corpus diversity, merge fidelity,
181
- // generation distribution, oracle spot-check). Health VIEWS only.
182
- const degradation = computeDegradationMetrics(db, since, until);
183
- if (degradation) {
184
- improveSummary.degradation = degradation;
185
- }
166
+ improve.wallTime = computeWallTimeStats(perRunSummaries.map((run) => run.wallTimeMs).filter((ms) => Number.isFinite(ms) && ms > 0));
167
+ improve.coverage = computeWindowProposalCoverage(db, since, until);
168
+ return { improve, runCount, perRunSummaries };
169
+ }
170
+ export function buildWindowMetrics(db, stateDbPath, since, until, now = () => Date.now()) {
171
+ const untilMs = new Date(until).getTime();
172
+ const taskRows = queryTaskHistory(db, { since }).filter((row) => {
173
+ const startMs = new Date(row.started_at).getTime();
174
+ return !Number.isFinite(untilMs) || startMs < untilMs;
175
+ });
176
+ const rates = computeTaskWindowRates(taskRows, now);
177
+ const { improve, runCount } = buildImproveWindowSummary(db, stateDbPath, since, until);
186
178
  const metrics = {
187
- taskFailRate: roundRate(taskFailRate),
188
- agentFailureRate: roundRate(agentFailureRate),
189
- agentFailureReasonCounts,
190
- stuckActiveRuns,
191
- logBackingRate: roundRate(logBackingRate),
192
- probeRoundTripMs: null,
179
+ taskFailRate: roundRate(rates.taskFailRate),
180
+ agentFailureRate: roundRate(rates.agentFailureRate),
181
+ agentFailureReasonCounts: rates.agentFailureReasonCounts,
182
+ stuckActiveRuns: rates.stuckActiveRuns,
193
183
  llmUsage: readLlmUsageAggregate(stateDbPath, since, until),
194
184
  };
195
- return { improve: improveSummary, metrics, runs: runCount };
185
+ return { improve, metrics, runs: runCount };
196
186
  }