akm-cli 0.9.1 → 0.9.2-alpha.1

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 (341) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/README.md +3 -1
  3. package/SECURITY.md +1 -1
  4. package/STABILITY.md +1 -1
  5. package/dist/akm +2 -2
  6. package/dist/akm-migrate +2 -2
  7. package/dist/assets/hints/cli-hints-full.md +14 -9
  8. package/dist/assets/improve-strategies/proactive-maintenance.json +1 -1
  9. package/dist/assets/improve-strategies/reflect-distill.json +1 -1
  10. package/dist/assets/models.json +35 -0
  11. package/dist/assets/tasks/core/extract.yml +6 -5
  12. package/dist/assets/tasks/core/improve.yml +6 -5
  13. package/dist/assets/tasks/core/index-refresh.yml +6 -5
  14. package/dist/assets/tasks/core/sync.yml +6 -5
  15. package/dist/assets/tasks/core/version-check.yml +6 -5
  16. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +6 -5
  17. package/dist/assets/tasks/improve/akm-improve-catchup.yml +6 -5
  18. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +6 -5
  19. package/dist/assets/tasks/improve/akm-improve-frequent.yml +6 -5
  20. package/dist/assets/tasks/improve/akm-improve-nightly.yml +6 -5
  21. package/dist/cli/confirm.js +2 -2
  22. package/dist/cli/parse-args.js +3 -24
  23. package/dist/cli/retired-commands.js +1 -1
  24. package/dist/cli/shared.js +2 -2
  25. package/dist/cli.js +11 -9
  26. package/dist/commands/agent/agent-dispatch.js +55 -89
  27. package/dist/commands/agent/contribute-cli.js +12 -45
  28. package/dist/commands/command/builtin-action.js +32 -0
  29. package/dist/commands/command/command-cli.js +99 -0
  30. package/dist/commands/command/command-execution.js +308 -0
  31. package/dist/commands/command/execution-source-loader.js +176 -0
  32. package/dist/commands/command/portable-template.js +60 -0
  33. package/dist/commands/config-cli.js +10 -4
  34. package/dist/commands/env/env.js +4 -2
  35. package/dist/commands/feedback-cli.js +1 -1
  36. package/dist/commands/health/checks.js +241 -29
  37. package/dist/commands/health/html-report.js +0 -14
  38. package/dist/commands/health/report-view-model.js +0 -1
  39. package/dist/commands/health/surfaces.js +6 -7
  40. package/dist/commands/health/types.js +0 -2
  41. package/dist/commands/health.js +63 -18
  42. package/dist/commands/improve/collapse-detector.js +2 -2
  43. package/dist/commands/improve/consolidate.js +251 -214
  44. package/dist/commands/improve/distill/promote-memory.js +71 -34
  45. package/dist/commands/improve/distill/quality-gate.js +17 -5
  46. package/dist/commands/improve/distill.js +232 -155
  47. package/dist/commands/improve/eligibility.js +112 -79
  48. package/dist/commands/improve/execution.js +57 -0
  49. package/dist/commands/improve/extract-cli.js +5 -5
  50. package/dist/commands/improve/extract.js +521 -342
  51. package/dist/commands/improve/improve-strategies.js +43 -14
  52. package/dist/commands/improve/improve.js +249 -29
  53. package/dist/commands/improve/loop-stages.js +11 -17
  54. package/dist/commands/improve/memory/memory-contradiction-detect.js +90 -66
  55. package/dist/commands/improve/outcome-loop.js +22 -38
  56. package/dist/commands/improve/planner.js +134 -0
  57. package/dist/commands/improve/preparation.js +730 -409
  58. package/dist/commands/improve/reflect.js +386 -223
  59. package/dist/commands/improve/run-context.js +3 -4
  60. package/dist/commands/improve/salience.js +6 -58
  61. package/dist/commands/improve/session-asset.js +12 -12
  62. package/dist/commands/lint/index.js +101 -29
  63. package/dist/commands/migrate-cli.js +11 -69
  64. package/dist/commands/migration-tool.js +6 -9
  65. package/dist/commands/models-cli.js +27 -0
  66. package/dist/commands/proposal/drain.js +258 -186
  67. package/dist/commands/proposal/proposal-cli.js +32 -10
  68. package/dist/commands/proposal/proposal.js +2 -5
  69. package/dist/commands/proposal/propose.js +192 -172
  70. package/dist/commands/proposal/repository.js +54 -91
  71. package/dist/commands/proposal/validators/proposal-validators.js +9 -7
  72. package/dist/commands/read/curate.js +10 -0
  73. package/dist/commands/read/registry-search.js +25 -9
  74. package/dist/commands/read/remember-cli.js +14 -2
  75. package/dist/commands/read/search.js +10 -4
  76. package/dist/commands/read/show.js +139 -153
  77. package/dist/commands/registry-cli.js +16 -7
  78. package/dist/commands/remember.js +33 -18
  79. package/dist/commands/sources/add-cli.js +19 -178
  80. package/dist/commands/sources/bundle-cli.js +15 -3
  81. package/dist/commands/sources/dangerous-env-audit.js +135 -0
  82. package/dist/commands/sources/info.js +2 -1
  83. package/dist/commands/sources/installed-stashes.js +835 -152
  84. package/dist/commands/sources/schema-repair.js +174 -95
  85. package/dist/commands/sources/self-update.js +30 -74
  86. package/dist/commands/sources/source-add.js +3 -5
  87. package/dist/commands/sources/sources-cli.js +2 -15
  88. package/dist/commands/sources/update-transaction.js +220 -0
  89. package/dist/commands/tasks/tasks-cli.js +3 -3
  90. package/dist/commands/tasks/tasks.js +736 -317
  91. package/dist/commands/workflow-cli.js +2 -2
  92. package/dist/core/adapter/adapters/agent-skills-adapter.js +3 -0
  93. package/dist/core/adapter/adapters/akm-adapter.js +83 -34
  94. package/dist/core/adapter/adapters/akm-lint.js +54 -39
  95. package/dist/core/adapter/adapters/akm-metadata.js +45 -45
  96. package/dist/core/adapter/adapters/akm-task-adapter.js +32 -49
  97. package/dist/core/adapter/adapters/akm-workflow-adapter.js +38 -23
  98. package/dist/core/adapter/adapters/dotenv-adapter.js +30 -1
  99. package/dist/core/adapter/adapters/generic-files-adapter.js +11 -0
  100. package/dist/core/adapter/adapters/index.js +0 -9
  101. package/dist/core/adapter/adapters/llm-wiki-adapter.js +4 -0
  102. package/dist/core/adapter/adapters/okf-adapter.js +4 -0
  103. package/dist/core/adapter/adapters/opencode-adapter.js +5 -8
  104. package/dist/core/adapter/adapters/tool-dir-shared.js +63 -6
  105. package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -0
  106. package/dist/core/adapter/execution-source.js +308 -0
  107. package/dist/core/adapter/recognize-match.js +36 -13
  108. package/dist/core/adapter/registry.js +0 -9
  109. package/dist/core/asset/stash-meta.js +94 -4
  110. package/dist/core/common.js +6 -11
  111. package/dist/core/config/config-io.js +3 -3
  112. package/dist/core/config/config-schema.js +18 -40
  113. package/dist/core/config/config-sources.js +11 -21
  114. package/dist/core/config/config-walker.js +31 -13
  115. package/dist/core/config/config.js +21 -20
  116. package/dist/core/config/schema/engines.js +8 -7
  117. package/dist/core/config/schema/improve-processes.js +29 -5
  118. package/dist/core/config/schema/primitives.js +1 -23
  119. package/dist/core/config/schema/sources-bundles.js +13 -16
  120. package/dist/core/errors.js +2 -0
  121. package/dist/core/events.js +68 -32
  122. package/dist/core/extra-params.js +1 -0
  123. package/dist/core/improve-result.js +315 -0
  124. package/dist/core/lesson-lint.js +0 -6
  125. package/dist/core/maintenance-barrier.js +4 -4
  126. package/dist/core/network-policy.js +152 -0
  127. package/dist/core/paths.js +1 -1
  128. package/dist/core/recognition-util.js +4 -4
  129. package/dist/core/registry-url.js +456 -0
  130. package/dist/core/state/migrations.js +161 -47
  131. package/dist/core/state-db.js +453 -80
  132. package/dist/core/system-error.js +32 -0
  133. package/dist/core/time.js +2 -12
  134. package/dist/core/write-source.js +0 -18
  135. package/dist/execution/directory-identity.js +52 -0
  136. package/dist/execution/executable-identity.js +107 -0
  137. package/dist/execution/guarded-source.js +398 -0
  138. package/dist/execution/json.js +95 -0
  139. package/dist/{commands/health/types-session-log.js → execution/limits.js} +2 -1
  140. package/dist/execution/record.js +55 -0
  141. package/dist/execution/resolved-request.js +730 -0
  142. package/dist/execution/source.js +320 -0
  143. package/dist/indexer/bundle-identity-guard.js +5 -4
  144. package/dist/indexer/db/graph-db.js +33 -0
  145. package/dist/indexer/graph/graph-boost.js +3 -4
  146. package/dist/indexer/graph/graph-extraction.js +562 -373
  147. package/dist/indexer/index-written-assets.js +65 -34
  148. package/dist/indexer/indexer.js +443 -222
  149. package/dist/indexer/installations.js +6 -0
  150. package/dist/indexer/lookup/adapter-concept-owner.js +283 -0
  151. package/dist/indexer/passes/memory-inference.js +227 -174
  152. package/dist/indexer/scan/doc-to-entry.js +7 -9
  153. package/dist/indexer/scan/drain-dir.js +51 -23
  154. package/dist/indexer/search/db-search.js +98 -22
  155. package/dist/indexer/search/search-fields.js +1 -1
  156. package/dist/indexer/search/search-hit-enrichers.js +1 -1
  157. package/dist/indexer/search/search-source.js +7 -16
  158. package/dist/indexer/search/semantic-status.js +10 -1
  159. package/dist/indexer/usage/show-usage.js +105 -0
  160. package/dist/indexer/usage/usage-events.js +7 -2
  161. package/dist/indexer/walk/matchers.js +40 -10
  162. package/dist/indexer/walk/path-resolver.js +5 -2
  163. package/dist/indexer/walk/walker.js +20 -2
  164. package/dist/integrations/agent/builder-shared.js +3 -6
  165. package/dist/integrations/agent/conversation-fallback.js +16 -0
  166. package/dist/integrations/agent/engine-resolution.js +87 -87
  167. package/dist/integrations/agent/execution-cascade.js +566 -0
  168. package/dist/integrations/agent/execution-definitions.js +211 -0
  169. package/dist/integrations/agent/execution-lowering.js +811 -0
  170. package/dist/integrations/agent/execution-preparation.js +67 -0
  171. package/dist/integrations/agent/index.js +0 -2
  172. package/dist/integrations/agent/inline-execution.js +74 -0
  173. package/dist/integrations/agent/model-map.js +515 -0
  174. package/dist/integrations/agent/persona-fallback.js +30 -0
  175. package/dist/integrations/agent/request-lowering.js +186 -0
  176. package/dist/integrations/agent/runner-dispatch.js +230 -37
  177. package/dist/integrations/agent/runner.js +12 -83
  178. package/dist/integrations/harnesses/aider/agent-builder.js +8 -0
  179. package/dist/integrations/harnesses/aider/index.js +0 -1
  180. package/dist/integrations/harnesses/amazonq/agent-builder.js +8 -0
  181. package/dist/integrations/harnesses/amazonq/index.js +0 -1
  182. package/dist/integrations/harnesses/claude/agent-builder.js +14 -1
  183. package/dist/integrations/harnesses/claude/index.js +1 -5
  184. package/dist/integrations/harnesses/claude/session-log.js +3 -33
  185. package/dist/integrations/harnesses/codex/agent-builder.js +8 -0
  186. package/dist/integrations/harnesses/codex/index.js +0 -1
  187. package/dist/integrations/harnesses/copilot/agent-builder.js +8 -0
  188. package/dist/integrations/harnesses/copilot/index.js +0 -1
  189. package/dist/integrations/harnesses/gemini/agent-builder.js +8 -0
  190. package/dist/integrations/harnesses/gemini/index.js +0 -1
  191. package/dist/integrations/harnesses/index.js +4 -44
  192. package/dist/integrations/harnesses/opencode/agent-builder.js +16 -9
  193. package/dist/integrations/harnesses/opencode/index.js +0 -2
  194. package/dist/integrations/harnesses/opencode/session-log.js +14 -204
  195. package/dist/integrations/harnesses/opencode-sdk/harness.js +12 -1
  196. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +40 -42
  197. package/dist/integrations/harnesses/openhands/agent-builder.js +8 -0
  198. package/dist/integrations/harnesses/openhands/index.js +0 -1
  199. package/dist/integrations/harnesses/pi/agent-builder.js +8 -0
  200. package/dist/integrations/harnesses/pi/index.js +0 -1
  201. package/dist/integrations/harnesses/shared.js +0 -1
  202. package/dist/integrations/harnesses/types.js +1 -3
  203. package/dist/integrations/lockfile.js +82 -79
  204. package/dist/integrations/session-logs/index.js +6 -17
  205. package/dist/integrations/session-logs/provider-base.js +1 -29
  206. package/dist/llm/client.js +10 -5
  207. package/dist/llm/embedder.js +6 -7
  208. package/dist/llm/embedders/local.js +37 -88
  209. package/dist/llm/embedders/types.js +1 -1
  210. package/dist/llm/graph-extract.js +75 -50
  211. package/dist/llm/index-passes.js +43 -5
  212. package/dist/llm/memory-infer.js +8 -6
  213. package/dist/llm/metadata-enhance.js +5 -3
  214. package/dist/llm/structured-call.js +122 -25
  215. package/dist/output/format-exempt.js +1 -1
  216. package/dist/output/render-registry.js +0 -16
  217. package/dist/output/renderers.js +12 -7
  218. package/dist/output/shapes/curate.js +1 -0
  219. package/dist/output/shapes/helpers.js +10 -2
  220. package/dist/output/shapes/passthrough.js +2 -0
  221. package/dist/output/text/command-format.js +28 -32
  222. package/dist/output/text/health-format.js +1 -29
  223. package/dist/output/text/migrate.js +6 -56
  224. package/dist/output/text/proposal-format.js +16 -1
  225. package/dist/output/text/workflow-format.js +16 -0
  226. package/dist/registry/network.js +279 -0
  227. package/dist/registry/pinned-request-helper.js +247 -0
  228. package/dist/registry/pinned-transport.js +717 -0
  229. package/dist/registry/providers/skills-sh.js +18 -6
  230. package/dist/registry/providers/static-index.js +20 -7
  231. package/dist/registry/resolve.js +53 -28
  232. package/dist/scripts/akm-migrate-node.js +19122 -52218
  233. package/dist/scripts/akm-migrate.js +19064 -51567
  234. package/dist/setup/registry-stash-loader.js +64 -20
  235. package/dist/setup/semantic-assets.js +9 -34
  236. package/dist/setup/setup.js +12 -30
  237. package/dist/setup/source-identity.js +17 -0
  238. package/dist/setup/steps/sources.js +36 -15
  239. package/dist/setup/steps/tasks.js +39 -11
  240. package/dist/sources/providers/git-provider.js +3 -3
  241. package/dist/sources/providers/npm.js +2 -2
  242. package/dist/sources/providers/provider-utils.js +4 -3
  243. package/dist/sources/providers/website.js +11 -7
  244. package/dist/sources/snapshot-fetchers/host-guard.js +9 -136
  245. package/dist/sources/snapshot-fetchers/website-ingest.js +25 -109
  246. package/dist/sources/website-url.js +73 -0
  247. package/dist/storage/engines/sqlite-migrations.js +81 -26
  248. package/dist/storage/managed-db.js +27 -24
  249. package/dist/storage/repositories/events-repository.js +3 -0
  250. package/dist/storage/repositories/index-connection.js +42 -10
  251. package/dist/storage/repositories/index-entries-repository.js +167 -207
  252. package/dist/storage/repositories/index-entry-mapper.js +8 -12
  253. package/dist/storage/repositories/index-entry-schema.js +255 -0
  254. package/dist/storage/repositories/index-fts-repository.js +10 -10
  255. package/dist/storage/repositories/index-llm-cache-repository.js +8 -13
  256. package/dist/storage/repositories/index-meta-repository.js +0 -11
  257. package/dist/storage/repositories/index-schema.js +71 -342
  258. package/dist/storage/repositories/index-utility-repository.js +12 -17
  259. package/dist/storage/repositories/index-vec-repository.js +1 -1
  260. package/dist/storage/repositories/proposals-repository.js +4 -127
  261. package/dist/storage/repositories/registry-cache.js +2 -1
  262. package/dist/storage/repositories/task-history-repository.js +20 -40
  263. package/dist/storage/repositories/workflow-runs-repository.js +228 -129
  264. package/dist/storage/sqlite-read-snapshot.js +148 -0
  265. package/dist/tasks/backends/cron.js +170 -42
  266. package/dist/tasks/backends/index.js +1 -1
  267. package/dist/tasks/backends/launchd.js +787 -202
  268. package/dist/tasks/backends/schtasks.js +282 -83
  269. package/dist/tasks/embedded.js +7 -7
  270. package/dist/tasks/frozen-script.js +50 -0
  271. package/dist/tasks/resolve-akm-bin.js +5 -1
  272. package/dist/tasks/runner.js +239 -251
  273. package/dist/tasks/runtime-v3.js +281 -0
  274. package/dist/tasks/scheduler-binding.js +272 -0
  275. package/dist/tasks/scheduler-invocation.js +57 -43
  276. package/dist/tasks/scheduler-sync.js +654 -0
  277. package/dist/tasks/source-v3.js +752 -0
  278. package/dist/tasks/standalone-script-entry.js +5 -0
  279. package/dist/tasks/task-id.js +29 -0
  280. package/dist/workflows/authoring/authoring.js +15 -32
  281. package/dist/workflows/exec/dispatch-redaction.js +14 -8
  282. package/dist/workflows/exec/exec-unit.js +7 -28
  283. package/dist/workflows/exec/frozen-judge.js +57 -89
  284. package/dist/workflows/exec/lowering-notices.js +23 -0
  285. package/dist/workflows/exec/native-executor.js +301 -458
  286. package/dist/workflows/exec/param-secrets.js +4 -3
  287. package/dist/workflows/exec/run-workflow.js +26 -32
  288. package/dist/workflows/exec/step-work.js +105 -109
  289. package/dist/workflows/exec/unit-dispatch.js +103 -27
  290. package/dist/workflows/exec/unit-writer.js +3 -3
  291. package/dist/workflows/exec/worktree.js +2 -2
  292. package/dist/workflows/ir/compile.js +86 -72
  293. package/dist/workflows/ir/environment-v4.js +328 -0
  294. package/dist/workflows/ir/freeze-v4.js +122 -0
  295. package/dist/workflows/ir/plan-hash.js +13 -7
  296. package/dist/workflows/ir/schema-v4.js +525 -0
  297. package/dist/workflows/ir/schema.js +25 -284
  298. package/dist/workflows/ir/source-freeze-v4.js +506 -0
  299. package/dist/workflows/parser.js +27 -24
  300. package/dist/workflows/program/schema.js +1 -2
  301. package/dist/workflows/renderer.js +42 -29
  302. package/dist/workflows/resource-limits.js +4 -5
  303. package/dist/workflows/runtime/agent-identity.js +11 -13
  304. package/dist/workflows/runtime/plan-classifier.js +8 -8
  305. package/dist/workflows/runtime/runs.js +27 -43
  306. package/dist/workflows/runtime/workflow-asset-loader.js +45 -205
  307. package/dist/workflows/source-files.js +373 -0
  308. package/dist/workflows/source-ir/compile.js +196 -0
  309. package/dist/workflows/source-ir/github-yaml.js +577 -0
  310. package/dist/workflows/source-ir/ordering.js +38 -0
  311. package/dist/workflows/source-ir/program.js +50 -0
  312. package/dist/workflows/source-ir/result.js +26 -0
  313. package/dist/workflows/source-ir/schema.js +772 -0
  314. package/dist/workflows/source-ir/semantics.js +242 -0
  315. package/dist/workflows/source-ir/uses.js +14 -0
  316. package/docs/README.md +2 -0
  317. package/docs/migration/README.md +3 -1
  318. package/docs/migration/release-notes/0.9.2.md +55 -0
  319. package/docs/migration/release-notes/README.md +5 -0
  320. package/docs/migration/v0.8-to-v0.9.md +76 -1077
  321. package/docs/migration/v0.9.0-troubleshooting.md +104 -516
  322. package/docs/migration/v0.9.1-to-v0.9.2.md +150 -0
  323. package/docs/reference/README.md +1 -0
  324. package/docs/reference/cli.md +230 -98
  325. package/docs/reference/configuration.md +153 -27
  326. package/docs/reference/data-and-telemetry.md +19 -1
  327. package/docs/reference/supported-formats.md +23 -3
  328. package/docs/reference/tasks.md +182 -0
  329. package/docs/reference/workflow-schema.md +91 -40
  330. package/docs/reference/workflows.md +33 -6
  331. package/package.json +10 -6
  332. package/schemas/akm-config.json +372 -216
  333. package/schemas/akm-task.json +324 -80
  334. package/schemas/akm-workflow.json +6 -9
  335. package/dist/core/migration-operation.js +0 -75
  336. package/dist/integrations/agent/model-aliases.js +0 -74
  337. package/dist/tasks/parser.js +0 -380
  338. package/dist/tasks/schema.js +0 -123
  339. package/dist/tasks/validator.js +0 -80
  340. package/dist/workflows/ir/freeze.js +0 -320
  341. package/dist/workflows/runtime/document-cache.js +0 -13
