akm-cli 0.9.16 → 0.9.17-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (403) hide show
  1. package/CHANGELOG.md +2101 -0
  2. package/STABILITY.md +11 -10
  3. package/dist/akm +124 -193
  4. package/dist/akm-migrate +38 -19
  5. package/dist/assets/hints/cli-hints-full.md +6 -7
  6. package/dist/assets/improve-strategies/catchup.json +0 -3
  7. package/dist/assets/improve-strategies/consolidate.json +0 -1
  8. package/dist/assets/improve-strategies/default.json +1 -2
  9. package/dist/assets/improve-strategies/proactive-maintenance.json +1 -2
  10. package/dist/assets/improve-strategies/quick.json +1 -2
  11. package/dist/assets/improve-strategies/reflect-distill.json +1 -2
  12. package/dist/assets/improve-strategies/thorough.json +0 -3
  13. package/dist/assets/prompts/consolidate-pair.md +20 -0
  14. package/dist/assets/prompts/consolidate-system.md +4 -11
  15. package/dist/assets/prompts/retrieval-relevance-judge.md +6 -0
  16. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +20 -20
  17. package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -2
  18. package/dist/assets/templates/html/health.html +3 -5
  19. package/dist/cli/retired-commands.js +1 -1
  20. package/dist/cli/shared.js +6 -2
  21. package/dist/cli/unknown-flags.js +24 -1
  22. package/dist/cli.js +68 -10
  23. package/dist/commands/agent/agent-dispatch.js +1 -1
  24. package/dist/commands/command/command-execution.js +24 -62
  25. package/dist/commands/feedback-cli.js +0 -1
  26. package/dist/commands/health/accept-rate.js +6 -0
  27. package/dist/commands/health/archive-usage.js +92 -0
  28. package/dist/commands/health/checks.js +83 -74
  29. package/dist/commands/health/config-skew.js +38 -0
  30. package/dist/commands/health/data-dir-usage.js +25 -13
  31. package/dist/commands/health/egress.js +54 -0
  32. package/dist/commands/health/html-report.js +1 -42
  33. package/dist/commands/health/improve-metrics.js +136 -591
  34. package/dist/commands/health/md-report.js +1 -6
  35. package/dist/commands/health/plugin-staleness.js +53 -3
  36. package/dist/commands/health/renderers.js +12 -4
  37. package/dist/commands/health/report-view-model.js +14 -120
  38. package/dist/commands/health/types-improve.js +4 -19
  39. package/dist/commands/health/windows.js +64 -74
  40. package/dist/commands/health.js +145 -143
  41. package/dist/commands/improve/consolidate/chunking.js +26 -117
  42. package/dist/commands/improve/consolidate/continuity-check.js +137 -0
  43. package/dist/commands/improve/consolidate/pair-pass.js +791 -0
  44. package/dist/commands/improve/consolidate/sanitize.js +54 -149
  45. package/dist/commands/improve/consolidate.js +589 -1127
  46. package/dist/commands/improve/content-hash.js +16 -24
  47. package/dist/commands/improve/distill/content-repair.js +18 -100
  48. package/dist/commands/improve/distill-guards.js +20 -81
  49. package/dist/commands/improve/distill-promotion-policy.js +23 -243
  50. package/dist/commands/improve/distill.js +608 -1041
  51. package/dist/commands/improve/eligibility.js +126 -390
  52. package/dist/commands/improve/execution.js +8 -10
  53. package/dist/commands/improve/extract-prompt.js +1 -2
  54. package/dist/commands/improve/extract.js +487 -1046
  55. package/dist/commands/improve/feedback-valence.js +0 -25
  56. package/dist/commands/improve/improve-cli.js +75 -169
  57. package/dist/commands/improve/improve-result-file.js +10 -66
  58. package/dist/commands/improve/improve-strategies.js +52 -4
  59. package/dist/commands/improve/improve-usage-report.js +18 -64
  60. package/dist/commands/improve/improve.js +480 -1074
  61. package/dist/commands/improve/ledger.js +119 -0
  62. package/dist/commands/improve/locks.js +2 -8
  63. package/dist/commands/improve/loop-stages.js +415 -1073
  64. package/dist/commands/improve/memory/derived-ref.js +12 -77
  65. package/dist/commands/improve/memory/memory-belief.js +16 -118
  66. package/dist/commands/improve/memory/memory-improve.js +266 -14
  67. package/dist/commands/improve/outcome-loop.js +28 -156
  68. package/dist/commands/improve/planner.js +5 -15
  69. package/dist/commands/improve/preparation.js +779 -2319
  70. package/dist/commands/improve/proactive-maintenance.js +34 -101
  71. package/dist/commands/improve/reflect-noise.js +104 -280
  72. package/dist/commands/improve/reflect.js +642 -1353
  73. package/dist/commands/improve/retrieval-gate.js +127 -0
  74. package/dist/commands/improve/retrieval-scope.js +92 -0
  75. package/dist/commands/improve/salience.js +41 -240
  76. package/dist/commands/improve/session-asset.js +19 -100
  77. package/dist/commands/improve/stage.js +322 -0
  78. package/dist/commands/lint/base-linter.js +37 -15
  79. package/dist/commands/proposal/drain.js +261 -578
  80. package/dist/commands/proposal/proposal-cli.js +19 -20
  81. package/dist/commands/proposal/proposal-types.js +31 -24
  82. package/dist/commands/proposal/proposal.js +38 -8
  83. package/dist/commands/proposal/propose.js +134 -160
  84. package/dist/commands/proposal/repository.js +1097 -1394
  85. package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
  86. package/dist/commands/proposal/validators/proposal-validators.js +1 -1
  87. package/dist/commands/proposal/validators/proposals.js +22 -89
  88. package/dist/commands/read/curate.js +105 -462
  89. package/dist/commands/read/knowledge.js +3 -2
  90. package/dist/commands/read/search-cli.js +16 -33
  91. package/dist/commands/read/search.js +17 -23
  92. package/dist/commands/read/show.js +57 -108
  93. package/dist/commands/sources/bundle-cli.js +25 -2
  94. package/dist/commands/sources/bundle-config-ops.js +4 -0
  95. package/dist/commands/sources/dangerous-env-audit.js +1 -2
  96. package/dist/commands/sources/info.js +127 -29
  97. package/dist/commands/sources/installed-stashes.js +197 -746
  98. package/dist/commands/sources/schema-repair.js +98 -129
  99. package/dist/commands/sources/source-add.js +62 -12
  100. package/dist/commands/sources/source-manage.js +9 -2
  101. package/dist/commands/sources/stash-cli.js +24 -4
  102. package/dist/commands/tasks/explain.js +10 -13
  103. package/dist/commands/tasks/tasks-cli.js +12 -13
  104. package/dist/commands/tasks/tasks.js +350 -936
  105. package/dist/commands/tasks/validate.js +26 -24
  106. package/dist/commands/workflow/plan.js +22 -29
  107. package/dist/commands/workflow-cli.js +4 -4
  108. package/dist/core/adapter/adapters/akm-adapter.js +2 -1
  109. package/dist/core/adapter/adapters/akm-lint.js +2 -3
  110. package/dist/core/adapter/adapters/akm-metadata.js +42 -12
  111. package/dist/core/adapter/adapters/akm-task-adapter.js +29 -8
  112. package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
  113. package/dist/core/adapter/execution-source.js +17 -29
  114. package/dist/core/asset/asset-placement.js +4 -13
  115. package/dist/core/asset/frontmatter.js +106 -1
  116. package/dist/core/asset/resolve-ref.js +1 -1
  117. package/dist/core/bundle-id.js +42 -5
  118. package/dist/core/bundle-rename.js +285 -0
  119. package/dist/core/config/config-io.js +1 -2
  120. package/dist/core/config/config-schema.js +9 -34
  121. package/dist/core/config/config-walker.js +1 -1
  122. package/dist/core/config/config.js +184 -111
  123. package/dist/core/config/engine-semantics.js +0 -2
  124. package/dist/core/config/legacy-source-shape-shim.js +38 -9
  125. package/dist/core/config/schema/embedding.js +20 -5
  126. package/dist/core/config/schema/engines.js +5 -0
  127. package/dist/core/config/schema/execution.js +1 -1
  128. package/dist/core/config/schema/experimental.js +1 -1
  129. package/dist/core/config/schema/improve-processes.js +54 -125
  130. package/dist/core/config/schema/improve.js +4 -42
  131. package/dist/core/config/schema/index-config.js +9 -48
  132. package/dist/core/config/schema/scheduler.js +12 -12
  133. package/dist/core/config/schema/search.js +6 -22
  134. package/dist/core/env-secret-ref.js +0 -1
  135. package/dist/core/errors.js +8 -9
  136. package/dist/core/file-change.js +13 -5
  137. package/dist/core/file-lock.js +76 -173
  138. package/dist/core/improve-result.js +35 -7
  139. package/dist/core/improve-types.js +0 -1
  140. package/dist/core/logs-db.js +2 -2
  141. package/dist/core/loopback.js +7 -12
  142. package/dist/core/non-task-input.js +20 -0
  143. package/dist/core/parse.js +13 -16
  144. package/dist/core/paths.js +0 -24
  145. package/dist/core/redaction.js +109 -2
  146. package/dist/core/run-lock.js +2 -5
  147. package/dist/core/spawn-env.js +1 -1
  148. package/dist/core/state/migrations.js +123 -61
  149. package/dist/core/state-db-scope.js +2 -4
  150. package/dist/core/state-db.js +126 -692
  151. package/dist/core/time.js +0 -20
  152. package/dist/core/type-presentation.js +1 -9
  153. package/dist/core/write-source.js +294 -1005
  154. package/dist/execution/input-contract.js +1 -1
  155. package/dist/execution/resolved-request.js +135 -689
  156. package/dist/execution/source.js +63 -257
  157. package/dist/execution/target-ref.js +1 -1
  158. package/dist/indexer/bundle-identity-guard.js +2 -2
  159. package/dist/indexer/db/llm-cache.js +2 -2
  160. package/dist/indexer/ensure-index.js +77 -73
  161. package/dist/indexer/index-rebuild-lock.js +3 -11
  162. package/dist/indexer/index-writer-lock.js +8 -17
  163. package/dist/indexer/index-written-assets.js +141 -154
  164. package/dist/indexer/indexer.js +400 -1124
  165. package/dist/indexer/links/declared-links.js +90 -0
  166. package/dist/indexer/materialize-embeddings.js +60 -397
  167. package/dist/indexer/passes/memory-inference.js +96 -90
  168. package/dist/indexer/passes/metadata.js +132 -219
  169. package/dist/indexer/read-preflight.js +0 -7
  170. package/dist/indexer/scan/doc-to-entry.js +2 -3
  171. package/dist/indexer/scan/drain-dir.js +1 -1
  172. package/dist/indexer/search/db-search.js +190 -590
  173. package/dist/indexer/search/fts-query.js +30 -41
  174. package/dist/indexer/search/ranking.js +28 -154
  175. package/dist/indexer/search/search-attribution.js +12 -32
  176. package/dist/indexer/search/search-fields.js +11 -15
  177. package/dist/indexer/search/search-hit-enrichers.js +54 -85
  178. package/dist/indexer/search/search-source.js +1 -4
  179. package/dist/indexer/usage/usage-events.js +36 -7
  180. package/dist/indexer/walk/walker.js +3 -4
  181. package/dist/integrations/agent/engine-fallback.js +23 -40
  182. package/dist/integrations/agent/engine-resolution.js +93 -183
  183. package/dist/integrations/agent/execution.js +507 -0
  184. package/dist/integrations/agent/model-map.js +28 -156
  185. package/dist/integrations/agent/request-lowering.js +66 -141
  186. package/dist/integrations/agent/runner-dispatch.js +143 -321
  187. package/dist/integrations/agent/runner.js +54 -14
  188. package/dist/integrations/lockfile.js +53 -101
  189. package/dist/llm/client.js +18 -6
  190. package/dist/llm/embedders/deterministic.js +2 -3
  191. package/dist/llm/embedders/profile.js +71 -0
  192. package/dist/llm/embedders/remote.js +11 -17
  193. package/dist/llm/feature-gate.js +0 -8
  194. package/dist/llm/index-passes.js +3 -5
  195. package/dist/llm/memory-infer.js +1 -2
  196. package/dist/llm/structured-call.js +5 -24
  197. package/dist/output/generic-render.js +23 -11
  198. package/dist/output/html-render.js +13 -10
  199. package/dist/output/render-registry.js +3 -32
  200. package/dist/output/shapes/helpers.js +25 -38
  201. package/dist/output/shapes/passthrough.js +1 -9
  202. package/dist/{indexer/graph/graph-types.js → output/text/bundle-rename.js} +4 -1
  203. package/dist/output/text/command-format.js +69 -31
  204. package/dist/output/text/helpers.js +1 -1
  205. package/dist/output/text/migrate.js +5 -14
  206. package/dist/output/text/proposal-format.js +48 -3
  207. package/dist/output/text/show-format.js +13 -17
  208. package/dist/output/text/workflow-format.js +0 -32
  209. package/dist/output/text.js +2 -0
  210. package/dist/registry/factory.js +4 -19
  211. package/dist/registry/network.js +66 -220
  212. package/dist/registry/providers/index.js +0 -2
  213. package/dist/registry/providers/skills-sh.js +3 -14
  214. package/dist/registry/providers/static-index.js +24 -26
  215. package/dist/registry/resolve.js +55 -131
  216. package/dist/scripts/akm-migrate-node.js +42948 -92369
  217. package/dist/scripts/akm-migrate.js +42935 -92354
  218. package/dist/setup/registry-stash-loader.js +4 -13
  219. package/dist/setup/semantic-assets.js +3 -44
  220. package/dist/setup/setup.js +1 -1
  221. package/dist/setup/steps/connection.js +5 -6
  222. package/dist/setup/steps/platforms.js +2 -2
  223. package/dist/setup/steps/tasks.js +25 -15
  224. package/dist/sources/provider-factory.js +17 -18
  225. package/dist/sources/providers/filesystem.js +2 -3
  226. package/dist/sources/providers/git-install.js +7 -1
  227. package/dist/sources/providers/git-provider.js +0 -3
  228. package/dist/sources/providers/git-stash.js +83 -21
  229. package/dist/sources/providers/npm.js +2 -4
  230. package/dist/sources/providers/provider-utils.js +5 -10
  231. package/dist/sources/providers/website.js +0 -2
  232. package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
  233. package/dist/sources/website-url.js +2 -2
  234. package/dist/storage/database.js +9 -35
  235. package/dist/storage/repositories/improve-ledger-repository.js +209 -0
  236. package/dist/storage/repositories/index-connection.js +39 -72
  237. package/dist/storage/repositories/index-entries-repository.js +131 -129
  238. package/dist/storage/repositories/index-entry-mapper.js +1 -2
  239. package/dist/storage/repositories/index-entry-schema.js +101 -268
  240. package/dist/storage/repositories/index-fts-repository.js +86 -256
  241. package/dist/storage/repositories/index-links-repository.js +143 -0
  242. package/dist/storage/repositories/index-llm-cache-repository.js +7 -9
  243. package/dist/storage/repositories/index-meta-repository.js +6 -4
  244. package/dist/storage/repositories/index-schema.js +257 -325
  245. package/dist/storage/repositories/index-utility-repository.js +8 -29
  246. package/dist/storage/repositories/index-vec-repository.js +133 -414
  247. package/dist/storage/repositories/outcome-repository.js +2 -1
  248. package/dist/storage/repositories/proposals-repository.js +104 -1
  249. package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
  250. package/dist/storage/repositories/salience-repository.js +1 -19
  251. package/dist/storage/repositories/task-history-repository.js +26 -4
  252. package/dist/storage/repositories/workflow-runs-repository.js +53 -244
  253. package/dist/storage/sqlite-migrations.js +136 -0
  254. package/dist/storage/sqlite-pragmas.js +11 -9
  255. package/dist/storage/sqlite-transaction.js +170 -0
  256. package/dist/storage/state-db-integrity.js +130 -0
  257. package/dist/tasks/activation-config.js +134 -62
  258. package/dist/tasks/backends/cron.js +191 -302
  259. package/dist/tasks/backends/exec-utils.js +2 -5
  260. package/dist/tasks/backends/launchd.js +141 -748
  261. package/dist/tasks/backends/schtasks.js +119 -623
  262. package/dist/tasks/prepare/prepare-support.js +5 -15
  263. package/dist/tasks/prepare/prepare.js +0 -2
  264. package/dist/tasks/resolve-akm-bin.js +20 -79
  265. package/dist/tasks/run/attempt-lifecycle.js +0 -1
  266. package/dist/tasks/run/load-task.js +1 -1
  267. package/dist/tasks/scheduler-binding.js +20 -238
  268. package/dist/tasks/scheduler-invocation.js +136 -244
  269. package/dist/tasks/scheduler-lock.js +53 -0
  270. package/dist/tasks/scheduler-sync.js +368 -679
  271. package/dist/tasks/source/parse-task-source.js +55 -9
  272. package/dist/tasks/source/task-source-v3-frozen.js +3 -4
  273. package/dist/tasks/source/task-to-v4.js +464 -88
  274. package/dist/workflows/authoring/authoring.js +3 -12
  275. package/dist/workflows/compile.js +211 -0
  276. package/dist/workflows/concurrency-policy.js +13 -74
  277. package/dist/workflows/exec/child-invocation.js +3 -17
  278. package/dist/workflows/exec/child-workflow.js +32 -141
  279. package/dist/workflows/exec/dispatch-redaction.js +13 -53
  280. package/dist/workflows/exec/environment.js +98 -0
  281. package/dist/workflows/exec/exec-unit.js +33 -140
  282. package/dist/workflows/exec/frozen-judge.js +7 -59
  283. package/dist/workflows/exec/native-executor.js +82 -341
  284. package/dist/workflows/exec/param-secrets.js +29 -47
  285. package/dist/workflows/exec/run-workflow.js +154 -387
  286. package/dist/workflows/exec/scheduler.js +9 -36
  287. package/dist/workflows/exec/step-work.js +127 -430
  288. package/dist/workflows/exec/unit-dispatch.js +11 -63
  289. package/dist/workflows/exec/unit-writer.js +8 -52
  290. package/dist/workflows/exec/worktree.js +39 -273
  291. package/dist/workflows/freeze/child-output-references.js +4 -15
  292. package/dist/workflows/freeze/environment.js +99 -92
  293. package/dist/workflows/freeze/freeze.js +172 -0
  294. package/dist/workflows/freeze/step-values.js +19 -21
  295. package/dist/workflows/freeze/targets/child-workflow.js +23 -92
  296. package/dist/workflows/freeze/targets/command.js +10 -33
  297. package/dist/workflows/freeze/targets/script.js +5 -12
  298. package/dist/workflows/freeze/targets/shell.js +3 -6
  299. package/dist/workflows/freeze/targets/task.js +25 -80
  300. package/dist/workflows/freeze/task-bindings.js +20 -67
  301. package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
  302. package/dist/workflows/ir/params.js +6 -51
  303. package/dist/workflows/ir/plan-hash.js +2 -34
  304. package/dist/workflows/parser.js +140 -43
  305. package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
  306. package/dist/workflows/renderer.js +36 -69
  307. package/dist/workflows/resource-limits.js +12 -120
  308. package/dist/workflows/runtime/agent-identity.js +8 -40
  309. package/dist/workflows/runtime/run-outputs.js +3 -6
  310. package/dist/workflows/runtime/run-plan.js +316 -0
  311. package/dist/workflows/runtime/runs.js +48 -200
  312. package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
  313. package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
  314. package/dist/workflows/validate-summary.js +2 -7
  315. package/docs/integration/bundling-akm.md +49 -42
  316. package/docs/migration/README.md +1 -0
  317. package/docs/migration/release-notes/0.9.17.md +43 -0
  318. package/docs/migration/v0.9.1-to-v0.9.2.md +23 -7
  319. package/docs/reference/cli.md +232 -135
  320. package/docs/reference/configuration.md +71 -57
  321. package/docs/reference/data-and-telemetry.md +20 -21
  322. package/docs/reference/tasks.md +105 -39
  323. package/docs/reference/workflow-schema.md +14 -18
  324. package/docs/reference/workflows.md +6 -9
  325. package/package.json +1 -1
  326. package/schemas/akm-config.json +115 -738
  327. package/schemas/akm-workflow.json +1 -0
  328. package/dist/assets/improve-strategies/graph-refresh.json +0 -15
  329. package/dist/assets/prompts/contradiction-judge.md +0 -33
  330. package/dist/assets/prompts/graph-extract-system.md +0 -1
  331. package/dist/assets/prompts/graph-extract-user-prompt.md +0 -35
  332. package/dist/assets/prompts/metadata-enhance-system.md +0 -1
  333. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +0 -4
  334. package/dist/commands/health/advisories.js +0 -150
  335. package/dist/commands/health/metrics.js +0 -329
  336. package/dist/commands/health/surfaces.js +0 -102
  337. package/dist/commands/improve/anti-collapse.js +0 -83
  338. package/dist/commands/improve/collapse-detector.js +0 -432
  339. package/dist/commands/improve/consolidate/eligibility.js +0 -48
  340. package/dist/commands/improve/consolidate/merge.js +0 -149
  341. package/dist/commands/improve/distill/promote-memory.js +0 -291
  342. package/dist/commands/improve/distill/quality-gate.js +0 -337
  343. package/dist/commands/improve/eval-cases.js +0 -52
  344. package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
  345. package/dist/commands/improve/proposal-envelope.js +0 -31
  346. package/dist/commands/improve/run-context.js +0 -123
  347. package/dist/commands/improve/shared.js +0 -31
  348. package/dist/commands/improve/source-identity.js +0 -28
  349. package/dist/commands/improve/triage.js +0 -96
  350. package/dist/commands/proposal/drain-policies.js +0 -151
  351. package/dist/commands/sources/update-transaction.js +0 -220
  352. package/dist/core/action-contributors.js +0 -28
  353. package/dist/core/config/config-version-shim.js +0 -101
  354. package/dist/core/fs-txn.js +0 -405
  355. package/dist/core/lexical-score.js +0 -25
  356. package/dist/core/maintenance-barrier.js +0 -167
  357. package/dist/execution/executable-identity.js +0 -105
  358. package/dist/execution/guarded-source.js +0 -427
  359. package/dist/indexer/db/graph-db.js +0 -444
  360. package/dist/indexer/graph/graph-boost.js +0 -427
  361. package/dist/indexer/graph/graph-dedup.js +0 -95
  362. package/dist/indexer/graph/graph-extraction.js +0 -1108
  363. package/dist/indexer/search/name-match.js +0 -35
  364. package/dist/indexer/search/ranking-contributors.js +0 -515
  365. package/dist/indexer/search/ranking-types.js +0 -4
  366. package/dist/indexer/walk/project-context.js +0 -192
  367. package/dist/integrations/agent/execution-cascade.js +0 -566
  368. package/dist/integrations/agent/execution-definitions.js +0 -202
  369. package/dist/integrations/agent/execution-lowering.js +0 -841
  370. package/dist/integrations/agent/execution-preparation.js +0 -98
  371. package/dist/integrations/agent/inline-execution.js +0 -74
  372. package/dist/llm/graph-extract.js +0 -728
  373. package/dist/llm/metadata-enhance.js +0 -96
  374. package/dist/registry/create-provider-registry.js +0 -29
  375. package/dist/registry/pinned-request-helper.js +0 -247
  376. package/dist/registry/pinned-transport.js +0 -717
  377. package/dist/sources/providers/index.js +0 -14
  378. package/dist/storage/engines/sqlite-migrations.js +0 -271
  379. package/dist/storage/repositories/canaries-repository.js +0 -107
  380. package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
  381. package/dist/storage/repositories/registry-cache.js +0 -113
  382. package/dist/tasks/scheduler-sync-preview.js +0 -52
  383. package/dist/tasks/source/task-to-v3.js +0 -507
  384. package/dist/workflows/freeze/resolve-steps.js +0 -86
  385. package/dist/workflows/freeze/source-freeze.js +0 -64
  386. package/dist/workflows/ir/compile.js +0 -321
  387. package/dist/workflows/ir/environment-v4.js +0 -330
  388. package/dist/workflows/ir/freeze-v4.js +0 -153
  389. package/dist/workflows/ir/schema-v4.js +0 -745
  390. package/dist/workflows/ir/schema.js +0 -354
  391. package/dist/workflows/program/schema.js +0 -77
  392. package/dist/workflows/runtime/checkin.js +0 -57
  393. package/dist/workflows/runtime/plan-classifier.js +0 -196
  394. package/dist/workflows/runtime/unit-checkin.js +0 -45
  395. package/dist/workflows/runtime/unit-phases.js +0 -20
  396. package/dist/workflows/schema.js +0 -4
  397. package/dist/workflows/source-ir/compile.js +0 -200
  398. package/dist/workflows/source-ir/program.js +0 -50
  399. package/dist/workflows/source-ir/result.js +0 -26
  400. package/dist/workflows/source-ir/schema.js +0 -786
  401. package/dist/workflows/source-ir/triggers.js +0 -79
  402. package/dist/workflows/source-ir/uses.js +0 -40
  403. package/dist/workflows/validator.js +0 -60
