akm-cli 0.9.17-alpha.1 → 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 (399) hide show
  1. package/CHANGELOG.md +1623 -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/retrieval-relevance-judge.md +6 -0
  15. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +20 -20
  16. package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -2
  17. package/dist/assets/templates/html/health.html +3 -5
  18. package/dist/cli/retired-commands.js +1 -1
  19. package/dist/cli/shared.js +6 -2
  20. package/dist/cli/unknown-flags.js +24 -1
  21. package/dist/cli.js +68 -10
  22. package/dist/commands/agent/agent-dispatch.js +1 -1
  23. package/dist/commands/command/command-execution.js +24 -62
  24. package/dist/commands/feedback-cli.js +0 -1
  25. package/dist/commands/health/accept-rate.js +2 -2
  26. package/dist/commands/health/archive-usage.js +92 -0
  27. package/dist/commands/health/checks.js +30 -75
  28. package/dist/commands/health/config-skew.js +38 -0
  29. package/dist/commands/health/data-dir-usage.js +25 -13
  30. package/dist/commands/health/egress.js +54 -0
  31. package/dist/commands/health/html-report.js +1 -42
  32. package/dist/commands/health/improve-metrics.js +136 -587
  33. package/dist/commands/health/md-report.js +1 -6
  34. package/dist/commands/health/plugin-staleness.js +53 -3
  35. package/dist/commands/health/renderers.js +12 -4
  36. package/dist/commands/health/report-view-model.js +14 -119
  37. package/dist/commands/health/types-improve.js +4 -19
  38. package/dist/commands/health/windows.js +64 -74
  39. package/dist/commands/health.js +135 -143
  40. package/dist/commands/improve/consolidate/chunking.js +25 -100
  41. package/dist/commands/improve/consolidate/continuity-check.js +137 -0
  42. package/dist/commands/improve/consolidate/pair-pass.js +791 -0
  43. package/dist/commands/improve/consolidate/sanitize.js +54 -149
  44. package/dist/commands/improve/consolidate.js +573 -1124
  45. package/dist/commands/improve/content-hash.js +16 -24
  46. package/dist/commands/improve/distill/content-repair.js +18 -100
  47. package/dist/commands/improve/distill-guards.js +20 -81
  48. package/dist/commands/improve/distill-promotion-policy.js +23 -243
  49. package/dist/commands/improve/distill.js +608 -1075
  50. package/dist/commands/improve/eligibility.js +126 -400
  51. package/dist/commands/improve/execution.js +8 -10
  52. package/dist/commands/improve/extract-prompt.js +1 -2
  53. package/dist/commands/improve/extract.js +487 -1046
  54. package/dist/commands/improve/feedback-valence.js +0 -25
  55. package/dist/commands/improve/improve-cli.js +54 -171
  56. package/dist/commands/improve/improve-result-file.js +10 -66
  57. package/dist/commands/improve/improve-strategies.js +35 -9
  58. package/dist/commands/improve/improve-usage-report.js +18 -64
  59. package/dist/commands/improve/improve.js +451 -1082
  60. package/dist/commands/improve/ledger.js +119 -0
  61. package/dist/commands/improve/locks.js +2 -8
  62. package/dist/commands/improve/loop-stages.js +401 -1192
  63. package/dist/commands/improve/memory/derived-ref.js +12 -77
  64. package/dist/commands/improve/memory/memory-belief.js +16 -118
  65. package/dist/commands/improve/memory/memory-improve.js +266 -14
  66. package/dist/commands/improve/outcome-loop.js +28 -156
  67. package/dist/commands/improve/planner.js +5 -15
  68. package/dist/commands/improve/preparation.js +776 -2349
  69. package/dist/commands/improve/proactive-maintenance.js +34 -101
  70. package/dist/commands/improve/reflect-noise.js +104 -280
  71. package/dist/commands/improve/reflect.js +642 -1364
  72. package/dist/commands/improve/retrieval-gate.js +127 -0
  73. package/dist/commands/improve/retrieval-scope.js +92 -0
  74. package/dist/commands/improve/salience.js +41 -240
  75. package/dist/commands/improve/session-asset.js +19 -100
  76. package/dist/commands/improve/stage.js +322 -0
  77. package/dist/commands/lint/base-linter.js +37 -15
  78. package/dist/commands/proposal/drain.js +258 -644
  79. package/dist/commands/proposal/proposal-cli.js +19 -20
  80. package/dist/commands/proposal/proposal-types.js +27 -41
  81. package/dist/commands/proposal/proposal.js +38 -8
  82. package/dist/commands/proposal/propose.js +134 -160
  83. package/dist/commands/proposal/repository.js +1099 -1475
  84. package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
  85. package/dist/commands/proposal/validators/proposal-validators.js +1 -1
  86. package/dist/commands/proposal/validators/proposals.js +22 -89
  87. package/dist/commands/read/curate.js +105 -462
  88. package/dist/commands/read/knowledge.js +3 -2
  89. package/dist/commands/read/search-cli.js +16 -33
  90. package/dist/commands/read/search.js +17 -23
  91. package/dist/commands/read/show.js +57 -108
  92. package/dist/commands/sources/bundle-cli.js +25 -2
  93. package/dist/commands/sources/bundle-config-ops.js +4 -0
  94. package/dist/commands/sources/dangerous-env-audit.js +1 -2
  95. package/dist/commands/sources/info.js +127 -29
  96. package/dist/commands/sources/installed-stashes.js +197 -746
  97. package/dist/commands/sources/schema-repair.js +98 -129
  98. package/dist/commands/sources/source-add.js +62 -12
  99. package/dist/commands/sources/source-manage.js +9 -2
  100. package/dist/commands/sources/stash-cli.js +24 -4
  101. package/dist/commands/tasks/explain.js +10 -13
  102. package/dist/commands/tasks/tasks-cli.js +12 -13
  103. package/dist/commands/tasks/tasks.js +350 -936
  104. package/dist/commands/tasks/validate.js +26 -24
  105. package/dist/commands/workflow/plan.js +22 -29
  106. package/dist/commands/workflow-cli.js +4 -4
  107. package/dist/core/adapter/adapters/akm-adapter.js +2 -1
  108. package/dist/core/adapter/adapters/akm-lint.js +2 -3
  109. package/dist/core/adapter/adapters/akm-metadata.js +42 -12
  110. package/dist/core/adapter/adapters/akm-task-adapter.js +29 -8
  111. package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
  112. package/dist/core/adapter/execution-source.js +17 -29
  113. package/dist/core/asset/asset-placement.js +4 -13
  114. package/dist/core/asset/resolve-ref.js +1 -1
  115. package/dist/core/bundle-id.js +42 -5
  116. package/dist/core/bundle-rename.js +285 -0
  117. package/dist/core/config/config-io.js +1 -2
  118. package/dist/core/config/config-schema.js +9 -34
  119. package/dist/core/config/config-walker.js +1 -1
  120. package/dist/core/config/config.js +184 -111
  121. package/dist/core/config/engine-semantics.js +0 -2
  122. package/dist/core/config/legacy-source-shape-shim.js +38 -9
  123. package/dist/core/config/schema/embedding.js +20 -5
  124. package/dist/core/config/schema/engines.js +5 -0
  125. package/dist/core/config/schema/execution.js +1 -1
  126. package/dist/core/config/schema/experimental.js +1 -1
  127. package/dist/core/config/schema/improve-processes.js +37 -135
  128. package/dist/core/config/schema/improve.js +4 -42
  129. package/dist/core/config/schema/index-config.js +9 -48
  130. package/dist/core/config/schema/scheduler.js +12 -12
  131. package/dist/core/config/schema/search.js +6 -22
  132. package/dist/core/env-secret-ref.js +0 -1
  133. package/dist/core/errors.js +8 -9
  134. package/dist/core/file-change.js +13 -5
  135. package/dist/core/file-lock.js +76 -173
  136. package/dist/core/improve-result.js +26 -7
  137. package/dist/core/improve-types.js +0 -1
  138. package/dist/core/logs-db.js +2 -2
  139. package/dist/core/loopback.js +7 -12
  140. package/dist/core/non-task-input.js +20 -0
  141. package/dist/core/parse.js +13 -16
  142. package/dist/core/paths.js +0 -31
  143. package/dist/core/redaction.js +109 -2
  144. package/dist/core/run-lock.js +2 -5
  145. package/dist/core/spawn-env.js +1 -1
  146. package/dist/core/state/migrations.js +123 -61
  147. package/dist/core/state-db-scope.js +2 -4
  148. package/dist/core/state-db.js +126 -692
  149. package/dist/core/time.js +0 -20
  150. package/dist/core/type-presentation.js +1 -9
  151. package/dist/core/write-source.js +294 -1005
  152. package/dist/execution/input-contract.js +1 -1
  153. package/dist/execution/resolved-request.js +135 -689
  154. package/dist/execution/source.js +63 -257
  155. package/dist/execution/target-ref.js +1 -1
  156. package/dist/indexer/bundle-identity-guard.js +2 -2
  157. package/dist/indexer/db/llm-cache.js +2 -2
  158. package/dist/indexer/ensure-index.js +46 -87
  159. package/dist/indexer/index-rebuild-lock.js +3 -11
  160. package/dist/indexer/index-writer-lock.js +8 -17
  161. package/dist/indexer/index-written-assets.js +141 -154
  162. package/dist/indexer/indexer.js +400 -1124
  163. package/dist/indexer/links/declared-links.js +90 -0
  164. package/dist/indexer/materialize-embeddings.js +60 -397
  165. package/dist/indexer/passes/memory-inference.js +81 -90
  166. package/dist/indexer/passes/metadata.js +132 -219
  167. package/dist/indexer/read-preflight.js +0 -7
  168. package/dist/indexer/scan/doc-to-entry.js +2 -3
  169. package/dist/indexer/scan/drain-dir.js +1 -1
  170. package/dist/indexer/search/db-search.js +190 -590
  171. package/dist/indexer/search/fts-query.js +30 -41
  172. package/dist/indexer/search/ranking.js +28 -154
  173. package/dist/indexer/search/search-attribution.js +12 -32
  174. package/dist/indexer/search/search-fields.js +11 -15
  175. package/dist/indexer/search/search-hit-enrichers.js +54 -85
  176. package/dist/indexer/search/search-source.js +1 -4
  177. package/dist/indexer/usage/usage-events.js +36 -7
  178. package/dist/indexer/walk/walker.js +3 -4
  179. package/dist/integrations/agent/engine-fallback.js +23 -40
  180. package/dist/integrations/agent/engine-resolution.js +93 -183
  181. package/dist/integrations/agent/execution.js +507 -0
  182. package/dist/integrations/agent/model-map.js +28 -156
  183. package/dist/integrations/agent/request-lowering.js +66 -141
  184. package/dist/integrations/agent/runner-dispatch.js +143 -321
  185. package/dist/integrations/agent/runner.js +54 -14
  186. package/dist/integrations/lockfile.js +53 -101
  187. package/dist/llm/client.js +8 -10
  188. package/dist/llm/embedders/deterministic.js +2 -3
  189. package/dist/llm/embedders/profile.js +71 -0
  190. package/dist/llm/embedders/remote.js +11 -17
  191. package/dist/llm/feature-gate.js +0 -8
  192. package/dist/llm/index-passes.js +3 -5
  193. package/dist/llm/memory-infer.js +1 -2
  194. package/dist/llm/structured-call.js +5 -24
  195. package/dist/output/generic-render.js +23 -11
  196. package/dist/output/html-render.js +13 -10
  197. package/dist/output/render-registry.js +3 -32
  198. package/dist/output/shapes/helpers.js +25 -38
  199. package/dist/output/shapes/passthrough.js +1 -9
  200. package/dist/{indexer/graph/graph-types.js → output/text/bundle-rename.js} +4 -1
  201. package/dist/output/text/command-format.js +69 -31
  202. package/dist/output/text/helpers.js +1 -1
  203. package/dist/output/text/migrate.js +5 -14
  204. package/dist/output/text/proposal-format.js +48 -3
  205. package/dist/output/text/show-format.js +13 -17
  206. package/dist/output/text/workflow-format.js +0 -32
  207. package/dist/output/text.js +2 -0
  208. package/dist/registry/factory.js +4 -19
  209. package/dist/registry/network.js +66 -220
  210. package/dist/registry/providers/index.js +0 -2
  211. package/dist/registry/providers/skills-sh.js +3 -14
  212. package/dist/registry/providers/static-index.js +24 -26
  213. package/dist/registry/resolve.js +55 -131
  214. package/dist/scripts/akm-migrate-node.js +42938 -92375
  215. package/dist/scripts/akm-migrate.js +42930 -92365
  216. package/dist/setup/registry-stash-loader.js +4 -13
  217. package/dist/setup/semantic-assets.js +3 -44
  218. package/dist/setup/setup.js +1 -1
  219. package/dist/setup/steps/connection.js +5 -6
  220. package/dist/setup/steps/platforms.js +2 -2
  221. package/dist/setup/steps/tasks.js +25 -15
  222. package/dist/sources/provider-factory.js +17 -18
  223. package/dist/sources/providers/filesystem.js +2 -3
  224. package/dist/sources/providers/git-install.js +7 -1
  225. package/dist/sources/providers/git-provider.js +0 -3
  226. package/dist/sources/providers/git-stash.js +83 -21
  227. package/dist/sources/providers/npm.js +2 -4
  228. package/dist/sources/providers/provider-utils.js +5 -10
  229. package/dist/sources/providers/website.js +0 -2
  230. package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
  231. package/dist/sources/website-url.js +2 -2
  232. package/dist/storage/database.js +9 -35
  233. package/dist/storage/repositories/improve-ledger-repository.js +209 -0
  234. package/dist/storage/repositories/index-connection.js +39 -72
  235. package/dist/storage/repositories/index-entries-repository.js +88 -129
  236. package/dist/storage/repositories/index-entry-mapper.js +1 -2
  237. package/dist/storage/repositories/index-entry-schema.js +101 -268
  238. package/dist/storage/repositories/index-fts-repository.js +86 -256
  239. package/dist/storage/repositories/index-links-repository.js +143 -0
  240. package/dist/storage/repositories/index-llm-cache-repository.js +7 -9
  241. package/dist/storage/repositories/index-meta-repository.js +6 -4
  242. package/dist/storage/repositories/index-schema.js +257 -325
  243. package/dist/storage/repositories/index-utility-repository.js +8 -29
  244. package/dist/storage/repositories/index-vec-repository.js +133 -414
  245. package/dist/storage/repositories/outcome-repository.js +2 -1
  246. package/dist/storage/repositories/proposals-repository.js +100 -0
  247. package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
  248. package/dist/storage/repositories/salience-repository.js +1 -19
  249. package/dist/storage/repositories/task-history-repository.js +26 -4
  250. package/dist/storage/repositories/workflow-runs-repository.js +53 -244
  251. package/dist/storage/sqlite-migrations.js +136 -0
  252. package/dist/storage/sqlite-pragmas.js +11 -9
  253. package/dist/storage/sqlite-transaction.js +170 -0
  254. package/dist/storage/state-db-integrity.js +34 -27
  255. package/dist/tasks/activation-config.js +134 -62
  256. package/dist/tasks/backends/cron.js +191 -302
  257. package/dist/tasks/backends/exec-utils.js +2 -5
  258. package/dist/tasks/backends/launchd.js +141 -748
  259. package/dist/tasks/backends/schtasks.js +119 -623
  260. package/dist/tasks/prepare/prepare-support.js +5 -15
  261. package/dist/tasks/prepare/prepare.js +0 -2
  262. package/dist/tasks/resolve-akm-bin.js +20 -79
  263. package/dist/tasks/run/attempt-lifecycle.js +0 -1
  264. package/dist/tasks/run/load-task.js +1 -1
  265. package/dist/tasks/scheduler-binding.js +20 -238
  266. package/dist/tasks/scheduler-invocation.js +136 -244
  267. package/dist/tasks/scheduler-lock.js +53 -0
  268. package/dist/tasks/scheduler-sync.js +368 -679
  269. package/dist/tasks/source/parse-task-source.js +55 -9
  270. package/dist/tasks/source/task-source-v3-frozen.js +3 -4
  271. package/dist/tasks/source/task-to-v4.js +464 -88
  272. package/dist/workflows/authoring/authoring.js +3 -12
  273. package/dist/workflows/compile.js +211 -0
  274. package/dist/workflows/concurrency-policy.js +13 -74
  275. package/dist/workflows/exec/child-invocation.js +3 -17
  276. package/dist/workflows/exec/child-workflow.js +32 -141
  277. package/dist/workflows/exec/dispatch-redaction.js +13 -53
  278. package/dist/workflows/exec/environment.js +98 -0
  279. package/dist/workflows/exec/exec-unit.js +33 -140
  280. package/dist/workflows/exec/frozen-judge.js +7 -59
  281. package/dist/workflows/exec/native-executor.js +82 -341
  282. package/dist/workflows/exec/param-secrets.js +29 -47
  283. package/dist/workflows/exec/run-workflow.js +154 -387
  284. package/dist/workflows/exec/scheduler.js +9 -36
  285. package/dist/workflows/exec/step-work.js +127 -430
  286. package/dist/workflows/exec/unit-dispatch.js +11 -63
  287. package/dist/workflows/exec/unit-writer.js +8 -52
  288. package/dist/workflows/exec/worktree.js +39 -273
  289. package/dist/workflows/freeze/child-output-references.js +4 -15
  290. package/dist/workflows/freeze/environment.js +99 -92
  291. package/dist/workflows/freeze/freeze.js +172 -0
  292. package/dist/workflows/freeze/step-values.js +19 -21
  293. package/dist/workflows/freeze/targets/child-workflow.js +23 -92
  294. package/dist/workflows/freeze/targets/command.js +10 -33
  295. package/dist/workflows/freeze/targets/script.js +5 -12
  296. package/dist/workflows/freeze/targets/shell.js +3 -6
  297. package/dist/workflows/freeze/targets/task.js +25 -80
  298. package/dist/workflows/freeze/task-bindings.js +20 -67
  299. package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
  300. package/dist/workflows/ir/params.js +6 -51
  301. package/dist/workflows/ir/plan-hash.js +2 -34
  302. package/dist/workflows/parser.js +140 -43
  303. package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
  304. package/dist/workflows/renderer.js +36 -69
  305. package/dist/workflows/resource-limits.js +12 -120
  306. package/dist/workflows/runtime/agent-identity.js +8 -40
  307. package/dist/workflows/runtime/run-outputs.js +3 -6
  308. package/dist/workflows/runtime/run-plan.js +316 -0
  309. package/dist/workflows/runtime/runs.js +48 -200
  310. package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
  311. package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
  312. package/dist/workflows/validate-summary.js +2 -7
  313. package/docs/integration/bundling-akm.md +49 -42
  314. package/docs/migration/README.md +1 -0
  315. package/docs/migration/release-notes/0.9.17.md +43 -0
  316. package/docs/migration/v0.9.1-to-v0.9.2.md +23 -7
  317. package/docs/reference/cli.md +229 -133
  318. package/docs/reference/configuration.md +71 -57
  319. package/docs/reference/data-and-telemetry.md +19 -21
  320. package/docs/reference/tasks.md +105 -39
  321. package/docs/reference/workflow-schema.md +14 -18
  322. package/docs/reference/workflows.md +6 -9
  323. package/package.json +1 -1
  324. package/schemas/akm-config.json +87 -754
  325. package/dist/assets/improve-strategies/graph-refresh.json +0 -15
  326. package/dist/assets/prompts/contradiction-judge.md +0 -33
  327. package/dist/assets/prompts/graph-extract-system.md +0 -1
  328. package/dist/assets/prompts/graph-extract-user-prompt.md +0 -35
  329. package/dist/assets/prompts/metadata-enhance-system.md +0 -1
  330. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +0 -4
  331. package/dist/commands/health/advisories.js +0 -150
  332. package/dist/commands/health/metrics.js +0 -329
  333. package/dist/commands/health/surfaces.js +0 -102
  334. package/dist/commands/improve/anti-collapse.js +0 -83
  335. package/dist/commands/improve/collapse-detector.js +0 -432
  336. package/dist/commands/improve/consolidate/eligibility.js +0 -48
  337. package/dist/commands/improve/consolidate/merge.js +0 -146
  338. package/dist/commands/improve/distill/promote-memory.js +0 -329
  339. package/dist/commands/improve/distill/quality-gate.js +0 -500
  340. package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
  341. package/dist/commands/improve/proposal-envelope.js +0 -31
  342. package/dist/commands/improve/run-context.js +0 -123
  343. package/dist/commands/improve/shared.js +0 -21
  344. package/dist/commands/improve/source-identity.js +0 -28
  345. package/dist/commands/improve/triage.js +0 -96
  346. package/dist/commands/proposal/drain-policies.js +0 -151
  347. package/dist/commands/sources/update-transaction.js +0 -220
  348. package/dist/core/action-contributors.js +0 -28
  349. package/dist/core/config/config-version-shim.js +0 -101
  350. package/dist/core/fs-txn.js +0 -405
  351. package/dist/core/lexical-score.js +0 -25
  352. package/dist/core/maintenance-barrier.js +0 -167
  353. package/dist/execution/executable-identity.js +0 -105
  354. package/dist/execution/guarded-source.js +0 -427
  355. package/dist/indexer/db/graph-db.js +0 -444
  356. package/dist/indexer/graph/graph-boost.js +0 -427
  357. package/dist/indexer/graph/graph-dedup.js +0 -95
  358. package/dist/indexer/graph/graph-extraction.js +0 -1182
  359. package/dist/indexer/search/name-match.js +0 -35
  360. package/dist/indexer/search/ranking-contributors.js +0 -515
  361. package/dist/indexer/search/ranking-types.js +0 -4
  362. package/dist/indexer/walk/project-context.js +0 -192
  363. package/dist/integrations/agent/execution-cascade.js +0 -566
  364. package/dist/integrations/agent/execution-definitions.js +0 -202
  365. package/dist/integrations/agent/execution-lowering.js +0 -841
  366. package/dist/integrations/agent/execution-preparation.js +0 -98
  367. package/dist/integrations/agent/inline-execution.js +0 -74
  368. package/dist/llm/graph-extract.js +0 -872
  369. package/dist/llm/metadata-enhance.js +0 -96
  370. package/dist/registry/create-provider-registry.js +0 -29
  371. package/dist/registry/pinned-request-helper.js +0 -247
  372. package/dist/registry/pinned-transport.js +0 -717
  373. package/dist/sources/providers/index.js +0 -14
  374. package/dist/storage/engines/sqlite-migrations.js +0 -271
  375. package/dist/storage/repositories/canaries-repository.js +0 -107
  376. package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
  377. package/dist/storage/repositories/registry-cache.js +0 -113
  378. package/dist/tasks/scheduler-sync-preview.js +0 -52
  379. package/dist/tasks/source/task-to-v3.js +0 -507
  380. package/dist/workflows/freeze/resolve-steps.js +0 -86
  381. package/dist/workflows/freeze/source-freeze.js +0 -64
  382. package/dist/workflows/ir/compile.js +0 -321
  383. package/dist/workflows/ir/environment-v4.js +0 -330
  384. package/dist/workflows/ir/freeze-v4.js +0 -153
  385. package/dist/workflows/ir/schema-v4.js +0 -745
  386. package/dist/workflows/ir/schema.js +0 -354
  387. package/dist/workflows/program/schema.js +0 -78
  388. package/dist/workflows/runtime/checkin.js +0 -57
  389. package/dist/workflows/runtime/plan-classifier.js +0 -196
  390. package/dist/workflows/runtime/unit-checkin.js +0 -45
  391. package/dist/workflows/runtime/unit-phases.js +0 -20
  392. package/dist/workflows/schema.js +0 -4
  393. package/dist/workflows/source-ir/compile.js +0 -200
  394. package/dist/workflows/source-ir/program.js +0 -50
  395. package/dist/workflows/source-ir/result.js +0 -26
  396. package/dist/workflows/source-ir/schema.js +0 -786
  397. package/dist/workflows/source-ir/triggers.js +0 -79
  398. package/dist/workflows/source-ir/uses.js +0 -40
  399. package/dist/workflows/validator.js +0 -60
