akm-cli 0.9.0-rc.0 → 0.9.0-rc.13

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 (598) hide show
  1. package/CHANGELOG.md +1283 -22
  2. package/README.md +62 -37
  3. package/SECURITY.md +46 -31
  4. package/dist/akm +162 -38
  5. package/dist/akm-migrate +44 -0
  6. package/dist/assets/backends/schtasks-template.xml +2 -1
  7. package/dist/assets/hints/cli-hints-full.md +268 -118
  8. package/dist/assets/hints/cli-hints-short.md +87 -24
  9. package/dist/assets/{profiles → improve-strategies}/catchup.json +3 -1
  10. package/dist/assets/{profiles → improve-strategies}/consolidate.json +3 -1
  11. package/dist/assets/{profiles → improve-strategies}/default.json +6 -7
  12. package/dist/assets/improve-strategies/frequent.json +15 -0
  13. package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +4 -2
  14. package/dist/assets/{profiles → improve-strategies}/memory-focus.json +4 -1
  15. package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +5 -5
  16. package/dist/assets/{profiles → improve-strategies}/quick.json +4 -2
  17. package/dist/assets/improve-strategies/reflect-distill.json +30 -0
  18. package/dist/assets/{profiles → improve-strategies}/thorough.json +1 -1
  19. package/dist/assets/prompts/consolidate-system.md +5 -5
  20. package/dist/assets/prompts/extract-session.md +2 -6
  21. package/dist/assets/prompts/memory-infer-user.md +2 -3
  22. package/dist/assets/prompts/reflect-llm-framed-contract.md +11 -0
  23. package/dist/assets/prompts/reflect-llm-schema-contract.md +3 -0
  24. package/dist/assets/prompts/reflect-output-repair.md +3 -0
  25. package/dist/assets/prompts/workflow-unit-preamble.md +26 -0
  26. package/dist/assets/stash-skeleton/README.md +38 -10
  27. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
  28. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
  29. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
  30. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
  31. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
  32. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
  33. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
  34. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
  35. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
  36. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
  37. package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
  38. package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
  39. package/dist/assets/tasks/core/extract.yml +3 -2
  40. package/dist/assets/tasks/core/improve.yml +2 -1
  41. package/dist/assets/tasks/core/index-refresh.yml +1 -0
  42. package/dist/assets/tasks/core/sync.yml +1 -0
  43. package/dist/assets/tasks/core/version-check.yml +2 -1
  44. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
  45. package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
  46. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
  47. package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
  48. package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
  49. package/dist/assets/templates/html/health.html +5 -4
  50. package/dist/assets/workflows/workflow-template.md +31 -15
  51. package/dist/cli/invocation.js +279 -0
  52. package/dist/cli/parse-args.js +5 -90
  53. package/dist/cli/retired-commands.js +78 -0
  54. package/dist/cli/shared.js +158 -48
  55. package/dist/cli-node.mjs +2 -1
  56. package/dist/cli.js +747 -293
  57. package/dist/commands/agent/agent-dispatch.js +19 -18
  58. package/dist/commands/agent/agent-support.js +0 -24
  59. package/dist/commands/agent/contribute-cli.js +43 -97
  60. package/dist/commands/completions.js +80 -23
  61. package/dist/commands/config-cli.js +44 -281
  62. package/dist/commands/env/env-binding.js +99 -0
  63. package/dist/commands/env/env-cli.js +84 -224
  64. package/dist/commands/env/env.js +12 -163
  65. package/dist/commands/env/marker-path.js +6 -0
  66. package/dist/commands/env/secret-cli.js +45 -61
  67. package/dist/commands/env/secret.js +32 -62
  68. package/dist/commands/feedback-cli.js +179 -85
  69. package/dist/commands/health/accept-rate.js +58 -0
  70. package/dist/commands/health/advisories.js +7 -8
  71. package/dist/commands/health/checks.js +279 -94
  72. package/dist/commands/health/html-report.js +197 -578
  73. package/dist/commands/health/improve-metrics.js +277 -246
  74. package/dist/commands/health/llm-usage.js +19 -19
  75. package/dist/commands/health/md-report.js +16 -7
  76. package/dist/commands/health/metrics.js +67 -32
  77. package/dist/commands/health/renderers.js +47 -0
  78. package/dist/commands/health/report-view-model.js +508 -0
  79. package/dist/commands/health/stash-exposure.js +1 -1
  80. package/dist/commands/health/surfaces.js +16 -56
  81. package/dist/commands/health/task-runs.js +3 -67
  82. package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
  83. package/dist/commands/health/types-improve.js +29 -0
  84. package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
  85. package/dist/commands/health/types-result.js +7 -0
  86. package/dist/commands/health/types-runs.js +4 -0
  87. package/dist/commands/health/types-session-log.js +4 -0
  88. package/dist/commands/health/types-windows.js +4 -0
  89. package/dist/commands/health/types.js +26 -21
  90. package/dist/commands/health/windows.js +2 -3
  91. package/dist/commands/health.js +296 -167
  92. package/dist/commands/improve/anti-collapse.js +5 -5
  93. package/dist/commands/improve/autonomy-gate.js +68 -0
  94. package/dist/commands/improve/collapse-detector.js +65 -52
  95. package/dist/commands/improve/consolidate/chunking.js +9 -7
  96. package/dist/commands/improve/consolidate/eligibility.js +1 -23
  97. package/dist/commands/improve/consolidate/merge.js +4 -0
  98. package/dist/commands/improve/consolidate.js +454 -1354
  99. package/dist/commands/improve/content-hash.js +39 -0
  100. package/dist/commands/improve/distill/content-repair.js +4 -10
  101. package/dist/commands/improve/distill/promote-memory.js +89 -64
  102. package/dist/commands/improve/distill/quality-gate.js +118 -42
  103. package/dist/commands/improve/distill-guards.js +1 -1
  104. package/dist/commands/improve/distill-promotion-policy.js +33 -888
  105. package/dist/commands/improve/distill.js +607 -363
  106. package/dist/commands/improve/eligibility.js +165 -79
  107. package/dist/commands/improve/extract-cli.js +35 -126
  108. package/dist/commands/improve/extract-prompt.js +6 -35
  109. package/dist/commands/improve/extract.js +640 -391
  110. package/dist/commands/improve/feedback-valence.js +2 -12
  111. package/dist/commands/improve/improve-cli.js +134 -135
  112. package/dist/commands/improve/improve-result-file.js +30 -50
  113. package/dist/commands/improve/improve-run-types.js +4 -0
  114. package/dist/commands/improve/improve-strategies.js +135 -0
  115. package/dist/commands/improve/improve.js +904 -701
  116. package/dist/commands/improve/locks.js +64 -111
  117. package/dist/commands/improve/loop-stages.js +1110 -923
  118. package/dist/commands/improve/memory/derived-ref.js +124 -0
  119. package/dist/commands/improve/memory/memory-belief.js +79 -7
  120. package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
  121. package/dist/commands/improve/memory/memory-improve.js +25 -37
  122. package/dist/commands/improve/outcome-loop.js +25 -88
  123. package/dist/commands/improve/preparation.js +1034 -813
  124. package/dist/commands/improve/proactive-maintenance.js +34 -9
  125. package/dist/commands/improve/proposal-envelope.js +31 -0
  126. package/dist/commands/improve/reflect.js +983 -794
  127. package/dist/commands/improve/run-context.js +119 -0
  128. package/dist/commands/improve/salience.js +24 -127
  129. package/dist/commands/improve/session-asset.js +7 -3
  130. package/dist/commands/improve/shared.js +14 -34
  131. package/dist/commands/improve/source-identity.js +28 -0
  132. package/dist/commands/improve/triage.js +20 -17
  133. package/dist/commands/lint/base-linter.js +340 -313
  134. package/dist/commands/lint/env-key-rules.js +31 -47
  135. package/dist/commands/lint/index.js +185 -30
  136. package/dist/commands/{events.js → log.js} +28 -38
  137. package/dist/commands/migrate-cli.js +54 -0
  138. package/dist/commands/migration-tool.js +55 -0
  139. package/dist/commands/observability-cli.js +70 -208
  140. package/dist/commands/proposal/diff-format.js +50 -0
  141. package/dist/commands/proposal/drain-policies.js +0 -6
  142. package/dist/commands/proposal/drain.js +91 -40
  143. package/dist/commands/proposal/proposal-cli.js +134 -132
  144. package/dist/commands/proposal/proposal-types.js +56 -0
  145. package/dist/commands/proposal/proposal.js +83 -65
  146. package/dist/commands/proposal/propose-cli.js +88 -0
  147. package/dist/commands/proposal/propose.js +105 -88
  148. package/dist/commands/proposal/repository.js +1303 -278
  149. package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
  150. package/dist/commands/proposal/validators/proposal-validators.js +61 -12
  151. package/dist/commands/proposal/validators/proposals.js +6 -8
  152. package/dist/commands/read/curate.js +78 -73
  153. package/dist/commands/read/knowledge.js +510 -13
  154. package/dist/commands/read/registry-search.js +2 -2
  155. package/dist/commands/read/remember-cli.js +84 -15
  156. package/dist/commands/read/search-cli.js +203 -96
  157. package/dist/commands/read/search.js +126 -94
  158. package/dist/commands/read/show.js +226 -250
  159. package/dist/commands/registry-cli.js +34 -60
  160. package/dist/commands/remember.js +18 -57
  161. package/dist/commands/sources/add-cli.js +104 -49
  162. package/dist/commands/sources/bundle-cli.js +166 -0
  163. package/dist/commands/sources/bundle-config-ops.js +63 -0
  164. package/dist/commands/sources/info.js +27 -15
  165. package/dist/commands/sources/init.js +30 -40
  166. package/dist/commands/sources/installed-stashes.js +469 -172
  167. package/dist/commands/sources/migration-help.js +7 -4
  168. package/dist/commands/sources/schema-repair.js +10 -9
  169. package/dist/commands/sources/self-update.js +182 -121
  170. package/dist/commands/sources/source-add.js +169 -178
  171. package/dist/commands/sources/source-clone.js +144 -41
  172. package/dist/commands/sources/source-manage.js +94 -59
  173. package/dist/commands/sources/sources-cli.js +64 -205
  174. package/dist/commands/sources/stash-cli.js +91 -54
  175. package/dist/commands/sources/stash-skeleton.js +1 -1
  176. package/dist/commands/tasks/tasks-cli.js +106 -104
  177. package/dist/commands/tasks/tasks.js +445 -262
  178. package/dist/commands/workflow-cli.js +232 -121
  179. package/dist/core/action-contributors.js +1 -1
  180. package/dist/core/activation-policy.js +49 -0
  181. package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
  182. package/dist/core/adapter/adapters/akm-adapter.js +528 -0
  183. package/dist/core/adapter/adapters/akm-lint.js +392 -0
  184. package/dist/core/adapter/adapters/akm-metadata.js +387 -0
  185. package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
  186. package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
  187. package/dist/core/adapter/adapters/claude-adapter.js +61 -0
  188. package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
  189. package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
  190. package/dist/core/adapter/adapters/index.js +80 -0
  191. package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
  192. package/dist/core/adapter/adapters/okf-adapter.js +391 -0
  193. package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
  194. package/dist/core/adapter/adapters/shared.js +286 -0
  195. package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
  196. package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
  197. package/dist/core/adapter/bundle-adapter.js +4 -0
  198. package/dist/core/adapter/detect-adapter.js +17 -0
  199. package/dist/core/adapter/recognize-match.js +44 -0
  200. package/dist/core/adapter/registry.js +56 -0
  201. package/dist/core/adapter/types.js +4 -0
  202. package/dist/core/asset/akm-markdown.js +30 -0
  203. package/dist/core/asset/asset-placement.js +243 -0
  204. package/dist/core/asset/asset-ref.js +110 -79
  205. package/dist/core/asset/asset-serialize.js +20 -0
  206. package/dist/core/asset/frontmatter.js +28 -12
  207. package/dist/core/asset/markdown.js +40 -51
  208. package/dist/core/asset/resolve-ref.js +274 -0
  209. package/dist/core/asset/stash-meta.js +2 -2
  210. package/dist/core/bundle-id.js +51 -0
  211. package/dist/core/common.js +281 -86
  212. package/dist/core/config/config-io.js +42 -128
  213. package/dist/core/config/config-schema.js +233 -834
  214. package/dist/core/config/config-sources.js +162 -39
  215. package/dist/core/config/config-types.js +16 -11
  216. package/dist/core/config/config-version.js +29 -0
  217. package/dist/core/config/config-walker.js +126 -37
  218. package/dist/core/config/config.js +154 -331
  219. package/dist/core/config/deep-merge.js +41 -0
  220. package/dist/core/config/engine-semantics.js +28 -0
  221. package/dist/core/config/experimental.js +21 -0
  222. package/dist/core/config/schema/embedding.js +38 -0
  223. package/dist/core/config/schema/engines.js +116 -0
  224. package/dist/core/config/schema/experimental.js +47 -0
  225. package/dist/core/config/schema/feedback.js +31 -0
  226. package/dist/core/config/schema/improve-processes.js +389 -0
  227. package/dist/core/config/schema/improve.js +94 -0
  228. package/dist/core/config/schema/index-config.js +176 -0
  229. package/dist/core/config/schema/output.js +18 -0
  230. package/dist/core/config/schema/primitives.js +94 -0
  231. package/dist/core/config/schema/search.js +30 -0
  232. package/dist/core/config/schema/setup.js +18 -0
  233. package/dist/core/config/schema/sources-bundles.js +169 -0
  234. package/dist/core/config/schema/workflow.js +29 -0
  235. package/dist/core/env-secret-ref.js +155 -20
  236. package/dist/core/errors.js +17 -15
  237. package/dist/core/events-types.js +4 -0
  238. package/dist/core/events.js +46 -128
  239. package/dist/core/extra-params.js +62 -0
  240. package/dist/core/file-change.js +17 -0
  241. package/dist/core/file-lock.js +202 -57
  242. package/dist/core/fs-txn.js +392 -0
  243. package/dist/core/git-message.js +59 -0
  244. package/dist/core/improve-result.js +167 -0
  245. package/dist/core/json-schema.js +142 -0
  246. package/dist/core/lesson-lint.js +1 -17
  247. package/dist/core/logs-db.js +1 -1
  248. package/dist/core/maintenance-barrier.js +135 -0
  249. package/dist/core/migration-operation.js +44 -0
  250. package/dist/core/mutation-target.js +78 -0
  251. package/dist/core/paths.js +22 -25
  252. package/dist/core/platform.js +10 -0
  253. package/dist/core/recognition-util.js +128 -0
  254. package/dist/core/redaction.js +392 -0
  255. package/dist/core/standards/resolve-standards-context.js +36 -65
  256. package/dist/core/standards/resolve-stash-standards.js +2 -2
  257. package/dist/core/standards/resolve-type-conventions.js +5 -5
  258. package/dist/core/state/migrations.js +242 -11
  259. package/dist/core/state-db.js +98 -10
  260. package/dist/core/structured.js +1 -1
  261. package/dist/core/subprocess.js +303 -0
  262. package/dist/core/text-truncation.js +9 -5
  263. package/dist/core/time.js +20 -0
  264. package/dist/core/type-presentation.js +130 -0
  265. package/dist/core/warn.js +0 -3
  266. package/dist/core/write-source.js +834 -118
  267. package/dist/indexer/bundle-identity-guard.js +92 -0
  268. package/dist/indexer/db/graph-db.js +1 -25
  269. package/dist/indexer/db/llm-cache.js +1 -1
  270. package/dist/indexer/ensure-index.js +30 -9
  271. package/dist/indexer/graph/graph-boost.js +9 -30
  272. package/dist/indexer/graph/graph-extraction.js +41 -27
  273. package/dist/indexer/graph/graph-types.js +4 -0
  274. package/dist/indexer/index-writer-lock.js +93 -49
  275. package/dist/indexer/index-written-assets.js +100 -53
  276. package/dist/indexer/indexer.js +746 -329
  277. package/dist/indexer/init.js +18 -25
  278. package/dist/indexer/installations.js +142 -0
  279. package/dist/indexer/passes/dir-staleness.js +18 -10
  280. package/dist/indexer/passes/memory-inference.js +25 -15
  281. package/dist/indexer/passes/metadata.js +412 -243
  282. package/dist/indexer/scan/doc-to-entry.js +160 -0
  283. package/dist/indexer/scan/drain-dir.js +134 -0
  284. package/dist/indexer/search/db-search.js +292 -108
  285. package/dist/indexer/search/fts-query.js +64 -0
  286. package/dist/indexer/search/ranking-contributors.js +145 -25
  287. package/dist/indexer/search/ranking-types.js +4 -0
  288. package/dist/indexer/search/ranking.js +28 -71
  289. package/dist/indexer/search/search-attribution.js +67 -0
  290. package/dist/indexer/search/search-fields.js +18 -3
  291. package/dist/indexer/search/search-hit-enrichers.js +30 -40
  292. package/dist/indexer/search/search-source.js +157 -111
  293. package/dist/indexer/search/semantic-status.js +4 -1
  294. package/dist/indexer/usage/usage-events.js +10 -30
  295. package/dist/indexer/walk/file-context.js +3 -45
  296. package/dist/indexer/walk/matchers.js +42 -34
  297. package/dist/indexer/walk/path-resolver.js +11 -5
  298. package/dist/indexer/walk/walker.js +42 -14
  299. package/dist/integrations/agent/builder-shared.js +7 -0
  300. package/dist/integrations/agent/builders.js +5 -56
  301. package/dist/integrations/agent/config.js +3 -143
  302. package/dist/integrations/agent/detect.js +17 -2
  303. package/dist/integrations/agent/engine-resolution.js +231 -0
  304. package/dist/integrations/agent/index.js +1 -2
  305. package/dist/integrations/agent/model-aliases.js +16 -2
  306. package/dist/integrations/agent/profiles.js +36 -62
  307. package/dist/integrations/agent/prompts.js +46 -18
  308. package/dist/integrations/agent/runner-dispatch.js +93 -4
  309. package/dist/integrations/agent/runner.js +76 -208
  310. package/dist/integrations/agent/spawn.js +88 -196
  311. package/dist/integrations/harnesses/aider/agent-builder.js +114 -0
  312. package/dist/integrations/harnesses/aider/index.js +48 -0
  313. package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
  314. package/dist/integrations/harnesses/amazonq/agent-builder.js +147 -0
  315. package/dist/integrations/harnesses/amazonq/index.js +45 -0
  316. package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
  317. package/dist/integrations/harnesses/claude/agent-builder.js +46 -8
  318. package/dist/integrations/harnesses/claude/config-import.js +1 -3
  319. package/dist/integrations/harnesses/claude/index.js +24 -35
  320. package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
  321. package/dist/integrations/harnesses/claude/session-log.js +27 -75
  322. package/dist/integrations/harnesses/codex/agent-builder.js +138 -0
  323. package/dist/integrations/harnesses/codex/index.js +52 -0
  324. package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
  325. package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
  326. package/dist/integrations/harnesses/copilot/index.js +48 -0
  327. package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
  328. package/dist/integrations/harnesses/gemini/agent-builder.js +120 -0
  329. package/dist/integrations/harnesses/gemini/index.js +48 -0
  330. package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
  331. package/dist/integrations/harnesses/ids.js +24 -0
  332. package/dist/integrations/harnesses/index.js +54 -34
  333. package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
  334. package/dist/integrations/harnesses/opencode/config-import.js +1 -3
  335. package/dist/integrations/harnesses/opencode/index.js +14 -32
  336. package/dist/integrations/harnesses/opencode/session-log.js +67 -125
  337. package/dist/integrations/harnesses/opencode-sdk/harness.js +51 -0
  338. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +681 -108
  339. package/dist/integrations/harnesses/openhands/agent-builder.js +128 -0
  340. package/dist/integrations/harnesses/openhands/index.js +48 -0
  341. package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
  342. package/dist/integrations/harnesses/pi/agent-builder.js +97 -0
  343. package/dist/integrations/harnesses/pi/index.js +45 -0
  344. package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
  345. package/dist/integrations/harnesses/shared.js +17 -0
  346. package/dist/integrations/harnesses/types.js +43 -32
  347. package/dist/integrations/lockfile.js +211 -24
  348. package/dist/integrations/session-logs/index.js +36 -39
  349. package/dist/integrations/session-logs/provider-base.js +113 -0
  350. package/dist/llm/client.js +182 -110
  351. package/dist/llm/embedders/deterministic.js +2 -2
  352. package/dist/llm/embedders/remote.js +21 -9
  353. package/dist/llm/feature-gate.js +17 -57
  354. package/dist/llm/graph-extract.js +12 -13
  355. package/dist/llm/index-passes.js +8 -42
  356. package/dist/llm/memory-infer.js +144 -1
  357. package/dist/llm/metadata-enhance.js +45 -30
  358. package/dist/llm/structured-call.js +16 -8
  359. package/dist/llm/usage-persist.js +30 -5
  360. package/dist/llm/usage-telemetry.js +59 -6
  361. package/dist/output/cli-hints.js +1 -2
  362. package/dist/output/command-registry.js +27 -0
  363. package/dist/output/context.js +22 -7
  364. package/dist/output/format-exempt.js +80 -0
  365. package/dist/output/generic-render.js +251 -0
  366. package/dist/output/html-render.js +11 -16
  367. package/dist/output/render-registry.js +57 -0
  368. package/dist/output/renderers.js +14 -279
  369. package/dist/output/shapes/curate.js +10 -1
  370. package/dist/output/shapes/events.js +12 -7
  371. package/dist/output/shapes/helpers.js +58 -84
  372. package/dist/output/shapes/passthrough.js +11 -39
  373. package/dist/output/shapes/proposal/producer.js +15 -7
  374. package/dist/output/shapes/registry.js +12 -6
  375. package/dist/output/shapes.js +0 -9
  376. package/dist/output/text/{init.js → bundle-create.js} +3 -1
  377. package/dist/output/text/bundle-show.js +7 -0
  378. package/dist/output/text/command-format.js +562 -0
  379. package/dist/output/text/env.js +1 -3
  380. package/dist/output/text/events.js +8 -7
  381. package/dist/output/text/helpers.js +15 -1164
  382. package/dist/output/text/proposal/producer.js +4 -2
  383. package/dist/output/text/proposal-format.js +202 -0
  384. package/dist/output/text/registry-commands.js +1 -2
  385. package/dist/output/text/registry.js +12 -6
  386. package/dist/output/text/show-directives.js +117 -0
  387. package/dist/output/text/show-format.js +103 -0
  388. package/dist/output/text/sync.js +5 -0
  389. package/dist/output/text/workflow-format.js +332 -0
  390. package/dist/output/text/workflow.js +3 -2
  391. package/dist/output/text.js +10 -19
  392. package/dist/registry/factory.js +4 -6
  393. package/dist/registry/origin-resolve.js +16 -27
  394. package/dist/registry/providers/skills-sh.js +3 -3
  395. package/dist/registry/providers/static-index.js +15 -25
  396. package/dist/registry/resolve.js +43 -94
  397. package/dist/registry/semver.js +43 -0
  398. package/dist/runtime.js +81 -12
  399. package/dist/scripts/akm-migrate.js +35529 -0
  400. package/dist/setup/detect.js +5 -7
  401. package/dist/setup/detected-engines.js +136 -0
  402. package/dist/setup/engine-config.js +100 -0
  403. package/dist/setup/registry-stash-loader.js +3 -3
  404. package/dist/setup/semantic-assets.js +12 -9
  405. package/dist/setup/setup.js +444 -208
  406. package/dist/setup/steps/connection-shared.js +120 -0
  407. package/dist/setup/steps/connection.js +108 -305
  408. package/dist/setup/steps/platforms.js +13 -12
  409. package/dist/setup/steps/semantic.js +15 -3
  410. package/dist/setup/steps/sources.js +21 -15
  411. package/dist/setup/steps/stashdir.js +6 -4
  412. package/dist/setup/steps/tasks.js +236 -119
  413. package/dist/setup/steps.js +3 -2
  414. package/dist/sources/freshness.js +39 -0
  415. package/dist/sources/provider-factory.js +11 -17
  416. package/dist/sources/providers/filesystem.js +2 -3
  417. package/dist/sources/providers/git-install.js +278 -34
  418. package/dist/sources/providers/git-provider.js +54 -56
  419. package/dist/sources/providers/git-stash.js +420 -91
  420. package/dist/sources/providers/git.js +2 -2
  421. package/dist/sources/providers/npm.js +16 -19
  422. package/dist/sources/providers/provider-utils.js +47 -22
  423. package/dist/sources/providers/sync-from-ref.js +3 -9
  424. package/dist/sources/providers/website.js +2 -2
  425. package/dist/sources/resolve.js +11 -10
  426. package/dist/sources/snapshot-fetchers/types.js +4 -0
  427. package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
  428. package/dist/storage/database.js +60 -4
  429. package/dist/storage/engines/sqlite-migrations.js +156 -5
  430. package/dist/storage/locations.js +1 -2
  431. package/dist/storage/repositories/canaries-repository.js +1 -1
  432. package/dist/storage/repositories/events-repository.js +51 -11
  433. package/dist/storage/repositories/improve-runs-repository.js +6 -32
  434. package/dist/storage/repositories/index-connection.js +79 -0
  435. package/dist/storage/repositories/index-db.js +4 -3
  436. package/dist/storage/repositories/index-entries-repository.js +863 -0
  437. package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
  438. package/dist/storage/repositories/index-entry-types.js +4 -0
  439. package/dist/storage/repositories/index-fts-repository.js +167 -0
  440. package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
  441. package/dist/storage/repositories/index-meta-repository.js +49 -0
  442. package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
  443. package/dist/storage/repositories/index-sql.js +12 -0
  444. package/dist/storage/repositories/index-utility-repository.js +356 -0
  445. package/dist/storage/repositories/index-vec-repository.js +250 -0
  446. package/dist/storage/repositories/outcome-repository.js +119 -0
  447. package/dist/storage/repositories/proposals-repository.js +317 -75
  448. package/dist/storage/repositories/registry-cache.js +1 -1
  449. package/dist/storage/repositories/salience-repository.js +172 -0
  450. package/dist/storage/repositories/task-history-repository.js +110 -3
  451. package/dist/storage/repositories/workflow-runs-repository.js +240 -19
  452. package/dist/tasks/backends/cron.js +169 -46
  453. package/dist/tasks/backends/exec-utils.js +76 -3
  454. package/dist/tasks/backends/index.js +6 -9
  455. package/dist/tasks/backends/launchd.js +292 -55
  456. package/dist/tasks/backends/schtasks.js +557 -70
  457. package/dist/tasks/backends/types.js +4 -0
  458. package/dist/tasks/command-executable.js +93 -0
  459. package/dist/tasks/embedded.js +56 -38
  460. package/dist/tasks/parser.js +156 -64
  461. package/dist/tasks/resolve-akm-bin.js +144 -51
  462. package/dist/tasks/runner.js +377 -209
  463. package/dist/tasks/schedule.js +108 -19
  464. package/dist/tasks/scheduler-invocation.js +296 -0
  465. package/dist/tasks/schema.js +1 -1
  466. package/dist/tasks/task-id.js +35 -0
  467. package/dist/tasks/validator.js +30 -16
  468. package/dist/text-import-hook.mjs +1 -1
  469. package/dist/workflows/authoring/authoring.js +104 -43
  470. package/dist/workflows/authoring/scope-key.js +1 -1
  471. package/dist/workflows/cli.js +0 -16
  472. package/dist/workflows/concurrency-policy.js +15 -0
  473. package/dist/workflows/exec/brief.js +450 -0
  474. package/dist/workflows/exec/frozen-judge.js +47 -0
  475. package/dist/workflows/exec/native-executor.js +1038 -0
  476. package/dist/workflows/exec/param-secrets.js +115 -0
  477. package/dist/workflows/exec/report.js +1460 -0
  478. package/dist/workflows/exec/run-workflow.js +602 -0
  479. package/dist/workflows/exec/scheduler.js +71 -0
  480. package/dist/workflows/exec/step-work.js +1190 -0
  481. package/dist/workflows/exec/unit-writer.js +23 -0
  482. package/dist/workflows/exec/workflow-engine-gate.js +67 -0
  483. package/dist/workflows/exec/worktree.js +171 -0
  484. package/dist/workflows/ir/compile.js +246 -0
  485. package/dist/workflows/ir/freeze.js +233 -0
  486. package/dist/workflows/ir/params.js +54 -0
  487. package/dist/workflows/ir/plan-hash.js +68 -0
  488. package/dist/workflows/ir/schema.js +540 -0
  489. package/dist/workflows/parser.js +878 -304
  490. package/dist/workflows/program/expressions.js +181 -0
  491. package/dist/workflows/program/schema.js +51 -0
  492. package/dist/workflows/renderer.js +100 -45
  493. package/dist/workflows/resource-limits.js +22 -0
  494. package/dist/workflows/runtime/agent-identity.js +59 -14
  495. package/dist/workflows/runtime/checkin.js +1 -1
  496. package/dist/workflows/runtime/plan-classifier.js +131 -0
  497. package/dist/workflows/runtime/runs.js +376 -119
  498. package/dist/workflows/runtime/unit-checkin.js +45 -0
  499. package/dist/workflows/runtime/unit-phases.js +20 -0
  500. package/dist/workflows/runtime/workflow-asset-loader.js +241 -40
  501. package/dist/workflows/schema.js +1 -11
  502. package/dist/workflows/validate-summary.js +2 -3
  503. package/dist/workflows/validator.js +52 -30
  504. package/docs/README.md +42 -78
  505. package/docs/migration/README.md +8 -0
  506. package/docs/migration/release-notes/0.6.0.md +1 -1
  507. package/docs/migration/release-notes/0.7.0.md +9 -8
  508. package/docs/migration/release-notes/0.9.0.md +158 -14
  509. package/docs/migration/v0.7-to-v0.8.md +46 -47
  510. package/docs/migration/v0.8-to-v0.9.md +844 -0
  511. package/docs/reference/README.md +12 -0
  512. package/docs/reference/data-and-telemetry.md +333 -0
  513. package/package.json +21 -17
  514. package/schemas/akm-asset-envelope.json +93 -0
  515. package/schemas/akm-config.json +4636 -0
  516. package/schemas/akm-task.json +87 -0
  517. package/schemas/akm-workflow.json +373 -0
  518. package/dist/akm-migrate-storage +0 -38
  519. package/dist/assets/help/help-accept.md +0 -12
  520. package/dist/assets/help/help-improve.md +0 -84
  521. package/dist/assets/help/help-proposals.md +0 -17
  522. package/dist/assets/help/help-propose.md +0 -17
  523. package/dist/assets/help/help-reject.md +0 -11
  524. package/dist/assets/profiles/frequent.json +0 -13
  525. package/dist/assets/profiles/recombine-only.json +0 -21
  526. package/dist/assets/profiles/reflect-distill.json +0 -30
  527. package/dist/assets/profiles/synthesize.json +0 -15
  528. package/dist/assets/prompts/procedural-system.md +0 -44
  529. package/dist/assets/prompts/recombine-system.md +0 -40
  530. package/dist/assets/prompts/staleness-detect-system.md +0 -6
  531. package/dist/assets/tasks/core/backup.yml +0 -4
  532. package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
  533. package/dist/assets/templates/html/default.html +0 -78
  534. package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
  535. package/dist/assets/wiki/index-template.md +0 -12
  536. package/dist/assets/wiki/ingest-workflow-template.md +0 -83
  537. package/dist/assets/wiki/log-template.md +0 -8
  538. package/dist/assets/wiki/schema-template.md +0 -61
  539. package/dist/cli/config-migrate.js +0 -150
  540. package/dist/cli/config-validate.js +0 -39
  541. package/dist/commands/graph/graph-cli.js +0 -124
  542. package/dist/commands/graph/graph.js +0 -487
  543. package/dist/commands/improve/calibration.js +0 -161
  544. package/dist/commands/improve/dedup.js +0 -482
  545. package/dist/commands/improve/extract-watch.js +0 -140
  546. package/dist/commands/improve/hot-probation.js +0 -45
  547. package/dist/commands/improve/improve-auto-accept.js +0 -276
  548. package/dist/commands/improve/improve-profiles.js +0 -168
  549. package/dist/commands/improve/procedural.js +0 -398
  550. package/dist/commands/improve/recombine.js +0 -818
  551. package/dist/commands/improve/schema-similarity-gate.js +0 -168
  552. package/dist/commands/lint/agent-linter.js +0 -44
  553. package/dist/commands/lint/command-linter.js +0 -44
  554. package/dist/commands/lint/default-linter.js +0 -16
  555. package/dist/commands/lint/fact-linter.js +0 -39
  556. package/dist/commands/lint/knowledge-linter.js +0 -16
  557. package/dist/commands/lint/memory-linter.js +0 -61
  558. package/dist/commands/lint/registry.js +0 -41
  559. package/dist/commands/lint/skill-linter.js +0 -45
  560. package/dist/commands/lint/task-linter.js +0 -50
  561. package/dist/commands/lint/workflow-linter.js +0 -81
  562. package/dist/commands/proposal/legacy-import.js +0 -115
  563. package/dist/commands/sources/history.js +0 -196
  564. package/dist/commands/tasks/default-tasks.js +0 -186
  565. package/dist/commands/wiki-cli.js +0 -292
  566. package/dist/core/asset/asset-registry.js +0 -76
  567. package/dist/core/asset/asset-spec.js +0 -259
  568. package/dist/core/config/config-migration.js +0 -602
  569. package/dist/core/deep-merge.js +0 -38
  570. package/dist/core/eval/rank-metrics.js +0 -113
  571. package/dist/core/ripgrep/install.js +0 -163
  572. package/dist/core/ripgrep/resolve.js +0 -81
  573. package/dist/indexer/db/db.js +0 -1413
  574. package/dist/indexer/manifest.js +0 -170
  575. package/dist/indexer/passes/metadata-contributors.js +0 -31
  576. package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
  577. package/dist/integrations/harnesses/opencode-sdk/index.js +0 -49
  578. package/dist/llm/call-ai.js +0 -62
  579. package/dist/llm/memory-infer-impl.js +0 -138
  580. package/dist/output/shapes/distill.js +0 -14
  581. package/dist/output/shapes/history.js +0 -11
  582. package/dist/output/text/distill.js +0 -6
  583. package/dist/output/text/enable-disable.js +0 -8
  584. package/dist/output/text/history.js +0 -6
  585. package/dist/output/text/wiki.js +0 -16
  586. package/dist/registry/build-index.js +0 -386
  587. package/dist/scripts/migrate-storage.js +0 -19108
  588. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -9411
  589. package/dist/scripts/migrations/v16-to-v17.js +0 -141
  590. package/dist/setup/legacy-config.js +0 -106
  591. package/dist/storage/repositories/consolidation-repository.js +0 -38
  592. package/dist/storage/repositories/recombine-repository.js +0 -213
  593. package/dist/wiki/wiki-templates.js +0 -15
  594. package/dist/wiki/wiki.js +0 -1012
  595. package/dist/workflows/db.js +0 -215
  596. package/docs/data-and-telemetry.md +0 -226
  597. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
  598. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
