akm-cli 0.9.0-rc.8 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (450) hide show
  1. package/CHANGELOG.md +1063 -44
  2. package/README.md +51 -25
  3. package/SECURITY.md +14 -1
  4. package/STABILITY.md +497 -0
  5. package/dist/akm +148 -35
  6. package/dist/{akm-migrate-storage → akm-migrate} +6 -9
  7. package/dist/assets/hints/cli-hints-full.md +223 -95
  8. package/dist/assets/hints/cli-hints-short.md +85 -22
  9. package/dist/assets/improve-strategies/default.json +1 -1
  10. package/dist/assets/improve-strategies/reflect-distill.json +1 -1
  11. package/dist/assets/prompts/memory-infer-user.md +2 -3
  12. package/dist/assets/stash-skeleton/README.md +6 -5
  13. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +2 -0
  14. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +2 -0
  15. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +2 -0
  16. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +2 -0
  17. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +2 -0
  18. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +2 -0
  19. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +2 -0
  20. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +2 -0
  21. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +2 -0
  22. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +2 -0
  23. package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -0
  24. package/dist/assets/stash-skeleton/facts/conventions/organization.md +20 -9
  25. package/dist/assets/tasks/core/extract.yml +1 -1
  26. package/dist/assets/tasks/core/version-check.yml +1 -1
  27. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
  28. package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
  29. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
  30. package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
  31. package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
  32. package/dist/assets/templates/html/health.html +1 -3
  33. package/dist/assets/workflows/workflow-template.md +32 -15
  34. package/dist/cli/invocation.js +40 -15
  35. package/dist/cli/parse-args.js +0 -22
  36. package/dist/cli/retired-commands.js +121 -0
  37. package/dist/cli/shared.js +154 -22
  38. package/dist/cli/unknown-flags.js +236 -0
  39. package/dist/cli-node.mjs +2 -1
  40. package/dist/cli.js +696 -258
  41. package/dist/commands/agent/agent-dispatch.js +14 -3
  42. package/dist/commands/agent/contribute-cli.js +73 -88
  43. package/dist/commands/completions.js +79 -22
  44. package/dist/commands/config-cli.js +17 -150
  45. package/dist/commands/env/env-cli.js +59 -143
  46. package/dist/commands/env/env.js +12 -163
  47. package/dist/commands/env/marker-path.js +6 -0
  48. package/dist/commands/env/secret-cli.js +36 -66
  49. package/dist/commands/env/secret.js +24 -57
  50. package/dist/commands/feedback-cli.js +141 -87
  51. package/dist/commands/health/accept-rate.js +58 -0
  52. package/dist/commands/health/advisories.js +3 -4
  53. package/dist/commands/health/checks.js +85 -23
  54. package/dist/commands/health/html-report.js +7 -10
  55. package/dist/commands/health/improve-metrics.js +25 -83
  56. package/dist/commands/health/md-report.js +5 -9
  57. package/dist/commands/health/metrics.js +62 -20
  58. package/dist/commands/health/renderers.js +47 -0
  59. package/dist/commands/health/report-view-model.js +4 -5
  60. package/dist/commands/health/stash-exposure.js +1 -1
  61. package/dist/commands/health/surfaces.js +3 -48
  62. package/dist/commands/health/task-runs.js +3 -67
  63. package/dist/commands/health/types-improve.js +7 -0
  64. package/dist/commands/health.js +99 -28
  65. package/dist/commands/improve/anti-collapse.js +2 -2
  66. package/dist/commands/improve/autonomy-gate.js +68 -0
  67. package/dist/commands/improve/collapse-detector.js +41 -40
  68. package/dist/commands/improve/consolidate/eligibility.js +1 -23
  69. package/dist/commands/improve/consolidate/merge.js +4 -0
  70. package/dist/commands/improve/consolidate.js +140 -1000
  71. package/dist/commands/improve/distill/promote-memory.js +12 -12
  72. package/dist/commands/improve/distill/quality-gate.js +6 -6
  73. package/dist/commands/improve/distill.js +58 -69
  74. package/dist/commands/improve/eligibility.js +105 -57
  75. package/dist/commands/improve/extract-cli.js +14 -133
  76. package/dist/commands/improve/improve-cli.js +98 -114
  77. package/dist/commands/improve/improve-result-file.js +1 -28
  78. package/dist/commands/improve/improve-strategies.js +8 -5
  79. package/dist/commands/improve/improve.js +128 -91
  80. package/dist/commands/improve/loop-stages.js +182 -20
  81. package/dist/commands/improve/memory/derived-ref.js +45 -43
  82. package/dist/commands/improve/memory/memory-belief.js +1 -1
  83. package/dist/commands/improve/memory/memory-contradiction-detect.js +4 -12
  84. package/dist/commands/improve/memory/memory-improve.js +6 -5
  85. package/dist/commands/improve/outcome-loop.js +22 -65
  86. package/dist/commands/improve/preparation.js +114 -123
  87. package/dist/commands/improve/proactive-maintenance.js +2 -5
  88. package/dist/commands/improve/reflect.js +56 -160
  89. package/dist/commands/improve/salience.js +11 -122
  90. package/dist/commands/improve/source-identity.js +10 -38
  91. package/dist/commands/lint/base-linter.js +20 -124
  92. package/dist/commands/lint/env-key-rules.js +31 -47
  93. package/dist/commands/lint/index.js +249 -43
  94. package/dist/commands/{events.js → log.js} +33 -38
  95. package/dist/commands/migrate-cli.js +92 -12
  96. package/dist/commands/migration-tool.js +46 -0
  97. package/dist/commands/observability-cli.js +70 -209
  98. package/dist/commands/proposal/drain.js +101 -29
  99. package/dist/commands/proposal/proposal-cli.js +76 -48
  100. package/dist/commands/proposal/proposal.js +54 -18
  101. package/dist/commands/proposal/propose-cli.js +88 -0
  102. package/dist/commands/proposal/propose.js +23 -15
  103. package/dist/commands/proposal/repository.js +701 -278
  104. package/dist/commands/proposal/validators/proposal-quality-validators.js +2 -8
  105. package/dist/commands/proposal/validators/proposal-validators.js +55 -7
  106. package/dist/commands/proposal/validators/proposals.js +4 -7
  107. package/dist/commands/read/curate.js +34 -53
  108. package/dist/commands/read/knowledge.js +150 -95
  109. package/dist/commands/read/registry-search.js +2 -2
  110. package/dist/commands/read/remember-cli.js +42 -15
  111. package/dist/commands/read/search-cli.js +180 -78
  112. package/dist/commands/read/search.js +58 -43
  113. package/dist/commands/read/show.js +197 -141
  114. package/dist/commands/registry-cli.js +12 -51
  115. package/dist/commands/remember.js +14 -57
  116. package/dist/commands/sources/add-cli.js +100 -31
  117. package/dist/commands/sources/bundle-cli.js +166 -0
  118. package/dist/commands/sources/bundle-config-ops.js +7 -2
  119. package/dist/commands/sources/info.js +18 -5
  120. package/dist/commands/sources/init.js +12 -12
  121. package/dist/commands/sources/installed-stashes.js +382 -98
  122. package/dist/commands/sources/schema-repair.js +3 -2
  123. package/dist/commands/sources/self-update.js +131 -38
  124. package/dist/commands/sources/source-add.js +72 -17
  125. package/dist/commands/sources/source-clone.js +129 -45
  126. package/dist/commands/sources/source-manage.js +43 -23
  127. package/dist/commands/sources/sources-cli.js +57 -208
  128. package/dist/commands/sources/stash-cli.js +46 -53
  129. package/dist/commands/tasks/tasks-cli.js +91 -97
  130. package/dist/commands/tasks/tasks.js +276 -421
  131. package/dist/commands/workflow-cli.js +175 -450
  132. package/dist/core/adapter/adapters/akm-adapter.js +47 -28
  133. package/dist/core/adapter/adapters/akm-lint.js +42 -27
  134. package/dist/core/adapter/adapters/akm-metadata.js +15 -44
  135. package/dist/core/adapter/adapters/akm-task-adapter.js +15 -13
  136. package/dist/core/adapter/adapters/akm-workflow-adapter.js +55 -71
  137. package/dist/core/adapter/adapters/dotenv-adapter.js +1 -1
  138. package/dist/core/adapter/adapters/generic-files-adapter.js +2 -0
  139. package/dist/core/adapter/adapters/index.js +6 -6
  140. package/dist/core/adapter/adapters/llm-wiki-adapter.js +14 -8
  141. package/dist/core/adapter/adapters/okf-adapter.js +187 -19
  142. package/dist/core/adapter/adapters/shared.js +3 -19
  143. package/dist/core/adapter/adapters/tool-dir-shared.js +8 -3
  144. package/dist/core/adapter/adapters/website-snapshot-adapter.js +1 -0
  145. package/dist/core/adapter/detect-adapter.js +17 -0
  146. package/dist/core/adapter/recognize-match.js +6 -4
  147. package/dist/core/adapter/validate-context.js +214 -0
  148. package/dist/core/asset/akm-markdown.js +63 -0
  149. package/dist/core/asset/asset-placement.js +20 -6
  150. package/dist/core/asset/asset-ref.js +11 -9
  151. package/dist/core/asset/frontmatter-lint.js +30 -0
  152. package/dist/core/asset/frontmatter.js +37 -9
  153. package/dist/core/asset/markdown.js +40 -51
  154. package/dist/core/asset/resolve-ref.js +89 -18
  155. package/dist/core/asset/stash-meta.js +1 -1
  156. package/dist/core/bundle-id.js +51 -0
  157. package/dist/core/common.js +152 -38
  158. package/dist/core/config/config-io.js +12 -1
  159. package/dist/core/config/config-schema.js +35 -8
  160. package/dist/core/config/config-sources.js +55 -11
  161. package/dist/core/config/config-walker.js +25 -9
  162. package/dist/core/config/config.js +9 -48
  163. package/dist/core/config/experimental.js +21 -0
  164. package/dist/core/config/schema/embedding.js +5 -1
  165. package/dist/core/config/schema/experimental.js +30 -0
  166. package/dist/core/config/schema/improve-processes.js +0 -6
  167. package/dist/core/config/schema/improve.js +21 -3
  168. package/dist/core/config/schema/index-config.js +8 -15
  169. package/dist/core/config/schema/output.js +4 -1
  170. package/dist/core/config/schema/setup.js +9 -18
  171. package/dist/core/config/schema/sources-bundles.js +49 -33
  172. package/dist/core/config/schema/workflow.js +3 -3
  173. package/dist/core/env-secret-ref.js +76 -46
  174. package/dist/core/errors.js +18 -12
  175. package/dist/core/events.js +46 -128
  176. package/dist/core/file-change.js +6 -5
  177. package/dist/core/fs-txn.js +83 -7
  178. package/dist/core/git-message.js +2 -2
  179. package/dist/core/improve-result.js +1 -100
  180. package/dist/core/lesson-lint.js +1 -17
  181. package/dist/core/logs-db.js +2 -1
  182. package/dist/core/migration-operation.js +16 -0
  183. package/dist/core/mutation-target.js +78 -0
  184. package/dist/core/parse.js +4 -1
  185. package/dist/core/paths.js +17 -20
  186. package/dist/core/recognition-util.js +12 -14
  187. package/dist/core/redaction.js +34 -0
  188. package/dist/core/standards/resolve-standards-context.js +2 -14
  189. package/dist/core/standards/resolve-stash-standards.js +2 -2
  190. package/dist/core/standards/resolve-type-conventions.js +2 -2
  191. package/dist/core/state/migrations.js +41 -18
  192. package/dist/core/state-db.js +5 -14
  193. package/dist/core/structured.js +1 -1
  194. package/dist/core/subprocess.js +6 -4
  195. package/dist/core/text-truncation.js +9 -5
  196. package/dist/core/type-presentation.js +3 -3
  197. package/dist/core/warn.js +0 -3
  198. package/dist/core/write-source.js +771 -95
  199. package/dist/indexer/bundle-identity-guard.js +3 -2
  200. package/dist/indexer/db/graph-db.js +0 -24
  201. package/dist/indexer/ensure-index.js +1 -0
  202. package/dist/indexer/graph/graph-boost.js +9 -34
  203. package/dist/indexer/graph/graph-extraction.js +8 -5
  204. package/dist/indexer/index-writer-lock.js +53 -17
  205. package/dist/indexer/index-written-assets.js +16 -22
  206. package/dist/indexer/indexer.js +497 -239
  207. package/dist/indexer/installations.js +14 -96
  208. package/dist/indexer/passes/dir-staleness.js +16 -9
  209. package/dist/indexer/passes/memory-inference.js +11 -9
  210. package/dist/indexer/passes/metadata.js +113 -47
  211. package/dist/indexer/scan/doc-to-entry.js +38 -1
  212. package/dist/indexer/scan/drain-dir.js +13 -23
  213. package/dist/indexer/search/db-search.js +99 -54
  214. package/dist/indexer/search/fts-query.js +47 -24
  215. package/dist/indexer/search/ranking-contributors.js +42 -20
  216. package/dist/indexer/search/ranking.js +18 -99
  217. package/dist/indexer/search/search-fields.js +7 -2
  218. package/dist/indexer/search/search-source.js +82 -93
  219. package/dist/indexer/usage/usage-events.js +0 -89
  220. package/dist/indexer/walk/file-context.js +2 -1
  221. package/dist/indexer/walk/matchers.js +30 -43
  222. package/dist/indexer/walk/path-resolver.js +7 -2
  223. package/dist/indexer/walk/walker.js +38 -12
  224. package/dist/integrations/agent/builders.js +0 -6
  225. package/dist/integrations/agent/config.js +2 -2
  226. package/dist/integrations/agent/detect.js +49 -19
  227. package/dist/integrations/agent/engine-fallback.js +76 -0
  228. package/dist/integrations/agent/profiles.js +14 -0
  229. package/dist/integrations/agent/prompts.js +12 -8
  230. package/dist/integrations/agent/runner-dispatch.js +4 -2
  231. package/dist/integrations/agent/runner.js +0 -1
  232. package/dist/integrations/agent/spawn.js +5 -6
  233. package/dist/integrations/github.js +1 -1
  234. package/dist/integrations/harnesses/aider/agent-builder.js +6 -4
  235. package/dist/integrations/harnesses/amazonq/agent-builder.js +7 -4
  236. package/dist/integrations/harnesses/claude/session-log.js +0 -10
  237. package/dist/integrations/harnesses/codex/agent-builder.js +5 -2
  238. package/dist/integrations/harnesses/copilot/agent-builder.js +5 -3
  239. package/dist/integrations/harnesses/gemini/agent-builder.js +5 -3
  240. package/dist/integrations/harnesses/index.js +3 -7
  241. package/dist/integrations/harnesses/opencode/agent-builder.js +21 -2
  242. package/dist/integrations/harnesses/opencode/session-log.js +0 -15
  243. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +13 -4
  244. package/dist/integrations/harnesses/openhands/agent-builder.js +9 -6
  245. package/dist/integrations/harnesses/pi/agent-builder.js +6 -4
  246. package/dist/integrations/lockfile.js +101 -6
  247. package/dist/integrations/session-logs/index.js +3 -28
  248. package/dist/llm/client.js +136 -100
  249. package/dist/llm/embedders/remote.js +13 -5
  250. package/dist/llm/feature-gate.js +4 -12
  251. package/dist/llm/graph-extract.js +5 -11
  252. package/dist/llm/memory-infer.js +144 -1
  253. package/dist/llm/metadata-enhance.js +5 -7
  254. package/dist/llm/structured-call.js +1 -1
  255. package/dist/llm/usage-persist.js +26 -5
  256. package/dist/llm/usage-telemetry.js +25 -2
  257. package/dist/output/cli-hints.js +1 -2
  258. package/dist/output/context.js +22 -7
  259. package/dist/output/format-exempt.js +80 -0
  260. package/dist/output/generic-render.js +259 -0
  261. package/dist/output/render-registry.js +57 -0
  262. package/dist/output/renderers.js +14 -36
  263. package/dist/output/shapes/curate.js +10 -1
  264. package/dist/output/shapes/events.js +12 -7
  265. package/dist/output/shapes/helpers.js +56 -83
  266. package/dist/output/shapes/migrate.js +8 -0
  267. package/dist/output/shapes/passthrough.js +7 -41
  268. package/dist/output/shapes/proposal/producer.js +15 -7
  269. package/dist/output/shapes.js +2 -9
  270. package/dist/output/text/{init.js → bundle-create.js} +3 -1
  271. package/dist/output/text/bundle-show.js +7 -0
  272. package/dist/output/text/command-format.js +164 -96
  273. package/dist/output/text/env.js +1 -3
  274. package/dist/output/text/events.js +8 -7
  275. package/dist/output/text/health-format.js +103 -0
  276. package/dist/output/text/health.js +7 -0
  277. package/dist/output/text/helpers.js +10 -8
  278. package/dist/output/text/lint-format.js +43 -0
  279. package/dist/output/text/{save.js → lint.js} +2 -2
  280. package/dist/output/text/migrate.js +88 -0
  281. package/dist/output/text/proposal/producer.js +4 -2
  282. package/dist/output/text/proposal-format.js +44 -72
  283. package/dist/output/text/registry-commands.js +1 -2
  284. package/dist/output/text/show-directives.js +15 -7
  285. package/dist/output/text/status-list.js +32 -0
  286. package/dist/output/text/sync.js +5 -0
  287. package/dist/output/text/workflow-format.js +24 -203
  288. package/dist/output/text/workflow.js +1 -7
  289. package/dist/output/text.js +16 -17
  290. package/dist/registry/factory.js +4 -6
  291. package/dist/registry/origin-resolve.js +16 -27
  292. package/dist/registry/providers/skills-sh.js +3 -3
  293. package/dist/registry/providers/static-index.js +13 -23
  294. package/dist/registry/resolve.js +42 -7
  295. package/dist/registry/semver.js +34 -84
  296. package/dist/runtime.js +2 -23
  297. package/dist/scripts/akm-migrate-node.js +60290 -0
  298. package/dist/scripts/akm-migrate.js +59628 -0
  299. package/dist/setup/detect.js +42 -15
  300. package/dist/setup/registry-stash-loader.js +2 -2
  301. package/dist/setup/setup.js +236 -136
  302. package/dist/setup/steps/connection.js +7 -9
  303. package/dist/setup/steps/platforms.js +9 -9
  304. package/dist/setup/steps/semantic.js +15 -3
  305. package/dist/setup/steps/sources.js +12 -13
  306. package/dist/setup/steps/stashdir.js +2 -3
  307. package/dist/setup/steps/tasks.js +237 -120
  308. package/dist/sources/freshness.js +1 -1
  309. package/dist/sources/provider-factory.js +11 -17
  310. package/dist/sources/providers/filesystem.js +2 -3
  311. package/dist/sources/providers/git-install.js +278 -34
  312. package/dist/sources/providers/git-provider.js +25 -23
  313. package/dist/sources/providers/git-stash.js +395 -106
  314. package/dist/sources/providers/git.js +2 -2
  315. package/dist/sources/providers/npm.js +16 -19
  316. package/dist/sources/providers/provider-utils.js +7 -4
  317. package/dist/sources/providers/sync-from-ref.js +3 -9
  318. package/dist/sources/providers/website.js +6 -1
  319. package/dist/sources/resolve.js +6 -5
  320. package/dist/sources/snapshot-fetchers/bluesky.js +146 -0
  321. package/dist/sources/snapshot-fetchers/content-extract.js +566 -0
  322. package/dist/sources/snapshot-fetchers/fetcher-util.js +41 -0
  323. package/dist/sources/snapshot-fetchers/github.js +100 -0
  324. package/dist/sources/snapshot-fetchers/host-guard.js +291 -0
  325. package/dist/sources/snapshot-fetchers/registry.js +17 -1
  326. package/dist/sources/snapshot-fetchers/robots.js +348 -0
  327. package/dist/sources/snapshot-fetchers/rss.js +282 -0
  328. package/dist/sources/snapshot-fetchers/secret-seam.js +42 -0
  329. package/dist/sources/snapshot-fetchers/website-ingest.js +566 -268
  330. package/dist/sources/snapshot-fetchers/x.js +910 -0
  331. package/dist/storage/database.js +7 -0
  332. package/dist/storage/engines/sqlite-migrations.js +23 -111
  333. package/dist/storage/managed-db.js +2 -2
  334. package/dist/storage/repositories/canaries-repository.js +1 -1
  335. package/dist/storage/repositories/events-repository.js +27 -11
  336. package/dist/storage/repositories/improve-runs-repository.js +6 -12
  337. package/dist/storage/repositories/index-connection.js +17 -6
  338. package/dist/storage/repositories/index-entries-repository.js +151 -240
  339. package/dist/storage/repositories/index-entry-mapper.js +15 -11
  340. package/dist/storage/repositories/index-fts-repository.js +5 -2
  341. package/dist/storage/repositories/index-llm-cache-repository.js +0 -1
  342. package/dist/storage/repositories/index-meta-repository.js +2 -3
  343. package/dist/storage/repositories/index-schema.js +10 -25
  344. package/dist/storage/repositories/index-utility-repository.js +15 -28
  345. package/dist/storage/repositories/index-vec-repository.js +6 -1
  346. package/dist/storage/repositories/outcome-repository.js +119 -0
  347. package/dist/storage/repositories/proposals-repository.js +296 -59
  348. package/dist/storage/repositories/registry-cache.js +19 -0
  349. package/dist/storage/repositories/salience-repository.js +172 -0
  350. package/dist/storage/repositories/task-history-repository.js +15 -13
  351. package/dist/storage/repositories/workflow-runs-repository.js +52 -40
  352. package/dist/tasks/backends/cron.js +105 -15
  353. package/dist/tasks/backends/index.js +1 -1
  354. package/dist/tasks/backends/launchd.js +85 -38
  355. package/dist/tasks/backends/schtasks.js +135 -15
  356. package/dist/tasks/embedded.js +56 -40
  357. package/dist/tasks/parser.js +7 -157
  358. package/dist/tasks/resolve-akm-bin.js +137 -59
  359. package/dist/tasks/runner.js +79 -42
  360. package/dist/tasks/scheduler-invocation.js +220 -10
  361. package/dist/tasks/schema.js +24 -1
  362. package/dist/tasks/task-id.js +1 -3
  363. package/dist/tasks/validator.js +20 -6
  364. package/dist/workflows/authoring/authoring.js +94 -143
  365. package/dist/workflows/authoring/scope-key.js +1 -1
  366. package/dist/workflows/exec/frozen-judge.js +28 -2
  367. package/dist/workflows/exec/native-executor.js +77 -57
  368. package/dist/workflows/exec/param-secrets.js +9 -9
  369. package/dist/workflows/exec/run-workflow.js +133 -79
  370. package/dist/workflows/exec/step-work.js +219 -346
  371. package/dist/{migrate-storage-node.mjs → workflows/exec/unit-dispatch.js} +1 -5
  372. package/dist/workflows/ir/compile.js +141 -270
  373. package/dist/workflows/ir/freeze.js +40 -30
  374. package/dist/workflows/ir/params.js +135 -11
  375. package/dist/workflows/ir/plan-hash.js +1 -1
  376. package/dist/workflows/ir/schema.js +25 -26
  377. package/dist/workflows/parser.js +872 -307
  378. package/dist/workflows/program/expressions.js +20 -208
  379. package/dist/workflows/program/schema.js +7 -10
  380. package/dist/workflows/renderer.js +95 -68
  381. package/dist/workflows/resource-limits.js +2 -0
  382. package/dist/workflows/runtime/checkin.js +3 -3
  383. package/dist/workflows/runtime/plan-classifier.js +16 -75
  384. package/dist/workflows/runtime/runs.js +186 -127
  385. package/dist/workflows/runtime/unit-checkin.js +1 -1
  386. package/dist/workflows/runtime/unit-phases.js +2 -2
  387. package/dist/workflows/runtime/workflow-asset-loader.js +232 -83
  388. package/dist/workflows/schema.js +1 -11
  389. package/dist/workflows/validate-summary.js +30 -36
  390. package/dist/workflows/validator.js +21 -62
  391. package/docs/README.md +68 -0
  392. package/docs/migration/README.md +8 -0
  393. package/docs/migration/release-notes/0.7.0.md +11 -11
  394. package/docs/migration/release-notes/0.9.0.md +208 -27
  395. package/docs/migration/v0.7-to-v0.8.md +46 -47
  396. package/docs/migration/v0.8-to-v0.9.md +564 -208
  397. package/docs/migration/v0.9.0-troubleshooting.md +561 -0
  398. package/docs/reference/README.md +12 -0
  399. package/docs/reference/cli.md +2253 -0
  400. package/docs/reference/configuration.md +358 -0
  401. package/docs/reference/data-and-telemetry.md +105 -42
  402. package/docs/reference/workflows.md +647 -0
  403. package/package.json +22 -11
  404. package/schemas/akm-asset-envelope.json +93 -0
  405. package/schemas/akm-config.json +81 -128
  406. package/schemas/akm-workflow.json +74 -73
  407. package/dist/assets/tasks/core/backup.yml +0 -5
  408. package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
  409. package/dist/cli/config-migrate.js +0 -1806
  410. package/dist/cli/config-validate.js +0 -41
  411. package/dist/commands/backup-cli.js +0 -56
  412. package/dist/commands/bundle/bundle-cli.js +0 -68
  413. package/dist/commands/bundle/bundle.js +0 -219
  414. package/dist/commands/graph/graph-cli.js +0 -124
  415. package/dist/commands/graph/graph.js +0 -489
  416. package/dist/commands/improve/extract-watch.js +0 -140
  417. package/dist/commands/mv-cli.js +0 -1221
  418. package/dist/commands/sources/history.js +0 -201
  419. package/dist/commands/tasks/default-tasks.js +0 -186
  420. package/dist/core/migration-backup.js +0 -1234
  421. package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -95
  422. package/dist/llm/memory-infer-impl.js +0 -138
  423. package/dist/migrate/legacy/config-source-migration.js +0 -223
  424. package/dist/migrate/legacy/content-migration.js +0 -305
  425. package/dist/migrate/legacy/legacy-layout.js +0 -779
  426. package/dist/migrate/legacy/legacy-paths.js +0 -25
  427. package/dist/migrate/legacy/legacy-stash-json.js +0 -72
  428. package/dist/migrate/legacy/proposal-fs-import.js +0 -168
  429. package/dist/migrate/legacy/task-target-ref-migration.js +0 -272
  430. package/dist/migrate/legacy/three-db-cutover.js +0 -841
  431. package/dist/migrate/legacy/workflow-migrations-bodies.js +0 -52
  432. package/dist/migrate/legacy/workflow-migrations-frozen.js +0 -21
  433. package/dist/migrate/legacy-ref-grammar.js +0 -214
  434. package/dist/output/shapes/distill.js +0 -14
  435. package/dist/output/shapes/history.js +0 -11
  436. package/dist/output/text/distill.js +0 -6
  437. package/dist/output/text/enable-disable.js +0 -8
  438. package/dist/output/text/history.js +0 -6
  439. package/dist/registry/build-index.js +0 -382
  440. package/dist/schemas/akm-config.json +0 -4704
  441. package/dist/schemas/akm-task.json +0 -87
  442. package/dist/schemas/akm-workflow.json +0 -372
  443. package/dist/scripts/migrate-storage.js +0 -3816
  444. package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
  445. package/dist/workflows/cli.js +0 -53
  446. package/dist/workflows/exec/brief.js +0 -481
  447. package/dist/workflows/exec/report.js +0 -1460
  448. package/dist/workflows/exec/watch.js +0 -116
  449. package/dist/workflows/program/parser.js +0 -813
  450. package/dist/workflows/program/project.js +0 -104