@@ -0,0 +1,92 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * `memory-cleanup-archive` advisory for `akm health` (item 4, 0.9.17-alpha.9
6
+ * plan §5.4/§8 step 8).
7
+ *
8
+ * Reports the archive's size and file count for every bundle, git-backed or
9
+ * not. A bundle with no `.git` of its own keeps every retirement's archived
10
+ * bytes forever (the purge sweep never runs there at all), so that alone is
11
+ * reported. A git-backed bundle can ALSO have bytes the purge sweep will
12
+ * never remove: `.git` presence alone does not prove a retirement was ever
13
+ * committed (`proposal accept` only commits for a `kind: "git"` write
14
+ * target, and a `kind: "filesystem"` bundle that merely happens to have a
15
+ * `.git` directory never gets one) — those bytes sit there indefinitely,
16
+ * however old they get, with nothing else to say so. This checks the SAME
17
+ * git state `purgeGracedArchive` checks (tracked, clean, verifiable) and
18
+ * reports how much of the archive fails it.
19
+ *
20
+ * Silent whenever there is nothing to say: the archive does not exist or is
21
+ * empty, or (for a git-backed bundle) every byte in it is purgeable once it
22
+ * ages out.
23
+ */
24
+ import fs from "node:fs";
25
+ import path from "node:path";
26
+ import { MEMORY_ARCHIVE_REL } from "../../core/asset/memory-archive.js";
27
+ import { toPosix } from "../../core/common.js";
28
+ import { checkGitPathSafety, isGitBackedStash } from "../../sources/providers/git-stash.js";
29
+ import { MAX_WALK_ENTRIES, sizeOfPath } from "./data-dir-usage.js";
30
+ /**
31
+ * Build the `memory-cleanup-archive` advisory, or `undefined` when there is
32
+ * nothing to report.
33
+ */
34
+ export function collectArchiveUsageAdvisory(stashDir) {
35
+ const archiveRoot = path.join(stashDir, MEMORY_ARCHIVE_REL);
36
+ if (!fs.existsSync(archiveRoot))
37
+ return undefined;
38
+ if (!isGitBackedStash(stashDir)) {
39
+ const usage = sizeOfPath(archiveRoot, { remaining: MAX_WALK_ENTRIES });
40
+ if (usage.files === 0)
41
+ return undefined;
42
+ const lowerBound = usage.truncated ? ` (a lower bound — the walk stopped after ${MAX_WALK_ENTRIES} entries)` : "";
43
+ return {
44
+ name: "memory-cleanup-archive",
45
+ kind: "deterministic",
46
+ status: "pass",
47
+ confidence: "high",
48
+ message: `${usage.files} archived file(s), ${usage.bytes} byte(s)${lowerBound} in .akm/memory-cleanup/archive — ` +
49
+ "this bundle has no git history, so the purge sweep leaves it untouched.",
50
+ evidence: { files: usage.files, bytes: usage.bytes, truncated: usage.truncated },
51
+ };
52
+ }
53
+ // Git-backed: the SAME three checks purgeGracedArchive runs (B1, G10) —
54
+ // computed once here, not per file, and reused via `onFile` below instead
55
+ // of a second walk of the same tree. A failed git check here fails the
56
+ // same way purgeGracedArchive's own sweep would: nothing in the archive
57
+ // can be proven purgeable, so every byte counts as unpurgeable rather
58
+ // than guessing (`checkGitPathSafety`'s `isSafe` is always `false` when
59
+ // `ok` is `false`).
60
+ const gitSafety = checkGitPathSafety(stashDir, MEMORY_ARCHIVE_REL);
61
+ let unpurgeableFiles = 0;
62
+ let unpurgeableBytes = 0;
63
+ const usage = sizeOfPath(archiveRoot, { remaining: MAX_WALK_ENTRIES }, (filePath, bytes) => {
64
+ const key = toPosix(path.relative(stashDir, filePath));
65
+ if (!gitSafety.isSafe(key)) {
66
+ unpurgeableFiles++;
67
+ unpurgeableBytes += bytes;
68
+ }
69
+ });
70
+ if (usage.files === 0)
71
+ return undefined;
72
+ if (unpurgeableFiles === 0)
73
+ return undefined; // everything here is purgeable once it ages out — nothing to say
74
+ const lowerBound = usage.truncated ? ` (a lower bound — the walk stopped after ${MAX_WALK_ENTRIES} entries)` : "";
75
+ return {
76
+ name: "memory-cleanup-archive",
77
+ kind: "deterministic",
78
+ status: "warn",
79
+ confidence: "high",
80
+ message: `${usage.files} archived file(s), ${usage.bytes} byte(s)${lowerBound} in .akm/memory-cleanup/archive; ` +
81
+ `${unpurgeableFiles} file(s), ${unpurgeableBytes} byte(s) of that cannot be purged (untracked, modified, ` +
82
+ "or unverifiable in git) — commit them so the purge sweep can remove them once they age out.",
83
+ evidence: {
84
+ files: usage.files,
85
+ bytes: usage.bytes,
86
+ truncated: usage.truncated,
87
+ unpurgeableFiles,
88
+ unpurgeableBytes,
89
+ gitStateKnown: gitSafety.ok,
90
+ },
91
+ };
92
+ }
@@ -10,7 +10,7 @@ import { EXTRACT_INFRASTRUCTURE_SKIP_REASONS } from "../../core/improve-types.js
10
10
  import { listPendingStateMigrations } from "../../core/state-db.js";