@@ -1,18 +1,19 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ import { decodeImproveResult } from "../../core/improve-result.js";
4
5
  import { queryImproveRuns } from "../../storage/repositories/improve-runs-repository.js";
5
- import { summarizeCalibration } from "../improve/calibration.js";
6
+ import { decodeTaskHistoryMetadata } from "../../storage/repositories/task-history-repository.js";
6
7
  export function roundRate(value) {
7
8
  return Number(value.toFixed(4));
8
9
  }
9
10
  export function parseTaskMetadata(row) {
10
- try {
11
- return JSON.parse(row.metadata_json);
12
- }
13
- catch {
14
- return {};
15
- }
11
+ const metadata = decodeTaskHistoryMetadata(row.metadata_json);
12
+ return {
13
+ ...(metadata.durationMs !== undefined ? { durationMs: metadata.durationMs } : {}),
14
+ ...(metadata.detail ? { detail: metadata.detail } : {}),
15
+ ...(metadata.engine !== undefined ? { engine: metadata.engine } : {}),
16
+ };
16
17
  }
17
18
  function createUnknownImproveMetrics() {
18
19
  return {
@@ -20,14 +21,14 @@ function createUnknownImproveMetrics() {
20
21
  completed: 0,
21
22
  skipped: 0,
22
23
  skipReasons: {},
24
+ resultRows: { total: 0, included: 0, skipped: { invalid: 0 } },
23
25
  plannedRefs: 0,
24
- profileFilteredRefs: 0,
26
+ strategyFilteredRefs: 0,
25
27
  actions: {
26
28
  reflect: { ok: 0, failed: 0, cooldown: 0, skipped: 0, guardRejected: 0, skippedByReason: {} },
27
29
  distill: {
28
30
  queued: 0,
29
31
  llmFailed: 0,
30
- qualityRejected: 0,
31
32
  judgeRejected: 0,
32
33
  validatorRejected: 0,
33
34
  configDisabled: 0,
@@ -42,7 +43,6 @@ function createUnknownImproveMetrics() {
42
43
  error: 0,
43
44
  },
44
45
  autoAccept: { promoted: 0, validationFailed: 0 },
45
- calibration: summarizeCalibration([]),
46
46
  reflectsWithErrorContext: 0,
47
47
  coverageGapCount: 0,
48
48
  evalCasesWritten: 0,
@@ -84,18 +84,16 @@ function createUnknownImproveMetrics() {
84
84
  skippedAborted: 0,
85
85
  unaccounted: 0,
86
86
  htmlErrorCount: 0,
87
- yieldEligibleRuns: 0,
88
- yieldEligibleConsidered: 0,
89
- yieldEligibleWritten: 0,
90
87
  yieldRate: 0,
91
88
  durationMs: 0,
92
- writes: 0,
93
89
  },
94
90
  graphExtraction: {
95
91
  ran: false,
96
92
  extractedFiles: 0,
93
+ consideredFiles: 0,
97
94
  entities: 0,
98
95
  relations: 0,
96
+ extractionCoverage: 0,
99
97
  cacheHits: 0,
100
98
  cacheMisses: 0,
101
99
  cacheHitRate: 0,
@@ -130,7 +128,6 @@ function createUnknownImproveMetrics() {
130
128
  perfTelemetry: {
131
129
  dedupPoolSize: 0,
132
130
  llmPoolSize: 0,
133
- judgedCacheSkipped: 0,
134
131
  embedMs: 0,
135
132
  embedCacheHits: 0,
136
133
  embedCacheMisses: 0,
@@ -171,140 +168,134 @@ export function summarizeImproveCompleted(events) {
171
168
  return metrics;
172
169
  }
173
170
  /**
174
- * Project a single `improve_runs.result_json` envelope into an accumulator-shaped
175
- * ImproveHealthMetrics. The aggregator merges these per-row metrics into one
176
- * window-level metric.
171
+ * Read the machine-readable reason from a distill `outcome: "skipped"` result.
177
172
  */
178
- function projectRunMetrics(result) {
179
- const metrics = createUnknownImproveMetrics();
173
+ function classifyDistillSkipReason(r) {
174
+ const explicitReason = typeof r?.skipReason === "string" ? r.skipReason : undefined;
175
+ return explicitReason || "unknown";
176
+ }
177
+ // ── projectRunMetrics phase helpers (chunk-9 WI-9.5c; file-level decompose of
178
+ // the single-envelope projection — each helper mutates its own disjoint
179
+ // subtree of the accumulator from the raw envelope, so call order does not
180
+ // matter; kept in envelope-field order for readability) ──────────────────────
181
+ /** plannedRefs / strategyFilteredRefs ref-count accounting. */
182
+ function applyPlannedRefs(metrics, result) {
180
183
  // plannedRefs (array of {ref, reason})
181
184
  const plannedRefs = result.plannedRefs;
182
185
  if (Array.isArray(plannedRefs))
183
186
  metrics.plannedRefs += plannedRefs.length;
184
- // profileFilteredRefs (array of {ref, reason}) — 2026-05-27: pre-filter
187
+ // strategyFilteredRefs (array of {ref, reason}) — 2026-05-27: pre-filter
185
188
  // bucket from `collectEligibleRefs` so the metric reflects work the
186
189
  // planner dropped before signal-delta / per-pass dispatch.
187
- const profileFilteredRefs = result.profileFilteredRefs;
188
- if (Array.isArray(profileFilteredRefs))
189
- metrics.profileFilteredRefs += profileFilteredRefs.length;
190
- // actions: split reflect / distill by outcome, count others.
191
- const actions = result.actions;
192
- if (Array.isArray(actions)) {
193
- for (const action of actions) {
194
- const mode = typeof action.mode === "string" ? action.mode : "";
195
- switch (mode) {
196
- case "reflect":
197
- metrics.actions.reflect.ok += 1;
198
- break;
199
- case "reflect-failed":
200
- metrics.actions.reflect.failed += 1;
190
+ const strategyFilteredRefs = result.strategyFilteredRefs;
191
+ if (Array.isArray(strategyFilteredRefs))
192
+ metrics.strategyFilteredRefs += strategyFilteredRefs.length;
193
+ }
194
+ /** One `actions[]` entry → the matching counter bucket (see ImproveHealthMetrics.actions jsdoc for the taxonomy). */
195
+ function applyAction(metrics, action) {
196
+ const mode = typeof action.mode === "string" ? action.mode : "";
197
+ switch (mode) {
198
+ case "reflect":
199
+ metrics.actions.reflect.ok += 1;
200
+ break;
201
+ case "reflect-failed":
202
+ metrics.actions.reflect.failed += 1;
203
+ break;
204
+ case "reflect-cooldown":
205
+ metrics.actions.reflect.cooldown += 1;
206
+ break;
207
+ case "reflect-skipped": {
208
+ metrics.actions.reflect.skipped += 1;
209
+ const r = action.result;
210
+ const reason = typeof r?.reason === "string" && r.reason.trim() ? r.reason : "unknown";
211
+ metrics.actions.reflect.skippedByReason[reason] = (metrics.actions.reflect.skippedByReason[reason] ?? 0) + 1;
212
+ break;
213
+ }
214
+ case "reflect-guard-rejected":
215
+ metrics.actions.reflect.guardRejected += 1;
216
+ break;
217
+ case "distill": {
218
+ const r = action.result;
219
+ const outcome = typeof r?.outcome === "string" ? r.outcome : "";
220
+ switch (outcome) {
221
+ case "queued":
222
+ metrics.actions.distill.queued += 1;
201
223
  break;
202
- case "reflect-cooldown":
203
- metrics.actions.reflect.cooldown += 1;
224
+ case "llm_failed":
225
+ metrics.actions.distill.llmFailed += 1;
204
226
  break;
205
- case "reflect-skipped": {
206
- metrics.actions.reflect.skipped += 1;
207
- const r = action.result;
208
- const reason = typeof r?.reason === "string" && r.reason.trim() ? r.reason : "unknown";
209
- metrics.actions.reflect.skippedByReason[reason] = (metrics.actions.reflect.skippedByReason[reason] ?? 0) + 1;
227
+ case "quality_rejected":
228
+ case "review_needed":
229
+ metrics.actions.distill.judgeRejected += 1;
210
230
  break;
211
- }
212
- case "reflect-guard-rejected":
213
- metrics.actions.reflect.guardRejected += 1;
231
+ case "validation_failed":
232
+ metrics.actions.distill.validatorRejected += 1;
214
233
  break;
215
- case "distill": {
216
- const r = action.result;
217
- const outcome = typeof r?.outcome === "string" ? r.outcome : "";
218
- switch (outcome) {
219
- case "queued":
220
- metrics.actions.distill.queued += 1;
221
- break;
222
- case "llm_failed":
223
- metrics.actions.distill.llmFailed += 1;
224
- break;
225
- case "quality_rejected":
226
- case "review_needed":
227
- metrics.actions.distill.qualityRejected += 1;
228
- metrics.actions.distill.judgeRejected += 1;
229
- break;
230
- case "validation_failed":
231
- metrics.actions.distill.qualityRejected += 1;
232
- metrics.actions.distill.validatorRejected += 1;
233
- break;
234
- case "config_disabled":
235
- metrics.actions.distill.configDisabled += 1;
236
- break;
237
- case "skipped": {
238
- // Previously dropped on the floor. The four sub-paths that emit
239
- // `outcome: "skipped"` (see distill.ts:893, 1024, 1120, 1576):
240
- // - recursive_lesson_input (type guard refused a lesson input)
241
- // - conflict_noop (LLM resolved destination conflict as NOOP)
242
- // - proposal-skipped cooldown / dedup at persistence
243
- // 465 events/7d in the user's live stack. The result message
244
- // typically encodes the reason; we also accept an explicit
245
- // `skipReason` field when downstream code sets it.
246
- metrics.actions.distill.deferred += 1;
247
- const explicitReason = typeof r?.skipReason === "string" ? r.skipReason : undefined;
248
- const msg = typeof r?.message === "string" ? r.message : "";
249
- let reason = explicitReason ?? "unknown";
250
- if (!explicitReason) {
251
- if (/lesson inputs/i.test(msg))
252
- reason = "recursive_lesson_input";
253
- else if (/NOOP/.test(msg))
254
- reason = "conflict_noop";
255
- else if (/cooldown/i.test(msg))
256
- reason = "proposal_cooldown";
257
- else if (/content[_ ]?hash/i.test(msg))
258
- reason = "content_hash_match";
259
- }
260
- metrics.actions.distill.deferredByReason[reason] =
261
- (metrics.actions.distill.deferredByReason[reason] ?? 0) + 1;
262
- break;
263
- }
264
- default:
265
- break;
266
- }
234
+ case "config_disabled":
235
+ metrics.actions.distill.configDisabled += 1;
267
236
  break;
268
- }
269
- case "distill-skipped": {
270
- metrics.actions.distill.skipped += 1;
271
- const r = action.result;
272
- const reason = typeof r?.reason === "string" && r.reason.trim() ? r.reason : "unknown";
273
- metrics.actions.distill.skippedByReason[reason] = (metrics.actions.distill.skippedByReason[reason] ?? 0) + 1;
237
+ case "skipped": {
238
+ // Previously dropped on the floor. The four sub-paths that emit
239
+ // `outcome: "skipped"` (see distill.ts:893, 1024, 1120, 1576):
240
+ // - recursive_lesson_input (type guard refused a lesson input)
241
+ // - conflict_noop (LLM resolved destination conflict as NOOP)
242
+ // - proposal-skipped cooldown / dedup at persistence
243
+ // 465 events/7d in the user's live stack. The result message
244
+ // typically encodes the reason; we also accept an explicit
245
+ // `skipReason` field when downstream code sets it.
246
+ metrics.actions.distill.deferred += 1;
247
+ const reason = classifyDistillSkipReason(r);
248
+ metrics.actions.distill.deferredByReason[reason] =
249
+ (metrics.actions.distill.deferredByReason[reason] ?? 0) + 1;
274
250
  break;
275
251
  }
276
- case "memory-prune":
277
- metrics.actions.memoryPrune += 1;
278
- break;
279
- case "memory-inference":
280
- metrics.actions.memoryInference += 1;
281
- break;
282
- case "graph-extraction":
283
- metrics.actions.graphExtraction += 1;
284
- break;
285
- case "error":
286
- metrics.actions.error += 1;
252
+ default:
287
253
  break;
288
254
  }
255
+ break;
289
256
  }
257
+ case "memory-prune":
258
+ metrics.actions.memoryPrune += 1;
259
+ break;
260
+ case "memory-inference":
261
+ metrics.actions.memoryInference += 1;
262
+ break;
263
+ case "graph-extraction":
264
+ metrics.actions.graphExtraction += 1;
265
+ break;
266
+ case "error":
267
+ metrics.actions.error += 1;
268
+ break;
290
269
  }
291
- // C1 (13-bus-factor): new runs persist the bounded `distillSkipped` aggregate
292
- // instead of per-ref `distill-skipped` rows. Read the total + per-reason
293
- // histogram from it into the SAME `distill.skipped` / `skippedByReason`
294
- // metric the per-ref loop above populated. Legacy rows carry the per-ref rows
295
- // and NO aggregate (counted above); new rows carry the aggregate and NO
296
- // per-ref rows (counted here) — so a run is never double-counted.
270
+ }
271
+ /** actions: split reflect / distill by outcome, count others. */
272
+ function applyActionsList(metrics, result) {
273
+ const actions = result.actions;
274
+ if (!Array.isArray(actions))
275
+ return;
276
+ for (const action of actions) {
277
+ applyAction(metrics, action);
278
+ }
279
+ }
280
+ /**
281
+ * Read the bounded `distillSkipped` aggregate into the corresponding total and
282
+ * per-reason health metrics.
283
+ */
284
+ function applyDistillSkippedAggregate(metrics, result) {
297
285
  const distillSkipped = result.distillSkipped;
298
- if (distillSkipped && typeof distillSkipped === "object") {
299
- metrics.actions.distill.skipped += toFiniteNumber(distillSkipped.total);
300
- const byReason = distillSkipped.byReason;
301
- if (byReason && typeof byReason === "object") {
302
- for (const [reason, count] of Object.entries(byReason)) {
303
- metrics.actions.distill.skippedByReason[reason] =
304
- (metrics.actions.distill.skippedByReason[reason] ?? 0) + toFiniteNumber(count);
305
- }
286
+ if (!distillSkipped || typeof distillSkipped !== "object")
287
+ return;
288
+ metrics.actions.distill.skipped += toFiniteNumber(distillSkipped.total);
289
+ const byReason = distillSkipped.byReason;
290
+ if (byReason && typeof byReason === "object") {
291
+ for (const [reason, count] of Object.entries(byReason)) {
292
+ metrics.actions.distill.skippedByReason[reason] =
293
+ (metrics.actions.distill.skippedByReason[reason] ?? 0) + toFiniteNumber(count);
306
294
  }
307
295
  }
296
+ }
297
+ /** autoAccept + the small envelope-level counters (reflectsWithErrorContext, coverageGaps, evalCasesWritten, deadUrls). */
298
+ function applyMiscCounters(metrics, result) {
308
299
  metrics.autoAccept.promoted += toFiniteNumber(result.gateAutoAcceptedCount);
309
300
  metrics.autoAccept.validationFailed += toFiniteNumber(result.gateAutoAcceptFailedCount);
310
301
  metrics.reflectsWithErrorContext += toFiniteNumber(result.reflectsWithErrorContext);
@@ -313,79 +304,86 @@ function projectRunMetrics(result) {
313
304
  metrics.evalCasesWritten += toFiniteNumber(result.evalCasesWritten);
314
305
  if (Array.isArray(result.deadUrls))
315
306
  metrics.deadUrlCount += result.deadUrls.length;
307
+ }
308
+ function applyMemorySummary(metrics, result) {
316
309
  const memorySummary = result.memorySummary;
317
- if (memorySummary) {
318
- metrics.memorySummary.eligible += toFiniteNumber(memorySummary.eligible);
319
- metrics.memorySummary.derived += toFiniteNumber(memorySummary.derived);
320
- }
310
+ if (!memorySummary)
311
+ return;
312
+ metrics.memorySummary.eligible += toFiniteNumber(memorySummary.eligible);
313
+ metrics.memorySummary.derived += toFiniteNumber(memorySummary.derived);
314
+ }
315
+ function applyMemoryCleanup(metrics, result) {
321
316
  const memoryCleanup = result.memoryCleanup;
322
- if (memoryCleanup) {
323
- if (Array.isArray(memoryCleanup.pruneCandidates))
324
- metrics.memoryCleanup.pruneCandidates += memoryCleanup.pruneCandidates.length;
325
- if (Array.isArray(memoryCleanup.contradictionCandidates))
326
- metrics.memoryCleanup.contradictionCandidates += memoryCleanup.contradictionCandidates.length;
327
- if (Array.isArray(memoryCleanup.beliefStateTransitions))
328
- metrics.memoryCleanup.beliefStateTransitions += memoryCleanup.beliefStateTransitions.length;
329
- if (Array.isArray(memoryCleanup.consolidationCandidates))
330
- metrics.memoryCleanup.consolidationCandidates += memoryCleanup.consolidationCandidates.length;
331
- if (Array.isArray(memoryCleanup.archived))
332
- metrics.memoryCleanup.archived += memoryCleanup.archived.length;
333
- if (Array.isArray(memoryCleanup.warnings))
334
- metrics.memoryCleanup.warnings += memoryCleanup.warnings.length;
335
- }
317
+ if (!memoryCleanup)
318
+ return;
319
+ if (Array.isArray(memoryCleanup.pruneCandidates))
320
+ metrics.memoryCleanup.pruneCandidates += memoryCleanup.pruneCandidates.length;
321
+ if (Array.isArray(memoryCleanup.contradictionCandidates))
322
+ metrics.memoryCleanup.contradictionCandidates += memoryCleanup.contradictionCandidates.length;
323
+ if (Array.isArray(memoryCleanup.beliefStateTransitions))
324
+ metrics.memoryCleanup.beliefStateTransitions += memoryCleanup.beliefStateTransitions.length;
325
+ if (Array.isArray(memoryCleanup.consolidationCandidates))
326
+ metrics.memoryCleanup.consolidationCandidates += memoryCleanup.consolidationCandidates.length;
327
+ if (Array.isArray(memoryCleanup.archived))
328
+ metrics.memoryCleanup.archived += memoryCleanup.archived.length;
329
+ if (Array.isArray(memoryCleanup.warnings))
330
+ metrics.memoryCleanup.warnings += memoryCleanup.warnings.length;
331
+ }
332
+ function applyConsolidation(metrics, result) {
336
333
  const consolidation = result.consolidation;
337
- if (consolidation) {
338
- metrics.consolidation.processed += toFiniteNumber(consolidation.processed);
339
- metrics.consolidation.merged += toFiniteNumber(consolidation.merged);
340
- metrics.consolidation.deleted += toFiniteNumber(consolidation.deleted);
341
- metrics.consolidation.contradicted += toFiniteNumber(consolidation.contradicted);
342
- if (Array.isArray(consolidation.promoted))
343
- metrics.consolidation.promoted += consolidation.promoted.length;
344
- metrics.consolidation.failedChunks += toFiniteNumber(consolidation.failedChunks);
345
- metrics.consolidation.totalChunks += toFiniteNumber(consolidation.totalChunks);
346
- metrics.consolidation.durationMs += toFiniteNumber(consolidation.durationMs);
347
- metrics.consolidation.judgedNoAction += toFiniteNumber(consolidation.judgedNoAction);
348
- metrics.consolidation.mergedSecondaries += toFiniteNumber(consolidation.mergedSecondaries);
349
- metrics.consolidation.failedChunkMemories += toFiniteNumber(consolidation.failedChunkMemories);
350
- // Structured emitter (new on this branch): consolidate.ts now pushes
351
- // per-ref grouped `{ref, skips: [{op, reason}]}` entries to `skipReasons`
352
- // for every deterministic post-LLM rejection. Each ref appears once but
353
- // may carry multiple skips; aggregate every reason. Pre-fix envelopes have
354
- // neither field, so be defensive.
355
- const skipReasons = consolidation.skipReasons;
356
- if (Array.isArray(skipReasons)) {
357
- for (const entry of skipReasons) {
358
- if (!entry || typeof entry !== "object")
334
+ if (!consolidation)
335
+ return;
336
+ metrics.consolidation.processed += toFiniteNumber(consolidation.processed);
337
+ metrics.consolidation.merged += toFiniteNumber(consolidation.merged);
338
+ metrics.consolidation.deleted += toFiniteNumber(consolidation.deleted);
339
+ metrics.consolidation.contradicted += toFiniteNumber(consolidation.contradicted);
340
+ if (Array.isArray(consolidation.promoted))
341
+ metrics.consolidation.promoted += consolidation.promoted.length;
342
+ metrics.consolidation.failedChunks += toFiniteNumber(consolidation.failedChunks);
343
+ metrics.consolidation.totalChunks += toFiniteNumber(consolidation.totalChunks);
344
+ metrics.consolidation.durationMs += toFiniteNumber(consolidation.durationMs);
345
+ metrics.consolidation.judgedNoAction += toFiniteNumber(consolidation.judgedNoAction);
346
+ metrics.consolidation.mergedSecondaries += toFiniteNumber(consolidation.mergedSecondaries);
347
+ metrics.consolidation.failedChunkMemories += toFiniteNumber(consolidation.failedChunkMemories);
348
+ // Structured emitter (new on this branch): consolidate.ts now pushes
349
+ // per-ref grouped `{ref, skips: [{op, reason}]}` entries to `skipReasons`
350
+ // for every deterministic post-LLM rejection. Each ref appears once but
351
+ // may carry multiple skips; aggregate every reason. Pre-fix envelopes have
352
+ // neither field, so be defensive.
353
+ const skipReasons = consolidation.skipReasons;
354
+ if (Array.isArray(skipReasons)) {
355
+ for (const entry of skipReasons) {
356
+ if (!entry || typeof entry !== "object")
357
+ continue;
358
+ const skips = entry.skips;
359
+ if (!Array.isArray(skips))
360
+ continue;
361
+ for (const skip of skips) {
362
+ if (!skip || typeof skip !== "object")
359
363
  continue;
360
- const skips = entry.skips;
361
- if (!Array.isArray(skips))
364
+ const reason = skip.reason;
365
+ if (typeof reason !== "string" || !reason.trim())
362
366
  continue;
363
- for (const skip of skips) {
364
- if (!skip || typeof skip !== "object")
365
- continue;
366
- const reason = skip.reason;
367
- if (typeof reason !== "string" || !reason.trim())
368
- continue;
369
- metrics.consolidation.skipReasons[reason] = (metrics.consolidation.skipReasons[reason] ?? 0) + 1;
370
- }
367
+ metrics.consolidation.skipReasons[reason] = (metrics.consolidation.skipReasons[reason] ?? 0) + 1;
371
368
  }
372
369
  }
373
- // WS-5: extract perf telemetry from the consolidation envelope.
374
- // Pre-WS-5 envelopes lack `perfTelemetry`; be defensive.
375
- const perf = consolidation.perfTelemetry;
376
- if (perf) {
377
- metrics.perfTelemetry.runsWithTelemetry += 1;
378
- metrics.perfTelemetry.dedupPoolSize += toFiniteNumber(perf.dedupPoolSize);
379
- metrics.perfTelemetry.llmPoolSize += toFiniteNumber(perf.llmPoolSize);
380
- metrics.perfTelemetry.judgedCacheSkipped += toFiniteNumber(perf.judgedCacheSkipped);
381
- metrics.perfTelemetry.embedMs += toFiniteNumber(perf.embedMs);
382
- metrics.perfTelemetry.embedCacheHits += toFiniteNumber(perf.embedCacheHits);
383
- metrics.perfTelemetry.embedCacheMisses += toFiniteNumber(perf.embedCacheMisses);
384
- const budgetFrac = toFiniteNumber(perf.estimatedBudgetFractionUsed);
385
- if (budgetFrac > 1.0)
386
- metrics.perfTelemetry.overBudgetRuns += 1;
387
- }
388
370
  }
371
+ // WS-5: extract perf telemetry from the consolidation envelope.
372
+ // Pre-WS-5 envelopes lack `perfTelemetry`; be defensive.
373
+ const perf = consolidation.perfTelemetry;
374
+ if (perf) {
375
+ metrics.perfTelemetry.runsWithTelemetry += 1;
376
+ metrics.perfTelemetry.dedupPoolSize += toFiniteNumber(perf.dedupPoolSize);
377
+ metrics.perfTelemetry.llmPoolSize += toFiniteNumber(perf.llmPoolSize);
378
+ metrics.perfTelemetry.embedMs += toFiniteNumber(perf.embedMs);
379
+ metrics.perfTelemetry.embedCacheHits += toFiniteNumber(perf.embedCacheHits);
380
+ metrics.perfTelemetry.embedCacheMisses += toFiniteNumber(perf.embedCacheMisses);
381
+ const budgetFrac = toFiniteNumber(perf.estimatedBudgetFractionUsed);
382
+ if (budgetFrac > 1.0)
383
+ metrics.perfTelemetry.overBudgetRuns += 1;
384
+ }
385
+ }
386
+ function applyMemoryInference(metrics, result) {
389
387
  const memoryInference = result.memoryInference;
390
388
  if (memoryInference) {
391
389
  const considered = toFiniteNumber(memoryInference.considered);
@@ -400,25 +398,17 @@ function projectRunMetrics(result) {
400
398
  metrics.memoryInference.skippedAborted += toFiniteNumber(memoryInference.skippedAborted);
401
399
  metrics.memoryInference.unaccounted += toFiniteNumber(memoryInference.unaccounted);
402
400
  metrics.memoryInference.htmlErrorCount += toFiniteNumber(memoryInference.htmlErrorCount);
403
- // Yield-rate gating: pre-cache-feature envelopes lack the `cacheHits`
404
- // field entirely. Treating their `considered` as freshAttempts (since
405
- // cacheHits=0) is mathematically tempting but operationally wrong —
406
- // historical runs with the legacy schema have no cache instrumentation
407
- // and the SUM dragged the reported rate to ~14% in local data. Only
408
- // contribute to the yield aggregate when the envelope actually carries
409
- // the field. See investigation 2026-05-26.
410
- if (Object.hasOwn(memoryInference, "cacheHits")) {
411
- metrics.memoryInference.yieldEligibleRuns += 1;
412
- metrics.memoryInference.yieldEligibleConsidered += considered;
413
- metrics.memoryInference.yieldEligibleWritten += writtenFacts;
414
- }
415
401
  }
416
402
  metrics.memoryInference.durationMs += toFiniteNumber(result.memoryInferenceDurationMs);
403
+ }
404
+ function applyGraphExtraction(metrics, result) {
417
405
  const graphExtraction = result.graphExtraction;
418
406
  if (graphExtraction) {
419
407
  const quality = graphExtraction.quality;
420
- if (quality)
408
+ if (quality) {
421
409
  metrics.graphExtraction.extractedFiles += toFiniteNumber(quality.extractedFiles);
410
+ metrics.graphExtraction.consideredFiles += toFiniteNumber(quality.consideredFiles);
411
+ }
422
412
  metrics.graphExtraction.entities += toFiniteNumber(graphExtraction.totalEntities);
423
413
  metrics.graphExtraction.relations += toFiniteNumber(graphExtraction.totalRelations);
424
414
  const telemetry = graphExtraction.telemetry;
@@ -433,18 +423,40 @@ function projectRunMetrics(result) {
433
423
  }
434
424
  }
435
425
  metrics.graphExtraction.durationMs += toFiniteNumber(result.graphExtractionDurationMs);
436
- if (Array.isArray(result.extract)) {
437
- for (const e of result.extract) {
438
- metrics.sessionExtraction.sessionsScanned += toFiniteNumber(e.sessionsProcessed);
439
- metrics.sessionExtraction.sessionsSkipped += toFiniteNumber(e.sessionsSkipped);
440
- if (Array.isArray(e.sessions)) {
441
- metrics.sessionExtraction.sessionsExtracted += e.sessions.filter((s) => Array.isArray(s.proposalIds) && s.proposalIds.length > 0).length;
442
- }
443
- metrics.sessionExtraction.proposalsCreated += Array.isArray(e.proposals) ? e.proposals.length : 0;
444
- metrics.sessionExtraction.warnings += Array.isArray(e.warnings) ? e.warnings.length : 0;
445
- metrics.sessionExtraction.durationMs += toFiniteNumber(e.durationMs);
426
+ }
427
+ function applySessionExtraction(metrics, result) {
428
+ if (!Array.isArray(result.extract))
429
+ return;
430
+ for (const e of result.extract) {
431
+ metrics.sessionExtraction.sessionsScanned += toFiniteNumber(e.sessionsProcessed);
432
+ metrics.sessionExtraction.sessionsSkipped += toFiniteNumber(e.sessionsSkipped);
433
+ if (Array.isArray(e.sessions)) {
434
+ metrics.sessionExtraction.sessionsExtracted += e.sessions.filter((s) => Array.isArray(s.proposalIds) && s.proposalIds.length > 0).length;
446
435
  }
436
+ metrics.sessionExtraction.proposalsCreated += Array.isArray(e.proposals) ? e.proposals.length : 0;
437
+ metrics.sessionExtraction.warnings += Array.isArray(e.warnings) ? e.warnings.length : 0;
438
+ metrics.sessionExtraction.durationMs += toFiniteNumber(e.durationMs);
447
439
  }
440
+ }
441
+ /**
442
+ * Project a single `improve_runs.result_json` envelope into an accumulator-shaped
443
+ * ImproveHealthMetrics. The aggregator merges these per-row metrics into one
444
+ * window-level metric. File-level decomposed (chunk-9 WI-9.5c) into one
445
+ * `apply*` helper per envelope section above; each mutates its own disjoint
446
+ * subtree of the accumulator so the call order below is not load-bearing.
447
+ */
448
+ function projectRunMetrics(result) {
449
+ const metrics = createUnknownImproveMetrics();
450
+ applyPlannedRefs(metrics, result);
451
+ applyActionsList(metrics, result);
452
+ applyDistillSkippedAggregate(metrics, result);
453
+ applyMiscCounters(metrics, result);
454
+ applyMemorySummary(metrics, result);
455
+ applyMemoryCleanup(metrics, result);
456
+ applyConsolidation(metrics, result);
457
+ applyMemoryInference(metrics, result);
458
+ applyGraphExtraction(metrics, result);
459
+ applySessionExtraction(metrics, result);
448
460
  return metrics;
449
461
  }
450
462
  /**
@@ -465,19 +477,11 @@ function finalizeImproveMetrics(metrics) {
465
477
  metrics.memoryInference.considered > 0 ||
466
478
  metrics.memoryInference.written > 0 ||
467
479
  metrics.memoryInference.durationMs > 0;
468
- metrics.memoryInference.writes = metrics.memoryInference.written;
469
- // Yield denominator excludes cache hits AND legacy (pre-cacheHits-field)
470
- // envelopes. Only runs whose envelope carries a `cacheHits` field
471
- // contribute to freshAttempts/yieldRate; legacy rows remain in
472
- // `considered`/`written` for totals but are excluded from the rate so
473
- // they cannot drag it down. See ImproveHealthMetrics.memoryInference
474
- // jsdoc for the rationale.
475
- metrics.memoryInference.freshAttempts = Math.max(0, metrics.memoryInference.yieldEligibleConsidered -
476
- metrics.memoryInference.cacheHits -
477
- 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);
478
482
  metrics.memoryInference.yieldRate =
479
483
  metrics.memoryInference.freshAttempts > 0
480
- ? roundRate(metrics.memoryInference.yieldEligibleWritten / metrics.memoryInference.freshAttempts)
484
+ ? roundRate(metrics.memoryInference.written / metrics.memoryInference.freshAttempts)
481
485
  : 0;
482
486
  metrics.graphExtraction.ran =
483
487
  metrics.graphExtraction.extractedFiles > 0 ||
@@ -485,6 +489,10 @@ function finalizeImproveMetrics(metrics) {
485
489
  metrics.graphExtraction.durationMs > 0;
486
490
  const cacheTotal = metrics.graphExtraction.cacheHits + metrics.graphExtraction.cacheMisses;
487
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;
488
496
  metrics.sessionExtraction.ran =
489
497
  metrics.sessionExtraction.sessionsScanned > 0 ||
490
498
  metrics.sessionExtraction.proposalsCreated > 0 ||
@@ -496,8 +504,8 @@ function finalizeImproveMetrics(metrics) {
496
504
  */
497
505
  function mergeImproveMetrics(dst, src) {
498
506
  dst.plannedRefs += src.plannedRefs;
499
- // profileFilteredRefs is the count of refs the planner drops up-front for the
500
- // active profile — recomputed against the (stable) stash every run, so it is a
507
+ // strategyFilteredRefs is the count of refs the planner drops up-front for the
508
+ // active strategy — recomputed against the (stable) stash every run, so it is a
501
509
  // snapshot, NOT a per-run increment. Summing it re-counts the same refs each
502
510
  // run (the ~2.4M bug). Set from the most recent run in summarizeImproveRuns.
503
511
  dst.actions.reflect.ok += src.actions.reflect.ok;
@@ -510,7 +518,6 @@ function mergeImproveMetrics(dst, src) {
510
518
  }
511
519
  dst.actions.distill.queued += src.actions.distill.queued;
512
520
  dst.actions.distill.llmFailed += src.actions.distill.llmFailed;
513
- dst.actions.distill.qualityRejected += src.actions.distill.qualityRejected;
514
521
  dst.actions.distill.judgeRejected += src.actions.distill.judgeRejected;
515
522
  dst.actions.distill.validatorRejected += src.actions.distill.validatorRejected;
516
523
  dst.actions.distill.configDisabled += src.actions.distill.configDisabled;
@@ -565,11 +572,10 @@ function mergeImproveMetrics(dst, src) {
565
572
  dst.memoryInference.skippedAborted += src.memoryInference.skippedAborted;
566
573
  dst.memoryInference.unaccounted += src.memoryInference.unaccounted;
567
574
  dst.memoryInference.htmlErrorCount += src.memoryInference.htmlErrorCount;
568
- dst.memoryInference.yieldEligibleRuns += src.memoryInference.yieldEligibleRuns;
569
- dst.memoryInference.yieldEligibleConsidered += src.memoryInference.yieldEligibleConsidered;
570
- dst.memoryInference.yieldEligibleWritten += src.memoryInference.yieldEligibleWritten;
575
+ dst.memoryInference.retryAttempts += src.memoryInference.retryAttempts;
571
576
  dst.memoryInference.durationMs += src.memoryInference.durationMs;
572
577
  dst.graphExtraction.extractedFiles += src.graphExtraction.extractedFiles;
578
+ dst.graphExtraction.consideredFiles += src.graphExtraction.consideredFiles;
573
579
  dst.graphExtraction.entities += src.graphExtraction.entities;
574
580
  dst.graphExtraction.relations += src.graphExtraction.relations;
575
581
  dst.graphExtraction.cacheHits += src.graphExtraction.cacheHits;
@@ -578,6 +584,7 @@ function mergeImproveMetrics(dst, src) {
578
584
  dst.graphExtraction.failures += src.graphExtraction.failures;
579
585
  dst.graphExtraction.htmlErrors += src.graphExtraction.htmlErrors;
580
586
  dst.graphExtraction.nonArrayBatchFailures += src.graphExtraction.nonArrayBatchFailures;
587
+ dst.graphExtraction.retryAttempts += src.graphExtraction.retryAttempts;
581
588
  dst.graphExtraction.durationMs += src.graphExtraction.durationMs;
582
589
  dst.sessionExtraction.sessionsScanned += src.sessionExtraction.sessionsScanned;
583
590
  dst.sessionExtraction.sessionsExtracted += src.sessionExtraction.sessionsExtracted;
@@ -588,7 +595,6 @@ function mergeImproveMetrics(dst, src) {
588
595
  // WS-5: merge perf telemetry (additive sums).
589
596
  dst.perfTelemetry.dedupPoolSize += src.perfTelemetry.dedupPoolSize;
590
597
  dst.perfTelemetry.llmPoolSize += src.perfTelemetry.llmPoolSize;
591
- dst.perfTelemetry.judgedCacheSkipped += src.perfTelemetry.judgedCacheSkipped;
592
598
  dst.perfTelemetry.embedMs += src.perfTelemetry.embedMs;
593
599
  dst.perfTelemetry.embedCacheHits += src.perfTelemetry.embedCacheHits;
594
600
  dst.perfTelemetry.embedCacheMisses += src.perfTelemetry.embedCacheMisses;
@@ -598,6 +604,15 @@ function mergeImproveMetrics(dst, src) {
598
604
  // totalAssets is intentionally NOT merged here — set from the most recent run in summarizeImproveRuns.
599
605
  dst.coverage.acceptedProposals += src.coverage.acceptedProposals;
600
606
  }
607
+ function compareImproveRunRecency(a, b) {
608
+ const started = a.started_at.localeCompare(b.started_at);
609
+ if (started !== 0)
610
+ return started;
611
+ const completed = a.completed_at.localeCompare(b.completed_at);
612
+ if (completed !== 0)
613
+ return completed;
614
+ return a.id.localeCompare(b.id);
615
+ }
601
616
  export function summarizeImproveRuns(db, since, until) {
602
617
  const accum = createUnknownImproveMetrics();
603
618
  const rows = queryImproveRuns(db, since, until);
@@ -611,24 +626,32 @@ export function summarizeImproveRuns(db, since, until) {
611
626
  };
612
627
  // memorySummary is a whole-stash snapshot per run, so the window value is the
613
628
  // MOST RECENT run's snapshot (current state) — not a sum across runs.
614
- let latestStartMs = Number.NEGATIVE_INFINITY;
629
+ let latestCompleteRow;
615
630
  let latestMemorySummary;
616
- let latestProfileFilteredRefs = 0;
631
+ let latestStrategyFilteredRefs = 0;
632
+ if (!accum.resultRows)
633
+ throw new Error("invariant: improve result-row accounting was not initialized");
634
+ accum.resultRows.total = rows.length;
617
635
  for (const row of rows) {
618
- let result;
636
+ let decoded;
619
637
  try {
620
- result = JSON.parse(row.result_json);
638
+ decoded = decodeImproveResult(row.result_json);
621
639
  }
622
640
  catch {
641
+ accum.resultRows.skipped.invalid += 1;
623
642
  continue;
624
643
  }
644
+ accum.resultRows.included += 1;
645
+ const result = decoded.envelope;
625
646
  const perRow = projectRunMetrics(result);
626
647
  mergeImproveMetrics(accum, perRow);
627
648
  const startMs = new Date(row.started_at).getTime();
628
- if (Number.isFinite(startMs) && startMs >= latestStartMs) {
629
- latestStartMs = startMs;
649
+ if (result.terminated === undefined &&
650
+ Number.isFinite(startMs) &&
651
+ (latestCompleteRow === undefined || compareImproveRunRecency(row, latestCompleteRow) > 0)) {
652
+ latestCompleteRow = row;
630
653
  latestMemorySummary = perRow.memorySummary;
631
- latestProfileFilteredRefs = perRow.profileFilteredRefs;
654
+ latestStrategyFilteredRefs = perRow.strategyFilteredRefs;
632
655
  }
633
656
  // Collect per-phase durations directly off the envelope. consolidation's
634
657
  // duration lives inside the sub-object; memoryInference and graphExtraction
@@ -648,7 +671,7 @@ export function summarizeImproveRuns(db, since, until) {
648
671
  finalizeImproveMetrics(accum);
649
672
  if (latestMemorySummary)
650
673
  accum.memorySummary = latestMemorySummary;
651
- accum.profileFilteredRefs = latestProfileFilteredRefs;
674
+ accum.strategyFilteredRefs = latestStrategyFilteredRefs;
652
675
  accum.wallTime.byPhase = {
653
676
  consolidation: summarizePhaseDurations(phaseDurations.consolidation),
654
677
  memoryInference: summarizePhaseDurations(phaseDurations.memoryInference),
@@ -681,11 +704,16 @@ export function summarizePhaseDurations(samples) {
681
704
  */
682
705
  export function projectImproveRunSummary(row, wallTimeMs, taskId) {
683
706
  let result = {};
707
+ let resultStatus = "invalid";
684
708
  try {
685
- result = JSON.parse(row.result_json);
709
+ const decoded = decodeImproveResult(row.result_json);
710
+ result = decoded.envelope;
711
+ resultStatus = "valid";
686
712
  }
687
713
  catch {
688
- // fall through with empty result so per-stage rollups are zeros
714
+ // Keep the persisted row visible in per-run output, but do not project its
715
+ // unknown payload or admit its duration to result-derived denominators.
716
+ wallTimeMs = 0;
689
717
  }
690
718
  const perRow = projectRunMetrics(result);
691
719
  finalizeImproveMetrics(perRow);
@@ -699,6 +727,9 @@ export function projectImproveRunSummary(row, wallTimeMs, taskId) {
699
727
  completedAt: row.completed_at,
700
728
  wallTimeMs,
701
729
  ok: row.ok === 1,
730
+ resultStatus,
731
+ resultComplete: resultStatus === "valid" && result.terminated === undefined,
732
+ strategy: row.strategy,
702
733
  scope: {
703
734
  mode: row.scope_mode,
704
735
  ...(row.scope_value ? { value: row.scope_value } : {}),
@@ -744,10 +775,10 @@ export function buildImproveSkipSummary(events) {
744
775
  // - Per-occurrence (no `count`): one event per skipped ref → SUM is correct.
745
776
  // - Aggregated snapshot (carries `count`): a single per-run event whose count
746
777
  // is the number of refs that hit a STABLE, whole-stash condition that run
747
- // (`no_new_signal`, `profile_filtered_all_passes`). Each run re-counts the
778
+ // (`no_new_signal`, `strategy_filtered_all_passes`). Each run re-counts the
748
779
  // same stable set, so summing across the window re-counts it N times (the
749
780
  // 2.7M / 3M inflation). For these we keep the MOST RECENT run's count — the
750
- // current snapshot — matching how memorySummary/profileFilteredRefs are
781
+ // current snapshot — matching how memorySummary/strategyFilteredRefs are
751
782
  // handled. Events arrive in chronological (offset) order, so the last
752
783
  // count-bearing event per reason is the latest run's value.
753
784
  const summed = {};