@@ -1,21 +1,14 @@
1
1
  You are the akm consolidate assistant analyzing memory assets.
2
2
 
3
3
  Rules:
4
- 1. MERGE: Two or more memories are substantially duplicated or closely related → propose merging. Return the primary ref to keep and secondary refs to delete. Do NOT include mergedContent — the merge will be executed in a separate step.
5
- 2. DELETE: Memory is clearly outdated, contradicted, or redundant → propose deletion. NEVER propose delete for memories annotated `(captureMode: hot)` — they are user-explicit and only the user can retire them. The downstream guard will refuse these regardless, so proposing them just wastes tokens.
6
- 3. PROMOTE: Memory expresses a stable, reusable fact suitable as a `knowledge/` asset → propose promotion. Do NOT delete the source memory. NEVER propose promote / merge / contradict for memories annotated `(already queued)` — they have a pending proposal whose body matches; a duplicate will be deterministically dropped, so proposing them just wastes tokens.
7
- 4. CONTRADICT: Two memories assert logically exclusive facts such that following BOTH simultaneously is impossible — not merely related or overlapping. You MUST cite the exact sentence from Memory A and the exact sentence from Memory B that are in direct conflict. If you cannot cite specific opposing sentences, use KEEP instead. Sharing a topic, tool, domain, or workflow stage is NOT sufficient. Only direct factual opposites qualify: opposing recommended commands, opposing boolean flags, opposing version numbers, or mutually exclusive instructions. Use confidence ≥ 0.92 only; omit the op entirely if below that threshold.
8
- 5. KEEP: Memory is unique and current → omit from output.
4
+ 1. PROMOTE: Memory expresses a stable, reusable fact suitable as a `knowledge/` asset → propose promotion. Do NOT delete the source memory. NEVER propose promote for memories annotated `(already queued)` — they have a pending proposal whose body matches; a duplicate will be deterministically dropped, so proposing them just wastes tokens.
5
+ 2. KEEP: Memory is unique and current → omit from output.
9
6
 