11
11
  import { withEngineFallback } from "../../integrations/agent/engine-fallback.js";
12
12
  import { isLlmCredentialAvailable, resolveEngine, } from "../../integrations/agent/engine-resolution.js";
13
- import { executionEngineDefinitionsFromConfig } from "../../integrations/agent/execution-definitions.js";
13
+ import { executionEngineDefinitionsFromConfig } from "../../integrations/agent/execution.js";
14
14
  import { loadModelMap, mergeModelMapLayers, parseModelMapLayer, readInstalledModelMapText, resolveModelMapAlias, userModelMapPath, } from "../../integrations/agent/model-map.js";
15
15
  import { probeEndpointOnce } from "../../llm/client.js";
16
16
  import { STATE_DB_FREELIST_WARN_RATIO, } from "../../storage/state-db-integrity.js";
@@ -784,16 +784,10 @@ export function runSelectedModelAliasesProbe(deps = {}) {
784
784
  };
785
785
  }
786
786
  /**
787
- * Hard check: state.db's migration ledger has no pending entries.
788
- *
789
- * Read-only via `listPendingStateMigrations` (a preflight open, never a
790
- * managed one), so running this check is always safe — even when the
791
- * corresponding managed open would refuse outright because a pending
792
- * migration is historical-destructive (see `beforeMigrationLocked` in
793
- * `src/core/state/migrations.ts`). This is what lets `akm health` report that
794
- * refusal as an ordinary `fail` check instead of crashing the whole command —
795
- * and what replaces a bundler grepping akm's refusal error text
796
- * to detect the same case.
787
+ * `state-db-migrations` when the open itself failed: the migrations still
788
+ * pending after a failed apply, from a read-only listing that never applies
789
+ * anything. A `fail` row, not a crash, is what a bundler watches for instead
790
+ * of grepping akm's error text.
797
791
  */