@@ -3,11 +3,13 @@
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  import { spawnSync } from "node:child_process";
5
5
  import { loadConfig } from "../../core/config/config.js";
6
+ import { ConfigError } from "../../core/errors.js";
6
7
  import { withEngineFallback } from "../../integrations/agent/engine-fallback.js";
7
8
  import { resolveEngine } from "../../integrations/agent/engine-resolution.js";
8
- import { resolveModel } from "../../integrations/agent/model-aliases.js";
9
+ import { executionEngineDefinitionsFromConfig } from "../../integrations/agent/execution-definitions.js";
10
+ import { loadModelMap, mergeModelMapLayers, parseModelMapLayer, readInstalledModelMapText, resolveModelMapAlias, userModelMapPath, } from "../../integrations/agent/model-map.js";
9
11
  import { resolveImprovePlan } from "../improve/improve-strategies.js";
10
- import { ACTIVE_RUN_WARN_MS, TASK_FAIL_RATE_WARN, } from "./types.js";
12
+ import { ACTIVE_RUN_WARN_MS, TASK_FAIL_RATE_WARN } from "./types.js";
11
13
  function credentialAvailable(credential, env) {
12
14
  return !credential?.required || credential.names.some((name) => Boolean(env[name]?.trim()));
13
15
  }
