akm-cli 0.9.0-rc.8 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (450) hide show
  1. package/CHANGELOG.md +1063 -44
  2. package/README.md +51 -25
  3. package/SECURITY.md +14 -1
  4. package/STABILITY.md +497 -0
  5. package/dist/akm +148 -35
  6. package/dist/{akm-migrate-storage → akm-migrate} +6 -9
  7. package/dist/assets/hints/cli-hints-full.md +223 -95
  8. package/dist/assets/hints/cli-hints-short.md +85 -22
  9. package/dist/assets/improve-strategies/default.json +1 -1
  10. package/dist/assets/improve-strategies/reflect-distill.json +1 -1
  11. package/dist/assets/prompts/memory-infer-user.md +2 -3
  12. package/dist/assets/stash-skeleton/README.md +6 -5
  13. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +2 -0
  14. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +2 -0
  15. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +2 -0
  16. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +2 -0
  17. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +2 -0
  18. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +2 -0
  19. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +2 -0
  20. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +2 -0
  21. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +2 -0
  22. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +2 -0
  23. package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -0
  24. package/dist/assets/stash-skeleton/facts/conventions/organization.md +20 -9
  25. package/dist/assets/tasks/core/extract.yml +1 -1
  26. package/dist/assets/tasks/core/version-check.yml +1 -1
  27. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
  28. package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
  29. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
  30. package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
  31. package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
  32. package/dist/assets/templates/html/health.html +1 -3
  33. package/dist/assets/workflows/workflow-template.md +32 -15
  34. package/dist/cli/invocation.js +40 -15
  35. package/dist/cli/parse-args.js +0 -22
  36. package/dist/cli/retired-commands.js +121 -0
  37. package/dist/cli/shared.js +154 -22
  38. package/dist/cli/unknown-flags.js +236 -0
  39. package/dist/cli-node.mjs +2 -1
  40. package/dist/cli.js +696 -258
  41. package/dist/commands/agent/agent-dispatch.js +14 -3
  42. package/dist/commands/agent/contribute-cli.js +73 -88
  43. package/dist/commands/completions.js +79 -22
  44. package/dist/commands/config-cli.js +17 -150
  45. package/dist/commands/env/env-cli.js +59 -143
  46. package/dist/commands/env/env.js +12 -163
  47. package/dist/commands/env/marker-path.js +6 -0
  48. package/dist/commands/env/secret-cli.js +36 -66
  49. package/dist/commands/env/secret.js +24 -57
  50. package/dist/commands/feedback-cli.js +141 -87
  51. package/dist/commands/health/accept-rate.js +58 -0
  52. package/dist/commands/health/advisories.js +3 -4
  53. package/dist/commands/health/checks.js +85 -23
  54. package/dist/commands/health/html-report.js +7 -10
  55. package/dist/commands/health/improve-metrics.js +25 -83
  56. package/dist/commands/health/md-report.js +5 -9
  57. package/dist/commands/health/metrics.js +62 -20
  58. package/dist/commands/health/renderers.js +47 -0
  59. package/dist/commands/health/report-view-model.js +4 -5
  60. package/dist/commands/health/stash-exposure.js +1 -1
  61. package/dist/commands/health/surfaces.js +3 -48
  62. package/dist/commands/health/task-runs.js +3 -67
  63. package/dist/commands/health/types-improve.js +7 -0
  64. package/dist/commands/health.js +99 -28
  65. package/dist/commands/improve/anti-collapse.js +2 -2
  66. package/dist/commands/improve/autonomy-gate.js +68 -0
  67. package/dist/commands/improve/collapse-detector.js +41 -40
  68. package/dist/commands/improve/consolidate/eligibility.js +1 -23
  69. package/dist/commands/improve/consolidate/merge.js +4 -0
  70. package/dist/commands/improve/consolidate.js +140 -1000
  71. package/dist/commands/improve/distill/promote-memory.js +12 -12
  72. package/dist/commands/improve/distill/quality-gate.js +6 -6
  73. package/dist/commands/improve/distill.js +58 -69
  74. package/dist/commands/improve/eligibility.js +105 -57
  75. package/dist/commands/improve/extract-cli.js +14 -133
  76. package/dist/commands/improve/improve-cli.js +98 -114
  77. package/dist/commands/improve/improve-result-file.js +1 -28
  78. package/dist/commands/improve/improve-strategies.js +8 -5
  79. package/dist/commands/improve/improve.js +128 -91
  80. package/dist/commands/improve/loop-stages.js +182 -20
  81. package/dist/commands/improve/memory/derived-ref.js +45 -43
  82. package/dist/commands/improve/memory/memory-belief.js +1 -1
  83. package/dist/commands/improve/memory/memory-contradiction-detect.js +4 -12
  84. package/dist/commands/improve/memory/memory-improve.js +6 -5
  85. package/dist/commands/improve/outcome-loop.js +22 -65
  86. package/dist/commands/improve/preparation.js +114 -123
  87. package/dist/commands/improve/proactive-maintenance.js +2 -5
  88. package/dist/commands/improve/reflect.js +56 -160
  89. package/dist/commands/improve/salience.js +11 -122
  90. package/dist/commands/improve/source-identity.js +10 -38
  91. package/dist/commands/lint/base-linter.js +20 -124
  92. package/dist/commands/lint/env-key-rules.js +31 -47
  93. package/dist/commands/lint/index.js +249 -43
  94. package/dist/commands/{events.js → log.js} +33 -38
  95. package/dist/commands/migrate-cli.js +92 -12
  96. package/dist/commands/migration-tool.js +46 -0
  97. package/dist/commands/observability-cli.js +70 -209
  98. package/dist/commands/proposal/drain.js +101 -29
  99. package/dist/commands/proposal/proposal-cli.js +76 -48
  100. package/dist/commands/proposal/proposal.js +54 -18
  101. package/dist/commands/proposal/propose-cli.js +88 -0
  102. package/dist/commands/proposal/propose.js +23 -15
  103. package/dist/commands/proposal/repository.js +701 -278
  104. package/dist/commands/proposal/validators/proposal-quality-validators.js +2 -8
  105. package/dist/commands/proposal/validators/proposal-validators.js +55 -7
  106. package/dist/commands/proposal/validators/proposals.js +4 -7
  107. package/dist/commands/read/curate.js +34 -53
  108. package/dist/commands/read/knowledge.js +150 -95
  109. package/dist/commands/read/registry-search.js +2 -2
  110. package/dist/commands/read/remember-cli.js +42 -15
  111. package/dist/commands/read/search-cli.js +180 -78
  112. package/dist/commands/read/search.js +58 -43
  113. package/dist/commands/read/show.js +197 -141
  114. package/dist/commands/registry-cli.js +12 -51
  115. package/dist/commands/remember.js +14 -57
  116. package/dist/commands/sources/add-cli.js +100 -31
  117. package/dist/commands/sources/bundle-cli.js +166 -0
  118. package/dist/commands/sources/bundle-config-ops.js +7 -2
  119. package/dist/commands/sources/info.js +18 -5
  120. package/dist/commands/sources/init.js +12 -12
  121. package/dist/commands/sources/installed-stashes.js +382 -98
  122. package/dist/commands/sources/schema-repair.js +3 -2
  123. package/dist/commands/sources/self-update.js +131 -38
  124. package/dist/commands/sources/source-add.js +72 -17
  125. package/dist/commands/sources/source-clone.js +129 -45
  126. package/dist/commands/sources/source-manage.js +43 -23
  127. package/dist/commands/sources/sources-cli.js +57 -208
  128. package/dist/commands/sources/stash-cli.js +46 -53
  129. package/dist/commands/tasks/tasks-cli.js +91 -97
  130. package/dist/commands/tasks/tasks.js +276 -421
  131. package/dist/commands/workflow-cli.js +175 -450
  132. package/dist/core/adapter/adapters/akm-adapter.js +47 -28
  133. package/dist/core/adapter/adapters/akm-lint.js +42 -27
  134. package/dist/core/adapter/adapters/akm-metadata.js +15 -44
  135. package/dist/core/adapter/adapters/akm-task-adapter.js +15 -13
  136. package/dist/core/adapter/adapters/akm-workflow-adapter.js +55 -71
  137. package/dist/core/adapter/adapters/dotenv-adapter.js +1 -1
  138. package/dist/core/adapter/adapters/generic-files-adapter.js +2 -0
  139. package/dist/core/adapter/adapters/index.js +6 -6
  140. package/dist/core/adapter/adapters/llm-wiki-adapter.js +14 -8
  141. package/dist/core/adapter/adapters/okf-adapter.js +187 -19
  142. package/dist/core/adapter/adapters/shared.js +3 -19
  143. package/dist/core/adapter/adapters/tool-dir-shared.js +8 -3
  144. package/dist/core/adapter/adapters/website-snapshot-adapter.js +1 -0
  145. package/dist/core/adapter/detect-adapter.js +17 -0
  146. package/dist/core/adapter/recognize-match.js +6 -4
  147. package/dist/core/adapter/validate-context.js +214 -0
  148. package/dist/core/asset/akm-markdown.js +63 -0
  149. package/dist/core/asset/asset-placement.js +20 -6
  150. package/dist/core/asset/asset-ref.js +11 -9
  151. package/dist/core/asset/frontmatter-lint.js +30 -0
  152. package/dist/core/asset/frontmatter.js +37 -9
  153. package/dist/core/asset/markdown.js +40 -51
  154. package/dist/core/asset/resolve-ref.js +89 -18
  155. package/dist/core/asset/stash-meta.js +1 -1
  156. package/dist/core/bundle-id.js +51 -0
  157. package/dist/core/common.js +152 -38
  158. package/dist/core/config/config-io.js +12 -1
  159. package/dist/core/config/config-schema.js +35 -8
  160. package/dist/core/config/config-sources.js +55 -11
  161. package/dist/core/config/config-walker.js +25 -9
  162. package/dist/core/config/config.js +9 -48
  163. package/dist/core/config/experimental.js +21 -0
  164. package/dist/core/config/schema/embedding.js +5 -1
  165. package/dist/core/config/schema/experimental.js +30 -0
  166. package/dist/core/config/schema/improve-processes.js +0 -6
  167. package/dist/core/config/schema/improve.js +21 -3
  168. package/dist/core/config/schema/index-config.js +8 -15
  169. package/dist/core/config/schema/output.js +4 -1
  170. package/dist/core/config/schema/setup.js +9 -18
  171. package/dist/core/config/schema/sources-bundles.js +49 -33
  172. package/dist/core/config/schema/workflow.js +3 -3
  173. package/dist/core/env-secret-ref.js +76 -46
  174. package/dist/core/errors.js +18 -12
  175. package/dist/core/events.js +46 -128
  176. package/dist/core/file-change.js +6 -5
  177. package/dist/core/fs-txn.js +83 -7
  178. package/dist/core/git-message.js +2 -2
  179. package/dist/core/improve-result.js +1 -100
  180. package/dist/core/lesson-lint.js +1 -17
  181. package/dist/core/logs-db.js +2 -1
  182. package/dist/core/migration-operation.js +16 -0
  183. package/dist/core/mutation-target.js +78 -0
  184. package/dist/core/parse.js +4 -1
  185. package/dist/core/paths.js +17 -20
  186. package/dist/core/recognition-util.js +12 -14
  187. package/dist/core/redaction.js +34 -0
  188. package/dist/core/standards/resolve-standards-context.js +2 -14
  189. package/dist/core/standards/resolve-stash-standards.js +2 -2
  190. package/dist/core/standards/resolve-type-conventions.js +2 -2
  191. package/dist/core/state/migrations.js +41 -18
  192. package/dist/core/state-db.js +5 -14
  193. package/dist/core/structured.js +1 -1
  194. package/dist/core/subprocess.js +6 -4
  195. package/dist/core/text-truncation.js +9 -5
  196. package/dist/core/type-presentation.js +3 -3
  197. package/dist/core/warn.js +0 -3
  198. package/dist/core/write-source.js +771 -95
  199. package/dist/indexer/bundle-identity-guard.js +3 -2
  200. package/dist/indexer/db/graph-db.js +0 -24
  201. package/dist/indexer/ensure-index.js +1 -0
  202. package/dist/indexer/graph/graph-boost.js +9 -34
  203. package/dist/indexer/graph/graph-extraction.js +8 -5
  204. package/dist/indexer/index-writer-lock.js +53 -17
  205. package/dist/indexer/index-written-assets.js +16 -22
  206. package/dist/indexer/indexer.js +497 -239
  207. package/dist/indexer/installations.js +14 -96
  208. package/dist/indexer/passes/dir-staleness.js +16 -9
  209. package/dist/indexer/passes/memory-inference.js +11 -9
  210. package/dist/indexer/passes/metadata.js +113 -47
  211. package/dist/indexer/scan/doc-to-entry.js +38 -1
  212. package/dist/indexer/scan/drain-dir.js +13 -23
  213. package/dist/indexer/search/db-search.js +99 -54
  214. package/dist/indexer/search/fts-query.js +47 -24
  215. package/dist/indexer/search/ranking-contributors.js +42 -20
  216. package/dist/indexer/search/ranking.js +18 -99
  217. package/dist/indexer/search/search-fields.js +7 -2
  218. package/dist/indexer/search/search-source.js +82 -93
  219. package/dist/indexer/usage/usage-events.js +0 -89
  220. package/dist/indexer/walk/file-context.js +2 -1
  221. package/dist/indexer/walk/matchers.js +30 -43
  222. package/dist/indexer/walk/path-resolver.js +7 -2
  223. package/dist/indexer/walk/walker.js +38 -12
  224. package/dist/integrations/agent/builders.js +0 -6
  225. package/dist/integrations/agent/config.js +2 -2
  226. package/dist/integrations/agent/detect.js +49 -19
  227. package/dist/integrations/agent/engine-fallback.js +76 -0
  228. package/dist/integrations/agent/profiles.js +14 -0
  229. package/dist/integrations/agent/prompts.js +12 -8
  230. package/dist/integrations/agent/runner-dispatch.js +4 -2
  231. package/dist/integrations/agent/runner.js +0 -1
  232. package/dist/integrations/agent/spawn.js +5 -6
  233. package/dist/integrations/github.js +1 -1
  234. package/dist/integrations/harnesses/aider/agent-builder.js +6 -4
  235. package/dist/integrations/harnesses/amazonq/agent-builder.js +7 -4
  236. package/dist/integrations/harnesses/claude/session-log.js +0 -10
  237. package/dist/integrations/harnesses/codex/agent-builder.js +5 -2
  238. package/dist/integrations/harnesses/copilot/agent-builder.js +5 -3
  239. package/dist/integrations/harnesses/gemini/agent-builder.js +5 -3
  240. package/dist/integrations/harnesses/index.js +3 -7
  241. package/dist/integrations/harnesses/opencode/agent-builder.js +21 -2
  242. package/dist/integrations/harnesses/opencode/session-log.js +0 -15
  243. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +13 -4
  244. package/dist/integrations/harnesses/openhands/agent-builder.js +9 -6
  245. package/dist/integrations/harnesses/pi/agent-builder.js +6 -4
  246. package/dist/integrations/lockfile.js +101 -6
  247. package/dist/integrations/session-logs/index.js +3 -28
  248. package/dist/llm/client.js +136 -100
  249. package/dist/llm/embedders/remote.js +13 -5
  250. package/dist/llm/feature-gate.js +4 -12
  251. package/dist/llm/graph-extract.js +5 -11
  252. package/dist/llm/memory-infer.js +144 -1
  253. package/dist/llm/metadata-enhance.js +5 -7
  254. package/dist/llm/structured-call.js +1 -1
  255. package/dist/llm/usage-persist.js +26 -5
  256. package/dist/llm/usage-telemetry.js +25 -2
  257. package/dist/output/cli-hints.js +1 -2
  258. package/dist/output/context.js +22 -7
  259. package/dist/output/format-exempt.js +80 -0
  260. package/dist/output/generic-render.js +259 -0
  261. package/dist/output/render-registry.js +57 -0
  262. package/dist/output/renderers.js +14 -36
  263. package/dist/output/shapes/curate.js +10 -1
  264. package/dist/output/shapes/events.js +12 -7
  265. package/dist/output/shapes/helpers.js +56 -83
  266. package/dist/output/shapes/migrate.js +8 -0
  267. package/dist/output/shapes/passthrough.js +7 -41
  268. package/dist/output/shapes/proposal/producer.js +15 -7
  269. package/dist/output/shapes.js +2 -9
  270. package/dist/output/text/{init.js → bundle-create.js} +3 -1
  271. package/dist/output/text/bundle-show.js +7 -0
  272. package/dist/output/text/command-format.js +164 -96
  273. package/dist/output/text/env.js +1 -3
  274. package/dist/output/text/events.js +8 -7
  275. package/dist/output/text/health-format.js +103 -0
  276. package/dist/output/text/health.js +7 -0
  277. package/dist/output/text/helpers.js +10 -8
  278. package/dist/output/text/lint-format.js +43 -0
  279. package/dist/output/text/{save.js → lint.js} +2 -2
  280. package/dist/output/text/migrate.js +88 -0
  281. package/dist/output/text/proposal/producer.js +4 -2
  282. package/dist/output/text/proposal-format.js +44 -72
  283. package/dist/output/text/registry-commands.js +1 -2
  284. package/dist/output/text/show-directives.js +15 -7
  285. package/dist/output/text/status-list.js +32 -0
  286. package/dist/output/text/sync.js +5 -0
  287. package/dist/output/text/workflow-format.js +24 -203
  288. package/dist/output/text/workflow.js +1 -7
  289. package/dist/output/text.js +16 -17
  290. package/dist/registry/factory.js +4 -6
  291. package/dist/registry/origin-resolve.js +16 -27
  292. package/dist/registry/providers/skills-sh.js +3 -3
  293. package/dist/registry/providers/static-index.js +13 -23
  294. package/dist/registry/resolve.js +42 -7
  295. package/dist/registry/semver.js +34 -84
  296. package/dist/runtime.js +2 -23
  297. package/dist/scripts/akm-migrate-node.js +60290 -0
  298. package/dist/scripts/akm-migrate.js +59628 -0
  299. package/dist/setup/detect.js +42 -15
  300. package/dist/setup/registry-stash-loader.js +2 -2
  301. package/dist/setup/setup.js +236 -136
  302. package/dist/setup/steps/connection.js +7 -9
  303. package/dist/setup/steps/platforms.js +9 -9
  304. package/dist/setup/steps/semantic.js +15 -3
  305. package/dist/setup/steps/sources.js +12 -13
  306. package/dist/setup/steps/stashdir.js +2 -3
  307. package/dist/setup/steps/tasks.js +237 -120
  308. package/dist/sources/freshness.js +1 -1
  309. package/dist/sources/provider-factory.js +11 -17
  310. package/dist/sources/providers/filesystem.js +2 -3
  311. package/dist/sources/providers/git-install.js +278 -34
  312. package/dist/sources/providers/git-provider.js +25 -23
  313. package/dist/sources/providers/git-stash.js +395 -106
  314. package/dist/sources/providers/git.js +2 -2
  315. package/dist/sources/providers/npm.js +16 -19
  316. package/dist/sources/providers/provider-utils.js +7 -4
  317. package/dist/sources/providers/sync-from-ref.js +3 -9
  318. package/dist/sources/providers/website.js +6 -1
  319. package/dist/sources/resolve.js +6 -5
  320. package/dist/sources/snapshot-fetchers/bluesky.js +146 -0
  321. package/dist/sources/snapshot-fetchers/content-extract.js +566 -0
  322. package/dist/sources/snapshot-fetchers/fetcher-util.js +41 -0
  323. package/dist/sources/snapshot-fetchers/github.js +100 -0
  324. package/dist/sources/snapshot-fetchers/host-guard.js +291 -0
  325. package/dist/sources/snapshot-fetchers/registry.js +17 -1
  326. package/dist/sources/snapshot-fetchers/robots.js +348 -0
  327. package/dist/sources/snapshot-fetchers/rss.js +282 -0
  328. package/dist/sources/snapshot-fetchers/secret-seam.js +42 -0
  329. package/dist/sources/snapshot-fetchers/website-ingest.js +566 -268
  330. package/dist/sources/snapshot-fetchers/x.js +910 -0
  331. package/dist/storage/database.js +7 -0
  332. package/dist/storage/engines/sqlite-migrations.js +23 -111
  333. package/dist/storage/managed-db.js +2 -2
  334. package/dist/storage/repositories/canaries-repository.js +1 -1
  335. package/dist/storage/repositories/events-repository.js +27 -11
  336. package/dist/storage/repositories/improve-runs-repository.js +6 -12
  337. package/dist/storage/repositories/index-connection.js +17 -6
  338. package/dist/storage/repositories/index-entries-repository.js +151 -240
  339. package/dist/storage/repositories/index-entry-mapper.js +15 -11
  340. package/dist/storage/repositories/index-fts-repository.js +5 -2
  341. package/dist/storage/repositories/index-llm-cache-repository.js +0 -1
  342. package/dist/storage/repositories/index-meta-repository.js +2 -3
  343. package/dist/storage/repositories/index-schema.js +10 -25
  344. package/dist/storage/repositories/index-utility-repository.js +15 -28
  345. package/dist/storage/repositories/index-vec-repository.js +6 -1
  346. package/dist/storage/repositories/outcome-repository.js +119 -0
  347. package/dist/storage/repositories/proposals-repository.js +296 -59
  348. package/dist/storage/repositories/registry-cache.js +19 -0
  349. package/dist/storage/repositories/salience-repository.js +172 -0
  350. package/dist/storage/repositories/task-history-repository.js +15 -13
  351. package/dist/storage/repositories/workflow-runs-repository.js +52 -40
  352. package/dist/tasks/backends/cron.js +105 -15
  353. package/dist/tasks/backends/index.js +1 -1
  354. package/dist/tasks/backends/launchd.js +85 -38
  355. package/dist/tasks/backends/schtasks.js +135 -15
  356. package/dist/tasks/embedded.js +56 -40
  357. package/dist/tasks/parser.js +7 -157
  358. package/dist/tasks/resolve-akm-bin.js +137 -59
  359. package/dist/tasks/runner.js +79 -42
  360. package/dist/tasks/scheduler-invocation.js +220 -10
  361. package/dist/tasks/schema.js +24 -1
  362. package/dist/tasks/task-id.js +1 -3
  363. package/dist/tasks/validator.js +20 -6
  364. package/dist/workflows/authoring/authoring.js +94 -143
  365. package/dist/workflows/authoring/scope-key.js +1 -1
  366. package/dist/workflows/exec/frozen-judge.js +28 -2
  367. package/dist/workflows/exec/native-executor.js +77 -57
  368. package/dist/workflows/exec/param-secrets.js +9 -9
  369. package/dist/workflows/exec/run-workflow.js +133 -79
  370. package/dist/workflows/exec/step-work.js +219 -346
  371. package/dist/{migrate-storage-node.mjs → workflows/exec/unit-dispatch.js} +1 -5
  372. package/dist/workflows/ir/compile.js +141 -270
  373. package/dist/workflows/ir/freeze.js +40 -30
  374. package/dist/workflows/ir/params.js +135 -11
  375. package/dist/workflows/ir/plan-hash.js +1 -1
  376. package/dist/workflows/ir/schema.js +25 -26
  377. package/dist/workflows/parser.js +872 -307
  378. package/dist/workflows/program/expressions.js +20 -208
  379. package/dist/workflows/program/schema.js +7 -10
  380. package/dist/workflows/renderer.js +95 -68
  381. package/dist/workflows/resource-limits.js +2 -0
  382. package/dist/workflows/runtime/checkin.js +3 -3
  383. package/dist/workflows/runtime/plan-classifier.js +16 -75
  384. package/dist/workflows/runtime/runs.js +186 -127
  385. package/dist/workflows/runtime/unit-checkin.js +1 -1
  386. package/dist/workflows/runtime/unit-phases.js +2 -2
  387. package/dist/workflows/runtime/workflow-asset-loader.js +232 -83
  388. package/dist/workflows/schema.js +1 -11
  389. package/dist/workflows/validate-summary.js +30 -36
  390. package/dist/workflows/validator.js +21 -62
  391. package/docs/README.md +68 -0
  392. package/docs/migration/README.md +8 -0
  393. package/docs/migration/release-notes/0.7.0.md +11 -11
  394. package/docs/migration/release-notes/0.9.0.md +208 -27
  395. package/docs/migration/v0.7-to-v0.8.md +46 -47
  396. package/docs/migration/v0.8-to-v0.9.md +564 -208
  397. package/docs/migration/v0.9.0-troubleshooting.md +561 -0
  398. package/docs/reference/README.md +12 -0
  399. package/docs/reference/cli.md +2253 -0
  400. package/docs/reference/configuration.md +358 -0
  401. package/docs/reference/data-and-telemetry.md +105 -42
  402. package/docs/reference/workflows.md +647 -0
  403. package/package.json +22 -11
  404. package/schemas/akm-asset-envelope.json +93 -0
  405. package/schemas/akm-config.json +81 -128
  406. package/schemas/akm-workflow.json +74 -73
  407. package/dist/assets/tasks/core/backup.yml +0 -5
  408. package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
  409. package/dist/cli/config-migrate.js +0 -1806
  410. package/dist/cli/config-validate.js +0 -41
  411. package/dist/commands/backup-cli.js +0 -56
  412. package/dist/commands/bundle/bundle-cli.js +0 -68
  413. package/dist/commands/bundle/bundle.js +0 -219
  414. package/dist/commands/graph/graph-cli.js +0 -124
  415. package/dist/commands/graph/graph.js +0 -489
  416. package/dist/commands/improve/extract-watch.js +0 -140
  417. package/dist/commands/mv-cli.js +0 -1221
  418. package/dist/commands/sources/history.js +0 -201
  419. package/dist/commands/tasks/default-tasks.js +0 -186
  420. package/dist/core/migration-backup.js +0 -1234
  421. package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -95
  422. package/dist/llm/memory-infer-impl.js +0 -138
  423. package/dist/migrate/legacy/config-source-migration.js +0 -223
  424. package/dist/migrate/legacy/content-migration.js +0 -305
  425. package/dist/migrate/legacy/legacy-layout.js +0 -779
  426. package/dist/migrate/legacy/legacy-paths.js +0 -25
  427. package/dist/migrate/legacy/legacy-stash-json.js +0 -72
  428. package/dist/migrate/legacy/proposal-fs-import.js +0 -168
  429. package/dist/migrate/legacy/task-target-ref-migration.js +0 -272
  430. package/dist/migrate/legacy/three-db-cutover.js +0 -841
  431. package/dist/migrate/legacy/workflow-migrations-bodies.js +0 -52
  432. package/dist/migrate/legacy/workflow-migrations-frozen.js +0 -21
  433. package/dist/migrate/legacy-ref-grammar.js +0 -214
  434. package/dist/output/shapes/distill.js +0 -14
  435. package/dist/output/shapes/history.js +0 -11
  436. package/dist/output/text/distill.js +0 -6
  437. package/dist/output/text/enable-disable.js +0 -8
  438. package/dist/output/text/history.js +0 -6
  439. package/dist/registry/build-index.js +0 -382
  440. package/dist/schemas/akm-config.json +0 -4704
  441. package/dist/schemas/akm-task.json +0 -87
  442. package/dist/schemas/akm-workflow.json +0 -372
  443. package/dist/scripts/migrate-storage.js +0 -3816
  444. package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
  445. package/dist/workflows/cli.js +0 -53
  446. package/dist/workflows/exec/brief.js +0 -481
  447. package/dist/workflows/exec/report.js +0 -1460
  448. package/dist/workflows/exec/watch.js +0 -116
  449. package/dist/workflows/program/parser.js +0 -813
  450. package/dist/workflows/program/project.js +0 -104