798
792
  export function runPendingStateMigrationsCheck(stateDbPath, deps = {}) {
799
793
  const pending = (deps.listPendingStateMigrations ?? listPendingStateMigrations)(stateDbPath);
@@ -817,6 +811,27 @@ export function runPendingStateMigrationsCheck(stateDbPath, deps = {}) {
817
811
  evidence: { path: stateDbPath, pending },
818
812
  };
819
813
  }
814
+ /**
815
+ * Hard check: state.db's ledger is current. Every open applies the pending
816
+ * migrations (copying the file aside first when one drops schema), so after
817
+ * health's own open nothing is pending; this names what that open applied, so
818
+ * an upgrade that migrated state.db is visible in the report.
819
+ */
820
+ export function appliedStateMigrationsCheck(stateDbPath, report) {
821
+ const { applied, backupPath } = report;
822
+ const range = applied.length > 1 ? `${applied[0]} … ${applied[applied.length - 1]}` : applied[0];
823
+ return {
824
+ name: "state-db-migrations",
825
+ kind: "deterministic",
826
+ status: "pass",
827
+ confidence: "high",
828
+ message: applied.length === 0
829
+ ? "state.db has no pending migrations."
830
+ : `Applied ${applied.length} pending state.db migration(s) on open (${range})` +
831
+ (backupPath ? `; the pre-migration copy is ${backupPath}.` : "."),
832
+ evidence: { path: stateDbPath, pending: [], applied, ...(backupPath ? { backupPath } : {}) },
833
+ };
834
+ }
820
835
  /**
821
836
  * #943: name the dominant `detail.reason` behind `task-fail-rate`'s warning
822
837
  * when one reason accounts for at least half of the window's command-task
@@ -890,7 +905,9 @@ export const HEALTH_CHECKS = [
890
905
  status: "fail",
891
906
  confidence: "high",
892
907
  message: `state.db failed PRAGMA quick_check: ${detail}. Repair: back up state.db, then run ` +
893
- `sqlite3 state.db ".dump" | sqlite3 state.new.db, verify state.new.db passes quick_check, and swap it in.`,
908
+ `sqlite3 state.db ".recover" | sqlite3 state.new.db, verify state.new.db passes quick_check, stop ` +
909
+ "every akm process, then delete state.db-wal and state.db-shm before swapping state.new.db in as " +
910
+ "state.db — a leftover WAL from the OLD database is replayed onto the new one and corrupts it.",
894
911
  evidence: { path: ctx.stateDbPath, lines, freelistRatio },
895
912
  };
896
913
  }
@@ -925,7 +942,7 @@ export const HEALTH_CHECKS = [
925
942
  {
926
943
  name: "state-db-migrations",
927
944
  channel: "hard",
928
- run: (ctx) => runPendingStateMigrationsCheck(ctx.stateDbPath),
945
+ run: (ctx) => appliedStateMigrationsCheck(ctx.stateDbPath, ctx.stateDbMigrations),
929
946
  },
930
947
  {
931
948
  name: "task-history-read",
@@ -939,20 +956,6 @@ export const HEALTH_CHECKS = [
939
956
  evidence: { rows: ctx.taskRowCount, since: ctx.since },
940
957
  }),
941
958
  },
942
- {
943
- name: "task-log-backing",
944
- channel: "hard",
945
- run: (ctx) => ({
946
- name: "task-log-backing",
947
- kind: "deterministic",
948
- status: ctx.logBackingRate === 1 ? "pass" : "fail",
949
- confidence: "high",
950
- message: ctx.logBackingRate === 1
951
- ? "Every task_history log_path resolved on disk."
952
- : `${ctx.taskRowsWithLogsCount - ctx.existingLogRowsCount} task log(s) referenced in task_history are missing.`,
953
- evidence: { totalWithLogs: ctx.taskRowsWithLogsCount, existingLogs: ctx.existingLogRowsCount },
954
- }),
955
- },
956
959
  {
957
960
  name: "active-runs",
958
961
  channel: "hard",
@@ -1127,54 +1130,6 @@ export const HEALTH_CHECKS = [
1127
1130
  };
1128
1131
  },
1129
1132
  },
1130
- {
1131
- // #603: pool-saturation advisory. The raw `sessionsScanned` count fired on
1132
- // normal cadence changes (the Jun 12 false alarm). Instead track the ratio
1133
- // of NEW (unseen) sessions to the total session pool extract evaluated in
1134
- // the window: a low ratio is the *expected* steady state, only a near-zero
1135
- // ratio signals a possible discovery/dedup bug.
1136
- //
1137
- // unseen ≈ `sessionsScanned` (extract only processes new sessions; already-
1138
- // seen ones are deduped into `sessionsSkipped`). total = scanned + skipped.
1139
- // This is a heuristic approximation — `sessionsSkipped` also folds in
1140
- // too-short skips — so the check is informational and never gates status.
1141
- name: "pool-saturation",
1142
- channel: "advisory",
1143
- run: (ctx) => {
1144
- const sx = ctx.sessionExtraction;
1145
- const total = sx.sessionsScanned + sx.sessionsSkipped;
1146
- const unseen = sx.sessionsScanned;
1147
- const ratio = total > 0 ? unseen / total : null;
1148
- const pct = ratio === null ? null : Math.round(ratio * 1000) / 10;
1149
- let status = "pass";
1150
- let confidence = "low";
1151
- let message;
1152
- if (!sx.ran || ratio === null) {
1153
- message = "Pool saturation: no extract activity in the window — no signal.";
1154
- }
1155
- else if (ratio < 0.02) {
1156
- status = "warn";
1157
- confidence = "medium";
1158
- message = `Session pool near-exhausted: only ${pct}% of the ${total}-session pool was new (<2%). Possible discovery/dedup bug — verify extract is still finding new sessions.`;
1159
- }
1160
- else if (ratio < 0.1) {
1161
- confidence = "medium";
1162
- message = `Session pool saturation: ${pct}% of ${total} sessions were new (<10%, steady-state expected — informational).`;
1163
- }
1164
- else {
1165
- confidence = "medium";
1166
- message = `Session pool healthy: ${pct}% of ${total} sessions were new.`;
1167
- }
1168
- return {
1169
- name: "pool-saturation",
1170
- kind: "heuristic",
1171
- status,
1172
- confidence,
1173
- message,
1174
- evidence: { totalSessions: total, unseenSessions: unseen, saturationRatio: ratio },
1175
- };
1176
- },
1177
- },
1178
1133
  {
1179
1134
  name: "auto-accept-validation",
1180
1135
  channel: "advisory",
@@ -0,0 +1,38 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * `binary-config-skew` advisory for `akm health`: warn when config.json
6
+ * carries a `configVersion` NEWER than (or unorderable against) this binary's
7
+ * CURRENT_CONFIG_VERSION — a newer akm wrote the shared config, so this
8
+ * install is stale. That is the proven multi-install incident class. Silent
9
+ * for current or older versions and for unreadable configs (config loading
10
+ * reports its own errors).
11
+ */
12
+ import { readTextFile } from "../../core/common.js";
13
+ import { CURRENT_CONFIG_VERSION } from "../../core/config/config-schema.js";
14
+ import { compareConfigVersion } from "../../core/config/config-version.js";
15
+ export function collectConfigSkewAdvisory(configPath) {
16
+ let raw;
17
+ try {
18
+ raw = JSON.parse(readTextFile(configPath, "Config file"));
19
+ }
20
+ catch {
21
+ return undefined;
22
+ }
23
+ const onDisk = raw.configVersion;
24
+ const order = compareConfigVersion(onDisk, CURRENT_CONFIG_VERSION);
25
+ const skewed = order === 1 || (onDisk !== undefined && order === undefined);
26
+ if (!skewed)
27
+ return undefined;
28
+ return {
29
+ name: "binary-config-skew",
30
+ kind: "deterministic",
31
+ status: "warn",
32
+ confidence: "high",
33
+ message: `config.json has configVersion ${JSON.stringify(onDisk)} but this binary knows ${CURRENT_CONFIG_VERSION} — ` +
34
+ "a newer akm wrote the shared config, so this install is stale. Upgrade this install; do not keep a stale " +
35
+ "binary against the shared config/DBs.",
36
+ evidence: { onDiskConfigVersion: onDisk, binaryConfigVersion: CURRENT_CONFIG_VERSION },
37
+ };
38
+ }
@@ -41,7 +41,7 @@ const DOMINANT_SUBDIR_PERCENT_THRESHOLD = 50;
41
41
  * cap the walk stops descending further and the advisory says its size