@@ -36,8 +38,21 @@ function runConfiguredEngineProbe(checkName, engineName, config, deps) {
36
38
  packageAvailable = false;
37
39
  }
38
40
  const binary = configuredEngine.bin ?? "opencode";
39
- const version = (deps.spawnSync ?? spawnSync)(binary, ["--version"], { encoding: "utf8", timeout: 5_000 });
40
- const binaryAvailable = (version.status ?? 1) === 0;
41
+ let binaryAvailable;
42
+ try {
43
+ const version = (deps.spawnSync ?? spawnSync)(binary, ["--version"], { encoding: "utf8", timeout: 5_000 });
44
+ binaryAvailable = (version.status ?? 1) === 0;
45
+ }
46
+ catch {
47
+ return {
48
+ name: checkName,
49
+ kind: "deterministic",
50
+ status: "warn",
51
+ confidence: "high",
52
+ message: `SDK engine "${engineName}" executable availability could not be checked.`,
53
+ evidence: { engine: engineName, runtimeKind: "sdk", binaryAvailable: false },
54
+ };
55
+ }
41
56
  const fallbackEngine = configuredEngine.llmEngine ?? config.defaults?.llmEngine;
42
57
  let fallback;
43
58
  let fallbackCredential;
@@ -51,8 +66,8 @@ function runConfiguredEngineProbe(checkName, engineName, config, deps) {
51
66
  catch {
52
67
  sdkRunner = undefined;
53
68
  }
54
- if (sdkRunner?.fallbackConnection) {
55
- fallback = { kind: "llm", connection: sdkRunner.fallbackConnection };
69
+ if (sdkRunner?.fallbackConnection && fallbackEngine) {
70
+ fallback = { kind: "llm", engine: fallbackEngine, connection: sdkRunner.fallbackConnection };
56
71
  fallbackCredential = sdkRunner.fallbackCredential;
57
72
  }
58
73
  else if (fallbackEngine) {
@@ -67,9 +82,7 @@ function runConfiguredEngineProbe(checkName, engineName, config, deps) {
67
82
  fallback = undefined;
68
83
  }
69
84
  }
70
- const configuredModel = configuredEngine.model
71
- ? resolveModel(configuredEngine.model, "opencode-sdk", configuredEngine.modelAliases, config.modelAliases)
72
- : undefined;
85
+ const configuredModel = configuredEngine.model;
73
86
  const effectiveModel = sdkRunner?.profile.model ?? configuredModel ?? fallback?.connection.model;
74
87
  const fallbackCredentialAvailable = credentialAvailable(fallbackCredential, env);
75
88
  const missing = [
@@ -169,6 +182,58 @@ function runConfiguredEngineProbe(checkName, engineName, config, deps) {
169
182
  };
170
183
  }
171
184
  }
185
+ function projectEngineProbe(result, name) {
186
+ return result.name === name ? result : { ...result, name };
187
+ }
188
+ function projectSelectedEngineProbe(availability, engineName, checkName) {
189
+ const result = availability.get(engineName);
190
+ if (result)
191
+ return projectEngineProbe(result, checkName);
192
+ return {
193
+ name: checkName,
194
+ kind: "deterministic",
195
+ status: "warn",
196
+ confidence: "high",
197
+ message: `Engine "${engineName}" availability could not be checked.`,
198
+ evidence: { engine: engineName },
199
+ };
200
+ }
201
+ function unconfiguredEngineProbe(name) {
202
+ return {
203
+ name,
204
+ kind: "deterministic",
205
+ status: "unknown",
206
+ confidence: "high",
207
+ message: name === "default-llm-engine" ? "No default LLM engine is configured." : "No default engine is configured.",
208
+ };
209
+ }
210
+ function configuredEnginesProjection(engineNames, availability) {
211
+ if (engineNames.length === 0) {
212
+ return {
213
+ name: "configured-engines",
214
+ kind: "deterministic",
215
+ status: "unknown",
216
+ confidence: "high",
217
+ message: "No engines are explicitly configured.",
218
+ evidence: { engines: [] },
219
+ };
220
+ }
221
+ const engines = engineNames.map((engine) => ({
222
+ engine,
223
+ status: availability.get(engine)?.status === "pass" ? "pass" : "warn",
224
+ }));
225
+ const unavailable = engines.filter((engine) => engine.status === "warn").length;
226
+ return {
227
+ name: "configured-engines",
228
+ kind: "deterministic",
229
+ status: unavailable === 0 ? "pass" : "warn",
230
+ confidence: "high",
231
+ message: unavailable === 0
232
+ ? `All ${engines.length} explicitly configured engines are available.`
233
+ : `${unavailable} of ${engines.length} explicitly configured engines ${unavailable === 1 ? "is" : "are"} unavailable.`,
234
+ evidence: { engines },
235
+ };
236
+ }
172
237
  export function runDefaultEngineProbe(deps = {}) {
173
238
  // Probe the effective view: an install with no `defaults.engine` but a usable
174
239
  // opencode binary DOES have a working default, and reporting otherwise would
@@ -180,6 +245,38 @@ export function runDefaultLlmEngineProbe(deps = {}) {
180
245
  const config = deps.loadConfig?.() ?? loadConfig();
181
246
  return runConfiguredEngineProbe("default-llm-engine", config.defaults?.llmEngine, config, deps);
182
247
  }
248
+ /** Probe every explicitly configured engine without exposing connection or model material. */
249
+ export function runConfiguredEnginesProbe(deps = {}) {
250
+ const config = deps.loadConfig?.() ?? loadConfig();
251
+ const engineNames = Object.keys(config.engines ?? {}).sort();
252
+ const availability = new Map(engineNames.map((engine) => [engine, runConfiguredEngineProbe("configured-engine", engine, config, deps)]));
253
+ return configuredEnginesProjection(engineNames, availability);
254
+ }
255
+ /**
256
+ * Build the per-health-run availability snapshot. Each distinct selected or
257
+ * explicitly configured engine is probed once; the three public checks are
258
+ * projections of that immutable result set.
259
+ */
260
+ export function runHealthEngineProbes(deps = {}) {
261
+ const configured = deps.loadConfig?.() ?? loadConfig();
262
+ const effective = withEngineFallback(configured, deps.which).config;
263
+ const defaultEngineName = effective.defaults?.engine;
264
+ const defaultLlmEngineName = configured.defaults?.llmEngine;
265
+ const explicitEngineNames = Object.keys(configured.engines ?? {}).sort();
266
+ const probeNames = [...new Set([...explicitEngineNames, defaultEngineName, defaultLlmEngineName])]
267
+ .filter((name) => name !== undefined)
268
+ .sort();
269
+ const availability = new Map(probeNames.map((engine) => [engine, runConfiguredEngineProbe("configured-engine", engine, effective, deps)]));
270
+ return Object.freeze({
271
+ defaultEngine: defaultEngineName
272
+ ? projectSelectedEngineProbe(availability, defaultEngineName, "default-engine")
273
+ : unconfiguredEngineProbe("default-engine"),
274
+ defaultLlmEngine: defaultLlmEngineName
275
+ ? projectSelectedEngineProbe(availability, defaultLlmEngineName, "default-llm-engine")
276
+ : unconfiguredEngineProbe("default-llm-engine"),
277
+ configuredEngines: configuredEnginesProjection(explicitEngineNames, availability),
278
+ });
279
+ }
183
280
  export function runActiveImproveStrategyProbe(deps = {}) {
184
281
  const config = deps.loadConfig?.() ?? loadConfig();
185
282
  const strategyName = config.defaults?.improveStrategy ?? "default";
@@ -226,6 +323,124 @@ export function runActiveImproveStrategyProbe(deps = {}) {
226
323
  };
227
324
  }
228
325
  }
326
+ /**
327
+ * Validate the immutable installed model map and optional user overlay.
328
+ * Installed corruption is a package defect (fail); a bad optional user file
329
+ * is operator-fixable configuration (warn); absence is the normal state.
330
+ */
331
+ export function runModelMapProbe(options = {}) {
332
+ let installedText;
333
+ try {
334
+ installedText = readInstalledModelMapText(options);
335
+ mergeModelMapLayers(parseModelMapLayer(installedText, "installed models.json"));
336
+ }
337
+ catch (error) {
338
+ return {
339
+ name: "model-map-files",
340
+ kind: "deterministic",
341
+ status: "fail",
342
+ confidence: "high",
343
+ message: `Installed models.json is invalid; this AKM installation cannot resolve model aliases: ${error instanceof Error ? error.message : String(error)}`,
344
+ evidence: { installedSource: "package asset" },
345
+ };
346
+ }
347
+ try {
348
+ const loaded = loadModelMap({ ...options, installedText });
349
+ return {
350
+ name: "model-map-files",
351
+ kind: "deterministic",
352
+ status: "pass",
353
+ confidence: "high",
354
+ message: loaded.userStatus === "loaded"
355
+ ? `Installed defaults and user models.json at ${loaded.userPath} are valid.`
356
+ : "Installed model defaults are valid; no optional user models.json is present.",
357
+ evidence: {
358
+ installedSource: "package asset",
359
+ userPath: loaded.userPath,
360
+ userStatus: loaded.userStatus,
361
+ aliases: Object.keys(loaded.map.aliases).sort(),
362
+ },
363
+ };
364
+ }
365
+ catch (error) {
366
+ const hint = error instanceof ConfigError ? error.hint() : undefined;
367
+ return {
368
+ name: "model-map-files",
369
+ kind: "deterministic",
370
+ status: "warn",
371
+ confidence: "high",
372
+ message: `${error instanceof Error ? error.message : String(error)}${hint ? ` ${hint}` : ""}`,
373
+ evidence: {
374
+ installedSource: "package asset",
375
+ userPath: userModelMapPath(options.env),
376
+ userStatus: "invalid",
377
+ },
378
+ };
379
+ }
380
+ }
381
+ /**
382
+ * Check model selections owned by configured engines against the common model
383
+ * map. Unknown identifiers are deliberate exact-model pass-throughs; only an
384
+ * alias known somewhere in the map but absent for the selected engine warns.
385
+ */
386
+ export function runSelectedModelAliasesProbe(deps = {}) {
387
+ const config = deps.loadConfig?.() ?? loadConfig();
388
+ const definitions = executionEngineDefinitionsFromConfig(config);
389
+ const selected = Object.entries(definitions)
390
+ .sort(([left], [right]) => left.localeCompare(right))
391
+ .flatMap(([engine, definition]) => {
392
+ const model = definition.defaults?.model;
393
+ const modelMapKey = definition.modelMapKey ?? definition.selection.platform ?? definition.selection.name;
394
+ return typeof model === "string" ? [{ engine, alias: model, modelMapKey }] : [];
395
+ });
396
+ if (selected.length === 0) {
397
+ return {
398
+ name: "selected-model-aliases",
399
+ kind: "deterministic",
400
+ status: "unknown",
401
+ confidence: "high",
402
+ message: "No configured engines select a model.",
403
+ evidence: { checked: [], missing: [] },
404
+ };
405
+ }
406
+ let modelMap;
407
+ try {
408
+ modelMap = (deps.loadModelMap ?? loadModelMap)({ env: deps.env, installedText: deps.installedText });
409
+ }
410
+ catch {
411
+ return {
412
+ name: "selected-model-aliases",
413
+ kind: "deterministic",
414
+ status: "unknown",
415
+ confidence: "high",
416
+ message: "Configured model selections could not be checked because the model map is invalid.",
417
+ evidence: { checked: [], missing: [] },
418
+ };
419
+ }
420
+ const outcomes = selected.map(({ engine, alias, modelMapKey }) => {
421
+ try {
422
+ const resolution = resolveModelMapAlias(alias, modelMapKey, modelMap.map);
423
+ return resolution.interpretation === "alias"
424
+ ? { kind: "alias", evidence: { engine, alias, modelMapKey } }
425
+ : { kind: "exact" };
426
+ }
427
+ catch {
428
+ return { kind: "missing", evidence: { engine, alias, modelMapKey } };
429
+ }
430
+ });
431
+ const checked = outcomes.flatMap((outcome) => (outcome.kind === "exact" ? [] : [outcome.evidence]));
432
+ const missing = outcomes.flatMap((outcome) => (outcome.kind === "missing" ? [outcome.evidence] : []));
433
+ return {
434
+ name: "selected-model-aliases",
435
+ kind: "deterministic",
436
+ status: missing.length === 0 ? "pass" : "warn",
437
+ confidence: "high",
438
+ message: missing.length === 0
439
+ ? `All ${selected.length} configured model selections resolve for their selected engines.`
440
+ : `${missing.length} of ${selected.length} configured model selections ${missing.length === 1 ? "has" : "have"} no mapping for ${missing.length === 1 ? "its" : "their"} selected engine${missing.length === 1 ? "" : "s"}.`,
441
+ evidence: { checked, missing },
442
+ };
443
+ }
229
444
  /**
230
445
  * The ordered health-check registry. ORDER IS LOAD-BEARING: `akmHealth`
231
446
  * iterates this array and appends to hardChecks/advisories in sequence, so the
@@ -312,12 +527,27 @@ export const HEALTH_CHECKS = [
312
527
  {
313
528
  name: "default-engine",
314
529
  channel: "hard",
315
- run: () => runDefaultEngineProbe(),
530
+ run: (ctx) => ctx.engineProbes.defaultEngine,
531
+ },
532
+ {
533
+ name: "model-map-files",
534
+ channel: "hard",
535
+ run: () => runModelMapProbe(),
536
+ },
537
+ {
538
+ name: "selected-model-aliases",
539
+ channel: "hard",
540
+ run: () => runSelectedModelAliasesProbe(),
316
541
  },
317
542
  {
318
543
  name: "default-llm-engine",
319
544
  channel: "hard",
320
- run: () => runDefaultLlmEngineProbe(),
545
+ run: (ctx) => ctx.engineProbes.defaultLlmEngine,
546
+ },
547
+ {
548
+ name: "configured-engines",
549
+ channel: "hard",
550
+ run: (ctx) => ctx.engineProbes.configuredEngines,
321
551
  },
322
552
  {
323
553
  name: "active-improve-strategy",
@@ -409,24 +639,6 @@ export const HEALTH_CHECKS = [
409
639
  };
410
640
  },
411
641
  },
412
- {
413
- // session-log-failures: demoted to informational — the ERROR_PATTERNS regex
414
- // scans pre-LLM session text and produces false positives on diagnostic
415
- // conversation. It does not gate the real extraction pipeline (akmExtract).
416
- // Never triggers warn; kept for backward-compat visibility only.
417
- name: "session-log-failures",
418
- channel: "advisory",
419
- run: (ctx) => ({
420
- name: "session-log-failures",
421
- kind: "heuristic",
422
- status: "pass",
423
- confidence: "low",
424
- message: ctx.sessionLogEntries.length === 0
425
- ? "No repeated external session-log failure patterns were detected."
426
- : `${ctx.sessionLogEntries.length} raw session-log keyword match(es) detected (pre-LLM, informational only).`,
427
- evidence: { candidates: ctx.sessionLogEntries.slice(0, 5) },
428
- }),
429
- },
430
642
  {
431
643
  name: "session-extraction",
432
644
  channel: "advisory",
@@ -369,20 +369,6 @@ function renderActionItems(vm) {
369
369
  remedy: "akm config list",
370
370
  });
371
371
  }
372
- // Session-log notes (informational, lowest priority).
373
- if (vm.sessionLogAdvisories.length > 0) {
374
- const patterns = vm.sessionLogAdvisories
375
- .slice(0, 6)
376
- .map((p) => `<li>${esc(p.topic)}</li>`)
377
- .join("");
378
- pushItem({
379
- key: "session-log-notes",
380
- prio: "P3",
381
- cls: "warn",
382
- title: `${vm.sessionLogAdvisories.length} session-log note(s) (informational)`,
383
- descHtml: `<ul style="margin:4px 0 0 16px;padding:0;">${patterns}</ul>`,
384
- });
385
- }
386
372
  items.sort((a, b) => PRIO_RANK[a.prio] - PRIO_RANK[b.prio]);
387
373
  return items.length > 0
388
374
  ? items.map(actionItemCard).join("\n")
@@ -503,6 +503,5 @@ export function buildHealthReportViewModel(result, opts) {
503
503
  sliceCandidates: computeSliceCandidates(opts.window),
504
504
  distillReasons,
505
505
  advisories: result.advisories,
506
- sessionLogAdvisories: result.sessionLogAdvisories,
507
506
  };
508
507
  }
@@ -17,14 +17,13 @@
17
17
  import { MAX_CONFIG_FILE_BYTES, readTextFileWithLimit } from "../../core/common.js";
18
18
  import { CURRENT_CONFIG_VERSION } from "../../core/config/config-schema.js";
19
19
  import { compareConfigVersion } from "../../core/config/config-version.js";
20
+ import { formatRegistryUrl } from "../../core/registry-url.js";
20
21
  /**
21
22
  * `binary-config-skew` (08-F3): warn when config.json carries a configVersion
22
23
  * NEWER than (or unorderable against) this binary's CURRENT_CONFIG_VERSION —
23
24
  * i.e. a newer/foreign akm wrote the shared config and this install is stale.
24
- * That is exactly the state where auto-migration is skipped (downgrade
25
- * protection) and the proven multi-install incident class begins. Silent for
26
- * same/older versions (auto-migration handles those) and unreadable configs
27
- * (config loading surfaces its own errors).
25
+ * That is the proven multi-install incident class. Silent for current or older
26
+ * versions and unreadable configs (config loading surfaces its own errors).
28
27
  */
29
28
  export function collectConfigSkewAdvisory(configPath) {
30
29
  let raw;
@@ -45,8 +44,8 @@ export function collectConfigSkewAdvisory(configPath) {
45
44
  status: "warn",
46
45
  confidence: "high",
47
46
  message: `config.json has configVersion ${JSON.stringify(onDisk)} but this binary knows ${CURRENT_CONFIG_VERSION} — ` +
48
- "a newer akm wrote the shared config, so this install is stale and auto-migration is skipped " +
49
- "(downgrade protection). Upgrade this install; do not keep a stale binary against the shared config/DBs.",
47
+ "a newer akm wrote the shared config, so this install is stale. Upgrade this install; do not keep a stale " +
48
+ "binary against the shared config/DBs.",
50
49
  evidence: { onDiskConfigVersion: onDisk, binaryConfigVersion: CURRENT_CONFIG_VERSION },
51
50
  };
52
51
  }
@@ -64,7 +63,7 @@ export function collectEgressAdvisory(config) {
64
63
  for (const reg of config.registries ?? []) {
65
64
  if (reg.enabled === false || !reg.url)
66
65
  continue;
67
- endpoints.push(`registry ${reg.name ?? "(unnamed)"}: ${reg.url}`);
66
+ endpoints.push(`registry ${reg.name ?? "(unnamed)"}: ${formatRegistryUrl(reg.url)}`);
68
67
  }
69
68
  for (const [key, bundle] of Object.entries(config.bundles ?? {})) {
70
69
  if (!bundle)
@@ -16,7 +16,6 @@
16
16
  * - `./types-improve` — the {@link ImproveHealthMetrics} accumulator and its
17
17
  * WS-5 sub-rollups (coverage, perf telemetry, degradation, enrichment
18
18
  * minting).
19
- * - `./types-session-log` — {@link SessionLogAdvisory}.
20
19
  * - `./types-runs` — {@link ImproveRunSummary} (`--group-by run`).
21
20
  * - `./types-windows` — {@link WindowSpec}/{@link WindowResult}/{@link DeltaEntry}
22
21
  * (`--window-compare`/`--windows`).
@@ -27,5 +26,4 @@ export * from "./types-improve.js";
27
26
  export * from "./types-metrics.js";
28
27
  export * from "./types-result.js";
29
28
  export * from "./types-runs.js";
30
- export * from "./types-session-log.js";
31
29
  export * from "./types-windows.js";
@@ -10,14 +10,14 @@ import { readEvents } from "../core/events.js";
10
10
  import { listTxnJournalsTolerant, TXN_SWEEP_GRACE_MS } from "../core/fs-txn.js";
11
11
  import { openLogsDatabase } from "../core/logs-db.js";
12
12
  import { classifyPathAccess, describeInaccessiblePath } from "../core/path-access.js";
13
- import { getConfigPath, getDataDir, getStateDbPathInDataDir } from "../core/paths.js";
13
+ import { getConfigPath, getDataDir, getDbPath, getStateDbPathInDataDir } from "../core/paths.js";
14
14
  import { listExistingTableNames, openStateDatabase } from "../core/state-db.js";
15
15
  import { DURATION_UNITS, parseDuration, parseSinceToIso } from "../core/time.js";
16
16
  import { readSemanticStatus } from "../indexer/search/semantic-status.js";
17
- import { getExecutionLogCandidates } from "../integrations/session-logs/index.js";
17
+ import { closeDatabase, openReadonlyExistingDatabase } from "../storage/repositories/index-connection.js";
18
18
  import { queryTaskHistory } from "../storage/repositories/task-history-repository.js";
19
19
  import { collectImproveAdvisories } from "./health/advisories.js";
20
- import { HEALTH_CHECKS } from "./health/checks.js";
20
+ import { HEALTH_CHECKS, runHealthEngineProbes } from "./health/checks.js";
21
21
  import { buildImproveSkipSummary, computeWallTimeStats, parseTaskMetadata, roundRate, summarizeImproveCompleted, summarizeImproveRuns, } from "./health/improve-metrics.js";
22
22
  import { emptyLlmUsageAggregate, readLlmUsageAggregate } from "./health/llm-usage.js";
23
23
  import { computeDegradationMetrics, computeDenominatorFixedCoverage, computeEnrichmentMintingRollup, probeStateDbRoundTrip, } from "./health/metrics.js";
@@ -235,6 +235,9 @@ function gatherImproveSummaryPhase(db, stateDbPath, since, now) {
235
235
  */
236
236
  function gatherAncillaryAdvisories(db, stateDbPath, since, improveSummary, options, egressConfigView) {
237
237
  const advisories = [...collectImproveAdvisories(db, stateDbPath, since, improveSummary)];
238
+ const indexStateMismatch = detectIndexStateGenerationMismatch(db);
239
+ if (indexStateMismatch)
240
+ advisories.push(indexStateMismatch);
238
241
  // 08-F1: surface a `stash-git-exposure` advisory when env/secret assets are
239
242
  // git-tracked AND a remote is configured (the leak moment). Best-effort.
240
243
  // Cheap guard: only shell out to git when the stash has its OWN `.git` (or a
@@ -268,19 +271,64 @@ function gatherAncillaryAdvisories(db, stateDbPath, since, improveSummary, optio
268
271
  }
269
272
  return advisories;
270
273
  }
271
- /** Execution-log-derived session advisories. Best-effort: any failure yields an empty list. */
272
- function gatherSessionLogAdvisories(since, now, getExecutionLogCandidatesFn) {
274
+ /**
275
+ * Detect the durable signature of an interrupted cross-database update.
276
+ *
277
+ * `usage_events.entry_ref` is the stable identity while `entry_id` names the
278
+ * current, regenerable index row. A linked event whose id is absent or resolves
279
+ * to a different ref means index.db and state.db describe adjacent generations.
280
+ * Legacy/bare refs and deliberately detached rows are excluded. The scan is
281
+ * streaming and keeps only a bounded evidence sample so health cannot mirror
282
+ * either database into the JS heap.
283
+ *
284
+ * Best-effort by design: an absent/unreadable/incompatible index has its own
285
+ * diagnostics and must not make the state health path throw.
286
+ */
287
+ function detectIndexStateGenerationMismatch(stateDb) {
288
+ let indexDb;
273
289
  try {
274
- const sinceDays = Math.max(0, Math.ceil((now() - new Date(since).getTime()) / (24 * 60 * 60 * 1000)));
275
- return getExecutionLogCandidatesFn(sinceDays).map((entry) => ({
276
- topic: entry.topic,
277
- frequency: entry.frequency,
278
- source: entry.source,
279
- isFailurePattern: entry.isFailurePattern,
280
- }));
290
+ indexDb = openReadonlyExistingDatabase(getDbPath());
291
+ if (!indexDb)
292
+ return undefined;
293
+ const byId = indexDb.prepare("SELECT item_ref FROM entries WHERE id = ?");
294
+ const rows = stateDb
295
+ .prepare("SELECT DISTINCT entry_id, entry_ref FROM usage_events " +
296
+ "WHERE entry_id IS NOT NULL AND entry_ref IS NOT NULL AND instr(entry_ref, '//') > 0")
297
+ .iterate();
298
+ let mismatches = 0;
299
+ const sample = [];
300
+ for (const row of rows) {
301
+ const indexedRef = byId.get(row.entry_id)?.item_ref ?? null;
302
+ if (indexedRef === row.entry_ref)
303
+ continue;
304
+ mismatches += 1;
305
+ if (sample.length < 5)
306
+ sample.push({ entryId: row.entry_id, entryRef: row.entry_ref, indexedRef });
307
+ }
308
+ if (mismatches === 0)
309
+ return undefined;
310
+ return {
311
+ name: "index-state-generation",
312
+ kind: "deterministic",
313
+ status: "warn",
314
+ confidence: "high",
315
+ message: `${mismatches} durable usage link(s) disagree with the current searchable index generation. ` +
316
+ "Stop concurrent writers and run 'akm index --full' to relink state to the current index.",
317
+ evidence: { mismatches, sample },
318
+ };
281
319
  }
282
320
  catch {
283
- return [];
321
+ return undefined;
322
+ }
323
+ finally {
324
+ if (indexDb) {
325
+ try {
326
+ closeDatabase(indexDb);
327
+ }
328
+ catch {
329
+ // Best-effort advisory: a close failure must not abort health.
330
+ }
331
+ }
284
332
  }
285
333
  }
286
334
  /**
@@ -370,7 +418,6 @@ function unreadableStateDbReport(detail, options) {
370
418
  llmUsage: emptyLlmUsageAggregate(),
371
419
  },
372
420
  improve: summarizeImproveCompleted([]),
373
- sessionLogAdvisories: [],
374
421
  };
375
422
  }
376
423
  export function akmHealth(options = {}) {
@@ -380,7 +427,6 @@ export function akmHealth(options = {}) {
380
427
  const stateDbPath = options.stateDbPath ?? getStateDbPathInDataDir();
381
428
  const hardChecks = [];
382
429
  const advisories = [];
383
- const getExecutionLogCandidatesFn = options.getExecutionLogCandidatesFn ?? getExecutionLogCandidates;
384
430
  // #791: an UNREADABLE state.db is the one failure `akm health` most needs to
385
431
  // be able to report, because it is the command an operator runs to find out
386
432
  // why everything else is behaving oddly. Dying here with exit 78 meant health
@@ -414,7 +460,7 @@ export function akmHealth(options = {}) {
414
460
  const { semanticStatus, semanticSearchMode, embeddingEndpoint, egressConfigView } = gatherSemanticConfigPhase();
415
461
  const { improveSummary } = gatherImproveSummaryPhase(db, stateDbPath, since, now);
416
462
  advisories.push(...gatherAncillaryAdvisories(db, stateDbPath, since, improveSummary, options, egressConfigView));
417
- const sessionLogEntries = gatherSessionLogAdvisories(since, now, getExecutionLogCandidatesFn);
463
+ const engineProbes = runHealthEngineProbes();
418
464
  // Run the ordered health-check registry. Each check projects the shared
419
465
  // context computed above into one HealthCheckResult; `channel` routes it to
420
466
  // hardChecks or advisories. Declaration order in HEALTH_CHECKS is the
@@ -437,9 +483,9 @@ export function akmHealth(options = {}) {
437
483
  semanticStatus,
438
484
  semanticSearchMode,
439
485
  embeddingEndpoint,
440
- sessionLogEntries,
441
486
  sessionExtraction: improveSummary.sessionExtraction,
442
487
  autoAccept: improveSummary.autoAccept,
488
+ engineProbes,
443
489
  };
444
490
  for (const check of HEALTH_CHECKS) {
445
491
  const result = check.run(checkContext);
@@ -475,7 +521,6 @@ export function akmHealth(options = {}) {
475
521
  advisories,
476
522
  metrics,
477
523
  improve: improveSummary,
478
- sessionLogAdvisories: sessionLogEntries,
479
524
  ...(runs ? { runs } : {}),
480
525
  ...(windowResults ? { windows: windowResults } : {}),
481
526
  ...(deltas ? { deltas } : {}),
@@ -262,9 +262,9 @@ export function computeCycleMetrics(stateDb, indexDb, args) {
262
262
  contentHashes.add(normHash(fingerprint));
263
263
  if ((e.entry.generation ?? 0) > maxGeneration)
264
264
  overGeneration++;
265
- learningTexts.push({ key: e.entryKey, text: fingerprint });
265
+ learningTexts.push({ key: e.itemRef, text: fingerprint });
266
266
  }
267
- // Deterministic diversity sample: sort by entryKey, take every ⌈N/cap⌉-th row.
267
+ // Deterministic diversity sample: sort by item ref, take every ⌈N/cap⌉-th row.
268
268
  learningTexts.sort((a, b) => (a.key < b.key ? -1 : 1));
269
269
  const step = Math.max(1, Math.ceil(learningTexts.length / DIVERSITY_SAMPLE_CAP));
270
270
  let diversitySum = 0;