@@ -1,25 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- /**
5
- * @removeIn 0.10.0
6
- *
7
- * Legacy on-disk path helpers for the three-DB cutover. akm 0.9.0 chunk-8,
8
- * WI-8.3.
9
- *
10
- * The runtime `getWorkflowDbPath` core helper is DELETED in WI-8.3 (the runtime
11
- * no longer opens workflow.db — its durable rows live in state.db post-cutover).
12
- * But the migrator home (`src/migrate/legacy/`), the backup/restore machinery
13
- * (`src/core/migration-backup.ts` — backup artifacts + the pre-cutover ledger
14
- * probe) and config-migrate.ts's backward-looking arms still need the physical
15
- * `<dataDir>/workflow.db` path literal to FIND, roll, merge, back up, and delete
16
- * a pre-cutover workflow.db. This module is that path literal's only surviving
17
- * home in live code, quarantined under the migrator directory so the deleted
18
- * core helper cannot re-appear under another name in live core.
19
- */
20
- import path from "node:path";
21
- import { getDataDir } from "../../core/paths.js";
22
- /** Physical path of a pre-cutover workflow.db (`<dataDir>/workflow.db`). */
23
- export function getLegacyWorkflowDbPath() {
24
- return path.join(getDataDir(), "workflow.db");
25
- }
@@ -1,72 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- /**
5
- * Legacy `.stash.json` sidecar read/write — the pre-0.9.0 per-directory metadata
6
- * layout. This is 0.8-compat behavior that real stashes still depend on: the
7
- * indexer merges a directory's sidecar overrides onto the freshly-recognized
8
- * entries so curated metadata (captured openings, quality, descriptions) is not
9
- * lost on re-index.
10
- *
11
- * MIGRATOR-OWNED HOME (akm 0.9.0 Chunk-5 flip, scope-B ruling; relocated to
12
- * `src/migrate/legacy/` in Chunk-8 WI-8.5d): the sidecar layout is a pre-0.9
13
- * on-disk shape, so its reader/writer live under the frozen migrator home
14
- * alongside the other legacy-layout code rather than in the live indexer passes.
15
- * After WI-8.5d the live indexer no longer reads the sidecar — the only reader is
16
- * the `content-migration.ts` migrator step (folds the sidecar into per-file
17
- * frontmatter, then deletes it), so this module is now migrator-only.
18
- *
19
- * The `StashFile` container type and the per-entry `validateStashEntry` gate stay
20
- * in `indexer/passes/metadata.ts` (they are the live in-memory metadata shape and
21
- * the shared validator); this module imports them.
22
- */
23
- import fs from "node:fs";
24
- import path from "node:path";
25
- import { writeFileAtomic } from "../../core/common.js";
26
- import { warn } from "../../core/warn.js";
27
- import { validateStashEntry } from "../../indexer/passes/metadata.js";
28
- /** The pre-0.9.0 per-directory metadata sidecar filename. */
29
- const LEGACY_STASH_FILENAME = ".stash.json";
30
- /** Absolute path of a directory's legacy metadata sidecar. */
31
- export function legacyStashFilePath(dirPath) {
32
- return path.join(dirPath, LEGACY_STASH_FILENAME);
33
- }
34
- /**
35
- * Read a directory's legacy metadata sidecar and return its validated entries,
36
- * or `null` when absent/empty/corrupt. Was `loadStashFile` in `metadata.ts`;
37
- * relocated verbatim to the migrator home (scope-B ruling) — behavior unchanged.
38
- */
39
- export function readLegacyStashOverrides(dirPath, options) {
40
- const filePath = legacyStashFilePath(dirPath);
41
- if (!fs.existsSync(filePath))
42
- return null;
43
- try {
44
- const raw = JSON.parse(fs.readFileSync(filePath, "utf8"));
45
- if (!raw || !Array.isArray(raw.entries))
46
- return null;
47
- const entries = [];
48
- for (const e of raw.entries) {
49
- const validated = validateStashEntry(e);
50
- if (validated) {
51
- if (options?.requireFilename && !validated.filename)
52
- continue;
53
- entries.push(validated);
54
- }
55
- else {
56
- const name = typeof e === "object" && e !== null && typeof e.name === "string"
57
- ? e.name
58
- : "(unknown)";
59
- warn(`Warning: Skipping invalid entry "${name}" in ${filePath}`);
60
- }
61
- }
62
- return entries.length > 0 ? { entries } : null;
63
- }
64
- catch {
65
- return null;
66
- }
67
- }
68
- /** Write a legacy metadata sidecar (test/migrator fixtures). Was `writeStashFile`. */
69
- export function writeLegacyStashFile(dirPath, stash) {
70
- const filePath = legacyStashFilePath(dirPath);
71
- writeFileAtomic(filePath, `${JSON.stringify(stash, null, 2)}\n`);
72
- }
@@ -1,168 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- /**
5
- * @removeIn 0.10.0
6
- *
7
- * One-time import of pre-0.9.0 filesystem proposals into the migrated state.db
8
- * `proposals` table (akm 0.9.0 Chunk-5 fold, completed in Chunk-8; plan §3.4).
9
- *
10
- * Before 0.9.0 the proposal queue lived as per-uuid JSON directories under
11
- * `<stashDir>/.akm/proposals/` (live) and `…/proposals/archive/` (archived).
12
- * This fold USED to run on EVERY proposal operation (through
13
- * `withProposalsDb`, guarded by a `proposal_fs_imports` ledger). That disk
14
- * probe is gone from the live path: the import now runs ONCE, as an ADDITIVE
15
- * filesystem step of `akm migrate apply`'s `cutover-applied` phase — a sibling
16
- * of the `.stash.json`/D-R6 content migration — AFTER the committed state txn,
17
- * best-effort (a throw is swallowed + logged by the caller, never aborting a
18
- * committed cutover) and idempotent.
19
- *
20
- * Idempotency without the old ledger: each row lands through
21
- * {@link insertProposalIfAbsent} (INSERT OR IGNORE keyed on the proposal UUID),
22
- * so re-walking the still-on-disk legacy files on a resumed or re-run apply
23
- * inserts nothing new and never duplicates. The legacy files are never modified
24
- * or deleted — after import they are inert artifacts the operator can remove at
25
- * leisure. Legacy `backup.<ext>` files are inlined into `backupContent` so
26
- * `akm proposal revert` keeps working for proposals accepted before 0.9.0.
27
- *
28
- * The parsing/backup-inlining logic below is FROZEN pre-0.9.0 behavior, moved
29
- * verbatim from the deleted `src/commands/proposal/legacy-import.ts`.
30
- *
31
- * Migrator-only: opens state.db through the raw storage engine (leaving its
32
- * journal mode untouched — the apply has already collapsed it to single-file
33
- * DELETE mode) and never sits on a live indexer or command path.
34
- */
35
- import fs from "node:fs";
36
- import path from "node:path";
37
- import { warn } from "../../core/warn.js";
38
- import { openDatabase } from "../../storage/database.js";
39
- import { insertProposalIfAbsent } from "../../storage/repositories/proposals-repository.js";
40
- /** Legacy (pre-0.9.0) proposal directory: `<stashDir>/.akm/proposals[/archive]`. */
41
- function legacyProposalsRoot(stashDir, archive) {
42
- const root = path.join(stashDir, ".akm", "proposals");
43
- return archive ? path.join(root, "archive") : root;
44
- }
45
- /**
46
- * Import every stash root's legacy `proposal.json` files into the state.db at
47
- * `stateDbPath`. Returns the total number of rows actually inserted (a re-run
48
- * over the same roots returns 0 — every UUID is already present). Best-effort:
49
- * a per-root or per-file failure is logged and skipped, and a failure to open
50
- * state.db at all returns 0 rather than throwing (the committed cutover is
51
- * unaffected).
52
- */
53
- export function importLegacyProposalsIntoState(stateDbPath, stashRoots) {
54
- if (!fs.existsSync(stateDbPath))
55
- return 0;
56
- let db;
57
- try {
58
- db = openDatabase(stateDbPath);
59
- }
60
- catch (err) {
61
- warn(`[akm] content-migration: could not open state.db for legacy proposal import: ${errMsg(err)}`);
62
- return 0;
63
- }
64
- try {
65
- let imported = 0;
66
- const seen = new Set();
67
- for (const root of stashRoots) {
68
- const resolved = path.resolve(root);
69
- if (seen.has(resolved))
70
- continue;
71
- seen.add(resolved);
72
- imported += importLegacyProposalsForStash(db, resolved);
73
- }
74
- return imported;
75
- }
76
- finally {
77
- db.close();
78
- }
79
- }
80
- /**
81
- * Import one stash root's legacy proposal directories (live + archive) into the
82
- * open state.db. Returns the number of rows inserted for this stash.
83
- */
84
- function importLegacyProposalsForStash(db, stashDir) {
85
- const liveRoot = legacyProposalsRoot(stashDir, false);
86
- if (!fs.existsSync(liveRoot))
87
- return 0;
88
- let imported = 0;
89
- for (const archive of [false, true]) {
90
- const root = legacyProposalsRoot(stashDir, archive);
91
- let entries;
92
- try {
93
- entries = fs.readdirSync(root, { withFileTypes: true });
94
- }
95
- catch {
96
- continue;
97
- }
98
- for (const entry of entries) {
99
- if (!entry.isDirectory() || entry.name === "archive")
100
- continue;
101
- const proposalDir = path.join(root, entry.name);
102
- const proposal = readLegacyProposalFile(proposalDir);
103
- if (!proposal)
104
- continue;
105
- try {
106
- if (insertProposalIfAbsent(db, proposal, stashDir))
107
- imported += 1;
108
- }
109
- catch (err) {
110
- warn(`[akm] content-migration: could not import legacy proposal at ${proposalDir}: ${errMsg(err)}`);
111
- }
112
- }
113
- }
114
- if (imported > 0) {
115
- warn(`[akm] content-migration: imported ${imported} legacy proposal file(s) from ${liveRoot} into state.db`);
116
- }
117
- return imported;
118
- }
119
- /**
120
- * Parse one legacy proposal directory into a {@link Proposal}, inlining the
121
- * backup file (when present) as `backupContent`. Returns undefined — with a
122
- * warning — when the `proposal.json` is missing, unreadable, or malformed, so
123
- * a single corrupt legacy entry never blocks the import of the rest.
124
- */
125
- function readLegacyProposalFile(proposalDir) {
126
- const filePath = path.join(proposalDir, "proposal.json");
127
- let parsed;
128
- try {
129
- parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
130
- }
131
- catch (err) {
132
- warn(`[akm] content-migration: skipping legacy proposal at ${filePath}: ${errMsg(err)}`);
133
- return undefined;
134
- }
135
- if (typeof parsed !== "object" ||
136
- parsed === null ||
137
- typeof parsed.id !== "string" ||
138
- typeof parsed.ref !== "string") {
139
- warn(`[akm] content-migration: skipping legacy proposal at ${filePath}: not a proposal object`);
140
- return undefined;
141
- }
142
- const { backup, ...rest } = parsed;
143
- let backupContent;
144
- if (typeof backup === "string" && backup.length > 0) {
145
- try {
146
- backupContent = fs.readFileSync(path.join(proposalDir, backup), "utf8");
147
- }
148
- catch {
149
- // Backup file lost — import the proposal anyway; revert for it will
150
- // surface "no backup available", same as a new-asset proposal.
151
- }
152
- }
153
- return {
154
- ...rest,
155
- payload: {
156
- content: rest.payload?.content ?? "",
157
- ...(rest.payload?.frontmatter ? { frontmatter: rest.payload.frontmatter } : {}),
158
- },
159
- createdAt: rest.createdAt ?? "",
160
- updatedAt: rest.updatedAt ?? rest.createdAt ?? "",
161
- status: rest.status ?? "pending",
162
- source: rest.source ?? "import",
163
- ...(backupContent !== undefined ? { backupContent } : {}),
164
- };
165
- }
166
- function errMsg(error) {
167
- return error instanceof Error ? error.message : String(error);
168
- }
@@ -1,272 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- /**
5
- * @removeIn 0.10.0
6
- *
7
- * One-time rewrite of persisted 0.8 task `workflow:` targets. This module is
8
- * migrator-only: live task parsing remains strict 0.9 grammar. Planning parses
9
- * and resolves every legacy v1 target before `migrate apply` mutates core
10
- * artifacts; application then replaces only the YAML scalar bytes and uses an
11
- * atomic write. The apply coordinator journals the batch as a forward-recovery
12
- * phase, so an interrupted partial batch is safely re-planned and resumed.
13
- */
14
- import crypto from "node:crypto";
15
- import fs from "node:fs";
16
- import os from "node:os";
17
- import path from "node:path";
18
- import { isMap, isScalar, parseDocument } from "yaml";
19
- import { bundlesToSourceEntries } from "../../core/config/config.js";
20
- import { ConfigError } from "../../core/errors.js";
21
- import { resolveWritable } from "../../core/write-source.js";
22
- import { resolveEntryContentDir } from "../../indexer/search/search-source.js";
23
- import { classifyRefGrammar, legacyConceptId, parseAssetRef } from "../legacy-ref-grammar.js";
24
- import { canonicalizeWorkflowName, resolveAssetPathFromName, resolveSourcesForOrigin, } from "./legacy-layout.js";
25
- function migrationError(filePath, detail) {
26
- return new ConfigError(`Cannot migrate persisted task target in ${filePath}: ${detail} ` +
27
- "Repair or remove this task, then rerun `akm migrate apply`.", "INVALID_CONFIG_FILE");
28
- }
29
- function expandTilde(value) {
30
- if (value === "~")
31
- return os.homedir();
32
- if (value.startsWith("~/") || value.startsWith("~\\"))
33
- return path.join(os.homedir(), value.slice(2));
34
- return value;
35
- }
36
- function bundlesFromConfig(config) {
37
- const entries = Object.entries(config.bundles ?? {});
38
- const sourceEntries = new Map((bundlesToSourceEntries(config) ?? []).map((entry) => [entry.name, entry]));
39
- const defaultId = config.defaultBundle;
40
- const ordered = defaultId
41
- ? [...entries.filter(([id]) => id === defaultId), ...entries.filter(([id]) => id !== defaultId)]
42
- : entries;
43
- const bundles = [];
44
- const roots = new Map();
45
- for (const [id, rawEntry] of ordered) {
46
- const entry = rawEntry;
47
- const sourceEntry = sourceEntries.get(id);
48
- if (!sourceEntry)
49
- continue;
50
- const contentDir = resolveEntryContentDir(sourceEntry);
51
- if (!contentDir)
52
- continue;
53
- const root = path.resolve(expandTilde(contentDir));
54
- const rootIdentity = fs.existsSync(root) ? fs.realpathSync(root) : root;
55
- const prior = roots.get(rootIdentity);
56
- if (prior && prior !== id) {
57
- throw new ConfigError(`Cannot migrate persisted task targets because bundles "${prior}" and "${id}" resolve to the same root ${root}. ` +
58
- "Give each bundle a distinct path, then rerun `akm migrate apply`.", "INVALID_CONFIG_FILE");
59
- }
60
- roots.set(rootIdentity, id);
61
- bundles.push({
62
- id,
63
- root,
64
- ...(typeof entry.registryId === "string" && entry.registryId.length > 0 ? { registryId: entry.registryId } : {}),
65
- primary: id === defaultId,
66
- writable: resolveWritable(sourceEntry),
67
- });
68
- }
69
- return bundles;
70
- }
71
- function resolveOrigin(origin, bundles, filePath) {
72
- if (origin === "local" || origin === "stash") {
73
- const primary = bundles.find((bundle) => bundle.primary);
74
- if (primary)
75
- return primary;
76
- throw migrationError(filePath, `legacy origin "${origin}" has no configured default bundle.`);
77
- }
78
- let candidates = bundles.filter((bundle) => bundle.id === origin || bundle.registryId === origin);
79
- if (candidates.length === 0) {
80
- const sources = bundles.map((bundle) => ({
81
- path: bundle.root,
82
- registryId: bundle.registryId ?? bundle.id,
83
- }));
84
- const resolved = resolveSourcesForOrigin(origin, sources);
85
- candidates = resolved
86
- .map((source) => bundles[sources.indexOf(source)])
87
- .filter((bundle) => bundle !== undefined);
88
- }
89
- if (candidates.length === 0) {
90
- throw migrationError(filePath, `legacy workflow origin "${origin}" does not resolve to a configured bundle.`);
91
- }
92
- if (candidates.length > 1) {
93
- throw migrationError(filePath, `legacy workflow origin "${origin}" is ambiguous across bundles ${candidates.map((bundle) => `"${bundle.id}"`).join(", ")}.`);
94
- }
95
- const candidate = candidates[0];
96
- if (!candidate)
97
- throw migrationError(filePath, `legacy workflow origin "${origin}" did not resolve.`);
98
- return candidate;
99
- }
100
- function assertWorkflowExists(bundle, name, rawRef, filePath) {
101
- const candidate = resolveAssetPathFromName("workflow", path.join(bundle.root, "workflows"), name);
102
- if (!fs.existsSync(candidate) || !fs.statSync(candidate).isFile()) {
103
- throw migrationError(filePath, `legacy target "${rawRef}" was not found in bundle "${bundle.id}" at ${bundle.root}.`);
104
- }
105
- const realRoot = fs.realpathSync(bundle.root);
106
- const realCandidate = fs.realpathSync(candidate);
107
- const relative = path.relative(realRoot, realCandidate);
108
- if (relative.startsWith("..") || path.isAbsolute(relative)) {
109
- throw migrationError(filePath, `legacy target "${rawRef}" resolves outside bundle "${bundle.id}".`);
110
- }
111
- }
112
- function assertRealPathWithin(root, candidate, filePath, detail) {
113
- const relative = path.relative(fs.realpathSync(root), fs.realpathSync(candidate));
114
- if (relative.startsWith("..") || path.isAbsolute(relative))
115
- throw migrationError(filePath, detail);
116
- }
117
- function renderScalarLike(sourceToken, replacement, filePath) {
118
- if (sourceToken.startsWith("'") && sourceToken.endsWith("'")) {
119
- return `'${replacement.replaceAll("'", "''")}'`;
120
- }
121
- if (sourceToken.startsWith('"') && sourceToken.endsWith('"'))
122
- return JSON.stringify(replacement);
123
- if (/^[^\s#[\]{},&*!|>'"%@`]+$/.test(sourceToken))
124
- return replacement;
125
- throw migrationError(filePath, "the legacy workflow target uses an unsupported YAML scalar style.");
126
- }
127
- function planTaskFile(filePath, containing, bundles, durabilityPaths) {
128
- const before = fs.readFileSync(filePath);
129
- let text;
130
- try {
131
- text = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(before);
132
- }
133
- catch {
134
- throw migrationError(filePath, "task YAML contains invalid UTF-8 bytes.");
135
- }
136
- const doc = parseDocument(text, { uniqueKeys: true });
137
- const yamlError = doc.errors[0];
138
- if (yamlError)
139
- throw migrationError(filePath, `invalid YAML (${yamlError.message}).`);
140
- if (!isMap(doc.contents))
141
- throw migrationError(filePath, "task YAML must be a mapping.");
142
- const version = doc.get("version");
143
- if (version !== undefined && version !== 1)
144
- return undefined;
145
- if (!doc.has("workflow"))
146
- return undefined;
147
- const node = doc.get("workflow", true);
148
- if (!isScalar(node) || typeof node.value !== "string") {
149
- throw migrationError(filePath, "legacy `workflow` must be a string scalar.");
150
- }
151
- const from = node.value.trim();
152
- if (classifyRefGrammar(from) !== "legacy") {
153
- durabilityPaths.push(filePath);
154
- return undefined;
155
- }
156
- let parsed;
157
- try {
158
- parsed = parseAssetRef(from);
159
- }
160
- catch (error) {
161
- throw migrationError(filePath, `legacy workflow target "${from}" is invalid (${error instanceof Error ? error.message : String(error)}).`);
162
- }
163
- if (parsed.type !== "workflow") {
164
- throw migrationError(filePath, `legacy target "${from}" has type "${parsed.type}", not "workflow".`);
165
- }
166
- const name = canonicalizeWorkflowName(parsed.name);
167
- const targetBundle = parsed.origin ? resolveOrigin(parsed.origin, bundles, filePath) : containing;
168
- assertWorkflowExists(targetBundle, name, from, filePath);
169
- const conceptId = legacyConceptId("workflow", name);
170
- const to = parsed.origin ? `${targetBundle.id}//${conceptId}` : conceptId;
171
- const range = node.range;
172
- if (!range)
173
- throw migrationError(filePath, "the legacy workflow target has no stable source range.");
174
- const token = text.slice(range[0], range[1]);
175
- const replacement = renderScalarLike(token, to, filePath);
176
- const after = Buffer.from(text.slice(0, range[0]) + replacement + text.slice(range[1]));
177
- return { filePath, from, to, before, after, mode: fs.lstatSync(filePath).mode & 0o777 };
178
- }
179
- /** Preflight every persisted v1 task target without changing disk. */
180
- export function planTaskTargetRefMigration(config) {
181
- const bundles = bundlesFromConfig(config);
182
- const rewrites = [];
183
- const durabilityPaths = [];
184
- for (const bundle of bundles) {
185
- if (!bundle.writable)
186
- continue;
187
- const tasksDir = path.join(bundle.root, "tasks");
188
- if (!fs.existsSync(tasksDir))
189
- continue;
190
- const tasksStat = fs.lstatSync(tasksDir);
191
- if (tasksStat.isSymbolicLink()) {
192
- throw new ConfigError(`Cannot migrate persisted task targets because ${tasksDir} is a symbolic link. Replace it with a real ` +
193
- "directory, then rerun `akm migrate apply`.", "INVALID_CONFIG_FILE");
194
- }
195
- if (!tasksStat.isDirectory()) {
196
- throw new ConfigError(`Cannot migrate persisted task targets because ${tasksDir} is not a directory. Repair it, then rerun ` +
197
- "`akm migrate apply`.", "INVALID_CONFIG_FILE");
198
- }
199
- assertRealPathWithin(bundle.root, tasksDir, tasksDir, "the tasks directory resolves outside its bundle.");
200
- for (const entry of fs
201
- .readdirSync(tasksDir, { withFileTypes: true })
202
- .sort((a, b) => a.name.localeCompare(b.name))) {
203
- if (!entry.name.endsWith(".yml"))
204
- continue;
205
- const filePath = path.join(tasksDir, entry.name);
206
- if (!entry.isFile())
207
- throw migrationError(filePath, "task migration does not follow symbolic links or special files.");
208
- assertRealPathWithin(bundle.root, filePath, filePath, "the task file resolves outside its bundle.");
209
- const rewrite = planTaskFile(filePath, bundle, bundles, durabilityPaths);
210
- if (rewrite)
211
- rewrites.push(rewrite);
212
- }
213
- }
214
- return { rewrites, durabilityPaths };
215
- }
216
- function syncParentDirectory(filePath) {
217
- const fd = fs.openSync(path.dirname(filePath), "r");
218
- try {
219
- fs.fsyncSync(fd);
220
- }
221
- finally {
222
- fs.closeSync(fd);
223
- }
224
- }
225
- function writeTaskFileDurably(target, content, mode) {
226
- const temp = `${target}.tmp-${process.pid}-${crypto.randomBytes(8).toString("hex")}`;
227
- let renamed = false;
228
- try {
229
- const fd = fs.openSync(temp, "wx", mode);
230
- try {
231
- fs.fchmodSync(fd, mode);
232
- let offset = 0;
233
- while (offset < content.byteLength) {
234
- const written = fs.writeSync(fd, content, offset, content.byteLength - offset);
235
- if (written <= 0)
236
- throw new Error(`Could not make progress writing task migration temp file ${temp}.`);
237
- offset += written;
238
- }
239
- fs.fsyncSync(fd);
240
- }
241
- finally {
242
- fs.closeSync(fd);
243
- }
244
- fs.renameSync(temp, target);
245
- renamed = true;
246
- syncParentDirectory(target);
247
- }
248
- catch (error) {
249
- if (!renamed)
250
- fs.rmSync(temp, { force: true });
251
- throw error;
252
- }
253
- }
254
- /** Apply a preflighted plan with exact-byte fencing and durable atomic writes. */
255
- export function applyTaskTargetRefMigration(plan) {
256
- let rewritten = 0;
257
- for (const rewrite of plan.rewrites) {
258
- const current = fs.readFileSync(rewrite.filePath);
259
- if (current.equals(rewrite.after)) {
260
- syncParentDirectory(rewrite.filePath);
261
- continue;
262
- }
263
- if (!current.equals(rewrite.before)) {
264
- throw migrationError(rewrite.filePath, "the task changed after migration preflight; it was left untouched.");
265
- }
266
- writeTaskFileDurably(rewrite.filePath, rewrite.after, rewrite.mode);
267
- rewritten++;
268
- }
269
- for (const filePath of plan.durabilityPaths)
270
- syncParentDirectory(filePath);
271
- return rewritten;
272
- }