42
42
  * figures are a lower bound.
43
43
  */
44
- const MAX_WALK_ENTRIES = 100_000;
44
+ export const MAX_WALK_ENTRIES = 100_000;
45
45
  /**
46
46
  * Below this the data dir is not worth an opinion. The advisory exists for
47
47
  * disk blowups (74 GB in the incident); on a small directory a ratio is
@@ -59,31 +59,42 @@ function liveDbBytesFor(name, sizes) {
59
59
  return ((sizes.get(name)?.bytes ?? 0) + (sizes.get(`${name}-wal`)?.bytes ?? 0) + (sizes.get(`${name}-shm`)?.bytes ?? 0));
60
60
  }
61
61
  /**
62
- * Recursively sum file sizes under `root` (stat-only, symlinks not
63
- * followed so a cyclic or huge-target symlink can't blow up the walk).
64
- * `budget` is a shared mutable counter across the whole tree so the
65
- * `MAX_WALK_ENTRIES` cap applies to the walk as a whole, not per-branch.
62
+ * Recursively sum file sizes (and count files) under `root` (stat-only,
63
+ * symlinks not followed so a cyclic or huge-target symlink can't blow up the
64
+ * walk). `budget` is a shared mutable counter across the whole tree so the
65
+ * entry cap applies to the walk as a whole, not per-branch — callers
66
+ * typically pass {@link MAX_WALK_ENTRIES}, sized for this module's own data
67
+ * dir walk, but a smaller/larger budget is fine for a different tree.
68
+ * Shared with the `archive-usage` advisory (N2) — the same "don't let a
69
+ * pathological tree hang a health check" concern applies to both.
70
+ *
71
+ * `onFile`, when given, is called once per leaf file (path, bytes) as the
72
+ * walk visits it — `archive-usage` uses this to classify each file's git
73
+ * state without a second, separate walk of the same tree.
66
74
  */