10
7
  Return ONLY JSON (no prose, no code fences):
11
8
  {
12
9
  "operations": [
13
- { "op": "merge", "primary": "memories/<name>", "secondaries": ["memories/<name>", ...], "mergeStrategy": "synthesize", "confidence": 0.95 },
14
- { "op": "delete", "ref": "memories/<name>", "reason": "<brief reason>", "confidence": 0.90 },
15
- { "op": "promote", "ref": "memories/<name>", "knowledgeRef": "knowledge/<suggested-slug>", "reason": "<brief reason>", "description": "<one sentence describing the new knowledge asset>", "confidence": 0.92 },
16
- { "op": "contradict", "ref": "memories/<name>", "contradictedByRef": "memories/<name>", "reason": "<brief reason>", "confidence": 0.88 }
17
- ],
18
- "warnings": ["<optional concerns>"]
10
+ { "op": "promote", "ref": "memories/<name>", "knowledgeRef": "knowledge/<suggested-slug>", "reason": "<brief reason>", "description": "<one sentence describing the new knowledge asset>", "confidence": 0.92 }
11
+ ]
19
12
  }
20
13
 
21
14
  For every operation, emit a `confidence` field in [0, 1] expressing your certainty that the operation is correct and safe. Use 0.95+ only when evidence is unambiguous. Omit the field rather than guessing if you are uncertain.
