akm-cli 0.9.0-rc.9 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (450) hide show
  1. package/CHANGELOG.md +1063 -44
  2. package/README.md +51 -25
  3. package/SECURITY.md +14 -1
  4. package/STABILITY.md +497 -0
  5. package/dist/akm +148 -35
  6. package/dist/{akm-migrate-storage → akm-migrate} +6 -9
  7. package/dist/assets/hints/cli-hints-full.md +223 -95
  8. package/dist/assets/hints/cli-hints-short.md +85 -22
  9. package/dist/assets/improve-strategies/default.json +1 -1
  10. package/dist/assets/improve-strategies/reflect-distill.json +1 -1
  11. package/dist/assets/prompts/memory-infer-user.md +2 -3
  12. package/dist/assets/stash-skeleton/README.md +6 -5
  13. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +2 -0
  14. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +2 -0
  15. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +2 -0
  16. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +2 -0
  17. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +2 -0
  18. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +2 -0
  19. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +2 -0
  20. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +2 -0
  21. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +2 -0
  22. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +2 -0
  23. package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -0
  24. package/dist/assets/stash-skeleton/facts/conventions/organization.md +20 -9
  25. package/dist/assets/tasks/core/extract.yml +1 -1
  26. package/dist/assets/tasks/core/version-check.yml +1 -1
  27. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
  28. package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
  29. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
  30. package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
  31. package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
  32. package/dist/assets/templates/html/health.html +1 -3
  33. package/dist/assets/workflows/workflow-template.md +32 -15
  34. package/dist/cli/invocation.js +40 -15
  35. package/dist/cli/parse-args.js +0 -22
  36. package/dist/cli/retired-commands.js +121 -0
  37. package/dist/cli/shared.js +154 -22
  38. package/dist/cli/unknown-flags.js +236 -0
  39. package/dist/cli-node.mjs +2 -1
  40. package/dist/cli.js +696 -258
  41. package/dist/commands/agent/agent-dispatch.js +14 -3
  42. package/dist/commands/agent/contribute-cli.js +73 -88
  43. package/dist/commands/completions.js +79 -22
  44. package/dist/commands/config-cli.js +17 -150
  45. package/dist/commands/env/env-cli.js +59 -143
  46. package/dist/commands/env/env.js +12 -163
  47. package/dist/commands/env/marker-path.js +6 -0
  48. package/dist/commands/env/secret-cli.js +36 -66
  49. package/dist/commands/env/secret.js +24 -57
  50. package/dist/commands/feedback-cli.js +141 -87
  51. package/dist/commands/health/accept-rate.js +58 -0
  52. package/dist/commands/health/advisories.js +3 -4
  53. package/dist/commands/health/checks.js +85 -23
  54. package/dist/commands/health/html-report.js +7 -10
  55. package/dist/commands/health/improve-metrics.js +25 -83
  56. package/dist/commands/health/md-report.js +5 -9
  57. package/dist/commands/health/metrics.js +62 -20
  58. package/dist/commands/health/renderers.js +47 -0
  59. package/dist/commands/health/report-view-model.js +4 -5
  60. package/dist/commands/health/stash-exposure.js +1 -1
  61. package/dist/commands/health/surfaces.js +3 -48
  62. package/dist/commands/health/task-runs.js +3 -67
  63. package/dist/commands/health/types-improve.js +7 -0
  64. package/dist/commands/health.js +99 -28
  65. package/dist/commands/improve/anti-collapse.js +2 -2
  66. package/dist/commands/improve/autonomy-gate.js +68 -0
  67. package/dist/commands/improve/collapse-detector.js +41 -40
  68. package/dist/commands/improve/consolidate/eligibility.js +1 -23
  69. package/dist/commands/improve/consolidate/merge.js +4 -0
  70. package/dist/commands/improve/consolidate.js +140 -1000
  71. package/dist/commands/improve/distill/promote-memory.js +12 -12
  72. package/dist/commands/improve/distill/quality-gate.js +6 -6
  73. package/dist/commands/improve/distill.js +58 -69
  74. package/dist/commands/improve/eligibility.js +95 -55
  75. package/dist/commands/improve/extract-cli.js +14 -133
  76. package/dist/commands/improve/improve-cli.js +98 -114
  77. package/dist/commands/improve/improve-result-file.js +1 -28
  78. package/dist/commands/improve/improve-strategies.js +8 -5
  79. package/dist/commands/improve/improve.js +128 -91
  80. package/dist/commands/improve/loop-stages.js +182 -20
  81. package/dist/commands/improve/memory/derived-ref.js +45 -43
  82. package/dist/commands/improve/memory/memory-belief.js +1 -1
  83. package/dist/commands/improve/memory/memory-contradiction-detect.js +4 -12
  84. package/dist/commands/improve/memory/memory-improve.js +6 -5
  85. package/dist/commands/improve/outcome-loop.js +22 -65
  86. package/dist/commands/improve/preparation.js +114 -123
  87. package/dist/commands/improve/proactive-maintenance.js +2 -5
  88. package/dist/commands/improve/reflect.js +56 -160
  89. package/dist/commands/improve/salience.js +11 -122
  90. package/dist/commands/improve/source-identity.js +10 -38
  91. package/dist/commands/lint/base-linter.js +20 -124
  92. package/dist/commands/lint/env-key-rules.js +31 -47
  93. package/dist/commands/lint/index.js +249 -43
  94. package/dist/commands/{events.js → log.js} +33 -38
  95. package/dist/commands/migrate-cli.js +92 -12
  96. package/dist/commands/migration-tool.js +46 -0
  97. package/dist/commands/observability-cli.js +70 -209
  98. package/dist/commands/proposal/drain.js +101 -29
  99. package/dist/commands/proposal/proposal-cli.js +76 -48
  100. package/dist/commands/proposal/proposal.js +54 -18
  101. package/dist/commands/proposal/propose-cli.js +88 -0
  102. package/dist/commands/proposal/propose.js +23 -15
  103. package/dist/commands/proposal/repository.js +701 -278
  104. package/dist/commands/proposal/validators/proposal-quality-validators.js +2 -8
  105. package/dist/commands/proposal/validators/proposal-validators.js +55 -7
  106. package/dist/commands/proposal/validators/proposals.js +4 -7
  107. package/dist/commands/read/curate.js +34 -53
  108. package/dist/commands/read/knowledge.js +150 -95
  109. package/dist/commands/read/registry-search.js +2 -2
  110. package/dist/commands/read/remember-cli.js +42 -15
  111. package/dist/commands/read/search-cli.js +180 -78
  112. package/dist/commands/read/search.js +58 -43
  113. package/dist/commands/read/show.js +197 -141
  114. package/dist/commands/registry-cli.js +12 -51
  115. package/dist/commands/remember.js +14 -57
  116. package/dist/commands/sources/add-cli.js +100 -31
  117. package/dist/commands/sources/bundle-cli.js +166 -0
  118. package/dist/commands/sources/bundle-config-ops.js +7 -2
  119. package/dist/commands/sources/info.js +18 -5
  120. package/dist/commands/sources/init.js +12 -12
  121. package/dist/commands/sources/installed-stashes.js +382 -98
  122. package/dist/commands/sources/schema-repair.js +3 -2
  123. package/dist/commands/sources/self-update.js +131 -38
  124. package/dist/commands/sources/source-add.js +72 -17
  125. package/dist/commands/sources/source-clone.js +129 -45
  126. package/dist/commands/sources/source-manage.js +43 -23
  127. package/dist/commands/sources/sources-cli.js +57 -208
  128. package/dist/commands/sources/stash-cli.js +46 -53
  129. package/dist/commands/tasks/tasks-cli.js +91 -97
  130. package/dist/commands/tasks/tasks.js +276 -421
  131. package/dist/commands/workflow-cli.js +175 -450
  132. package/dist/core/adapter/adapters/akm-adapter.js +47 -28
  133. package/dist/core/adapter/adapters/akm-lint.js +42 -27
  134. package/dist/core/adapter/adapters/akm-metadata.js +15 -44
  135. package/dist/core/adapter/adapters/akm-task-adapter.js +15 -13
  136. package/dist/core/adapter/adapters/akm-workflow-adapter.js +55 -71
  137. package/dist/core/adapter/adapters/dotenv-adapter.js +1 -1
  138. package/dist/core/adapter/adapters/generic-files-adapter.js +2 -0
  139. package/dist/core/adapter/adapters/index.js +6 -6
  140. package/dist/core/adapter/adapters/llm-wiki-adapter.js +14 -8
  141. package/dist/core/adapter/adapters/okf-adapter.js +187 -19
  142. package/dist/core/adapter/adapters/shared.js +3 -19
  143. package/dist/core/adapter/adapters/tool-dir-shared.js +8 -3
  144. package/dist/core/adapter/adapters/website-snapshot-adapter.js +1 -0
  145. package/dist/core/adapter/detect-adapter.js +17 -0
  146. package/dist/core/adapter/recognize-match.js +6 -4
  147. package/dist/core/adapter/validate-context.js +214 -0
  148. package/dist/core/asset/akm-markdown.js +63 -0
  149. package/dist/core/asset/asset-placement.js +20 -6
  150. package/dist/core/asset/asset-ref.js +11 -9
  151. package/dist/core/asset/frontmatter-lint.js +30 -0
  152. package/dist/core/asset/frontmatter.js +25 -9
  153. package/dist/core/asset/markdown.js +40 -51
  154. package/dist/core/asset/resolve-ref.js +89 -18
  155. package/dist/core/asset/stash-meta.js +1 -1
  156. package/dist/core/bundle-id.js +51 -0
  157. package/dist/core/common.js +152 -38
  158. package/dist/core/config/config-io.js +12 -1
  159. package/dist/core/config/config-schema.js +35 -8
  160. package/dist/core/config/config-sources.js +55 -11
  161. package/dist/core/config/config-walker.js +25 -9
  162. package/dist/core/config/config.js +9 -48
  163. package/dist/core/config/experimental.js +21 -0
  164. package/dist/core/config/schema/embedding.js +5 -1
  165. package/dist/core/config/schema/experimental.js +30 -0
  166. package/dist/core/config/schema/improve-processes.js +0 -6
  167. package/dist/core/config/schema/improve.js +21 -3
  168. package/dist/core/config/schema/index-config.js +8 -15
  169. package/dist/core/config/schema/output.js +4 -1
  170. package/dist/core/config/schema/setup.js +9 -18
  171. package/dist/core/config/schema/sources-bundles.js +49 -33
  172. package/dist/core/config/schema/workflow.js +3 -3
  173. package/dist/core/env-secret-ref.js +76 -46
  174. package/dist/core/errors.js +18 -12
  175. package/dist/core/events.js +46 -128
  176. package/dist/core/file-change.js +6 -5
  177. package/dist/core/fs-txn.js +83 -7
  178. package/dist/core/git-message.js +2 -2
  179. package/dist/core/improve-result.js +1 -100
  180. package/dist/core/lesson-lint.js +1 -17
  181. package/dist/core/logs-db.js +2 -1
  182. package/dist/core/migration-operation.js +16 -0
  183. package/dist/core/mutation-target.js +78 -0
  184. package/dist/core/parse.js +4 -1
  185. package/dist/core/paths.js +17 -20
  186. package/dist/core/recognition-util.js +12 -14
  187. package/dist/core/redaction.js +34 -0
  188. package/dist/core/standards/resolve-standards-context.js +2 -14
  189. package/dist/core/standards/resolve-stash-standards.js +2 -2
  190. package/dist/core/standards/resolve-type-conventions.js +2 -2
  191. package/dist/core/state/migrations.js +41 -18
  192. package/dist/core/state-db.js +5 -14
  193. package/dist/core/structured.js +1 -1
  194. package/dist/core/subprocess.js +6 -4
  195. package/dist/core/text-truncation.js +9 -5
  196. package/dist/core/type-presentation.js +3 -3
  197. package/dist/core/warn.js +0 -3
  198. package/dist/core/write-source.js +771 -95
  199. package/dist/indexer/bundle-identity-guard.js +3 -2
  200. package/dist/indexer/db/graph-db.js +0 -24
  201. package/dist/indexer/ensure-index.js +1 -0
  202. package/dist/indexer/graph/graph-boost.js +9 -34
  203. package/dist/indexer/graph/graph-extraction.js +8 -5
  204. package/dist/indexer/index-writer-lock.js +53 -17
  205. package/dist/indexer/index-written-assets.js +16 -22
  206. package/dist/indexer/indexer.js +497 -239
  207. package/dist/indexer/installations.js +14 -96
  208. package/dist/indexer/passes/dir-staleness.js +16 -9
  209. package/dist/indexer/passes/memory-inference.js +11 -9
  210. package/dist/indexer/passes/metadata.js +113 -47
  211. package/dist/indexer/scan/doc-to-entry.js +38 -1
  212. package/dist/indexer/scan/drain-dir.js +13 -23
  213. package/dist/indexer/search/db-search.js +99 -54
  214. package/dist/indexer/search/fts-query.js +47 -24
  215. package/dist/indexer/search/ranking-contributors.js +42 -20
  216. package/dist/indexer/search/ranking.js +18 -99
  217. package/dist/indexer/search/search-fields.js +7 -2
  218. package/dist/indexer/search/search-source.js +82 -93
  219. package/dist/indexer/usage/usage-events.js +0 -89
  220. package/dist/indexer/walk/file-context.js +2 -1
  221. package/dist/indexer/walk/matchers.js +30 -43
  222. package/dist/indexer/walk/path-resolver.js +7 -2
  223. package/dist/indexer/walk/walker.js +38 -12
  224. package/dist/integrations/agent/builders.js +0 -6
  225. package/dist/integrations/agent/config.js +2 -2
  226. package/dist/integrations/agent/detect.js +49 -19
  227. package/dist/integrations/agent/engine-fallback.js +76 -0
  228. package/dist/integrations/agent/profiles.js +14 -0
  229. package/dist/integrations/agent/prompts.js +12 -8
  230. package/dist/integrations/agent/runner-dispatch.js +4 -2
  231. package/dist/integrations/agent/runner.js +0 -1
  232. package/dist/integrations/agent/spawn.js +5 -6
  233. package/dist/integrations/github.js +1 -1
  234. package/dist/integrations/harnesses/aider/agent-builder.js +6 -4
  235. package/dist/integrations/harnesses/amazonq/agent-builder.js +7 -4
  236. package/dist/integrations/harnesses/claude/session-log.js +0 -10
  237. package/dist/integrations/harnesses/codex/agent-builder.js +5 -2
  238. package/dist/integrations/harnesses/copilot/agent-builder.js +5 -3
  239. package/dist/integrations/harnesses/gemini/agent-builder.js +5 -3
  240. package/dist/integrations/harnesses/index.js +3 -7
  241. package/dist/integrations/harnesses/opencode/agent-builder.js +21 -2
  242. package/dist/integrations/harnesses/opencode/session-log.js +0 -15
  243. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +13 -4
  244. package/dist/integrations/harnesses/openhands/agent-builder.js +9 -6
  245. package/dist/integrations/harnesses/pi/agent-builder.js +6 -4
  246. package/dist/integrations/lockfile.js +88 -7
  247. package/dist/integrations/session-logs/index.js +3 -28
  248. package/dist/llm/client.js +136 -100
  249. package/dist/llm/embedders/remote.js +13 -5
  250. package/dist/llm/feature-gate.js +4 -12
  251. package/dist/llm/graph-extract.js +5 -11
  252. package/dist/llm/memory-infer.js +144 -1
  253. package/dist/llm/metadata-enhance.js +5 -7
  254. package/dist/llm/structured-call.js +1 -1
  255. package/dist/llm/usage-persist.js +26 -5
  256. package/dist/llm/usage-telemetry.js +25 -2
  257. package/dist/output/cli-hints.js +1 -2
  258. package/dist/output/context.js +22 -7
  259. package/dist/output/format-exempt.js +80 -0
  260. package/dist/output/generic-render.js +259 -0
  261. package/dist/output/render-registry.js +57 -0
  262. package/dist/output/renderers.js +14 -36
  263. package/dist/output/shapes/curate.js +10 -1
  264. package/dist/output/shapes/events.js +12 -7
  265. package/dist/output/shapes/helpers.js +56 -83
  266. package/dist/output/shapes/migrate.js +8 -0
  267. package/dist/output/shapes/passthrough.js +7 -41
  268. package/dist/output/shapes/proposal/producer.js +15 -7
  269. package/dist/output/shapes.js +2 -9
  270. package/dist/output/text/{init.js → bundle-create.js} +3 -1
  271. package/dist/output/text/bundle-show.js +7 -0
  272. package/dist/output/text/command-format.js +164 -96
  273. package/dist/output/text/env.js +1 -3
  274. package/dist/output/text/events.js +8 -7
  275. package/dist/output/text/health-format.js +103 -0
  276. package/dist/output/text/health.js +7 -0
  277. package/dist/output/text/helpers.js +10 -8
  278. package/dist/output/text/lint-format.js +43 -0
  279. package/dist/output/text/{save.js → lint.js} +2 -2
  280. package/dist/output/text/migrate.js +88 -0
  281. package/dist/output/text/proposal/producer.js +4 -2
  282. package/dist/output/text/proposal-format.js +44 -72
  283. package/dist/output/text/registry-commands.js +1 -2
  284. package/dist/output/text/show-directives.js +15 -7
  285. package/dist/output/text/status-list.js +32 -0
  286. package/dist/output/text/sync.js +5 -0
  287. package/dist/output/text/workflow-format.js +24 -203
  288. package/dist/output/text/workflow.js +1 -7
  289. package/dist/output/text.js +16 -17
  290. package/dist/registry/factory.js +4 -6
  291. package/dist/registry/origin-resolve.js +16 -27
  292. package/dist/registry/providers/skills-sh.js +3 -3
  293. package/dist/registry/providers/static-index.js +13 -23
  294. package/dist/registry/resolve.js +42 -7
  295. package/dist/registry/semver.js +34 -84
  296. package/dist/runtime.js +2 -23
  297. package/dist/scripts/akm-migrate-node.js +60290 -0
  298. package/dist/scripts/akm-migrate.js +59628 -0
  299. package/dist/setup/detect.js +42 -15
  300. package/dist/setup/registry-stash-loader.js +2 -2
  301. package/dist/setup/setup.js +236 -136
  302. package/dist/setup/steps/connection.js +7 -9
  303. package/dist/setup/steps/platforms.js +9 -9
  304. package/dist/setup/steps/semantic.js +15 -3
  305. package/dist/setup/steps/sources.js +12 -13
  306. package/dist/setup/steps/stashdir.js +2 -3
  307. package/dist/setup/steps/tasks.js +237 -120
  308. package/dist/sources/freshness.js +1 -1
  309. package/dist/sources/provider-factory.js +11 -17
  310. package/dist/sources/providers/filesystem.js +2 -3
  311. package/dist/sources/providers/git-install.js +278 -34
  312. package/dist/sources/providers/git-provider.js +25 -23
  313. package/dist/sources/providers/git-stash.js +395 -106
  314. package/dist/sources/providers/git.js +2 -2
  315. package/dist/sources/providers/npm.js +16 -19
  316. package/dist/sources/providers/provider-utils.js +7 -4
  317. package/dist/sources/providers/sync-from-ref.js +3 -9
  318. package/dist/sources/providers/website.js +6 -1
  319. package/dist/sources/resolve.js +6 -5
  320. package/dist/sources/snapshot-fetchers/bluesky.js +146 -0
  321. package/dist/sources/snapshot-fetchers/content-extract.js +566 -0
  322. package/dist/sources/snapshot-fetchers/fetcher-util.js +41 -0
  323. package/dist/sources/snapshot-fetchers/github.js +100 -0
  324. package/dist/sources/snapshot-fetchers/host-guard.js +291 -0
  325. package/dist/sources/snapshot-fetchers/registry.js +17 -1
  326. package/dist/sources/snapshot-fetchers/robots.js +348 -0
  327. package/dist/sources/snapshot-fetchers/rss.js +282 -0
  328. package/dist/sources/snapshot-fetchers/secret-seam.js +42 -0
  329. package/dist/sources/snapshot-fetchers/website-ingest.js +566 -268
  330. package/dist/sources/snapshot-fetchers/x.js +910 -0
  331. package/dist/storage/database.js +7 -0
  332. package/dist/storage/engines/sqlite-migrations.js +23 -111
  333. package/dist/storage/managed-db.js +2 -2
  334. package/dist/storage/repositories/canaries-repository.js +1 -1
  335. package/dist/storage/repositories/events-repository.js +27 -11
  336. package/dist/storage/repositories/improve-runs-repository.js +6 -12
  337. package/dist/storage/repositories/index-connection.js +17 -6
  338. package/dist/storage/repositories/index-entries-repository.js +151 -240
  339. package/dist/storage/repositories/index-entry-mapper.js +15 -11
  340. package/dist/storage/repositories/index-fts-repository.js +5 -2
  341. package/dist/storage/repositories/index-llm-cache-repository.js +0 -1
  342. package/dist/storage/repositories/index-meta-repository.js +2 -3
  343. package/dist/storage/repositories/index-schema.js +10 -25
  344. package/dist/storage/repositories/index-utility-repository.js +15 -28
  345. package/dist/storage/repositories/index-vec-repository.js +6 -1
  346. package/dist/storage/repositories/outcome-repository.js +119 -0
  347. package/dist/storage/repositories/proposals-repository.js +296 -59
  348. package/dist/storage/repositories/registry-cache.js +19 -0
  349. package/dist/storage/repositories/salience-repository.js +172 -0
  350. package/dist/storage/repositories/task-history-repository.js +15 -13
  351. package/dist/storage/repositories/workflow-runs-repository.js +52 -40
  352. package/dist/tasks/backends/cron.js +105 -15
  353. package/dist/tasks/backends/index.js +1 -1
  354. package/dist/tasks/backends/launchd.js +85 -38
  355. package/dist/tasks/backends/schtasks.js +135 -15
  356. package/dist/tasks/embedded.js +56 -40
  357. package/dist/tasks/parser.js +7 -157
  358. package/dist/tasks/resolve-akm-bin.js +137 -59
  359. package/dist/tasks/runner.js +79 -42
  360. package/dist/tasks/scheduler-invocation.js +220 -10
  361. package/dist/tasks/schema.js +24 -1
  362. package/dist/tasks/task-id.js +1 -3
  363. package/dist/tasks/validator.js +20 -6
  364. package/dist/workflows/authoring/authoring.js +94 -143
  365. package/dist/workflows/authoring/scope-key.js +1 -1
  366. package/dist/workflows/exec/frozen-judge.js +28 -2
  367. package/dist/workflows/exec/native-executor.js +77 -57
  368. package/dist/workflows/exec/param-secrets.js +9 -9
  369. package/dist/workflows/exec/run-workflow.js +133 -79
  370. package/dist/workflows/exec/step-work.js +219 -346
  371. package/dist/{migrate-storage-node.mjs → workflows/exec/unit-dispatch.js} +1 -5
  372. package/dist/workflows/ir/compile.js +141 -270
  373. package/dist/workflows/ir/freeze.js +40 -30
  374. package/dist/workflows/ir/params.js +135 -11
  375. package/dist/workflows/ir/plan-hash.js +1 -1
  376. package/dist/workflows/ir/schema.js +25 -26
  377. package/dist/workflows/parser.js +872 -307
  378. package/dist/workflows/program/expressions.js +20 -208
  379. package/dist/workflows/program/schema.js +7 -10
  380. package/dist/workflows/renderer.js +95 -68
  381. package/dist/workflows/resource-limits.js +2 -0
  382. package/dist/workflows/runtime/checkin.js +3 -3
  383. package/dist/workflows/runtime/plan-classifier.js +16 -75
  384. package/dist/workflows/runtime/runs.js +186 -127
  385. package/dist/workflows/runtime/unit-checkin.js +1 -1
  386. package/dist/workflows/runtime/unit-phases.js +2 -2
  387. package/dist/workflows/runtime/workflow-asset-loader.js +232 -83
  388. package/dist/workflows/schema.js +1 -11
  389. package/dist/workflows/validate-summary.js +30 -36
  390. package/dist/workflows/validator.js +21 -62
  391. package/docs/README.md +68 -0
  392. package/docs/migration/README.md +8 -0
  393. package/docs/migration/release-notes/0.7.0.md +11 -11
  394. package/docs/migration/release-notes/0.9.0.md +208 -27
  395. package/docs/migration/v0.7-to-v0.8.md +46 -47
  396. package/docs/migration/v0.8-to-v0.9.md +564 -208
  397. package/docs/migration/v0.9.0-troubleshooting.md +561 -0
  398. package/docs/reference/README.md +12 -0
  399. package/docs/reference/cli.md +2253 -0
  400. package/docs/reference/configuration.md +358 -0
  401. package/docs/reference/data-and-telemetry.md +105 -42
  402. package/docs/reference/workflows.md +647 -0
  403. package/package.json +22 -11
  404. package/schemas/akm-asset-envelope.json +93 -0
  405. package/schemas/akm-config.json +81 -128
  406. package/schemas/akm-workflow.json +74 -73
  407. package/dist/assets/tasks/core/backup.yml +0 -5
  408. package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
  409. package/dist/cli/config-migrate.js +0 -1878
  410. package/dist/cli/config-validate.js +0 -41
  411. package/dist/commands/backup-cli.js +0 -56
  412. package/dist/commands/bundle/bundle-cli.js +0 -68
  413. package/dist/commands/bundle/bundle.js +0 -219
  414. package/dist/commands/graph/graph-cli.js +0 -124
  415. package/dist/commands/graph/graph.js +0 -489
  416. package/dist/commands/improve/extract-watch.js +0 -140
  417. package/dist/commands/mv-cli.js +0 -1221
  418. package/dist/commands/sources/history.js +0 -201
  419. package/dist/commands/tasks/default-tasks.js +0 -186
  420. package/dist/core/migration-backup.js +0 -1231
  421. package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -95
  422. package/dist/llm/memory-infer-impl.js +0 -138
  423. package/dist/migrate/legacy/config-source-migration.js +0 -257
  424. package/dist/migrate/legacy/content-migration.js +0 -350
  425. package/dist/migrate/legacy/legacy-layout.js +0 -779
  426. package/dist/migrate/legacy/legacy-paths.js +0 -25
  427. package/dist/migrate/legacy/legacy-stash-json.js +0 -80
  428. package/dist/migrate/legacy/proposal-fs-import.js +0 -168
  429. package/dist/migrate/legacy/task-target-ref-migration.js +0 -278
  430. package/dist/migrate/legacy/three-db-cutover.js +0 -845
  431. package/dist/migrate/legacy/workflow-migrations-bodies.js +0 -52
  432. package/dist/migrate/legacy/workflow-migrations-frozen.js +0 -21
  433. package/dist/migrate/legacy-ref-grammar.js +0 -214
  434. package/dist/output/shapes/distill.js +0 -14
  435. package/dist/output/shapes/history.js +0 -11
  436. package/dist/output/text/distill.js +0 -6
  437. package/dist/output/text/enable-disable.js +0 -8
  438. package/dist/output/text/history.js +0 -6
  439. package/dist/registry/build-index.js +0 -382
  440. package/dist/schemas/akm-config.json +0 -4704
  441. package/dist/schemas/akm-task.json +0 -87
  442. package/dist/schemas/akm-workflow.json +0 -372
  443. package/dist/scripts/migrate-storage.js +0 -3816
  444. package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
  445. package/dist/workflows/cli.js +0 -53
  446. package/dist/workflows/exec/brief.js +0 -481
  447. package/dist/workflows/exec/report.js +0 -1460
  448. package/dist/workflows/exec/watch.js +0 -116
  449. package/dist/workflows/program/parser.js +0 -813
  450. package/dist/workflows/program/project.js +0 -104