67
- function sizeOfPath(root, budget) {
75
+ export function sizeOfPath(root, budget, onFile) {
68
76
  let stat;
69
77
  try {
70
78
  stat = fs.lstatSync(root);
71
79
  }
72
80
  catch {
73
- return { bytes: 0, truncated: false };
81
+ return { bytes: 0, files: 0, truncated: false };
74
82
  }
75
83
  if (stat.isSymbolicLink())
76
- return { bytes: 0, truncated: false };
77
- if (!stat.isDirectory())
78
- return { bytes: stat.size, truncated: false };
84
+ return { bytes: 0, files: 0, truncated: false };
85
+ if (!stat.isDirectory()) {
86
+ onFile?.(root, stat.size);
87
+ return { bytes: stat.size, files: 1, truncated: false };
88
+ }
79
89
  let entries;
80
90
  try {
81
91
  entries = fs.readdirSync(root, { withFileTypes: true });
82
92
  }
83
93
  catch {
84
- return { bytes: 0, truncated: false };
94
+ return { bytes: 0, files: 0, truncated: false };
85
95
  }
86
96
  let bytes = 0;
97
+ let files = 0;
87
98
  let truncated = false;
88
99
  for (const entry of entries) {
89
100
  if (budget.remaining <= 0) {
@@ -91,12 +102,13 @@ function sizeOfPath(root, budget) {
91
102
  break;
92
103
  }
93
104
  budget.remaining--;
94
- const sub = sizeOfPath(path.join(root, entry.name), budget);
105
+ const sub = sizeOfPath(path.join(root, entry.name), budget, onFile);
95
106
  bytes += sub.bytes;
107
+ files += sub.files;
96
108
  if (sub.truncated)
97
109
  truncated = true;
98
110
  }
99
- return { bytes, truncated };
111
+ return { bytes, files, truncated };
100
112
  }
101
113
  /** `1610612736` -> `"1.5G"`. Values under 10 in a unit keep one decimal; 10+ round to an integer. */
102
114
  function formatBytes(bytes) {
@@ -0,0 +1,54 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * `egress-endpoints` advisory for `akm health` (meta-review 08, surfaces 3/9):
6
+ * the remote-destination list, for eyeball diff. A pure projection over the
7
+ * effective config (no process.env reads); silent when nothing remote is
8
+ * configured, matching the `stash-git-exposure` / `binary-config-skew`
9
+ * advisories' pattern.
10
+ */
11
+ import { formatRegistryUrl } from "../../core/registry-url.js";
12
+ /**
13
+ * `egress-endpoints` (08 surfaces 3/9): the full list of remote destinations
14
+ * akm can talk to under the effective config — registries, remote sources,
15
+ * LLM endpoints, embedding endpoint — as one pass-status informational entry
16
+ * for eyeball diff against expectations. Silent only when nothing remote is
17
+ * configured at all.
18
+ */
19
+ export function collectEgressAdvisory(config) {
20
+ if (!config)
21
+ return undefined;
22
+ const endpoints = [];
23
+ for (const reg of config.registries ?? []) {
24
+ if (reg.enabled === false || !reg.url)
25
+ continue;
26
+ endpoints.push(`registry ${reg.name ?? "(unnamed)"}: ${formatRegistryUrl(reg.url)}`);
27
+ }
28
+ for (const [key, bundle] of Object.entries(config.bundles ?? {})) {
29
+ if (!bundle)
30
+ continue;
31
+ const url = bundle.git ?? bundle.website?.url;
32
+ if (!url)
33
+ continue;
34
+ endpoints.push(`source ${key} (${bundle.git ? "git" : "website"}): ${url}`);
35
+ }
36
+ for (const [name, engine] of Object.entries(config.engines ?? {})) {
37
+ if (engine?.kind !== "llm" || !engine.endpoint)
38
+ continue;
39
+ endpoints.push(`llm ${name}: ${engine.endpoint}`);
40
+ }
41
+ if (config.embedding?.endpoint)
42
+ endpoints.push(`embedding: ${config.embedding.endpoint}`);
43
+ if (endpoints.length === 0)
44
+ return undefined;
45
+ return {
46
+ name: "egress-endpoints",
47
+ kind: "deterministic",
48
+ status: "pass",
49
+ confidence: "high",
50
+ message: `${endpoints.length} remote endpoint(s) in the effective config (registries/sources/LLM/embedding) — ` +
51
+ "review the evidence list for unexpected destinations.",
52
+ evidence: { endpoints },
53
+ };
54
+ }
@@ -131,7 +131,6 @@ function renderExecSummary(vm) {
131
131
  const trendRows = [
132
132
  trendLi("Decision quality", vm.trend.decisionQuality),
133
133
  trendLi("Output volume", vm.trend.outputVolume),
134
- trendLi("Failures", vm.trend.failures),
135
134
  trendLi("Latency", vm.trend.latency),
136
135
  ].join("");
137
136
  const deltaRows = [
@@ -151,7 +150,6 @@ function renderExecSummary(vm) {
151
150
  li("Promoted", String(vm.latest.promoted)),
152
151
  li("Judged: no action", `<abbr title="Candidates reviewed but intentionally left unchanged on this run.">${vm.latest.judgedNoAction}</abbr>`),
153
152
  li("MI written", String(vm.latest.miWritten)),
154
- li("Graph entities/relations", `${vm.latest.geEntities} / ${vm.latest.geRelations}`),
155
153
  ].join("")
156
154
  : '<li><span class="k">No runs in window</span><span class="v">—</span></li>';
157
155
  const windowRows = [
@@ -197,7 +195,7 @@ function renderExecSummary(vm) {
197
195
  </div>
198
196
  </div>
199
197
  <div class="overall">Overall trend: <b>${esc(vm.trend.overall)}</b> ${overallEmoji}
200
- &nbsp;·&nbsp; based on decision quality, output volume, failures, and latency ${vm.comparisonMode === "custom" ? "across the selected windows" : "vs the prior window"}.</div>`.trim();
198
+ &nbsp;·&nbsp; based on decision quality, output volume, and latency ${vm.comparisonMode === "custom" ? "across the selected windows" : "vs the prior window"}.</div>`.trim();
201
199
  }
202
200
  /**
203
201
  * Color is a health SIGNAL, not decoration: green/yellow/red where a card has
@@ -221,7 +219,6 @@ function renderKpiCards(vm) {
221
219
  kpiCard("neutral", "Median Duration", `${vm.medianDurMin}m`, `p95 = ${vm.p95DurMin}m`),
222
220
  kpiCard("blue", "Total Promoted", num(vm.consolidation.promoted), `avg ${vm.avgPromoted} / run`),
223
221
  kpiCard("blue", "MI Written", num(vm.miWritten), `${vm.miYieldRate} yield rate`),
224
- kpiCard("purple", "Graph Entities", num(vm.graphExtraction.entities), `+${num(vm.graphExtraction.relations)} relations`),
225
222
  kpiCard("neutral", "Stash Derived", num(vm.memorySummary.derived), `of ${num(vm.memorySummary.eligible)} eligible (whole-stash)`),
226
223
  // #576: real LLM work — duration leads, tokens compact, not a GPU proxy.
227
224
  kpiCard(vm.llm.calls > 0 ? "purple" : "neutral", "🧠 LLM Work", `${vm.llmTokensCompact} tok`, `${fmtMs(vm.llm.totalDurationMs)} · ${num(vm.llm.calls)} calls · ${compact(vm.llm.reasoningTokens)} reasoning`),
@@ -331,44 +328,6 @@ function renderActionItems(vm) {
331
328
  descHtml: `Newest run is ${esc(latestRunHuman)} — older than the 6h freshness threshold. Check the improve scheduler/cron.`,
332
329
  });
333
330
  }
334
- // WS-5: corpus entrenchment flag.
335
- if (vm.degradation?.entrenchmentFlagged) {
336
- pushItem({
337
- key: "corpus-entrenchment",
338
- prio: "P2",
339
- cls: "warn",
340
- title: "Corpus entrenchment risk: retrieval_salience Gini > 0.35",
341
- descHtml: "A small set of assets dominates retrieval — retrieval diversity is low. " +
342
- "Review top-ranked assets for stale or over-represented content. " +
343
- `Corpus diversity proxy: ${esc(String(vm.degradation.corpusCentroidDistance))}.`,
344
- remedy: "akm health --format json | jq '.improve.degradation'",
345
- });
346
- }
347
- // Low-tail companion: salience distribution collapsed toward uniform.
348
- if (vm.degradation?.salienceUniformityFlagged) {
349
- pushItem({
350
- key: "salience-uniformity-collapse",
351
- prio: "P2",
352
- cls: "warn",
353
- title: "Salience distribution collapsed: retrieval_salience Gini < 0.08",
354
- descHtml: `The ${vm.degradation.retrievalSalienceSampleSize} observed, resolvable salience scores are near-uniform — ` +
355
- "ranking carries little discrimination among assets with retrieval evidence. " +
356
- `Corpus diversity proxy: ${esc(String(vm.degradation.corpusCentroidDistance))}.`,
357
- remedy: "akm health --format json | jq '.improve.degradation'",
358
- });
359
- }
360
- // WS-5: over-budget consolidation advisory.
361
- if (vm.perf.overBudgetRuns > 0) {
362
- pushItem({
363
- key: "over-budget-consolidation",
364
- prio: "P2",
365
- cls: "warn",
366
- title: `${vm.perf.overBudgetRuns} consolidation run${vm.perf.overBudgetRuns === 1 ? "" : "s"} exceeded budget`,
367
- descHtml: "Consolidation phase wall time exceeded the total run budget on these runs. " +
368
- "Consider increasing the timeout or reducing the consolidation pool via strategy config.",
369
- remedy: "akm config list",
370
- });
371
- }
372
331
  items.sort((a, b) => PRIO_RANK[a.prio] - PRIO_RANK[b.prio]);
373
332
  return items.length > 0
374
333
  ? items.map(actionItemCard).join("\n")