@@ -24,9 +24,7 @@
24
24
  * `~1MB` `echarts.min.js` self-contained/"inline" mode was removed along with
25
25
  * the asset itself — `buildEchartsTag` always emits a `<script src>` tag
26
26
  * pointed at the jsDelivr CDN, so viewing the report now requires network
27
- * access. BEHAVIOR CHANGE (plan-accepted, ledgered): previously
28
- * `AKM_ECHARTS=cdn` opted IN to the CDN with "inline" as the default; there is
29
- * no more env var or option to opt back into an offline report.
27
+ * access. There is no env var or option to opt back into an offline report.
30
28
  */
31
29
  import { escapeHtml } from "../../output/html-render.js";
32
30
  import { pkgVersion } from "../../version.js";
@@ -158,10 +156,9 @@ function renderExecSummary(vm) {
158
156
  : '<li><span class="k">No runs in window</span><span class="v">—</span></li>';
159
157
  const windowRows = [
160
158
  li("Report window", esc(vm.window)),
161
- li("Compare window", esc(vm.compare)),
159
+ li(vm.comparisonMode === "custom" ? "Comparison windows" : "Compare window", esc(vm.compare)),
162
160
  li("Runs", `${num(vm.totalRuns)} (${vm.failedRuns} failed)`),
163
161
  li("Included result rows", num(vm.includedResultRows)),
164
- li("Normalized result rows", num(vm.normalizedResultRows)),
165
162
  li("Invalid result rows skipped", num(vm.skippedInvalidResultRows)),
166
163
  li("Stash derived", `<abbr title="Whole-stash recount of derived assets at report time — not a per-run sum.">${num(vm.memorySummary.derived)}</abbr>`),
167
164
  li("Stash eligible", `<abbr title="Whole-stash recount of eligible assets at report time — not a per-run sum.">${num(vm.memorySummary.eligible)}</abbr>`),
@@ -185,7 +182,7 @@ function renderExecSummary(vm) {
185
182
  <ul>${quickNumbers}</ul>
186
183
  </div>
187
184
  <div>
188
- <h4>Trend vs prior ${esc(vm.compare)}</h4>
185
+ <h4>${vm.comparisonMode === "custom" ? `Trend: ${esc(vm.compare)}` : `Trend vs prior ${esc(vm.compare)}`}</h4>
189
186
  <ul>${trendRows}</ul>
190
187
  <h4 style="margin-top:14px;">Period-over-period deltas</h4>
191
188
  <ul>${deltaRows}</ul>
@@ -200,7 +197,7 @@ function renderExecSummary(vm) {
200
197
  </div>
201
198
  </div>
202
199
  <div class="overall">Overall trend: <b>${esc(vm.trend.overall)}</b> ${overallEmoji}
203
- &nbsp;·&nbsp; based on decision quality, output volume, failures, and latency vs the prior window.</div>`.trim();
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();
204
201
  }
205
202
  /**
206
203
  * Color is a health SIGNAL, not decoration: green/yellow/red where a card has
@@ -297,7 +294,7 @@ function renderActionItems(vm) {
297
294
  cls: "warn",
298
295
  title: "Semantic search blocked",
299
296
  descHtml: `Embedding provider unreachable. ${esc(vm.sem.detail)}. Curate falls back to keyword search — relevance scoring degraded.`,
300
- remedy: "akm config show",
297
+ remedy: "akm config list",
301
298
  });
302
299
  }
303
300
  // Pending proposals to drain.
@@ -368,8 +365,8 @@ function renderActionItems(vm) {
368
365
  cls: "warn",
369
366
  title: `${vm.perf.overBudgetRuns} consolidation run${vm.perf.overBudgetRuns === 1 ? "" : "s"} exceeded budget`,
370
367
  descHtml: "Consolidation phase wall time exceeded the total run budget on these runs. " +
371
- "Consider increasing the timeout or reducing the consolidation pool via profile config.",
372
- remedy: "akm config show",
368
+ "Consider increasing the timeout or reducing the consolidation pool via strategy config.",
369
+ remedy: "akm config list",
373
370
  });
374
371
  }
375
372
  // Session-log notes (informational, lowest priority).
@@ -12,10 +12,7 @@ export function parseTaskMetadata(row) {
12
12
  return {
13
13
  ...(metadata.durationMs !== undefined ? { durationMs: metadata.durationMs } : {}),
14
14
  ...(metadata.detail ? { detail: metadata.detail } : {}),
15
- ...(metadata.metadataVersion === 2 && metadata.engine !== undefined ? { engine: metadata.engine } : {}),
16
- ...(metadata.metadataVersion === 1 && metadata.legacyProfile !== undefined
17
- ? { legacyProfile: metadata.legacyProfile }
18
- : {}),
15
+ ...(metadata.engine !== undefined ? { engine: metadata.engine } : {}),
19
16
  };
20
17
  }
21
18
  function createUnknownImproveMetrics() {
@@ -24,7 +21,7 @@ function createUnknownImproveMetrics() {
24
21
  completed: 0,
25
22
  skipped: 0,
26
23
  skipReasons: {},
27
- resultRows: { total: 0, included: 0, normalized: 0, skipped: { invalid: 0 } },
24
+ resultRows: { total: 0, included: 0, skipped: { invalid: 0 } },
28
25
  plannedRefs: 0,
29
26
  strategyFilteredRefs: 0,
30
27
  actions: {
@@ -32,7 +29,6 @@ function createUnknownImproveMetrics() {
32
29
  distill: {
33
30
  queued: 0,
34
31
  llmFailed: 0,
35
- qualityRejected: 0,
36
32
  judgeRejected: 0,
37
33
  validatorRejected: 0,
38
34
  configDisabled: 0,
@@ -88,18 +84,16 @@ function createUnknownImproveMetrics() {
88
84
  skippedAborted: 0,
89
85
  unaccounted: 0,
90
86
  htmlErrorCount: 0,
91
- yieldEligibleRuns: 0,
92
- yieldEligibleConsidered: 0,
93
- yieldEligibleWritten: 0,
94
87
  yieldRate: 0,
95
88
  durationMs: 0,
96
- writes: 0,
97
89
  },
98
90
  graphExtraction: {
99
91
  ran: false,
100
92
  extractedFiles: 0,
93
+ consideredFiles: 0,
101
94
  entities: 0,
102
95
  relations: 0,
96
+ extractionCoverage: 0,
103
97
  cacheHits: 0,
104
98
  cacheMisses: 0,
105
99
  cacheHitRate: 0,
@@ -174,29 +168,11 @@ export function summarizeImproveCompleted(events) {
174
168
  return metrics;
175
169
  }
176
170
  /**
177
- * Bucket a distill `outcome: "skipped"` result into a low-cardinality reason.
178
- * Prefers an explicit `skipReason`; otherwise sniffs the message. The WI-6.4
179
- * fingerprint/backoff vocabulary is checked before the legacy patterns, which
180
- * stay for historical improve_runs rows.
171
+ * Read the machine-readable reason from a distill `outcome: "skipped"` result.
181
172
  */
182
173
  function classifyDistillSkipReason(r) {
183
174
  const explicitReason = typeof r?.skipReason === "string" ? r.skipReason : undefined;
184
- if (explicitReason)
185
- return explicitReason;
186
- const msg = typeof r?.message === "string" ? r.message : "";
187
- if (/lesson inputs/i.test(msg))
188
- return "recursive_lesson_input";
189
- if (/NOOP/.test(msg))
190
- return "conflict_noop";
191
- if (/fingerprint/i.test(msg))
192
- return "fingerprint_match";
193
- if (/rejection backoff/i.test(msg))
194
- return "rejection_backoff";
195
- if (/cooldown/i.test(msg))
196
- return "proposal_cooldown";
197
- if (/content[_ ]?hash/i.test(msg))
198
- return "content_hash_match";
199
- return "unknown";
175
+ return explicitReason || "unknown";
200
176
  }
201
177
  // ── projectRunMetrics phase helpers (chunk-9 WI-9.5c; file-level decompose of
202
178
  // the single-envelope projection — each helper mutates its own disjoint
@@ -211,9 +187,7 @@ function applyPlannedRefs(metrics, result) {
211
187
  // strategyFilteredRefs (array of {ref, reason}) — 2026-05-27: pre-filter
212
188
  // bucket from `collectEligibleRefs` so the metric reflects work the
213
189
  // planner dropped before signal-delta / per-pass dispatch.
214
- // Health v3 reports strategy metrics only. Historical v1 profile filtering
215
- // remains legacy data and must not be silently relabelled as a strategy metric.
216
- const strategyFilteredRefs = result.schemaVersion === 2 ? result.strategyFilteredRefs : undefined;
190
+ const strategyFilteredRefs = result.strategyFilteredRefs;
217
191
  if (Array.isArray(strategyFilteredRefs))
218
192
  metrics.strategyFilteredRefs += strategyFilteredRefs.length;
219
193
  }
@@ -252,11 +226,9 @@ function applyAction(metrics, action) {
252
226
  break;
253
227
  case "quality_rejected":
254
228
  case "review_needed":
255
- metrics.actions.distill.qualityRejected += 1;
256
229
  metrics.actions.distill.judgeRejected += 1;
257
230
  break;
258
231
  case "validation_failed":
259
- metrics.actions.distill.qualityRejected += 1;
260
232
  metrics.actions.distill.validatorRejected += 1;
261
233
  break;
262
234
  case "config_disabled":
@@ -282,13 +254,6 @@ function applyAction(metrics, action) {
282
254
  }
283
255
  break;
284
256
  }
285
- case "distill-skipped": {
286
- metrics.actions.distill.skipped += 1;
287
- const r = action.result;
288
- const reason = typeof r?.reason === "string" && r.reason.trim() ? r.reason : "unknown";
289
- metrics.actions.distill.skippedByReason[reason] = (metrics.actions.distill.skippedByReason[reason] ?? 0) + 1;
290
- break;
291
- }
292
257
  case "memory-prune":
293
258
  metrics.actions.memoryPrune += 1;
294
259
  break;
@@ -313,12 +278,8 @@ function applyActionsList(metrics, result) {
313
278
  }
314
279
  }
315
280
  /**
316
- * C1 (13-bus-factor): new runs persist the bounded `distillSkipped` aggregate
317
- * instead of per-ref `distill-skipped` rows. Read the total + per-reason
318
- * histogram from it into the SAME `distill.skipped` / `skippedByReason`
319
- * metric the per-ref loop above populated. Legacy rows carry the per-ref rows
320
- * and NO aggregate (counted above); new rows carry the aggregate and NO
321
- * per-ref rows (counted here) — so a run is never double-counted.
281
+ * Read the bounded `distillSkipped` aggregate into the corresponding total and
282
+ * per-reason health metrics.
322
283
  */
323
284
  function applyDistillSkippedAggregate(metrics, result) {
324
285
  const distillSkipped = result.distillSkipped;
@@ -437,18 +398,6 @@ function applyMemoryInference(metrics, result) {
437
398
  metrics.memoryInference.skippedAborted += toFiniteNumber(memoryInference.skippedAborted);
438
399
  metrics.memoryInference.unaccounted += toFiniteNumber(memoryInference.unaccounted);
439
400
  metrics.memoryInference.htmlErrorCount += toFiniteNumber(memoryInference.htmlErrorCount);
440
- // Yield-rate gating: pre-cache-feature envelopes lack the `cacheHits`
441
- // field entirely. Treating their `considered` as freshAttempts (since
442
- // cacheHits=0) is mathematically tempting but operationally wrong —
443
- // historical runs with the legacy schema have no cache instrumentation
444
- // and the SUM dragged the reported rate to ~14% in local data. Only
445
- // contribute to the yield aggregate when the envelope actually carries
446
- // the field. See investigation 2026-05-26.
447
- if (Object.hasOwn(memoryInference, "cacheHits")) {
448
- metrics.memoryInference.yieldEligibleRuns += 1;
449
- metrics.memoryInference.yieldEligibleConsidered += considered;
450
- metrics.memoryInference.yieldEligibleWritten += writtenFacts;
451
- }
452
401
  }
453
402
  metrics.memoryInference.durationMs += toFiniteNumber(result.memoryInferenceDurationMs);
454
403
  }
@@ -456,8 +405,10 @@ function applyGraphExtraction(metrics, result) {
456
405
  const graphExtraction = result.graphExtraction;
457
406
  if (graphExtraction) {
458
407
  const quality = graphExtraction.quality;
459
- if (quality)
408
+ if (quality) {
460
409
  metrics.graphExtraction.extractedFiles += toFiniteNumber(quality.extractedFiles);
410
+ metrics.graphExtraction.consideredFiles += toFiniteNumber(quality.consideredFiles);
411
+ }
461
412
  metrics.graphExtraction.entities += toFiniteNumber(graphExtraction.totalEntities);
462
413
  metrics.graphExtraction.relations += toFiniteNumber(graphExtraction.totalRelations);
463
414
  const telemetry = graphExtraction.telemetry;
@@ -526,19 +477,11 @@ function finalizeImproveMetrics(metrics) {
526
477
  metrics.memoryInference.considered > 0 ||
527
478
  metrics.memoryInference.written > 0 ||
528
479
  metrics.memoryInference.durationMs > 0;
529
- metrics.memoryInference.writes = metrics.memoryInference.written;
530
- // Yield denominator excludes cache hits AND legacy (pre-cacheHits-field)
531
- // envelopes. Only runs whose envelope carries a `cacheHits` field
532
- // contribute to freshAttempts/yieldRate; legacy rows remain in
533
- // `considered`/`written` for totals but are excluded from the rate so
534
- // they cannot drag it down. See ImproveHealthMetrics.memoryInference
535
- // jsdoc for the rationale.
536
- metrics.memoryInference.freshAttempts = Math.max(0, metrics.memoryInference.yieldEligibleConsidered -
537
- metrics.memoryInference.cacheHits -
538
- metrics.memoryInference.skippedAborted);
480
+ // Yield denominator excludes cache hits and aborted records.
481
+ metrics.memoryInference.freshAttempts = Math.max(0, metrics.memoryInference.considered - metrics.memoryInference.cacheHits - metrics.memoryInference.skippedAborted);
539
482
  metrics.memoryInference.yieldRate =
540
483
  metrics.memoryInference.freshAttempts > 0
541
- ? roundRate(metrics.memoryInference.yieldEligibleWritten / metrics.memoryInference.freshAttempts)
484
+ ? roundRate(metrics.memoryInference.written / metrics.memoryInference.freshAttempts)
542
485
  : 0;
543
486
  metrics.graphExtraction.ran =
544
487
  metrics.graphExtraction.extractedFiles > 0 ||
@@ -546,6 +489,10 @@ function finalizeImproveMetrics(metrics) {
546
489
  metrics.graphExtraction.durationMs > 0;
547
490
  const cacheTotal = metrics.graphExtraction.cacheHits + metrics.graphExtraction.cacheMisses;
548
491
  metrics.graphExtraction.cacheHitRate = cacheTotal > 0 ? roundRate(metrics.graphExtraction.cacheHits / cacheTotal) : 0;
492
+ metrics.graphExtraction.extractionCoverage =
493
+ metrics.graphExtraction.consideredFiles > 0
494
+ ? roundRate(metrics.graphExtraction.extractedFiles / metrics.graphExtraction.consideredFiles)
495
+ : 0;
549
496
  metrics.sessionExtraction.ran =
550
497
  metrics.sessionExtraction.sessionsScanned > 0 ||
551
498
  metrics.sessionExtraction.proposalsCreated > 0 ||
@@ -571,7 +518,6 @@ function mergeImproveMetrics(dst, src) {
571
518
  }
572
519
  dst.actions.distill.queued += src.actions.distill.queued;
573
520
  dst.actions.distill.llmFailed += src.actions.distill.llmFailed;
574
- dst.actions.distill.qualityRejected += src.actions.distill.qualityRejected;
575
521
  dst.actions.distill.judgeRejected += src.actions.distill.judgeRejected;
576
522
  dst.actions.distill.validatorRejected += src.actions.distill.validatorRejected;
577
523
  dst.actions.distill.configDisabled += src.actions.distill.configDisabled;
@@ -626,11 +572,10 @@ function mergeImproveMetrics(dst, src) {
626
572
  dst.memoryInference.skippedAborted += src.memoryInference.skippedAborted;
627
573
  dst.memoryInference.unaccounted += src.memoryInference.unaccounted;
628
574
  dst.memoryInference.htmlErrorCount += src.memoryInference.htmlErrorCount;
629
- dst.memoryInference.yieldEligibleRuns += src.memoryInference.yieldEligibleRuns;
630
- dst.memoryInference.yieldEligibleConsidered += src.memoryInference.yieldEligibleConsidered;
631
- dst.memoryInference.yieldEligibleWritten += src.memoryInference.yieldEligibleWritten;
575
+ dst.memoryInference.retryAttempts += src.memoryInference.retryAttempts;
632
576
  dst.memoryInference.durationMs += src.memoryInference.durationMs;
633
577
  dst.graphExtraction.extractedFiles += src.graphExtraction.extractedFiles;
578
+ dst.graphExtraction.consideredFiles += src.graphExtraction.consideredFiles;
634
579
  dst.graphExtraction.entities += src.graphExtraction.entities;
635
580
  dst.graphExtraction.relations += src.graphExtraction.relations;
636
581
  dst.graphExtraction.cacheHits += src.graphExtraction.cacheHits;
@@ -639,6 +584,7 @@ function mergeImproveMetrics(dst, src) {
639
584
  dst.graphExtraction.failures += src.graphExtraction.failures;
640
585
  dst.graphExtraction.htmlErrors += src.graphExtraction.htmlErrors;
641
586
  dst.graphExtraction.nonArrayBatchFailures += src.graphExtraction.nonArrayBatchFailures;
587
+ dst.graphExtraction.retryAttempts += src.graphExtraction.retryAttempts;
642
588
  dst.graphExtraction.durationMs += src.graphExtraction.durationMs;
643
589
  dst.sessionExtraction.sessionsScanned += src.sessionExtraction.sessionsScanned;
644
590
  dst.sessionExtraction.sessionsExtracted += src.sessionExtraction.sessionsExtracted;
@@ -662,7 +608,7 @@ function compareImproveRunRecency(a, b) {
662
608
  const started = a.started_at.localeCompare(b.started_at);
663
609
  if (started !== 0)
664
610
  return started;
665
- const completed = (a.completed_at ?? "").localeCompare(b.completed_at ?? "");
611
+ const completed = a.completed_at.localeCompare(b.completed_at);
666
612
  if (completed !== 0)
667
613
  return completed;
668
614
  return a.id.localeCompare(b.id);
@@ -696,14 +642,11 @@ export function summarizeImproveRuns(db, since, until) {
696
642
  continue;
697
643
  }
698
644
  accum.resultRows.included += 1;
699
- if (decoded.normalizedLegacyPartial)
700
- accum.resultRows.normalized += 1;
701
645
  const result = decoded.envelope;
702
646
  const perRow = projectRunMetrics(result);
703
647
  mergeImproveMetrics(accum, perRow);
704
648
  const startMs = new Date(row.started_at).getTime();
705
- if (!decoded.normalizedLegacyPartial &&
706
- result.terminated === undefined &&
649
+ if (result.terminated === undefined &&
707
650
  Number.isFinite(startMs) &&
708
651
  (latestCompleteRow === undefined || compareImproveRunRecency(row, latestCompleteRow) > 0)) {
709
652
  latestCompleteRow = row;
@@ -765,7 +708,7 @@ export function projectImproveRunSummary(row, wallTimeMs, taskId) {
765
708
  try {
766
709
  const decoded = decodeImproveResult(row.result_json);
767
710
  result = decoded.envelope;
768
- resultStatus = decoded.normalizedLegacyPartial ? "normalized" : "valid";
711
+ resultStatus = "valid";
769
712
  }
770
713
  catch {
771
714
  // Keep the persisted row visible in per-run output, but do not project its
@@ -787,7 +730,6 @@ export function projectImproveRunSummary(row, wallTimeMs, taskId) {
787
730
  resultStatus,
788
731
  resultComplete: resultStatus === "valid" && result.terminated === undefined,
789
732
  strategy: row.strategy,
790
- legacyProfile: row.legacyProfile,
791
733
  scope: {
792
734
  mode: row.scope_mode,
793
735
  ...(row.scope_value ? { value: row.scope_value } : {}),
@@ -16,9 +16,7 @@ function renderTable(headers, rows) {
16
16
  }
17
17
  /**
18
18
  * Render `--detail per-run` rows as a TSV-ish aligned table. The column
19
- * shape was originally inherited from the retired
20
- * `scripts/improve-stats/runs-detail` bash helper; keep the same shape
21
- * so operator muscle memory carries over.
19
+ * shape is stable so repeated operator reports remain easy to compare.
22
20
  *
23
21
  * Columns: ts | ok | actions | refl_ok/fail/cd/skip |
24
22
  * distill_q/llm-fail/qrej/cfg/skip | cons_proc/promo/merge/del |
@@ -29,10 +27,9 @@ export function renderRunsDetailMd(runs) {
29
27
  "ts",
30
28
  "ok",
31
29
  "strategy",
32
- "legacy_profile",
33
30
  "actions",
34
31
  "refl_ok/fail/cd/skip",
35
- "distill_q/llm-fail/qrej/cfg/skip",
32
+ "distill_q/llm-fail/judge/validator/cfg/skip",
36
33
  "cons_proc/promo/merge/del",
37
34
  "mem_cons/written/skip",
38
35
  "graph_f/e/r",
@@ -47,7 +44,8 @@ export function renderRunsDetailMd(runs) {
47
44
  r.actions.reflect.skipped +
48
45
  r.actions.distill.queued +
49
46
  r.actions.distill.llmFailed +
50
- r.actions.distill.qualityRejected +
47
+ r.actions.distill.judgeRejected +
48
+ r.actions.distill.validatorRejected +
51
49
  r.actions.distill.configDisabled +
52
50
  r.actions.distill.skipped +
53
51
  r.actions.memoryPrune +
@@ -58,10 +56,9 @@ export function renderRunsDetailMd(runs) {
58
56
  r.startedAt,
59
57
  String(r.ok),
60
58
  r.strategy ?? "",
61
- r.legacyProfile ?? "",
62
59
  String(totalActions),
63
60
  `${r.actions.reflect.ok}/${r.actions.reflect.failed}/${r.actions.reflect.cooldown}/${r.actions.reflect.skipped}`,
64
- `${r.actions.distill.queued}/${r.actions.distill.llmFailed}/${r.actions.distill.qualityRejected}/${r.actions.distill.configDisabled}/${r.actions.distill.skipped}`,
61
+ `${r.actions.distill.queued}/${r.actions.distill.llmFailed}/${r.actions.distill.judgeRejected}/${r.actions.distill.validatorRejected}/${r.actions.distill.configDisabled}/${r.actions.distill.skipped}`,
65
62
  `${r.consolidation.processed}/${r.consolidation.promoted}/${r.consolidation.merged}/${r.consolidation.deleted}`,
66
63
  `${r.memoryInference.considered}/${r.memoryInference.written}/${r.memoryInference.skippedNoFacts}`,
67
64
  `${r.graphExtraction.extractedFiles}/${r.graphExtraction.entities}/${r.graphExtraction.relations}`,
@@ -94,7 +91,6 @@ export function renderWindowCompareMd(windows, deltas) {
94
91
  const paths = [
95
92
  "runs",
96
93
  "improve.resultRows.included",
97
- "improve.resultRows.normalized",
98
94
  "improve.resultRows.skipped.invalid",
99
95
  ...INTERESTING_DELTA_PATHS,
100
96
  ];
@@ -6,28 +6,71 @@
6
6
  * denominator-fixed coverage, the enrichment-vs-minting rollup, and the WS-5
7
7
  * per-run degradation metrics.
8
8
  */
9
- import { appendEvent, readEvents } from "../../core/events.js";
9
+ import { rethrowIfTestIsolationError } from "../../core/errors.js";
10
10
  import { decodeImproveResult } from "../../core/improve-result.js";
11
+ import { withStateDb } from "../../core/state-db.js";
12
+ import { insertEvent } from "../../storage/repositories/events-repository.js";
11
13
  import { queryImproveRuns } from "../../storage/repositories/improve-runs-repository.js";
12
14
  import { listStateProposals } from "../../storage/repositories/proposals-repository.js";
15
+ import { getTopRetrievalSalience } from "../../storage/repositories/salience-repository.js";
13
16
  import { roundRate, toFiniteNumber } from "./improve-metrics.js";
14
17
  import { ENRICHMENT_LANES, } from "./types.js";
15
18
  /** Event type appended + read back by the state.db round-trip probe. */
16
19
  const HEALTH_PROBE_EVENT = "health_probe";
20
+ /** Synthetic sentinel ref (ref-grammar decision D-R3): a colon-free
21
+ * `<subsystem>/_<marker>` label. `health` has no asset stash-subdir, so
22
+ * `health/_probe` names the subsystem. */
23
+ const HEALTH_PROBE_REF = "health/_probe";
24
+ /**
25
+ * Verify state.db can accept a write and read it back — WITHOUT leaving any
26
+ * permanent trace (R-030). Earlier versions appended a `health_probe` event
27
+ * on every `akm health` invocation and never removed it: a read-only health
28
+ * check ran on a cron would grow state.db without bound (the only purge is
29
+ * `improve`'s retention pass, which a health-only user never runs). The probe
30
+ * row inserted here is deleted again inside the SAME connection once the
31
+ * round trip is confirmed, so the net effect on the `events` table is always
32
+ * zero rows — the round trip still genuinely exercises append + read against
33
+ * the real table, it just doesn't accumulate.
34
+ */
17
35
  export function probeStateDbRoundTrip(stateDbPath) {
18
- const before = readEvents({}, { dbPath: stateDbPath }).nextOffset;
19
36
  const started = Date.now();
20
- // Synthetic sentinel ref (ref-grammar decision D-R3): a colon-free
21
- // `<subsystem>/_<marker>` label. `health` has no asset stash-subdir, so
22
- // `health/_probe` names the subsystem. Written and read back in lockstep here;
23
- // the round-trip matches on `eventType` + this exact ref, so both must agree.
24
- appendEvent({ eventType: HEALTH_PROBE_EVENT, ref: "health/_probe", metadata: { source: "akm health" } }, { dbPath: stateDbPath });
25
- const after = readEvents({ sinceOffset: before, type: HEALTH_PROBE_EVENT, ref: "health/_probe" }, { dbPath: stateDbPath });
26
- const durationMs = Date.now() - started;
27
- if (after.events.length === 0 || after.nextOffset <= before) {
28
- return { ok: false, durationMs, error: "probe event was not readable after append" };
37
+ try {
38
+ return withStateDb((db) => {
39
+ const ts = new Date().toISOString();
40
+ const insertedId = insertEvent(db, {
41
+ eventType: HEALTH_PROBE_EVENT,
42
+ ts,
43
+ ref: HEALTH_PROBE_REF,
44
+ metadata: { source: "akm health" },
45
+ });
46
+ const durationMs = Date.now() - started;
47
+ if (insertedId === undefined) {
48
+ return { ok: false, durationMs, error: "probe event insert did not return a row id" };
49
+ }
50
+ // The round-trip matches on the exact (id, eventType, ref) triple
51
+ // written above, then removes the row regardless of outcome — a
52
+ // failed round trip must not leak a row any more than a successful
53
+ // one should.
54
+ let roundTripOk = false;
55
+ try {
56
+ const row = db
57
+ .prepare("SELECT 1 AS present FROM events WHERE id = ? AND event_type = ? AND ref = ?")
58
+ .get(insertedId, HEALTH_PROBE_EVENT, HEALTH_PROBE_REF);
59
+ roundTripOk = row !== undefined;
60
+ }
61
+ finally {
62
+ db.prepare("DELETE FROM events WHERE id = ?").run(insertedId);
63
+ }
64
+ if (!roundTripOk) {
65
+ return { ok: false, durationMs, error: "probe event was not readable after append" };
66
+ }
67
+ return { ok: true, durationMs };
68
+ }, { path: stateDbPath });
69
+ }
70
+ catch (err) {
71
+ rethrowIfTestIsolationError(err);
72
+ return { ok: false, durationMs: Date.now() - started, error: err instanceof Error ? err.message : String(err) };
29
73
  }
30
- return { ok: true, durationMs };
31
74
  }
32
75
  // ── WS-5 Observability helpers ───────────────────────────────────────────────
33
76
  /**
@@ -170,10 +213,10 @@ export function computeDegradationMetrics(db, since, until) {
170
213
  let entrenchmentFlagged;
171
214
  let salienceUniformityFlagged;
172
215
  try {
173
- const rows = db
174
- .prepare(`SELECT retrieval_salience FROM asset_salience
175
- ORDER BY rank_score DESC LIMIT 100`)
176
- .all();
216
+ // Fail-open: the asset_salience table may not exist yet (pre-WS-1 install).
217
+ // getTopRetrievalSalience (storage/repositories/salience-repository.ts,
218
+ // #672 part 2) owns the raw SQL; this call site's try/catch is unchanged.
219
+ const rows = getTopRetrievalSalience(db, 100);
177
220
  if (rows.length >= 5) {
178
221
  const vals = rows.map((r) => r.retrieval_salience).sort((a, b) => a - b);
179
222
  const n = vals.length;
@@ -181,12 +224,11 @@ export function computeDegradationMetrics(db, since, until) {
181
224
  return acc + vals.slice(i + 1).reduce((a, xj) => a + Math.abs(xi - xj), 0);
182
225
  }, 0);
183
226
  const mean = vals.reduce((a, b) => a + b, 0) / n;
184
- // Gini = (sum |xi - xj|) / (2 n^2 mean); 0 = perfect equality, 1 = perfect inequality.
185
- const gini = mean > 0 ? sumAbsDiff / (2 * n * n * mean) : 0;
227
+ // `sumAbsDiff` contains each unordered pair once, so the standard Gini
228
+ // denominator is n² × mean (the equivalent ordered-pair formula has 2n²).
229
+ const gini = mean > 0 ? sumAbsDiff / (n * n * mean) : 0;
186
230
  // Re-express as a diversity proxy in [0,1]: high gini = low diversity.
187
231
  // corpusCentroidDistance approximation: gini is "distance from uniform".
188
- // Note: retrieval_salience values are in [0,1], so the max achievable Gini
189
- // with this formula is ~0.5 (when one asset dominates and others are near 0).
190
232
  // Two-tailed: >0.35 flags entrenchment (robustly above the ~0.1 uniform
191
233
  // baseline); <0.08 flags uniformity collapse — the distribution no longer
192
234
  // discriminates between assets (live 2026-07 value 0.040 sat unflagged
@@ -0,0 +1,47 @@
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
+ * `akm health` document renderers, registered rather than intercepted (D7).
6
+ *
7
+ * Both handlers are **pure functions of the shaped result**. Everything the
8
+ * rich report needs — per-run rows, window-compare deltas, the pending
9
+ * proposal queue, and the window labels — travels in the result itself
10
+ * (`runs`/`deltas`/`report`, populated by `akm health --report`). There is no
11
+ * out-of-band context: an earlier revision bound the proposal queue through
12
+ * module state set by the command right before `output()`, which coupled the
13
+ * renderer to call order and made the command branch on the output format to
14
+ * know when to bind it. Putting the data in the envelope removed both.
15
+ *
16
+ * Returning `null` falls through to the generic renderer, so a result without
17
+ * the report dataset still renders — generically — instead of erroring or
18
+ * emitting an empty table.
19
+ */
20
+ import { renderHtml, resolveTemplatePath } from "../../output/html-render.js";
21
+ import { registerHtmlRenderer, registerMdRenderer } from "../../output/render-registry.js";
22
+ import { buildHealthHtmlReplacements } from "./html-report.js";
23
+ import { renderRunsDetailMd, renderWindowCompareMd } from "./md-report.js";
24
+ function isHealthResult(value) {
25
+ return value !== null && typeof value === "object" && "status" in value;
26
+ }
27
+ registerMdRenderer("health", (result) => {
28
+ if (!isHealthResult(result))
29
+ return null;
30
+ if (result.windows && result.windows.length > 0) {
31
+ return renderWindowCompareMd(result.windows, result.deltas);
32
+ }
33
+ if (result.runs)
34
+ return renderRunsDetailMd(result.runs);
35
+ return null;
36
+ });
37
+ registerHtmlRenderer("health", (result) => {
38
+ if (!isHealthResult(result) || !result.report)
39
+ return null;
40
+ return renderHtml(resolveTemplatePath("health"), buildHealthHtmlReplacements(result, {
41
+ window: result.report.window,
42
+ compare: result.report.compare,
43
+ comparisonMode: result.report.comparisonMode,
44
+ proposals: result.report.pendingProposals,
45
+ deltas: result.deltas,
46
+ }));
47
+ });
@@ -75,7 +75,6 @@ function reshapeRun(r) {
75
75
  resultComplete: r.resultComplete ?? (r.resultStatus === undefined || r.resultStatus === "valid"),
76
76
  taskId: r.taskId ?? "manual",
77
77
  strategy: r.strategy,
78
- legacyProfile: r.legacyProfile,
79
78
  startedAt: r.startedAt,
80
79
  completedAt: r.completedAt,
81
80
  wallTimeMs: wall,
@@ -94,7 +93,7 @@ function reshapeRun(r) {
94
93
  processed: cons.processed,
95
94
  failedChunks: cons.failedChunks,
96
95
  totalChunks: cons.totalChunks,
97
- miWritten: mi.written || mi.writes || 0,
96
+ miWritten: mi.written,
98
97
  miConsidered: mi.considered,
99
98
  miYieldRate: mi.yieldRate,
100
99
  miCacheHits: mi.cacheHits,
@@ -238,7 +237,7 @@ function buildAggregatesPhase(result, runsPhase) {
238
237
  const failedRuns = runs.filter((r) => !r.ok).length;
239
238
  const invoked = improve.invoked || totalRuns;
240
239
  const completed = improve.completed || totalRuns - failedRuns;
241
- const miWritten = mi.written || mi.writes || 0;
240
+ const miWritten = mi.written;
242
241
  return {
243
242
  consolidation: cons,
244
243
  memoryInference: mi,
@@ -251,7 +250,6 @@ function buildAggregatesPhase(result, runsPhase) {
251
250
  llm,
252
251
  memorySummary: improve.memorySummary,
253
252
  includedResultRows: improve.resultRows?.included ?? totalRuns,
254
- normalizedResultRows: improve.resultRows?.normalized ?? 0,
255
253
  skippedInvalidResultRows: improve.resultRows?.skipped.invalid ?? invalidRuns.length,
256
254
  invoked,
257
255
  completed,
@@ -375,7 +373,7 @@ function buildSummaryRows(aggregates, trend) {
375
373
  "Stash derived",
376
374
  num(aggregates.memorySummary.derived),
377
375
  "up",
378
- "Whole-stash recount of derived assets at report time — not a per-run sum.",
376
+ "Whole-bundle recount of derived assets at report time — not a per-run sum.",
379
377
  ],
380
378
  ["Median wall time", fmtMs(wallTime.medianMs), trend.latency],
381
379
  ["P95 wall time", fmtMs(wallTime.p95Ms), trend.latency],
@@ -490,6 +488,7 @@ export function buildHealthReportViewModel(result, opts) {
490
488
  return {
491
489
  window: opts.window,
492
490
  compare: opts.compare,
491
+ comparisonMode: opts.comparisonMode ?? "duration",
493
492
  ...meta,
494
493
  runs: runsPhase.runs,
495
494
  invalidRuns: runsPhase.invalidRuns,
@@ -40,7 +40,7 @@ export function collectStashExposureAdvisory(stashDir, git = realGit) {
40
40
  message: `${trackedFiles.length} env/secret file(s) are git-tracked AND a remote is configured — ` +
41
41
  `a 'git push' can leak tokens/keys (${preview}). ` +
42
42
  "Run 'git rm --cached' on them (a .gitignore rule alone does NOT untrack already-tracked " +
43
- "files) and then add env/+secrets/ to .gitignore to prevent recurrence (akm init scaffolds it).",
43
+ "files) and then add env/+secrets/ to .gitignore to prevent recurrence (akm bundle create scaffolds it).",
44
44
  evidence: { trackedSecretFiles: trackedFiles },
45
45
  };
46
46
  }