@@ -0,0 +1,6 @@
1
+ You are grading search-and-retrieval results for an AI coding agent's knowledge base (the akm tool). For the given query and ONE candidate asset, grade how useful loading this asset would be, on this scale:
2
+ 3 = exactly the asset an agent should load for this query or task; it directly answers or performs the request.
3
+ 2 = relevant and clearly useful, though not the single best asset for the query.
4
+ 1 = same general topic as the query, but would not actually help complete this specific query or task.
5
+ 0 = unrelated to the query.
6
+ Reply with ONLY a JSON object: {"grade": <integer 0-3>, "reason": "<=25 words"}.
@@ -3,25 +3,26 @@ type: fact
3
3
  category: convention
4
4
  description: How to cross-link assets so retrieval compounds — a provenance xref when derived, sparse real associative xrefs, corrections as new assets, and canonical entity naming.
5
5
  when_to_use: Surfaced to authoring agents when they create or revise any asset that derives from, corrects, or relates to another asset.
6
- updated: 2026-07-28
6
+ updated: 2026-09-28
7
7
  ---
8
8
 
9
9
  <!--
10
10
  SOFT guidance only — advice, not a contract. Back-linking here is a RETRIEVAL
11
- mechanism, not decoration: `xrefs:` frontmatter folds into the search index;
12
- the entity/relation graph is extracted from BODY prose (memory + knowledge),
13
- never from frontmatter. Over-linking degrades ranking, so these rules are
14
- deliberately conservative. (LLM-wiki bundles carry their own xref system in
15
- their pages' frontmatter — this convention is for in-stash assets.)
11
+ mechanism, not decoration: `xrefs:` frontmatter folds into the search index
12
+ and is stored as a declared link `akm show` lists on both assets.
13
+ Over-linking degrades ranking, so these rules are deliberately conservative.
14
+ (LLM-wiki bundles carry their own xref system in their pages' frontmatter —
15
+ this convention is for in-stash assets.)
16
16
  -->
17
17
 
18
18
  # Back-linking conventions
19
19
 
20
20
  Cross-references are how knowledge compounds instead of being re-derived every
21
21
  session. In AKM they are also **indexed**: the strings in an asset's `xrefs:`
22
- frontmatter fold into its search-hint text, and knowledge/memory bodies feed an
23
- LLM-extracted entity/relation graph that boosts ranking. So links are a retrieval
24
- lever — which means both too few and too many hurt.
22
+ frontmatter fold into its search-hint text and are stored as links that
23
+ `akm show` lists on both assets (with `supersededBy:`, `contradictedBy:` and a
24
+ `.derived` memory's parent). So links are a retrieval lever — which means both
25
+ too few and too many hurt.
25
26
 
26
27
  ```yaml
27
28
  ---
@@ -46,10 +47,8 @@ xrefs:
46
47
  - **Associative xrefs are discretionary — real relationships only.** Add one when
47
48
  you already know a genuine load-bearing connection. Do **not** hit a link
48
49
  quota by pointing at the topically-nearest sibling — a plausible-but-wrong
49
- xref makes this asset a false search match for the other topic, and a wrong
50
- relationship asserted in prose poisons the entity graph. A relationship you
51
- want the graph to learn must be named in the body (e.g. open with "Corrects
52
- knowledge/auth/oauth-refresh-races").
50
+ xref makes this asset a false search match for the other topic and a false
51
+ declared link on both assets' `akm show` output.
53
52
  - **Cap total xrefs at ~5 (a heuristic, not a measured threshold).** Each xref
54
53
  folds its ref tokens into THIS asset's search hints — past a handful, the
55
54
  asset matches queries about several other topics and its own ranking signal
@@ -78,19 +77,20 @@ prose is indexed in the lowest-weight `content` field, so
78
77
  `description:`/`when_to_use:` remain the primary orientation channel. Then
79
78
  open the body with a plain title plus a one-line
80
79
  orientation naming what it is, its scope/domain, and its key entities in
81
- canonical spelling (`Postgres`, `OAuth`, `TLS`, `Acme`) — the entity/relation
82
- graph is extracted from body prose, and readers land here from `akm show`.
83
- Keep the canonical-spelling list in `facts/conventions/domains` so agents don't
84
- fragment `postgres` / `postgresql` / `pg`.
80
+ canonical spelling (`Postgres`, `OAuth`, `TLS`, `Acme`) — consistent spelling
81
+ keeps search matches from fragmenting across variants, and readers land here
82
+ from `akm show`. Keep the canonical-spelling list in `facts/conventions/domains`
83
+ so agents don't fragment `postgres` / `postgresql` / `pg`.
85
84
 
86
85
  ## Hubs are optional, not per-namespace obligations
87
86
 
88
87
  A hub (a `knowledge/` overview page that xrefs the key assets in a domain) is
89
88
  worth authoring for a **few genuinely high-traffic domains**. Do **not**
90
89
  mandate a hub per namespace and do not edit a hub on every write: that is O(n)
91
- maintenance, a concurrent-write contention point, and it flattens the multi-hop
92
- graph into a namespace-wide star. Let the FTS index be the catalog; spend the
93
- effort on per-asset self-situating headers instead.
90
+ maintenance, a concurrent-write contention point, and it flattens every linked
91
+ asset's declared links into a namespace-wide star centered on the hub. Let the
92
+ FTS index be the catalog; spend the effort on per-asset self-situating headers
93
+ instead.
94
94
 
95
95
  ## Keep assets atomic
96
96
 
@@ -48,8 +48,8 @@ volume justifies it.
48
48
  ## Canonical entity spellings
49
49
 
50
50
  Pick ONE name per entity and use it everywhere in asset **bodies** — retrieval
51
- is case-insensitive but treats aliases as different entities, so alias variants
52
- fragment the entity graph. Extend as your stash grows.
51
+ is case-insensitive but treats aliases as different terms, so alias variants
52
+ fragment search matches. Extend as your stash grows.
53
53
 
54
54
  - Postgres (not postgresql / pg)
55
55
  - Kubernetes (not k8s)
@@ -325,7 +325,7 @@
325
325
 
326
326
  <div class="chart-panel full-width">
327
327
  <h3>Per-Phase Wall Time Decomposition (stacked, min)</h3>
328
- <div id="chartPhases" class="ec tall" role="img" aria-label="Stacked area chart decomposing wall time per run into consolidation, memory inference, graph extraction, and unattributed phases"></div>
328
+ <div id="chartPhases" class="ec tall" role="img" aria-label="Stacked area chart decomposing wall time per run into consolidation, memory inference, and unattributed phases"></div>
329
329
  <div class="empty-overlay" id="emptyPhases">No runs in the selected slice.</div>
330
330
  </div>
331
331
 
@@ -390,7 +390,7 @@
390
390
  <div class="table-wrap">
391
391
  <table>
392
392
  <thead>
393
- <tr><th>Started</th><th>Task</th><th>Strategy</th><th>Wall</th><th>Promoted</th><th>Merged</th><th>Contradicted</th><th>MI Written</th><th>Entities</th><th>Lint Fixed</th><th>Status</th></tr>
393
+ <tr><th>Started</th><th>Task</th><th>Strategy</th><th>Wall</th><th>Promoted</th><th>Merged</th><th>Contradicted</th><th>MI Written</th><th>Lint Fixed</th><th>Status</th></tr>
394
394
  </thead>
395
395
  <tbody id="lastRunsTable"></tbody>
396
396
  </table>
@@ -539,7 +539,7 @@ mkChart('chartWallTime', {
539
539
  // ── 2. Per-phase wall time decomposition (stacked area) ──────────────────────
540
540
  mkChart('chartPhases', {
541
541
  tooltip: baseTooltip,
542
- legend: { ...baseLegend, data: ['Consolidation', 'Memory inference', 'Graph extraction', 'Unattributed'] },
542
+ legend: { ...baseLegend, data: ['Consolidation', 'Memory inference', 'Unattributed'] },
543
543
  grid: denseGrid,
544
544
  dataZoom: denseZoom,
545
545
  xAxis: { type: 'category', data: xLabels, ...baseAxis },
@@ -547,7 +547,6 @@ mkChart('chartPhases', {
547
547
  series: [
548
548
  { name: 'Consolidation', type: 'line', stack: 'p', areaStyle: { color: 'rgba(88,166,255,0.55)' }, lineStyle: { width: 0 }, showSymbol: false, data: rs.map(r => toMin(r.consDurationMs)) },
549
549
  { name: 'Memory inference', type: 'line', stack: 'p', areaStyle: { color: 'rgba(63,185,80,0.55)' }, lineStyle: { width: 0 }, showSymbol: false, data: rs.map(r => toMin(r.miDurationMs)) },
550
- { name: 'Graph extraction', type: 'line', stack: 'p', areaStyle: { color: 'rgba(188,140,255,0.55)' }, lineStyle: { width: 0 }, showSymbol: false, data: rs.map(r => toMin(r.geDurationMs)) },
551
550
  { name: 'Unattributed', type: 'line', stack: 'p', areaStyle: { color: 'rgba(210,153,34,0.45)' }, lineStyle: { width: 0 }, showSymbol: false, data: rs.map(r => toMin(r.otherMs)) },
552
551
  ],
553
552
  });
@@ -695,7 +694,6 @@ tbody.innerHTML = '';
695
694
  <td>${r.merged || 0}</td>
696
695
  <td style="color:${(r.contradicted||0)>5?'var(--yellow)':'var(--text)'};">${r.contradicted || 0}</td>
697
696
  <td style="color:var(--green);">${r.miWritten || 0}</td>
698
- <td>${r.geEntities || 0}</td>
699
697
  <td>${r.lintFixed || 0}</td>
700
698
  <td>${badge}</td>
701
699
  `;
@@ -38,7 +38,7 @@ const RETIRED_COMMAND_HINTS = {
38
38
  events: "`akm events` moved in 0.9 — use `akm log`.",
39
39
  // Removed observability surfaces.
40
40
  history: "`akm history` was removed in 0.9 — use `akm log --ref <ref>` for an asset's event trail.",
41
- graph: "`akm graph` was removed in 0.9 — graph counts appear in `akm health`; refresh extraction with `akm improve --strategy graph-refresh`.",
41
+ graph: "`akm graph` was removed in 0.9. The LLM entity graph it inspected was itself retired in 0.9.17-alpha.9 — use `akm show <ref>` for an asset's declared links.",
42
42
  lessons: "`akm lessons` was removed in 0.9 — lesson strength is indexed; use `akm search --type lesson`.",
43
43
  lesson: "`akm lesson` was removed in 0.9 — lesson strength is indexed; use `akm search --type lesson`.",
44
44
  // Relocated guidance / removed asset verbs.
@@ -9,12 +9,13 @@
9
9
  */
10
10
  import { defineCommand } from "citty";
11
11
  import { stringify as yamlStringify } from "yaml";
12
+ import { renderHealthHtml } from "../commands/health/renderers.js";
12
13
  import { assertNever } from "../core/assert.js";
13
14
  import { AkmError, UsageError } from "../core/errors.js";
14
15
  import { getOutputMode } from "../output/context.js";
15
16
  import { renderGenericHtml, renderGenericMarkdown, renderGenericText } from "../output/generic-render.js";
16
17
  import { deliverRendered } from "../output/html-render.js";
17
- import { getHtmlRendererHandler, getMdRendererHandler } from "../output/render-registry.js";
18
+ import { getMdRendererHandler } from "../output/render-registry.js";
18
19
  import { shapeForCommand } from "../output/shapes.js";
19
20
  import { formatPlain, outputJsonl } from "../output/text.js";
20
21
  import { parseAllFlagValues } from "./invocation.js";
@@ -330,7 +331,10 @@ export function output(command, result) {
330
331
  return;
331
332
  }
332
333
  case "html": {
333
- const rendered = getHtmlRendererHandler(command)?.(shaped, mode.detail);
334
+ // `akm health` is the only command with a bespoke HTML report, so it is
335
+ // called directly rather than through a registry with one possible
336
+ // registrant (see `output/render-registry.ts`).
337
+ const rendered = command === "health" ? renderHealthHtml(shaped) : null;
334
338
  deliverRendered(rendered ?? renderGenericHtml(command, shaped), mode.outputPath);
335
339
  return;
336
340
  }
@@ -26,8 +26,17 @@
26
26
  * validation) — conservative by design.
27
27
  */
28
28
  import { UsageError } from "../core/errors.js";
29
+ import { warn } from "../core/warn.js";
29
30
  import { cittyComparableName, findCittyTopLevelCommandIndex, toAliasArray, } from "./invocation.js";
30
31
  import { retiredFlagHint } from "./retired-commands.js";
32
+ /**
33
+ * Commands that must never refuse on an unrecognized flag — `akm info` warns
34
+ * and continues instead of exiting 2, the same tolerance a bare `akm help
35
+ * --whatever` already gets for free from its group-command fallback (no
36
+ * resolved subcommand, so this gate stands down entirely). `info` is a leaf
37
+ * command, so it needs an explicit opt-in here instead.
38
+ */
39
+ const UNKNOWN_FLAG_TOLERANT_COMMANDS = new Set(["info"]);
31
40
  /** Flags citty implements itself, which no command declares. */
32
41
  const IMPLICIT_FLAGS = ["help", "h", "version", "v"];
33
42
  /**
@@ -172,6 +181,10 @@ function throwUnknownFlag(shown, attempted, known) {
172
181
  ? `Did you mean \`${suggestion}\`? Run the command with \`--help\` to see its accepted flags.`
173
182
  : undefined);
174
183
  }
184
+ /** The {@link UNKNOWN_FLAG_TOLERANT_COMMANDS} counterpart to {@link throwUnknownFlag}: report, don't refuse. */
185
+ function warnUnknownFlag(shown, known) {
186
+ warn(`[akm ${known.path.join(" ")}] ignoring unknown flag "${shown}" — run with --help to see its accepted flags.`);
187
+ }
175
188
  /**
176
189
  * Throw a {@link UsageError} naming the first flag the resolved command does
177
190
  * not declare. Returns silently when every flag is known.
@@ -195,6 +208,7 @@ export function assertKnownFlags(root, rawArgs) {
195
208
  const dynamicNamedFlagCommands = new Set(["workflow run", "task run", "task explain"]);
196
209
  const dynamicWorkflowParams = dynamicNamedFlagCommands.has(known.path.join(" "));
197
210
  const selfDiagnosed = SELF_DIAGNOSED_FLAGS.get(known.path.join(" "));
211
+ const tolerant = UNKNOWN_FLAG_TOLERANT_COMMANDS.has(known.path.join(" "));
198
212
  for (let i = 0; i < ownArgs.length; i += 1) {
199
213
  const token = ownArgs[i];
200
214
  // Not a flag: positional, a bare `-` (stdin), or a negative number.
@@ -209,8 +223,13 @@ export function assertKnownFlags(root, rawArgs) {
209
223
  for (let offset = 0; offset < shortFlags.length; offset += 1) {
210
224
  const rawName = shortFlags[offset];
211
225
  const candidate = cittyComparableName(rawName);
212
- if (!known.names.has(candidate))
226
+ if (!known.names.has(candidate)) {
227
+ if (tolerant) {
228
+ warnUnknownFlag(token, known);
229
+ break;
230
+ }
213
231
  throwUnknownFlag(token, `-${rawName}`, known);
232
+ }
214
233
  if (known.valueFlags.has(candidate)) {
215
234
  if (offset === shortFlags.length - 1)
216
235
  i += 1;
@@ -239,6 +258,10 @@ export function assertKnownFlags(root, rawArgs) {
239
258
  // frozen plan before a run is inserted. Short flags remain strict.
240
259
  if (dynamicWorkflowParams)
241
260
  continue;
261
+ if (tolerant) {
262
+ warnUnknownFlag(token.split("=")[0], known);
263
+ continue;
264
+ }
242
265
  throwUnknownFlag(token.split("=")[0], `--${rawName}`, known);
243
266
  }
244
267
  // Skip a declared value flag's value so `--reason "--x"` is not scanned.
package/dist/cli.js CHANGED
@@ -177,7 +177,7 @@ const setupCommand = defineCommand({
177
177
  // the work, matching the `sync --push/--no-push` pattern. A flag
178
178
  // DECLARED as `no-init` can never be negated: `--no-init` parses as
179
179
  // "negate `init`", a name nothing declared, leaving the real key at its
180
- // default forever — see `search --no-project-context`'s identical fix.
180
+ // default forever — see `search --no-track-usage`'s identical fix.
181
181
  init: {
182
182
  type: "boolean",
183
183
  default: true,
@@ -545,19 +545,32 @@ const helpCommand = defineGroupCommand({
545
545
  process.stdout.write(`${await renderSectionedRootHelp()}\n`);
546
546
  },
547
547
  });
548
+ // Root `--help` text for the exit-code table. `EXIT_CODES` (src/cli/shared.ts)
549
+ // is the single source of the numbers; this only supplies the prose next to
550
+ // each one, so there is no third, independently-drifting copy of the table
551
+ // (the other copy is errors.ts's doc comment, which documents by reference
552
+ // instead of repeating the numbers).
553
+ const EXIT_CODE_DESCRIPTIONS = [
554
+ [EXIT_CODES.SUCCESS, "success"],
555
+ [EXIT_CODES.GENERAL, "not found / command-reported failure"],
556
+ [EXIT_CODES.USAGE, "usage error"],
557
+ [EXIT_CODES.HEALTH_WARN, "health warn (akm health only)"],
558
+ [EXIT_CODES.INTERNAL, "internal / unclassified error"],
559
+ [
560
+ EXIT_CODES.TEMPFAIL,
561
+ "transient (retry shortly — another akm process holds a lock or is writing state.db or index.db)",
562
+ ],
563
+ [EXIT_CODES.CONFIG, "config error"],
564
+ ];
565
+ function renderExitCodesHelp() {
566
+ return EXIT_CODE_DESCRIPTIONS.map(([code, description]) => ` ${String(code).padEnd(4)}${description}`).join("\n");
567
+ }
548
568
  export const main = defineCommand({
549
569
  meta: {
550
570
  name: "akm",
551
571
  version: pkgVersion,
552
572
  description: "Agent Knowledge Manager — search, show, and manage assets from your bundle.\n\n" +
553
- "Exit codes:\n" +
554
- " 0 success\n" +
555
- " 1 not found / command-reported failure\n" +
556
- " 2 usage error\n" +
557
- " 4 health warn (akm health only)\n" +
558
- " 70 internal / unclassified error\n" +
559
- " 75 transient (retry shortly — another akm process holds a lock or is writing state.db or index.db)\n" +
560
- " 78 config error",
573
+ `Exit codes:\n${renderExitCodesHelp()}`,
561
574
  },
562
575
  args: {
563
576
  // Single-sourced from GLOBAL_OUTPUT_ARGS (src/cli/shared.ts) so root help
@@ -632,6 +645,24 @@ export function shouldBypassConfigStartup(argv) {
632
645
  const subcommand = args.slice(configIndex + 1).find((arg) => !arg.startsWith("-"));
633
646
  return subcommand === "path";
634
647
  }
648
+ /**
649
+ * Whether `argv` resolves to the top-level `info` command — used by
650
+ * `runCli` (and mirrored in `tests/_helpers/cli.ts`) to scope the startup
651
+ * config read's best-effort fallback to `info` alone. `info` is NOT on
652
+ * {@link shouldBypassConfigStartup}'s allowlist: unlike a bare bypass, it
653
+ * still reads a valid config's `output.format`/`output.detail` like any
654
+ * other command, it just must not be aborted by one it cannot read (see
655
+ * `assembleInfo`'s doc comment, src/commands/sources/info.ts, for why).
656
+ * Every other command reads config exactly as before — a broken config
657
+ * throws here and the command never runs.
658
+ */
659
+ export function isInfoCommand(argv) {
660
+ const userArgs = argv.slice(2);
661
+ const separator = userArgs.indexOf("--");
662
+ const args = separator === -1 ? userArgs : userArgs.slice(0, separator);
663
+ const commandIndex = findCittyTopLevelCommandIndex(args, MAIN_TOP_LEVEL_ARGS);
664
+ return (commandIndex >= 0 ? args[commandIndex] : undefined) === "info";
665
+ }
635
666
  // ── Exit codes ──────────────────────────────────────────────────────────────
636
667
  // Canonical table lives in `src/cli/shared.ts` (EXIT_CODES). These aliases keep
637
668
  // the local call sites terse. EXIT_HEALTH_WARN (4) is the `akm health` "warn"
@@ -955,7 +986,34 @@ async function runCli() {
955
986
  try {
956
987
  applyEarlyStderrFlags(process.argv);
957
988
  const bypassConfig = shouldBypassConfigStartup(process.argv);
958
- initOutputMode(process.argv, bypassConfig ? (DEFAULT_CONFIG.output ?? {}) : (loadConfig().output ?? {}));
989
+ // Off the bypass allowlist, every command reads config here exactly as
990
+ // it always has: an invalid config.json throws, `emitJsonError` reports
991
+ // it, and the command never runs — no side effect of its own body ever
992
+ // happens (a lock taken, a network call made, a database opened
993
+ // read-write). `akm info` is the ONE exception (see `assembleInfo`'s
994
+ // doc comment, src/commands/sources/info.ts): only ITS read is
995
+ // best-effort, falling back to `DEFAULT_CONFIG.output` instead of
996
+ // throwing. Scoped narrowly on purpose — an earlier version of this fix
997
+ // made the read best-effort for every command, which silently changed
998
+ // outcomes across the CLI (some commands that should refuse at exit 78
999
+ // ran anyway; `health`/`index`/`config set`/`feedback` still failed,
1000
+ // but only after already taking a lock, opening a database read-write,
1001
+ // or making a network call).
1002
+ let outputDefaults = DEFAULT_CONFIG.output ?? {};
1003
+ if (!bypassConfig) {
1004
+ if (isInfoCommand(process.argv)) {
1005
+ try {
1006
+ outputDefaults = loadConfig().output ?? {};
1007
+ }
1008
+ catch {
1009
+ outputDefaults = DEFAULT_CONFIG.output ?? {};
1010
+ }
1011
+ }
1012
+ else {
1013
+ outputDefaults = loadConfig().output ?? {};
1014
+ }
1015
+ }
1016
+ initOutputMode(process.argv, outputDefaults);
959
1017
  }
960
1018
  catch (error) {
961
1019
  emitJsonError(error);
@@ -5,7 +5,7 @@ import { UsageError } from "../../core/errors.js";
5
5
  import { warn } from "../../core/warn.js";
6
6
  import { isPortableExecutionAgentSelector } from "../../execution/source.js";
7
7
  import { fallbackAnnouncement, NO_ENGINE_MESSAGE_SUFFIX, NO_ENGINE_REMEDY, withEngineFallback, } from "../../integrations/agent/engine-fallback.js";
8
- import { executeInteractiveAgentInvocation } from "../../integrations/agent/execution-lowering.js";
8
+ import { executeInteractiveAgentInvocation } from "../../integrations/agent/runner-dispatch.js";
9
9
  import { executeCommandInvocation } from "../command/command-execution.js";
10
10
  function canonicalCurrent(options) {
11
11
  const current = {};
@@ -1,31 +1,23 @@
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 { ConfigError, UsageError } from "../../core/errors.js";
5
- import { cloneExecutionJsonObject } from "../../execution/json.js";
4
+ import { UsageError } from "../../core/errors.js";
6
5
  import { createInlineResolvedCommand, createResolvedCommand, createResolvedPersona, } from "../../execution/resolved-request.js";
7
6
  import { isPortableExecutionAgentSelector, } from "../../execution/source.js";
8
7
  import { recordIndexedShowUsage } from "../../indexer/usage/show-usage.js";
9
8
  import { resolveUsageEventSource } from "../../indexer/usage/usage-events.js";
10
- import { fallbackAnnouncement, NO_ENGINE_MESSAGE_SUFFIX, NO_ENGINE_REMEDY, } from "../../integrations/agent/engine-fallback.js";
11
- import { requireAuthorizedExecutionPlan, } from "../../integrations/agent/execution-cascade.js";
12
- import { dispatchLoweredExecutionRequest, lowerResolvedExecutionRequest, } from "../../integrations/agent/execution-lowering.js";
13
- import { prepareResolvedExecution } from "../../integrations/agent/execution-preparation.js";
9
+ import { fallbackAnnouncement } from "../../integrations/agent/engine-fallback.js";
10
+ import { buildExecution, resolveExecution, } from "../../integrations/agent/execution.js";
11
+ import { runExecution } from "../../integrations/agent/runner-dispatch.js";
14
12
  import { parseBuiltinCommandAction } from "./builtin-action.js";
15
13
  import { loadAdapterExecutionSource, } from "./execution-source-loader.js";
16
14
  import { applyPortableCommandArguments } from "./portable-template.js";
17
15
  /**
18
- * F-1 (spec §5.2 point 3): resolve the ambient-first provenance stamp
19
- * (matching the native arm's own `process.env.AKM_EVENT_SOURCE ?? …`) and
20
- * hand it to `dispatchLoweredExecutionRequest`'s dedicated, single-purpose
21
- * `eventSource` field — never through `runOptions`/`agentOptions`, which
22
- * stays exactly as untrusted for overriding resolved content as it was
23
- * before P1b (a caller-supplied `runOptions.env` still cannot replace frozen
24
- * request data, including a scheduler-restored directory value — see
25
- * `tests/integration/tasks-runner.test.ts`'s "forwards scheduled AKM
26
- * directory context … without trusting task or caller overrides").
16
+ * The ambient `AKM_EVENT_SOURCE` wins over the task runner's provenance; it
17
+ * rides `runExecution`'s single-purpose `eventSource`, never `runOptions.env`,
18
+ * so a caller cannot replace the request's own environment.
27
19
  */
28
- function loweredDispatchOptions(options) {
20
+ function runOptionsFor(options) {
29
21
  const { eventSource, ...rest } = options;
30
22
  if (eventSource === undefined)
31
23
  return rest;
@@ -59,11 +51,7 @@ function qualifyCommandSelectedPersona(selector, command) {
59
51
  return selector;
60
52
  return `${command.identity.bundle}//${selector}`;
61
53
  }
62
- function snapshotCommandConfig(config, path = "command config") {
63
- return cloneExecutionJsonObject(config, path);
64
- }
65
54
  export async function prepareCommandInvocation(options) {
66
- const inputConfig = snapshotCommandConfig(options.config, "command input config");
67
55
  const action = parseBuiltinCommandAction(options.action);
68
56
  const sourceLoader = options.sourceLoader ?? defaultSourceLoader;
69
57
  let renderedCommand;
@@ -71,7 +59,7 @@ export async function prepareCommandInvocation(options) {
71
59
  let command;
72
60
  if (action.kind === "stored") {
73
61
  const rendered = await sourceLoader(action.ref, "command", {
74
- config: inputConfig,
62
+ config: options.config,
75
63
  ...(options.sourceLookup ? { lookup: options.sourceLookup } : {}),
76
64
  });
77
65
  if (rendered.kind !== "command")
@@ -110,7 +98,7 @@ export async function prepareCommandInvocation(options) {
110
98
  ? qualifyCommandSelectedPersona(selectedAgent.value, renderedCommand)
111
99
  : selectedAgent.value;
112
100
  const rendered = await sourceLoader(lookupRef, "persona", {
113
- config: inputConfig,
101
+ config: options.config,
114
102
  ...(options.sourceLookup ? { lookup: options.sourceLookup } : {}),
115
103
  });
116
104
  if (rendered.kind !== "persona")
@@ -118,10 +106,9 @@ export async function prepareCommandInvocation(options) {
118
106
  renderedPersona = rendered;
119
107
  }
120
108
  const persona = renderedPersona ? createResolvedPersona(renderedPersona) : selectedAgent.present ? null : undefined;
121
- return prepareResolvedExecution({
109
+ return resolveExecution({
122
110
  command,
123
- config: inputConfig,
124
- invocationKind: options.invocationKind ?? "direct",
111
+ config: options.config,
125
112
  ...(persona !== undefined ? { persona } : {}),
126
113
  ...(renderedPersona ? { agentLayer: { id: renderedPersona.identity.ref, values: renderedPersona.defaults } } : {}),
127
114
  commandLayer: {
@@ -131,7 +118,6 @@ export async function prepareCommandInvocation(options) {
131
118
  ...(options.invocationDefaults ? { invocationDefaults: options.invocationDefaults } : {}),
132
119
  ...(options.current ? { current: options.current } : {}),
133
120
  ...(options.modelMap ? { modelMap: options.modelMap } : {}),
134
- ...(options.authorizeTools ? { authorizeTools: options.authorizeTools } : {}),
135
121
  });
136
122
  }
137
123
  function compareText(left, right) {
@@ -207,21 +193,6 @@ function safeDiagnosticNotice(notice) {
207
193
  if (!safeDiagnosticToken(notice.adapter))
208
194
  return undefined;
209
195
  switch (notice.code) {
210
- case "engine-fallback":
211
- return Object.freeze({
212
- code: "engine-fallback",
213
- severity: "info",
214
- adapter: "akm",
215
- field: "engine",
216
- message: "No engine was selected; using the fixed opencode-sdk fallback.",
217
- });
218
- case "unrecognized-request-notice":
219
- return Object.freeze({
220
- code: "unrecognized-request-notice",
221
- severity: "warning",
222
- adapter: "akm",
223
- message: "An unrecognized durable execution notice was omitted at the engine lowering boundary.",
224
- });
225
196
  case "untranslated-field": {
226
197
  const field = canonicalDiagnosticNoticeField(notice.field);
227
198
  if (!field)
@@ -264,26 +235,20 @@ function diagnosticNotices(notices) {
264
235
  return Object.freeze([...canonical.values()].sort((left, right) => compareText(JSON.stringify(left), JSON.stringify(right))));
265
236
  }
266
237
  /**
267
- * Authorize and lower a prepared invocation, then project only safe structural
268
- * diagnostics. It never acquires a dispatch lease, materializes credentials,
269
- * records usage, or exposes request/plan values.
238
+ * Build a prepared invocation and project only safe structural diagnostics.
239
+ * Reads no credential, records no usage, and exposes no request values.
270
240
  */
271
241
  export function inspectPreparedCommandInvocation(prepared) {
272
- const request = requireAuthorizedExecutionPlan(prepared.plan);
273
- const lowered = lowerResolvedExecutionRequest(request, prepared.config);
274
- const selectedEngine = request.engine.name;
275
- if (!selectedEngine) {
276
- throw new ConfigError(`command ${NO_ENGINE_MESSAGE_SUFFIX} ${NO_ENGINE_REMEDY}`, "INVALID_CONFIG_FILE");
277
- }
278
- return Object.freeze({
242
+ const built = buildExecution(prepared.request, prepared.runner);
243
+ return {
279
244
  schemaVersion: 1,
280
245
  shape: "command-dry-run",
281
246
  ok: true,
282
247
  dryRun: true,
283
- engine: selectedEngine,
284
- provenance: diagnosticProvenance(prepared.plan.provenance),
285
- notices: diagnosticNotices(lowered.notices),
286
- });
248
+ engine: prepared.request.engine.name,
249
+ provenance: diagnosticProvenance(prepared.provenance),
250
+ notices: diagnosticNotices(built.notices),
251
+ };
287
252
  }
288
253
  function resultEnvelope(result, engine, warnings, notices) {
289
254
  return {
@@ -302,13 +267,10 @@ function resultEnvelope(result, engine, warnings, notices) {
302
267
  };
303
268
  }
304
269
  export async function dispatchPreparedCommandInvocation(prepared, options = {}) {
305
- const request = requireAuthorizedExecutionPlan(prepared.plan);
306
- const lowered = lowerResolvedExecutionRequest(request, prepared.config);
270
+ const { request } = prepared;
271
+ const built = buildExecution(request, prepared.runner);
307
272
  const selectedEngine = request.engine.name;
308
- if (!selectedEngine) {
309
- throw new ConfigError(`command ${NO_ENGINE_MESSAGE_SUFFIX} ${NO_ENGINE_REMEDY}`, "INVALID_CONFIG_FILE");
310
- }
311
- const result = await dispatchLoweredExecutionRequest(lowered, loweredDispatchOptions(options));
273
+ const result = await runExecution(built, runOptionsFor(options));
312
274
  const consumedRefs = new Set();
313
275
  if (request.command.source)
314
276
  consumedRefs.add(request.command.source.ref);
@@ -322,7 +284,7 @@ export async function dispatchPreparedCommandInvocation(prepared, options = {})
322
284
  for (const ref of consumedRefs)
323
285
  recordIndexedShowUsage(ref, eventSource);
324
286
  const announcement = fallbackAnnouncement(prepared.fallbackEngineName, selectedEngine);
325
- return resultEnvelope(result, selectedEngine, announcement ? [announcement] : [], lowered.notices);
287
+ return resultEnvelope(result, selectedEngine, announcement ? [announcement] : [], built.notices);
326
288
  }
327
289
  export async function executeCommandInvocation(options, dispatchOptions = {}) {
328
290
  return dispatchPreparedCommandInvocation(await prepareCommandInvocation(options), dispatchOptions);
@@ -95,7 +95,6 @@ function appendLessonStrength(refInput, feedbackRef) {
95
95
  let mutationStarted = false;
96
96
  try {
97
97
  withWriteTargetMutation(resolved.target, [filePath], {
98
- ignored: "reject",
99
98
  purpose: "feedback-lesson-credit",
100
99
  message: `Update ${makeBundleRef(bundleId, conceptId)}`,
101
100
  }, () => {
@@ -15,6 +15,7 @@
15
15
  * same read extended to the accepted/rejected archive.
16
16
  */
17
17
  import { resolveStashDir } from "../../core/common.js";
18
+ import { isProceduralRejection } from "../proposal/proposal-types.js";
18
19
  import { listProposals } from "../proposal/repository.js";
19
20
  /**
20
21
  * Compute accept-rate-per-source metrics from the proposal store. Defaults to
@@ -28,6 +29,11 @@ export function computeAcceptRateBySource(stashDir) {
28
29
  for (const status of statuses) {
29
30
  const proposals = listProposals(stash, { status, includeArchive });
30
31
  for (const p of proposals) {
32
+ // A stale-target auto-reject (STALE, R20) is procedural, not a
33
+ // judgement on the content — counting it would understate the
34
+ // source's real accept rate for content the drain will re-propose.
35
+ if (status === "rejected" && isProceduralRejection(p))
36
+ continue;
31
37
  const src = p.source || "(unknown)";
32
38
  const entry = bySource.get(src) ?? { accepted: 0, rejected: 0, pending: 0 };
33
39
  if (status === "accepted")