@@ -4,9 +4,12 @@
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
6
6
  import { parseFrontmatter } from "../../core/asset/frontmatter.js";
7
- import { conceptIdFromTypeName, parseRefInput } from "../../core/asset/resolve-ref.js";
7
+ import { conceptIdFromTypeName, parseRefInput, resolveRef } from "../../core/asset/resolve-ref.js";
8
+ import { loadConfig } from "../../core/config/config.js";
8
9
  import { NotFoundError, rethrowIfTestIsolationError, UsageError } from "../../core/errors.js";
9
10
  import { readEvents } from "../../core/events.js";
11
+ import { getDbPath } from "../../core/paths.js";
12
+ import { deriveInstallations } from "../../indexer/installations.js";
10
13
  import { getWritableStashDirs, resolveSourceEntries } from "../../indexer/search/search-source.js";
11
14
  import { resolveAssetPath } from "../../indexer/walk/path-resolver.js";
12
15
  import { closeDatabase, openExistingDatabase, openReadonlyExistingDatabase, } from "../../storage/repositories/index-connection.js";
@@ -19,6 +22,17 @@ import { improveStateReadRefs } from "./source-identity.js";
19
22
  // Eligibility / candidate-selection predicates for improve. Free functions
20
23
  // (no akmImprove closure state) extracted from improve.ts to shrink the
21
24
  // orchestrator and make candidate selection independently testable.
25
+ /**
26
+ * Open the index for eligibility queries, or `undefined` when no index exists
27
+ * yet. `openExistingDatabase` refuses to create a missing `index.db` (see
28
+ * index-connection.ts) — for eligibility, "no index" simply means nothing is
29
+ * eligible, exactly like the readOnly arm's `undefined`.
30
+ */
31
+ function openEligibilityDb(readOnly) {
32
+ if (readOnly)
33
+ return openReadonlyExistingDatabase();
34
+ return fs.existsSync(getDbPath()) ? openExistingDatabase() : undefined;
35
+ }
22
36
  export function resolveImproveScope(scope) {
23
37
  const trimmed = scope?.trim();
24
38
  if (!trimmed)
@@ -28,9 +42,8 @@ export function resolveImproveScope(scope) {
28
42
  return { mode: "ref", value: trimmed };
29
43
  }
30
44
  catch (err) {
31
- // Open type token (chunk 1.5, D1.5-1): a bare word with no `type:name`
32
- // shape (no colon) is a `--scope <type>` filter attempt, not a ref — ANY
33
- // such word is now accepted, including foreign/unknown type strings,
45
+ // A bare word with no ref separator is a `--scope <type>` filter attempt,
46
+ // not a ref. Any such word is accepted, including foreign/unknown type strings,
34
47
  // which simply match zero entries downstream (a read-only query filter,
35
48
  // not a data-acceptance gate, so no deny-list is needed here: an
36
49
  // unrecognized type just matches nothing, since nothing is ever indexed
@@ -42,7 +55,7 @@ export function resolveImproveScope(scope) {
42
55
  // deliberately-removed type like tool/vault, D1.5-6) — that must still
43
56
  // surface as a real error, not be silently absorbed into a type filter
44
57
  // that will never match anything.
45
- if (!trimmed.includes(":")) {
58
+ if (!/[/:#]/.test(trimmed)) {
46
59
  return { mode: "type", value: trimmed };
47
60
  }
48
61
  const message = err instanceof Error ? err.message : String(err);
@@ -50,7 +63,8 @@ export function resolveImproveScope(scope) {
50
63
  }
51
64
  }
52
65
  /**
53
- * Dedupe a list of eligible refs by `ref`, preserving first-seen order. Used to
66
+ * Dedupe eligible refs by their durable item ref when available, preserving
67
+ * the first candidate and its display ref. Used to
54
68
  * merge the eligibility sources (feedback-signal, Layer-2 proactive-maintenance,
55
69
  * high-salience) without admitting a ref into the loop twice.
56
70
  */
@@ -58,44 +72,76 @@ export function dedupeRefs(refs) {
58
72
  const seen = new Set();
59
73
  const out = [];
60
74
  for (const r of refs) {
61
- if (seen.has(r.ref))
75
+ const key = r.itemRef ?? r.ref;
76
+ if (seen.has(key))
62
77
  continue;
63
- seen.add(r.ref);
78
+ seen.add(key);
64
79
  out.push(r);
65
80
  }
66
81
  return out;
67
82
  }
68
- export async function collectEligibleRefs(scope, stashDir, improveProfile) {
69
- return collectEligibleRefsFromIndex(scope, stashDir, improveProfile, false);
83
+ export async function collectEligibleRefs(scope, stashDir, improveProfile, config) {
84
+ return collectEligibleRefsFromIndex(scope, stashDir, improveProfile, false, config);
70
85
  }
71
86
  /** Dry-run planner path: query an existing index without creating or mutating it. */
72
- export async function collectEligibleRefsReadOnly(scope, stashDir, improveProfile) {
73
- return collectEligibleRefsFromIndex(scope, stashDir, improveProfile, true);
87
+ export async function collectEligibleRefsReadOnly(scope, stashDir, improveProfile, config) {
88
+ return collectEligibleRefsFromIndex(scope, stashDir, improveProfile, true, config);
74
89
  }
75
- async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, readOnly) {
90
+ async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, readOnly, configOverride) {
91
+ const config = configOverride ?? loadConfig();
76
92
  if (scope.mode === "ref" && scope.value) {
77
- const parsed = parseRefInput(scope.value);
78
- const writableDirs = new Set(getWritableStashDirs(stashDir).map((dir) => path.resolve(dir)));
79
- const filePath = await findAssetFilePath(scope.value, stashDir, writableDirs);
80
- if (!filePath) {
93
+ const writableDirs = new Set(getWritableStashDirs(stashDir, config).map((dir) => path.resolve(dir)));
94
+ let db;
95
+ try {
96
+ db = openEligibilityDb(readOnly);
97
+ if (!db) {
98
+ return { plannedRefs: [], memorySummary: { eligible: 0, derived: 0 }, strategyFilteredRefs: [] };
99
+ }
100
+ const entries = getAllEntries(db);
101
+ const entriesByItemRef = new Map(entries.flatMap((entry) => entry.bundleId && entry.conceptId ? [[`${entry.bundleId}//${entry.conceptId}`, entry]] : []));
102
+ const installations = deriveInstallations(resolveSourceEntries(stashDir, config));
103
+ const resolved = resolveRef(scope.value, {
104
+ defaultBundle: config.defaultBundle,
105
+ bundles: installations.map((installation) => ({
106
+ id: installation.id,
107
+ hasConcept: (conceptId) => entriesByItemRef.has(`${installation.id}//${conceptId}`),
108
+ })),
109
+ });
110
+ const indexed = entriesByItemRef.get(`${resolved.bundle}//${resolved.conceptId}`);
111
+ if (!indexed?.bundleId || !indexed.conceptId || !fs.existsSync(indexed.filePath)) {
112
+ if (await findAssetFilePath(scope.value, stashDir)) {
113
+ return { plannedRefs: [], memorySummary: { eligible: 0, derived: 0 }, strategyFilteredRefs: [] };
114
+ }
115
+ throw new NotFoundError(`Asset not found in the selected writable source: ${scope.value}`, "ASSET_NOT_FOUND");
116
+ }
117
+ if (!isEntryInScope(indexed.stashDir, indexed.filePath, stashDir) ||
118
+ !isEntryInWritableSource(indexed.stashDir, indexed.filePath, writableDirs)) {
119
+ return { plannedRefs: [], memorySummary: { eligible: 0, derived: 0 }, strategyFilteredRefs: [] };
120
+ }
121
+ const itemRef = `${indexed.bundleId}//${indexed.conceptId}`;
81
122
  return {
82
- plannedRefs: [],
83
- memorySummary: { eligible: 0, derived: 0 },
123
+ plannedRefs: [{ ref: indexed.conceptId, itemRef, reason: "scope-ref", filePath: indexed.filePath }],
124
+ memorySummary: {
125
+ eligible: indexed.entry.type === "memory" ? 1 : 0,
126
+ derived: indexed.entry.type === "memory" && indexed.entry.name.endsWith(".derived") ? 1 : 0,
127
+ },
84
128
  strategyFilteredRefs: [],
85
129
  };
86
130
  }
87
- return {
88
- plannedRefs: [{ ref: scope.value, reason: "scope-ref", filePath }],
89
- memorySummary: {
90
- eligible: parsed.type === "memory" ? 1 : 0,
91
- derived: parsed.type === "memory" && parsed.name.endsWith(".derived") ? 1 : 0,
92
- },
93
- strategyFilteredRefs: [],
94
- };
131
+ catch (error) {
132
+ if (error instanceof Error && /no such table:\s*entries/i.test(error.message)) {
133
+ return { plannedRefs: [], memorySummary: { eligible: 0, derived: 0 }, strategyFilteredRefs: [] };
134
+ }
135
+ throw error;
136
+ }
137
+ finally {
138
+ if (db)
139
+ closeDatabase(db);
140
+ }
95
141
  }
96
142
  let sources;
97
143
  try {
98
- sources = resolveSourceEntries(stashDir);
144
+ sources = resolveSourceEntries(stashDir, config);
99
145
  }
100
146
  catch {
101
147
  return { plannedRefs: [], memorySummary: { eligible: 0, derived: 0 }, strategyFilteredRefs: [] };
@@ -107,7 +153,7 @@ async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, rea
107
153
  // or remote stashes that the user did not mark writable.
108
154
  let writableDirs;
109
155
  try {
110
- writableDirs = getWritableStashDirs(stashDir);
156
+ writableDirs = getWritableStashDirs(stashDir, config);
111
157
  }
112
158
  catch {
113
159
  writableDirs = sources.slice(0, 1).map((s) => s.path); // fallback: primary only
@@ -115,7 +161,7 @@ async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, rea
115
161
  const writableDirSet = new Set(writableDirs.map((d) => path.resolve(d)));
116
162
  let db;
117
163
  try {
118
- db = readOnly ? openReadonlyExistingDatabase() : openExistingDatabase();
164
+ db = openEligibilityDb(readOnly);
119
165
  if (!db) {
120
166
  return { plannedRefs: [], memorySummary: { eligible: 0, derived: 0 }, strategyFilteredRefs: [] };
121
167
  }
@@ -127,7 +173,7 @@ async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, rea
127
173
  return isEntryInWritableSource(indexed.stashDir, indexed.filePath, writableDirSet);
128
174
  });
129
175
  const planned = new Map();
130
- const profileFiltered = new Map();
176
+ const strategyFiltered = new Map();
131
177
  let memoryEligible = 0;
132
178
  let memoryDerived = 0;
133
179
  for (const indexed of entries) {
@@ -144,11 +190,8 @@ async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, rea
144
190
  continue;
145
191
  throw error;
146
192
  }
147
- // Chunk-5 flip F5d (Step 4): the durable `item_ref` (`<bundle>//<concept-id>`),
148
- // reconstructed from the mapper-unlocked provenance columns with ZERO extra
149
- // queries (D-R3 — derived from the resolved index entry, never raw input).
150
- // `undefined` for a NULL-provenance (pre-flip / write-back) row; the durable
151
- // writers then fall back to the legacy `type:name` key.
193
+ // Derive the durable item_ref from indexed provenance without another query.
194
+ // A provenance-free row uses the short conceptId ref for improve state.
152
195
  const itemRef = indexed.bundleId && indexed.conceptId ? `${indexed.bundleId}//${indexed.conceptId}` : undefined;
153
196
  const isDerived = indexed.entry.name.endsWith(".derived");
154
197
  // `.derived` memories are LLM-inferred and intentionally skip reflect
@@ -158,16 +201,16 @@ async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, rea
158
201
  // 2026-05-21: 11 derived refs re-planned every hour during idle periods.
159
202
  // The cleanup phase (analyzeMemoryCleanup) inspects derived memories
160
203
  // independently of `plannedRefs`, so dropping them here loses nothing.
161
- if (!isDerived && !planned.has(ref) && !profileFiltered.has(ref)) {
162
- // 2026-05-27: extend the .derived precedent to profile-incompatible
204
+ if (!isDerived && !planned.has(ref) && !strategyFiltered.has(ref)) {
205
+ // 2026-05-27: extend the .derived precedent to strategy-incompatible
163
206
  // refs. If every per-ref pass (reflect + distill) on the active
164
- // profile would refuse this ref, drop it from `plannedRefs`. The
207
+ // strategy would refuse this ref, drop it from `plannedRefs`. The
165
208
  // caller emits `improve_skipped { reason: strategy_filtered_all_passes }`
166
209
  // once `eventsCtx` is available so the audit trail is preserved in a
167
210
  // single event per ref instead of 2× synthetic actions per run.
168
211
  // Background: see /tmp/akm-health-investigations/planner-profile-metrics-deep-analysis.md
169
212
  if (improveProfile && isStrategyFilteredForAllPasses(ref, improveProfile)) {
170
- profileFiltered.set(ref, {
213
+ strategyFiltered.set(ref, {
171
214
  ref,
172
215
  reason: "strategy_filtered_all_passes",
173
216
  filePath: indexed.filePath,
@@ -192,7 +235,7 @@ async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, rea
192
235
  return {
193
236
  plannedRefs: [...planned.values()],
194
237
  memorySummary: { eligible: memoryEligible, derived: memoryDerived },
195
- strategyFilteredRefs: [...profileFiltered.values()],
238
+ strategyFilteredRefs: [...strategyFiltered.values()],
196
239
  };
197
240
  }
198
241
  catch (error) {
@@ -255,9 +298,8 @@ export function memoryCleanupParentRef(scope, stashDir) {
255
298
  continue;
256
299
  const raw = fs.readFileSync(candidate, "utf8");
257
300
  const fm = parseFrontmatter(raw).data;
258
- // The `source:` backref (the `derived_from` channel) is read through the
259
- // legacy-tolerant parseMemoryRef, whose NORMALISED output is now the 0.9.0
260
- // `memories/<name>` conceptId (Group-C item 2). That is exactly what
301
+ // The `source:` backref is normalized to the `memories/<name>` conceptId.
302
+ // That is exactly what
261
303
  // analyzeMemoryCleanup's parentRef filter compares against — resolveParentRef
262
304
  // emits the same conceptId — so the two sites stay in lockstep.
263
305
  const parent = parseMemoryRef(typeof fm.source === "string" ? fm.source : undefined);
@@ -290,7 +332,7 @@ export function isLessonCandidate(ref) {
290
332
  * which was true *only* for `lesson:*` refs — exactly the set distill refuses.
291
333
  * The result: every hourly run re-queued the same lesson refs, the same skip
292
334
  * message returned, and no work was ever done. See
293
- * `tests/commands/improve-distill-planner-skip-lessons.test.ts`.
335
+ * `tests/integration/commands/improve-distill-planner-skip-lessons.test.ts`.
294
336
  */
295
337
  export function isDistillCandidateRef(ref, stashDir) {
296
338
  const parsed = parseRefInput(ref);
@@ -333,13 +375,12 @@ export function shouldDistillMemoryRef(ref, stashDir) {
333
375
  * metadata events are ignored so a stray `akm feedback <ref>` invocation
334
376
  * without a flag doesn't trigger downstream re-processing.
335
377
  */
336
- export function buildLatestFeedbackTsMap(refs, sinceIso, sourceName, includeLegacyBare = false, itemRefByRef) {
378
+ export function buildLatestFeedbackTsMap(refs, sinceIso, itemRefByRef) {
337
379
  const out = new Map();
338
380
  if (refs.length === 0)
339
381
  return out;
340
- // Chunk-5 flip F5e — dual-arm on [item_ref, durable, bare] so an item_ref-
341
- // keyed feedback event resolves once the writers emit it. // Chunk-8: [item_ref].
342
- const refByDurableKey = new Map(refs.flatMap((ref) => improveStateReadRefs(ref, sourceName, includeLegacyBare, itemRefByRef?.get(ref)).map((key) => [key, ref])));
382
+ // Correlate item_ref-keyed events and conceptId-keyed direct invocations.
383
+ const refByDurableKey = new Map(refs.flatMap((ref) => improveStateReadRefs(ref, itemRefByRef?.get(ref)).map((key) => [key, ref])));
343
384
  const { events } = readEvents({ type: "feedback", since: sinceIso });
344
385
  for (const e of events) {
345
386
  const ref = e.ref ? refByDurableKey.get(e.ref) : undefined;
@@ -359,18 +400,17 @@ export function buildLatestFeedbackTsMap(refs, sinceIso, sourceName, includeLega
359
400
  * Latest proposal timestamp per input-ref, filtered by source ('reflect' or
360
401
  * 'distill'). Reads the corresponding `*_invoked` events from state.db —
361
402
  * these events are emitted at proposal creation time and carry the *input*
362
- * asset ref (memory:foo, skill:bar, etc.) directly. We use them rather than
403
+ * asset ref (`memories/foo`, `skills/bar`, etc.) directly. We use them rather than
363
404
  * `listProposals` because distill proposals are keyed by the derived
364
405
  * lesson/knowledge ref, not the source memory — joining back through the
365
406
  * payload would be fragile.
366
407
  */
367
- export function buildLatestProposalTsMap(refs, source, sourceName, includeLegacyBare = false, itemRefByRef) {
408
+ export function buildLatestProposalTsMap(refs, source, itemRefByRef) {
368
409
  const out = new Map();
369
410
  if (refs.length === 0)
370
411
  return out;
371
- // Chunk-5 flip F5e — dual-arm on [item_ref, durable, bare] so an item_ref-
372
- // keyed *_invoked event resolves once the writers emit it. // Chunk-8: [item_ref].
373
- const refByDurableKey = new Map(refs.flatMap((ref) => improveStateReadRefs(ref, sourceName, includeLegacyBare, itemRefByRef?.get(ref)).map((key) => [key, ref])));
412
+ // Correlate item_ref-keyed events and conceptId-keyed direct invocations.
413
+ const refByDurableKey = new Map(refs.flatMap((ref) => improveStateReadRefs(ref, itemRefByRef?.get(ref)).map((key) => [key, ref])));
374
414
  const eventType = source === "reflect" ? "reflect_invoked" : "distill_invoked";
375
415
  const { events } = readEvents({ type: eventType });
376
416
  for (const e of events) {
@@ -487,6 +527,6 @@ export async function findAssetFilePath(ref, stashDir, writableDirSet) {
487
527
  writableDirSet,
488
528
  directoryIndexNames: ["SKILL.md"],
489
529
  preserveDirectNameFallback: true,
490
- honorOrigin: false,
530
+ honorOrigin: true,
491
531
  });
492
532
  }
@@ -2,31 +2,30 @@
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
4
  /**
5
- * CLI surface for `akm extract`.
5
+ * CLI surface for `akm proposal extract` (formerly the top-level `akm
6
+ * extract`, moved under the `proposal` group in the 0.9 CLI overhaul, S8 —
7
+ * see src/commands/proposal/proposal-cli.ts for its registration).
6
8
  *
7
9
  * Examples:
8
- * akm extract --type claude-code --session-id <id>
9
- * akm extract --type claude-code --since 24h
10
- * akm extract --type opencode --since 7d --dry-run
11
- * akm extract --auto # iterate all available harnesses
12
- * akm extract --type claude-code --location /custom/path --session-id <id>
10
+ * akm proposal extract --type claude-code --session-id <id>
11
+ * akm proposal extract --type claude-code --since 24h
12
+ * akm proposal extract --type opencode --since 7d --dry-run
13
+ * akm proposal extract --auto # iterate all available harnesses
14
+ * akm proposal extract --type claude-code --location /custom/path --session-id <id>
13
15
  *
14
16
  * Output is the AkmExtractResult JSON envelope (or an aggregated one when
15
17
  * `--auto` runs multiple harnesses).
16
18
  */
17
- import fs from "node:fs";
18
- import path from "node:path";
19
19
  import { getStringArg } from "../../cli/parse-args.js";
20
20
  import { defineJsonCommand, EXIT_CODES, output } from "../../cli/shared.js";
21
21
  import { loadConfig } from "../../core/config/config.js";
22
22
  import { UsageError } from "../../core/errors.js";
23
- import { getAvailableHarnesses, getWatchTargets } from "../../integrations/session-logs/index.js";
24
- import { akmExtract, resolveStandaloneExtractPlan, } from "./extract.js";
25
- import { akmExtractWatch } from "./extract-watch.js";
23
+ import { getAvailableHarnesses } from "../../integrations/session-logs/index.js";
24
+ import { akmExtract, resolveStandaloneExtractPlan } from "./extract.js";
26
25
  export const extractCommand = defineJsonCommand({
27
26
  meta: {
28
27
  name: "extract",
29
- description: "Extract durable insights from native session files (claude-code, opencode) and queue them as proposals. Replaces the legacy session-checkpoint hook.",
28
+ description: "Extract durable insights from native session files (claude-code, opencode) and queue them as proposals.",
30
29
  },
31
30
  args: {
32
31
  type: {
@@ -72,15 +71,6 @@ export const extractCommand = defineJsonCommand({
72
71
  type: "string",
73
72
  description: "Improve strategy supplying extract behavior and engine. Mutually exclusive with --engine.",
74
73
  },
75
- watch: {
76
- type: "boolean",
77
- description: "Watch harness session-log directories and run extract on change (debounced). Stays alive until SIGINT/SIGTERM.",
78
- default: false,
79
- },
80
- "debounce-ms": {
81
- type: "string",
82
- description: "Debounce window in ms for --watch (default 2000).",
83
- },
84
74
  },
85
75
  async run({ args }) {
86
76
  const type = getStringArg(args, "type") ?? "";
@@ -101,17 +91,10 @@ export const extractCommand = defineJsonCommand({
101
91
  if (engine && strategy) {
102
92
  throw new UsageError("--engine and --strategy are mutually exclusive. Pick one.", "INVALID_FLAG_VALUE");
103
93
  }
104
- const watch = args.watch === true;
105
- const debounceMs = typeof args["debounce-ms"] === "string" && args["debounce-ms"] !== ""
106
- ? Number.parseInt(args["debounce-ms"], 10)
107
- : 2000;
108
- if (watch && (!Number.isFinite(debounceMs) || debounceMs <= 0)) {
109
- throw new UsageError(`--debounce-ms must be a positive integer (got "${args["debounce-ms"]}").`, "INVALID_FLAG_VALUE");
110
- }
111
- if (!watch && auto && type) {
94
+ if (auto && type) {
112
95
  throw new UsageError("--auto and --type are mutually exclusive. Pick one.", "INVALID_FLAG_VALUE");
113
96
  }
114
- if (!watch && !auto && !type) {
97
+ if (!auto && !type) {
115
98
  throw new UsageError("--type is required (or pass --auto to try every available harness).", "MISSING_REQUIRED_ARGUMENT");
116
99
  }
117
100
  const config = loadConfig();
@@ -120,10 +103,6 @@ export const extractCommand = defineJsonCommand({
120
103
  ...(strategy ? { strategy } : {}),
121
104
  ...(timeoutMs !== undefined ? { timeoutMs } : {}),
122
105
  });
123
- if (watch) {
124
- await runWatchMode({ debounceMs, dryRun, force, config, resolvedPlan, ...(since ? { since } : {}) });
125
- return;
126
- }
127
106
  const commonOptions = Object.freeze({
128
107
  ...(sessionId ? { sessionId } : {}),
129
108
  ...(location ? { location } : {}),
@@ -164,7 +143,7 @@ export const extractCommand = defineJsonCommand({
164
143
  // Signal failure to callers/schedulers when every harness failed. output()
165
144
  // only renders; without this a scheduled run exits 0 on a total failure
166
145
  // and the breakage is invisible to exit-code monitoring. process.exitCode
167
- // (not process.exit) lets stdout flush and the watcher/timers settle.
146
+ // (not process.exit) lets stdout flush before the process exits.
168
147
  if (!ok)
169
148
  process.exitCode = EXIT_CODES.GENERAL;
170
149
  return;
@@ -175,101 +154,3 @@ export const extractCommand = defineJsonCommand({
175
154
  process.exitCode = EXIT_CODES.GENERAL;
176
155
  },
177
156
  });
178
- /**
179
- * A thin {@link WatchEventSource} over `fs.watch` for each configured root.
180
- * This adapter is the ONLY place a real `fs.watch` is created (the core stays
181
- * injectable + fully unit-tested); it is intentionally not unit-covered.
182
- *
183
- * `fs.watch(dir, { recursive: true })` is unreliable for recursive mode on some
184
- * Node/Bun/Linux combinations. A root that cannot be watched is skipped while
185
- * successfully-created watchers continue running.
186
- */
187
- function createFsWatchEventSource(roots) {
188
- return {
189
- subscribe(listener) {
190
- const watchers = [];
191
- for (const root of roots) {
192
- try {
193
- const watcher = fs.watch(root, { recursive: true }, (_event, filename) => {
194
- if (!filename)
195
- return;
196
- const filePath = path.isAbsolute(filename.toString())
197
- ? filename.toString()
198
- : path.join(root, filename.toString());
199
- listener({ path: filePath });
200
- });
201
- watchers.push(watcher);
202
- }
203
- catch {
204
- // A root that can't be watched is skipped.
205
- }
206
- }
207
- return () => {
208
- for (const w of watchers) {
209
- try {
210
- w.close();
211
- }
212
- catch {
213
- // best-effort teardown
214
- }
215
- }
216
- };
217
- },
218
- };
219
- }
220
- /** Snapshot the CLI-resolved watch options once and reuse them for every debounced trigger. */
221
- export function createExtractWatchTrigger(options, extractFn = akmExtract) {
222
- const snapshot = Object.freeze({ ...options });
223
- return async (harnessName) => {
224
- await extractFn({ type: harnessName, ...snapshot });
225
- };
226
- }
227
- /**
228
- * Run `akm extract --watch`: watch every available harness's session-log
229
- * roots and run extract (debounced, per-harness) on change. Stays alive until
230
- * SIGINT/SIGTERM, then stops cleanly. PROCESS-HYGIENE: stop() removes every
231
- * watcher + pending timer before the process exits.
232
- */
233
- async function runWatchMode(opts) {
234
- const targets = getWatchTargets();
235
- if (targets.length === 0) {
236
- output("extract", {
237
- schemaVersion: 1,
238
- ok: false,
239
- shape: "extract-watch-started",
240
- warnings: ["no watchable harness session-log directories found on this machine"],
241
- watching: [],
242
- });
243
- return;
244
- }
245
- const allRoots = targets.flatMap((t) => t.roots);
246
- const eventSource = createFsWatchEventSource(allRoots);
247
- const onTrigger = createExtractWatchTrigger({
248
- dryRun: opts.dryRun,
249
- force: opts.force,
250
- config: opts.config,
251
- resolvedPlan: opts.resolvedPlan,
252
- ...(opts.since ? { since: opts.since } : {}),
253
- });
254
- const handle = akmExtractWatch({
255
- roots: targets,
256
- eventSource,
257
- debounceMs: opts.debounceMs,
258
- onTrigger,
259
- });
260
- output("extract", {
261
- schemaVersion: 1,
262
- ok: true,
263
- shape: "extract-watch-started",
264
- debounceMs: opts.debounceMs,
265
- watching: allRoots,
266
- });
267
- await new Promise((resolve) => {
268
- const shutdown = () => {
269
- handle.stop();
270
- resolve();
271
- };
272
- process.once("SIGINT", shutdown);
273
- process.once("SIGTERM", shutdown);
274
- });
275
- }