akm-cli 0.9.0-beta.9 → 0.9.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (381) hide show
  1. package/CHANGELOG.md +715 -0
  2. package/README.md +12 -4
  3. package/dist/akm +38 -0
  4. package/dist/akm-migrate-storage +38 -0
  5. package/dist/assets/help/help-improve.md +9 -6
  6. package/dist/assets/hints/cli-hints-full.md +6 -5
  7. package/dist/assets/profiles/default.json +9 -4
  8. package/dist/assets/profiles/frequent.json +1 -1
  9. package/dist/assets/profiles/memory-focus.json +1 -1
  10. package/dist/assets/profiles/proactive-maintenance.json +25 -0
  11. package/dist/assets/profiles/quick.json +1 -1
  12. package/dist/assets/profiles/recombine-only.json +21 -0
  13. package/dist/assets/profiles/reflect-distill.json +30 -0
  14. package/dist/assets/profiles/synthesize.json +15 -0
  15. package/dist/assets/profiles/thorough.json +1 -1
  16. package/dist/assets/prompts/consolidate-system.md +23 -0
  17. package/dist/assets/prompts/contradiction-judge.md +33 -0
  18. package/dist/assets/prompts/distill-knowledge-system.md +22 -0
  19. package/dist/assets/prompts/distill-lesson-system.md +36 -0
  20. package/dist/assets/prompts/extract-session.md +11 -3
  21. package/dist/assets/prompts/graph-extract-system.md +1 -0
  22. package/dist/assets/prompts/graph-extract-user-prompt.md +1 -1
  23. package/dist/assets/prompts/memory-infer-system.md +1 -0
  24. package/dist/assets/prompts/memory-infer-user.md +5 -0
  25. package/dist/assets/prompts/metadata-enhance-system.md +1 -0
  26. package/dist/assets/prompts/procedural-system.md +44 -0
  27. package/dist/assets/prompts/recombine-system.md +40 -0
  28. package/dist/assets/prompts/staleness-detect-system.md +6 -0
  29. package/dist/assets/prompts/validate-summary-judge.md +1 -0
  30. package/dist/assets/prompts/workflow-unit-preamble.md +26 -0
  31. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +38 -0
  32. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +38 -0
  33. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +39 -0
  34. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +40 -0
  35. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +43 -0
  36. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +38 -0
  37. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +43 -0
  38. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +40 -0
  39. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +43 -0
  40. package/dist/assets/templates/html/health.html +281 -111
  41. package/dist/assets/wiki/ingest-workflow-template.md +45 -16
  42. package/dist/assets/wiki/schema-template.md +4 -4
  43. package/dist/cli/clack.js +56 -0
  44. package/dist/cli/config-migrate.js +7 -1
  45. package/dist/cli/confirm.js +1 -1
  46. package/dist/cli/parse-args.js +46 -1
  47. package/dist/cli/shared.js +28 -0
  48. package/dist/cli.js +25 -21
  49. package/dist/commands/agent/agent-dispatch.js +3 -2
  50. package/dist/commands/agent/agent-support.js +0 -7
  51. package/dist/commands/agent/contribute-cli.js +26 -7
  52. package/dist/commands/config-cli.js +26 -13
  53. package/dist/commands/env/child-env.js +47 -0
  54. package/dist/commands/env/env-binding.js +95 -0
  55. package/dist/commands/env/env-cli.js +228 -292
  56. package/dist/commands/env/env.js +14 -67
  57. package/dist/commands/env/secret-cli.js +140 -138
  58. package/dist/commands/feedback-cli.js +156 -155
  59. package/dist/commands/graph/graph-cli.js +5 -13
  60. package/dist/commands/graph/graph.js +3 -3
  61. package/dist/commands/health/advisories.js +151 -0
  62. package/dist/commands/health/checks.js +103 -16
  63. package/dist/commands/health/html-report.js +447 -81
  64. package/dist/commands/health/improve-metrics.js +771 -0
  65. package/dist/commands/health/llm-usage.js +65 -0
  66. package/dist/commands/health/md-report.js +103 -0
  67. package/dist/commands/health/metrics.js +278 -0
  68. package/dist/commands/health/stash-exposure.js +46 -0
  69. package/dist/commands/health/surfaces.js +216 -0
  70. package/dist/commands/health/task-runs.js +135 -0
  71. package/dist/commands/health/types.js +26 -0
  72. package/dist/commands/health/windows.js +195 -0
  73. package/dist/commands/health.js +91 -1091
  74. package/dist/commands/improve/anti-collapse.js +170 -0
  75. package/dist/commands/improve/calibration.js +161 -0
  76. package/dist/commands/improve/collapse-detector.js +421 -0
  77. package/dist/commands/improve/consolidate/chunking.js +141 -0
  78. package/dist/commands/improve/consolidate/eligibility.js +64 -0
  79. package/dist/commands/improve/consolidate/merge.js +145 -0
  80. package/dist/commands/improve/consolidate/sanitize.js +231 -0
  81. package/dist/commands/{lint.js → improve/consolidate/types.js} +1 -1
  82. package/dist/commands/improve/consolidate.js +1295 -1277
  83. package/dist/commands/improve/dedup.js +482 -0
  84. package/dist/commands/improve/distill/content-repair.js +202 -0
  85. package/dist/commands/improve/distill/promote-memory.js +229 -0
  86. package/dist/commands/improve/distill/quality-gate.js +236 -0
  87. package/dist/commands/improve/distill-guards.js +127 -0
  88. package/dist/commands/improve/distill-promotion-policy.js +826 -167
  89. package/dist/commands/improve/distill.js +228 -605
  90. package/dist/commands/improve/eligibility.js +434 -0
  91. package/dist/commands/improve/encoding-salience.js +205 -0
  92. package/dist/commands/improve/extract-cli.js +179 -59
  93. package/dist/commands/improve/extract-prompt.js +54 -3
  94. package/dist/commands/improve/extract-watch.js +140 -0
  95. package/dist/commands/improve/extract.js +409 -43
  96. package/dist/commands/improve/feedback-valence.js +54 -0
  97. package/dist/commands/improve/hot-probation.js +45 -0
  98. package/dist/commands/improve/improve-auto-accept.js +157 -10
  99. package/dist/commands/improve/improve-cli.js +115 -73
  100. package/dist/commands/improve/improve-profiles.js +28 -8
  101. package/dist/commands/improve/improve-result-file.js +15 -25
  102. package/dist/commands/improve/improve-session.js +58 -0
  103. package/dist/commands/improve/improve.js +485 -2764
  104. package/dist/commands/improve/locks.js +154 -0
  105. package/dist/commands/improve/loop-stages.js +1100 -0
  106. package/dist/commands/improve/memory/memory-belief.js +14 -15
  107. package/dist/commands/improve/memory/memory-contradiction-detect.js +83 -60
  108. package/dist/commands/improve/memory/memory-improve.js +27 -27
  109. package/dist/commands/improve/outcome-loop.js +270 -0
  110. package/dist/commands/improve/preparation.js +2002 -0
  111. package/dist/commands/improve/proactive-maintenance.js +37 -35
  112. package/dist/commands/improve/procedural.js +398 -0
  113. package/dist/commands/improve/recombine.js +818 -0
  114. package/dist/commands/improve/reflect-noise.js +0 -0
  115. package/dist/commands/improve/reflect.js +206 -45
  116. package/dist/commands/improve/salience.js +455 -0
  117. package/dist/commands/improve/schema-similarity-gate.js +168 -0
  118. package/dist/commands/improve/shared.js +51 -0
  119. package/dist/commands/improve/triage.js +93 -0
  120. package/dist/commands/lint/agent-linter.js +19 -24
  121. package/dist/commands/lint/base-linter.js +173 -60
  122. package/dist/commands/lint/command-linter.js +19 -24
  123. package/dist/commands/lint/env-key-rules.js +38 -1
  124. package/dist/commands/lint/fact-linter.js +39 -0
  125. package/dist/commands/lint/index.js +31 -13
  126. package/dist/commands/lint/memory-linter.js +1 -1
  127. package/dist/commands/lint/registry.js +7 -2
  128. package/dist/commands/lint/task-linter.js +3 -3
  129. package/dist/commands/lint/workflow-linter.js +26 -1
  130. package/dist/commands/observability-cli.js +4 -4
  131. package/dist/commands/proposal/drain-policies.js +13 -4
  132. package/dist/commands/proposal/drain.js +45 -51
  133. package/dist/commands/proposal/legacy-import.js +115 -0
  134. package/dist/commands/proposal/proposal-cli.js +24 -34
  135. package/dist/commands/proposal/proposal.js +2 -1
  136. package/dist/commands/proposal/propose.js +8 -3
  137. package/dist/commands/proposal/repository.js +829 -0
  138. package/dist/commands/proposal/validators/proposal-quality-validators.js +9 -8
  139. package/dist/commands/proposal/validators/proposals.js +93 -895
  140. package/dist/commands/read/curate.js +410 -111
  141. package/dist/commands/read/knowledge.js +10 -3
  142. package/dist/commands/read/remember-cli.js +133 -138
  143. package/dist/commands/read/search-cli.js +15 -8
  144. package/dist/commands/read/search.js +22 -11
  145. package/dist/commands/read/show.js +106 -14
  146. package/dist/commands/registry-cli.js +76 -87
  147. package/dist/commands/remember.js +11 -12
  148. package/dist/commands/sources/add-cli.js +91 -95
  149. package/dist/commands/sources/history.js +1 -1
  150. package/dist/commands/sources/init.js +66 -18
  151. package/dist/commands/sources/installed-stashes.js +11 -3
  152. package/dist/commands/sources/migration-help.js +7 -4
  153. package/dist/commands/sources/schema-repair.js +44 -46
  154. package/dist/commands/sources/self-update.js +2 -2
  155. package/dist/commands/sources/source-add.js +7 -3
  156. package/dist/commands/sources/sources-cli.js +3 -3
  157. package/dist/commands/sources/stash-cli.js +19 -39
  158. package/dist/commands/sources/stash-skeleton.js +57 -8
  159. package/dist/commands/tasks/default-tasks.js +15 -2
  160. package/dist/commands/tasks/tasks-cli.js +20 -29
  161. package/dist/commands/tasks/tasks.js +39 -11
  162. package/dist/commands/wiki-cli.js +23 -38
  163. package/dist/commands/workflow-cli.js +291 -13
  164. package/dist/core/asset/asset-registry.js +3 -1
  165. package/dist/core/asset/asset-spec.js +79 -5
  166. package/dist/core/asset/frontmatter.js +188 -167
  167. package/dist/core/asset/markdown.js +8 -0
  168. package/dist/core/authoring-rules.js +92 -0
  169. package/dist/core/common.js +4 -23
  170. package/dist/core/concurrent.js +10 -1
  171. package/dist/core/config/config-io.js +10 -1
  172. package/dist/core/config/config-migration.js +18 -40
  173. package/dist/core/config/config-schema.js +403 -62
  174. package/dist/core/config/config-types.js +3 -3
  175. package/dist/core/config/config.js +67 -22
  176. package/dist/core/deep-merge.js +38 -0
  177. package/dist/core/errors.js +1 -0
  178. package/dist/core/eval/rank-metrics.js +113 -0
  179. package/dist/core/events.js +4 -7
  180. package/dist/core/improve-types.js +47 -8
  181. package/dist/core/json-schema.js +142 -0
  182. package/dist/core/logs-db.js +14 -75
  183. package/dist/core/parse.js +36 -16
  184. package/dist/core/paths.js +18 -18
  185. package/dist/core/standards/resolve-standards-context.js +87 -0
  186. package/dist/core/standards/resolve-stash-standards.js +99 -0
  187. package/dist/core/standards/resolve-type-conventions.js +66 -0
  188. package/dist/core/state/migrations.js +770 -0
  189. package/dist/core/state-db.js +132 -1126
  190. package/dist/core/structured.js +69 -0
  191. package/dist/core/time.js +53 -0
  192. package/dist/core/warn.js +21 -0
  193. package/dist/core/write-source.js +37 -0
  194. package/dist/indexer/db/db.js +261 -770
  195. package/dist/indexer/db/entry-mapper.js +41 -0
  196. package/dist/indexer/db/graph-db.js +129 -86
  197. package/dist/indexer/db/llm-cache.js +2 -2
  198. package/dist/indexer/db/schema.js +516 -0
  199. package/dist/indexer/ensure-index.js +36 -92
  200. package/dist/indexer/feedback/utility-policy.js +75 -0
  201. package/dist/indexer/graph/graph-boost.js +51 -41
  202. package/dist/indexer/graph/graph-extraction.js +207 -4
  203. package/dist/indexer/index-writer-lock.js +18 -11
  204. package/dist/indexer/index-written-assets.js +105 -0
  205. package/dist/indexer/indexer.js +182 -204
  206. package/dist/indexer/passes/dir-staleness.js +114 -0
  207. package/dist/indexer/passes/memory-inference.js +13 -5
  208. package/dist/indexer/passes/metadata.js +20 -0
  209. package/dist/indexer/read-preflight.js +23 -0
  210. package/dist/indexer/search/db-search.js +89 -13
  211. package/dist/indexer/search/fts-query.js +51 -0
  212. package/dist/indexer/search/ranking-contributors.js +95 -9
  213. package/dist/indexer/search/ranking.js +79 -3
  214. package/dist/indexer/search/search-fields.js +6 -0
  215. package/dist/indexer/search/search-source.js +32 -21
  216. package/dist/indexer/search/semantic-status.js +4 -0
  217. package/dist/indexer/walk/matchers.js +48 -0
  218. package/dist/indexer/walk/walker.js +21 -13
  219. package/dist/integrations/agent/builders.js +41 -13
  220. package/dist/integrations/agent/config.js +20 -59
  221. package/dist/integrations/agent/detect.js +9 -0
  222. package/dist/integrations/agent/index.js +3 -19
  223. package/dist/integrations/agent/model-aliases.js +16 -2
  224. package/dist/integrations/agent/profiles.js +79 -6
  225. package/dist/integrations/agent/prompts.js +75 -9
  226. package/dist/integrations/agent/runner-dispatch.js +83 -0
  227. package/dist/integrations/agent/runner.js +13 -9
  228. package/dist/integrations/agent/spawn.js +206 -81
  229. package/dist/integrations/harnesses/aider/agent-builder.js +113 -0
  230. package/dist/integrations/harnesses/aider/index.js +58 -0
  231. package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
  232. package/dist/integrations/harnesses/amazonq/agent-builder.js +153 -0
  233. package/dist/integrations/harnesses/amazonq/index.js +59 -0
  234. package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
  235. package/dist/integrations/harnesses/claude/agent-builder.js +46 -7
  236. package/dist/integrations/harnesses/claude/index.js +27 -23
  237. package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
  238. package/dist/integrations/harnesses/claude/session-log.js +10 -0
  239. package/dist/integrations/harnesses/codex/agent-builder.js +137 -0
  240. package/dist/integrations/harnesses/codex/index.js +63 -0
  241. package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
  242. package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
  243. package/dist/integrations/harnesses/copilot/index.js +60 -0
  244. package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
  245. package/dist/integrations/harnesses/gemini/agent-builder.js +121 -0
  246. package/dist/integrations/harnesses/gemini/index.js +60 -0
  247. package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
  248. package/dist/integrations/harnesses/index.js +28 -7
  249. package/dist/integrations/harnesses/opencode/agent-builder.js +1 -1
  250. package/dist/integrations/harnesses/opencode/index.js +17 -16
  251. package/dist/integrations/harnesses/opencode/session-log.js +173 -3
  252. package/dist/integrations/harnesses/opencode-sdk/harness.js +65 -0
  253. package/dist/integrations/harnesses/opencode-sdk/index.js +10 -34
  254. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +642 -71
  255. package/dist/integrations/harnesses/openhands/agent-builder.js +126 -0
  256. package/dist/integrations/harnesses/openhands/index.js +58 -0
  257. package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
  258. package/dist/integrations/harnesses/pi/agent-builder.js +104 -0
  259. package/dist/integrations/harnesses/pi/index.js +58 -0
  260. package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
  261. package/dist/integrations/harnesses/types.js +8 -0
  262. package/dist/integrations/session-logs/index.js +40 -11
  263. package/dist/llm/call-ai.js +2 -2
  264. package/dist/llm/client.js +34 -11
  265. package/dist/llm/embedder.js +67 -4
  266. package/dist/llm/embedders/cache.js +3 -1
  267. package/dist/llm/embedders/deterministic.js +66 -0
  268. package/dist/llm/embedders/local.js +73 -3
  269. package/dist/llm/feature-gate.js +16 -15
  270. package/dist/llm/graph-extract.js +67 -44
  271. package/dist/llm/memory-infer-impl.js +138 -0
  272. package/dist/llm/memory-infer.js +1 -127
  273. package/dist/llm/metadata-enhance.js +44 -31
  274. package/dist/llm/structured-call.js +49 -0
  275. package/dist/migrate-storage-node.mjs +8 -0
  276. package/dist/output/context.js +5 -5
  277. package/dist/output/renderers.js +87 -15
  278. package/dist/output/shapes/curate.js +14 -2
  279. package/dist/output/shapes/helpers.js +0 -3
  280. package/dist/output/shapes/passthrough.js +6 -1
  281. package/dist/output/text/helpers.js +241 -2
  282. package/dist/output/text/workflow.js +4 -1
  283. package/dist/registry/providers/skills-sh.js +21 -147
  284. package/dist/registry/providers/static-index.js +15 -157
  285. package/dist/registry/resolve.js +27 -9
  286. package/dist/runtime.js +25 -1
  287. package/dist/schemas/akm-config.json +14225 -0
  288. package/dist/schemas/akm-workflow.json +328 -0
  289. package/dist/scripts/migrate-storage.js +2743 -8390
  290. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +1652 -607
  291. package/dist/setup/detect.js +9 -0
  292. package/dist/setup/legacy-config.js +106 -0
  293. package/dist/setup/prompt.js +57 -0
  294. package/dist/setup/providers.js +14 -0
  295. package/dist/setup/registry-stash-loader.js +12 -0
  296. package/dist/setup/semantic-assets.js +124 -0
  297. package/dist/setup/setup.js +52 -1614
  298. package/dist/setup/steps/connection.js +734 -0
  299. package/dist/setup/steps/output.js +31 -0
  300. package/dist/setup/steps/platforms.js +124 -0
  301. package/dist/setup/steps/semantic.js +27 -0
  302. package/dist/setup/steps/sources.js +222 -0
  303. package/dist/setup/steps/stashdir.js +42 -0
  304. package/dist/setup/steps/tasks.js +152 -0
  305. package/dist/sources/include.js +6 -2
  306. package/dist/sources/providers/filesystem.js +0 -1
  307. package/dist/sources/providers/git-install.js +210 -0
  308. package/dist/sources/providers/git-provider.js +234 -0
  309. package/dist/sources/providers/git-stash.js +248 -0
  310. package/dist/sources/providers/git.js +10 -661
  311. package/dist/sources/providers/npm.js +2 -6
  312. package/dist/sources/providers/provider-utils.js +13 -7
  313. package/dist/sources/providers/sync-from-ref.js +9 -1
  314. package/dist/sources/providers/website.js +9 -5
  315. package/dist/sources/website-ingest.js +187 -29
  316. package/dist/sources/wiki-fetchers/registry.js +53 -0
  317. package/dist/sources/wiki-fetchers/youtube.js +239 -0
  318. package/dist/storage/database.js +45 -10
  319. package/dist/storage/managed-db.js +82 -0
  320. package/dist/storage/repositories/canaries-repository.js +107 -0
  321. package/dist/storage/repositories/consolidation-repository.js +38 -0
  322. package/dist/storage/repositories/embeddings-repository.js +72 -0
  323. package/dist/storage/repositories/events-repository.js +187 -0
  324. package/dist/storage/repositories/extract-sessions-repository.js +96 -0
  325. package/dist/storage/repositories/improve-runs-repository.js +146 -0
  326. package/dist/storage/repositories/index-db.js +14 -8
  327. package/dist/storage/repositories/proposals-repository.js +220 -0
  328. package/dist/storage/repositories/recombine-repository.js +213 -0
  329. package/dist/storage/repositories/registry-cache.js +93 -0
  330. package/dist/storage/repositories/registry-index-cache-repository.js +46 -0
  331. package/dist/storage/repositories/task-history-repository.js +93 -0
  332. package/dist/storage/repositories/workflow-runs-repository.js +189 -1
  333. package/dist/storage/sqlite-pragmas.js +146 -0
  334. package/dist/tasks/backends/cron.js +1 -1
  335. package/dist/tasks/backends/index.js +9 -0
  336. package/dist/tasks/backends/launchd.js +1 -1
  337. package/dist/tasks/backends/schtasks.js +1 -1
  338. package/dist/tasks/{resolveAkmBin.js → resolve-akm-bin.js} +2 -2
  339. package/dist/tasks/runner.js +15 -13
  340. package/dist/text-import-hook.mjs +1 -1
  341. package/dist/wiki/wiki.js +52 -11
  342. package/dist/workflows/authoring/authoring.js +123 -10
  343. package/dist/workflows/authoring/workflow-program-template.yaml +31 -0
  344. package/dist/workflows/cli.js +5 -0
  345. package/dist/workflows/db.js +138 -4
  346. package/dist/workflows/exec/brief.js +484 -0
  347. package/dist/workflows/exec/native-executor.js +975 -0
  348. package/dist/workflows/exec/param-secrets.js +115 -0
  349. package/dist/workflows/exec/report.js +1295 -0
  350. package/dist/workflows/exec/run-workflow.js +596 -0
  351. package/dist/workflows/exec/scheduler.js +100 -0
  352. package/dist/workflows/exec/step-work.js +1156 -0
  353. package/dist/workflows/exec/unit-writer.js +23 -0
  354. package/dist/workflows/exec/watch.js +116 -0
  355. package/dist/workflows/exec/worktree.js +171 -0
  356. package/dist/workflows/ir/compile.js +388 -0
  357. package/dist/workflows/ir/params.js +54 -0
  358. package/dist/workflows/ir/plan-hash.js +33 -0
  359. package/dist/workflows/ir/schema.js +4 -0
  360. package/dist/workflows/parser.js +3 -1
  361. package/dist/workflows/program/expressions.js +369 -0
  362. package/dist/workflows/program/parser.js +760 -0
  363. package/dist/workflows/program/project.js +105 -0
  364. package/dist/workflows/program/schema.js +54 -0
  365. package/dist/workflows/renderer.js +82 -5
  366. package/dist/workflows/runtime/agent-identity.js +59 -14
  367. package/dist/workflows/runtime/runs.js +248 -153
  368. package/dist/workflows/runtime/unit-checkin.js +45 -0
  369. package/dist/workflows/runtime/workflow-asset-loader.js +188 -0
  370. package/dist/workflows/validate-summary.js +26 -10
  371. package/dist/workflows/validator.js +1 -1
  372. package/docs/README.md +69 -18
  373. package/docs/data-and-telemetry.md +7 -5
  374. package/docs/migration/release-notes/0.7.0.md +1 -1
  375. package/docs/migration/release-notes/0.9.0-beta.60.md +19 -0
  376. package/docs/migration/release-notes/0.9.0.md +39 -0
  377. package/package.json +10 -10
  378. package/dist/assets/tasks/core/update-stashes.yml +0 -4
  379. package/dist/commands/db-cli.js +0 -23
  380. package/dist/indexer/db/db-backup.js +0 -376
  381. package/dist/indexer/passes/staleness-detect.js +0 -488
@@ -0,0 +1,388 @@
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
+ * Frontends → Workflow Plan Graph (IR v2) compilers.
6
+ *
7
+ * Two frontends, one IR (redesign addendum, R1):
8
+ *
9
+ * - {@link compileWorkflowProgram} — YAML orchestration programs
10
+ * (`program/parser.ts`). Pure and deterministic; performs FULL expression
11
+ * validation (closed `${{ … }}` grammar, earlier-step references,
12
+ * whole-value contexts, `item`/`item_index` scoping) and MERGES the
13
+ * program's `defaults` block into every unit node so the frozen plan is
14
+ * self-contained. Returns accumulated `WorkflowError`s rather than
15
+ * throwing.
16
+ * - {@link compileWorkflowPlan} — classic LINEAR markdown workflows
17
+ * (`parser.ts`), the stable CLI contract: one `agent` node per step with
18
+ * `runner: inherit` and the fail-fast default, exactly as today. The P1
19
+ * markdown orchestration grammar is gone — this path is linear-only.
20
+ *
21
+ * Node-id convention (stable, unique within a plan):
22
+ * step root → `<stepId>` (agent) or `<stepId>.map` (map)
23
+ * map unit → `<stepId>.unit` (template instantiated per item)
24
+ * gate → `<stepId>.gate`
25
+ */
26
+ import { formatReference, listReferences, parseTemplate } from "../program/expressions.js";
27
+ import { WORKFLOW_IR_VERSION, } from "./schema.js";
28
+ /**
29
+ * Compile a parsed YAML program into a frozen-plan-ready graph. Assumes the
30
+ * program came out of `parseWorkflowProgram` ok (structure already valid);
31
+ * this pass owns the expression-language rules the parser deliberately does
32
+ * not check:
33
+ *
34
+ * - every `${{ … }}` in instructions / `map.over` / `route.input` parses
35
+ * against the CLOSED grammar;
36
+ * - `steps.<id>` references name an EARLIER step (a producer that has
37
+ * already run when the reference resolves);
38
+ * - `map.over` and `route.input` are single whole-value references — a bare
39
+ * `${{ … }}` with no surrounding text;
40
+ * - `item` / `item_index` appear only inside a map unit's instructions.
41
+ */
42
+ export function compileWorkflowProgram(program) {
43
+ const errors = [];
44
+ const allStepIds = new Set(program.steps.map((s) => s.id));
45
+ const earlierStepIds = new Set();
46
+ const steps = [];
47
+ program.steps.forEach((step, index) => {
48
+ const check = { allStepIds, earlierStepIds, errors };
49
+ if (step.unit) {
50
+ checkTemplateExpressions(step.unit.instructions, {
51
+ ...check,
52
+ line: step.unit.source.start,
53
+ label: `Step "${step.id}" instructions`,
54
+ inMapUnit: false,
55
+ });
56
+ }
57
+ if (step.map) {
58
+ checkWholeValueExpression(step.map.over, {
59
+ ...check,
60
+ line: step.source.start,
61
+ label: `Step "${step.id}" map.over`,
62
+ });
63
+ checkTemplateExpressions(step.map.unit.instructions, {
64
+ ...check,
65
+ line: step.map.unit.source.start,
66
+ label: `Step "${step.id}" instructions`,
67
+ inMapUnit: true,
68
+ });
69
+ }
70
+ if (step.route) {
71
+ checkWholeValueExpression(step.route.input, {
72
+ ...check,
73
+ line: step.source.start,
74
+ label: `Step "${step.id}" route.input`,
75
+ });
76
+ }
77
+ steps.push(compileProgramStep(step, index, program.defaults));
78
+ earlierStepIds.add(step.id);
79
+ });
80
+ if (errors.length > 0)
81
+ return { ok: false, errors };
82
+ const paramNames = program.params ? Object.keys(program.params) : [];
83
+ return {
84
+ ok: true,
85
+ // Non-fatal advisories (redesign addendum). Warnings NEVER change the plan
86
+ // or its hash — they are computed alongside the frozen plan and surfaced by
87
+ // `workflow validate` / `workflow start`, never persisted onto the run row.
88
+ warnings: collectProgramWarnings(program),
89
+ plan: {
90
+ irVersion: WORKFLOW_IR_VERSION,
91
+ title: program.name,
92
+ ...(paramNames.length > 0 ? { params: paramNames } : {}),
93
+ // Reviewer #12: freeze the per-param schemas into the plan so `--params`
94
+ // can be validated at start and re-asserted at brief/report against the
95
+ // exact schemas the run was created with (the plan hash covers them).
96
+ ...(program.params && paramNames.length > 0 ? { paramSchemas: program.params } : {}),
97
+ // Budget ceilings (addendum R2): frozen onto the plan so enforcement is
98
+ // a pure function of (frozen plan, journal) — never the live asset.
99
+ ...(program.budget
100
+ ? {
101
+ budget: {
102
+ ...(program.budget.maxTokens !== undefined ? { maxTokens: program.budget.maxTokens } : {}),
103
+ ...(program.budget.maxUnits !== undefined ? { maxUnits: program.budget.maxUnits } : {}),
104
+ },
105
+ }
106
+ : {}),
107
+ steps,
108
+ },
109
+ };
110
+ }
111
+ function compileProgramStep(step, index, defaults) {
112
+ const gate = {
113
+ kind: "gate",
114
+ id: `${step.id}.gate`,
115
+ stepId: step.id,
116
+ criteria: step.gate?.criteria ?? [],
117
+ // TODO(R2): maxLoops execution (bounded evaluator-optimizer) is engine
118
+ // rework scope; carried through the frozen plan now.
119
+ ...(step.gate?.maxLoops !== undefined ? { maxLoops: step.gate.maxLoops } : {}),
120
+ // Reviewer #18: a required gate rides the frozen plan so BOTH surfaces
121
+ // (engine + report) enforce it identically.
122
+ ...(step.gate?.required !== undefined ? { required: step.gate.required } : {}),
123
+ };
124
+ let root;
125
+ if (step.unit) {
126
+ root = compileProgramUnit(step.unit, step.id, defaults);
127
+ }
128
+ else if (step.map) {
129
+ root = {
130
+ kind: "map",
131
+ id: `${step.id}.map`,
132
+ over: step.map.over,
133
+ template: compileProgramUnit(step.map.unit, `${step.id}.unit`, defaults),
134
+ ...(step.map.concurrency !== undefined ? { concurrency: step.map.concurrency } : {}),
135
+ reducer: step.map.reducer ?? "collect",
136
+ source: step.source,
137
+ };
138
+ }
139
+ return {
140
+ stepId: step.id,
141
+ title: step.title ?? step.id,
142
+ sequenceIndex: index,
143
+ ...(root ? { root } : {}),
144
+ ...(step.route
145
+ ? {
146
+ route: {
147
+ input: step.route.input,
148
+ when: Object.fromEntries(step.route.branches.map((b) => [b.match, b.stepId])),
149
+ ...(step.route.defaultStepId !== undefined ? { defaultStepId: step.route.defaultStepId } : {}),
150
+ },
151
+ }
152
+ : {}),
153
+ // TODO(R2): validating the reducer result against this schema (typed step
154
+ // artifacts) is engine-rework scope; the frozen plan carries it now.
155
+ ...(step.output !== undefined ? { outputSchema: step.output } : {}),
156
+ gate,
157
+ };
158
+ }
159
+ /**
160
+ * Lower one program unit into an agent node, merging the run-level `defaults`
161
+ * block (frozen resolution — addendum: "the plan is self-contained"). Per-unit
162
+ * declarations always win; the fail-fast `on_error` default applies last.
163
+ */
164
+ function compileProgramUnit(unit, id, defaults) {
165
+ const model = unit.model ?? defaults?.model;
166
+ const timeoutMs = unit.timeoutMs !== undefined ? unit.timeoutMs : defaults?.timeoutMs;
167
+ return {
168
+ kind: "agent",
169
+ id,
170
+ instructions: unit.instructions,
171
+ // YAML program instructions are `${{ … }}` templates (validated above);
172
+ // the executor resolves them per unit.
173
+ templating: "expressions",
174
+ runner: unit.runner ?? defaults?.runner ?? "inherit",
175
+ ...(unit.profile !== undefined ? { profile: unit.profile } : {}),
176
+ ...(model !== undefined ? { model } : {}),
177
+ ...(unit.output !== undefined ? { schema: unit.output } : {}),
178
+ ...(timeoutMs !== undefined ? { timeoutMs } : {}),
179
+ // TODO(R2): retry dispatch is engine-rework scope; carried through now.
180
+ ...(unit.retry ? { retry: { max: unit.retry.max, on: [...unit.retry.on] } } : {}),
181
+ onError: unit.onError ?? defaults?.onError ?? "fail",
182
+ ...(unit.env ? { env: [...unit.env] } : {}),
183
+ ...(unit.isolation !== undefined ? { isolation: unit.isolation } : {}),
184
+ source: unit.source,
185
+ };
186
+ }
187
+ /** Validate every `${{ … }}` in a free-text template (instructions). */
188
+ function checkTemplateExpressions(text, check) {
189
+ const parsed = parseTemplate(text);
190
+ if (!parsed.ok) {
191
+ for (const err of parsed.errors) {
192
+ check.errors.push({ line: check.line, message: `${check.label}: ${err.message}` });
193
+ }
194
+ return;
195
+ }
196
+ for (const ref of listReferences(parsed.segments)) {
197
+ checkReference(ref, check, check.inMapUnit);
198
+ }
199
+ }
200
+ /**
201
+ * Validate a whole-value field (`map.over`, `route.input`): the text must be
202
+ * exactly one `${{ … }}` reference with no surrounding literal text, so the
203
+ * engine can resolve it to a RAW value (array/object), never a string splice.
204
+ */
205
+ function checkWholeValueExpression(text, check) {
206
+ const parsed = parseTemplate(text);
207
+ if (!parsed.ok) {
208
+ for (const err of parsed.errors) {
209
+ check.errors.push({ line: check.line, message: `${check.label}: ${err.message}` });
210
+ }
211
+ return;
212
+ }
213
+ const [first] = parsed.segments;
214
+ if (parsed.segments.length !== 1 || first?.kind !== "reference") {
215
+ check.errors.push({
216
+ line: check.line,
217
+ message: `${check.label} must be a single whole-value \${{ … }} reference with no surrounding text ` +
218
+ `(e.g. "\${{ steps.discover.output.files }}"), got ${JSON.stringify(text)}.`,
219
+ });
220
+ return;
221
+ }
222
+ // `item`/`item_index` never exist where a whole-value field resolves (the
223
+ // item list itself, or a spine route input), so inMapUnit is always false.
224
+ checkReference(first.expr, check, false);
225
+ }
226
+ function checkReference(ref, check, inMapUnit) {
227
+ switch (ref.kind) {
228
+ case "item":
229
+ case "itemIndex": {
230
+ if (!inMapUnit) {
231
+ check.errors.push({
232
+ line: check.line,
233
+ message: `${check.label}: "\${{ ${formatReference(ref)} }}" is only valid inside a map unit's instructions.`,
234
+ });
235
+ }
236
+ return;
237
+ }
238
+ case "stepOutput": {
239
+ if (!check.earlierStepIds.has(ref.stepId)) {
240
+ const why = check.allStepIds.has(ref.stepId)
241
+ ? `step "${ref.stepId}" does not come before this step — references must name an earlier step (a producer that has already run)`
242
+ : `"${ref.stepId}" is not a step in this workflow`;
243
+ check.errors.push({
244
+ line: check.line,
245
+ message: `${check.label}: "\${{ ${formatReference(ref)} }}" cannot be resolved — ${why}.`,
246
+ });
247
+ }
248
+ return;
249
+ }
250
+ case "param": {
251
+ // Param presence is a RUN-SCOPE concern, never a compile-time one. A
252
+ // declared `params:` block is NOT a closed set of legal references: the
253
+ // runtime resolves any param SUPPLIED at start (`resolveReference`), and
254
+ // `validateWorkflowParams` documents that undeclared params are permitted
255
+ // — so `${{ params.mode }}` with `mode` passed via `--params` runs fine
256
+ // even when only `files` is declared. At compile time an undeclared
257
+ // reference is indistinguishable from that legitimate start-supplied
258
+ // extra, so treating the block as closed would reject a runtime-supported
259
+ // authoring pattern and put the two layers in disagreement. A genuine typo
260
+ // (`params.changed_file` for `changed_files`) surfaces at run time with a
261
+ // precise "is not defined in the run's params" error instead. As a lint-time
262
+ // heads-up short of rejection, `collectProgramWarnings` (below) emits a
263
+ // non-fatal WARNING for an undeclared reference when a `params:` block is
264
+ // declared — never an error, so the runtime-supported pattern still compiles.
265
+ return;
266
+ }
267
+ }
268
+ }
269
+ // ── Non-fatal warnings ───────────────────────────────────────────────────────
270
+ /**
271
+ * Collect the program's non-fatal WARNINGS — advisories that never fail
272
+ * compilation, never change the frozen plan or its hash, and are surfaced by
273
+ * `workflow validate` (human + JSON) and as `warn()` lines at `workflow start`.
274
+ *
275
+ * Two promised-but-previously-missing warnings (redesign addendum):
276
+ *
277
+ * A. A unit/map step with NO step-level `output:` schema carries its units'
278
+ * raw results as an untyped artifact — permitted, but the addendum says
279
+ * "the validator warns". Anchored on the STEP's `output` (the reducer /
280
+ * step-artifact schema); a per-unit `output:` types the unit result but
281
+ * leaves the step artifact untyped.
282
+ * B. A `${{ params.<name> }}` reference to an UNDECLARED param, but ONLY when
283
+ * the program declares a `params:` block. Compile-time REJECTION was tried
284
+ * and reverted (see the `case "param"` note above): the runtime legitimately
285
+ * resolves any param supplied at start, declared or not. The agreed middle
286
+ * ground is a warning — a likely typo (`changed_file` for `changed_files`)
287
+ * surfaces at lint time, while a genuinely start-supplied extra still runs.
288
+ * With no `params:` block there is nothing to compare against, so B is silent.
289
+ *
290
+ * Pure and deterministic; the returned order is document order per step
291
+ * (warning A, then each undeclared-param reference in field/document order).
292
+ * Only called on an OK compile, so every template here already parsed cleanly.
293
+ */
294
+ export function collectProgramWarnings(program) {
295
+ const warnings = [];
296
+ const declaredParams = program.params ? new Set(Object.keys(program.params)) : undefined;
297
+ for (const step of program.steps) {
298
+ // Warning A — a unit/map step with no step-level output schema.
299
+ if ((step.unit || step.map) && step.output === undefined) {
300
+ warnings.push({
301
+ line: step.source.start,
302
+ message: `Step "${step.id}" declares no \`output:\` schema — its unit results are carried as an untyped ` +
303
+ `artifact (permitted). Add an \`output:\` JSON Schema to type and validate the step artifact.`,
304
+ });
305
+ }
306
+ // Warning B — references to a param the declared `params:` block omits.
307
+ if (declaredParams)
308
+ collectUndeclaredParamWarnings(step, declaredParams, warnings);
309
+ }
310
+ return warnings;
311
+ }
312
+ /**
313
+ * Push a warning for every `${{ params.<name> }}` reference in `step` whose
314
+ * name is not in the declared param set. Walks the same template-bearing
315
+ * fields the compiler validates (unit / map.over + map unit / route.input) so
316
+ * the step + field context in the message matches the error labels.
317
+ */
318
+ function collectUndeclaredParamWarnings(step, declared, warnings) {
319
+ const declaredList = [...declared].join(", ");
320
+ const scan = (text, line, label) => {
321
+ const parsed = parseTemplate(text);
322
+ if (!parsed.ok)
323
+ return; // OK compile guarantees this parses; defensive only.
324
+ for (const ref of listReferences(parsed.segments)) {
325
+ if (ref.kind !== "param" || declared.has(ref.name))
326
+ continue;
327
+ warnings.push({
328
+ line,
329
+ message: `${label}: "\${{ ${formatReference(ref)} }}" references a param not declared in \`params:\` ` +
330
+ `(declared: ${declaredList || "none"}) — likely a typo. An undeclared param supplied at start still ` +
331
+ `resolves at run time.`,
332
+ });
333
+ }
334
+ };
335
+ if (step.unit)
336
+ scan(step.unit.instructions, step.unit.source.start, `Step "${step.id}" instructions`);
337
+ if (step.map) {
338
+ scan(step.map.over, step.source.start, `Step "${step.id}" map.over`);
339
+ scan(step.map.unit.instructions, step.map.unit.source.start, `Step "${step.id}" instructions`);
340
+ }
341
+ if (step.route)
342
+ scan(step.route.input, step.source.start, `Step "${step.id}" route.input`);
343
+ }
344
+ // ─────────────────────────────────────────────────────────────────────────────
345
+ // Frontend B — classic markdown workflow
346
+ // ─────────────────────────────────────────────────────────────────────────────
347
+ /**
348
+ * Compile a markdown `WorkflowDocument` to IR v2. Pure and deterministic: the
349
+ * same document always compiles to the same plan. Linear workflows — the
350
+ * stable contract — produce one `agent` node per step (`runner: inherit`,
351
+ * fail-fast) guarded by its gate, identical behavior to today's step loop.
352
+ */
353
+ export function compileWorkflowPlan(document) {
354
+ const params = document.parameters?.map((p) => p.name);
355
+ return {
356
+ irVersion: WORKFLOW_IR_VERSION,
357
+ title: document.title,
358
+ ...(params && params.length > 0 ? { params } : {}),
359
+ steps: document.steps.map(compileMarkdownStep),
360
+ };
361
+ }
362
+ function compileMarkdownStep(step) {
363
+ const gate = {
364
+ kind: "gate",
365
+ id: `${step.id}.gate`,
366
+ stepId: step.id,
367
+ criteria: step.completionCriteria?.map((c) => c.text) ?? [],
368
+ };
369
+ return {
370
+ stepId: step.id,
371
+ title: step.title,
372
+ sequenceIndex: step.sequenceIndex,
373
+ root: {
374
+ kind: "agent",
375
+ id: step.id,
376
+ instructions: step.instructions.text,
377
+ // Stable contract: markdown instructions are opaque data, passed to the
378
+ // agent byte-exact. A literal `${{ … }}` (GitHub Actions syntax, docs of
379
+ // the YAML format) is content here, never expression grammar.
380
+ templating: "verbatim",
381
+ runner: "inherit",
382
+ // Markdown has no failure-policy surface; the fail-fast default applies.
383
+ onError: "fail",
384
+ source: step.instructions.source,
385
+ },
386
+ gate,
387
+ };
388
+ }
@@ -0,0 +1,54 @@
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
+ * Run-parameter validation against the frozen plan's param schemas (reviewer
6
+ * #12). A program can declare `params.files: { type: array }`; supplying
7
+ * `--params '{"files":"not-an-array"}'` must be rejected at start rather than
8
+ * silently flowing into a unit prompt. The schemas are frozen into the plan
9
+ * ({@link WorkflowPlanGraph.paramSchemas}, program path only) so validation is
10
+ * a pure function of the frozen plan and the supplied params — no live-asset
11
+ * re-read.
12
+ *
13
+ * Uses the same bounded {@link validateJsonSchemaSubset} the engine applies to
14
+ * unit output: undeclared params are permitted (the schema map only constrains
15
+ * the params it names), and a workflow with no declared schemas (every Markdown
16
+ * workflow, and programs without a `params:` block) validates trivially.
17
+ *
18
+ * Pure module: no IO, no engine imports.
19
+ */
20
+ import { UsageError } from "../../core/errors.js";
21
+ import { validateJsonSchemaSubset } from "../../core/json-schema.js";
22
+ /**
23
+ * Validate a run's supplied params against the plan's frozen param schemas.
24
+ * Returns a flat list of human-readable, path-prefixed error strings (empty =
25
+ * valid). Params the plan does not declare a schema for are not constrained.
26
+ */
27
+ export function validateWorkflowParams(plan, params) {
28
+ const schemas = plan.paramSchemas;
29
+ if (!schemas || Object.keys(schemas).length === 0)
30
+ return [];
31
+ // Validate the params object as a whole against a synthetic object schema
32
+ // whose `properties` are the declared param schemas. Missing declared params
33
+ // are NOT required (params may be optional / defaulted downstream); only a
34
+ // PRESENT param that violates its declared schema is an error.
35
+ // Re-root the validator's `$` JSON-pointer prefix to `params` for messages
36
+ // that read naturally in a start/CLI error (e.g. `params.files: expected …`).
37
+ return validateJsonSchemaSubset(params, { type: "object", properties: schemas }).map((e) => e.replace(/^\$/, "params"));
38
+ }
39
+ /**
40
+ * Brief/report integrity assert (reviewer #12): the journaled `params_json`
41
+ * row must STILL satisfy the frozen param schemas. `startWorkflowRun` already
42
+ * validated the params it stored, so a violation here means the row was edited
43
+ * after the run started — loud corruption, exactly like the frozen-plan hash
44
+ * mismatch and the tampered-params replay-divergence path. Refuse to describe
45
+ * or drive the run rather than resolve prompts from schema-violating params.
46
+ */
47
+ export function assertRunParamsSatisfyPlan(runId, plan, params) {
48
+ const errors = validateWorkflowParams(plan, params);
49
+ if (errors.length === 0)
50
+ return;
51
+ throw new UsageError(`Workflow run ${runId} failed the frozen param-schema integrity check: the journaled params row no longer ` +
52
+ `satisfies the workflow's declared parameter schemas (edited after the run started). Refusing to execute it. ` +
53
+ `Start a new run.\n${errors.map((e) => ` - ${e}`).join("\n")}`);
54
+ }
@@ -0,0 +1,33 @@
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
+ * Plan hashing for the frozen-plan contract (redesign addendum, R1).
6
+ *
7
+ * `workflow start` persists `plan_json` + `plan_hash` on the run row
8
+ * (migration 006); every later invocation executes that snapshot. The hash is
9
+ * the sha256 (hex) of the plan's CANONICAL JSON — object keys recursively
10
+ * sorted — so two structurally-equal plans hash identically regardless of key
11
+ * insertion order, and the same program always freezes to the same hash.
12
+ *
13
+ * Pure module: no IO beyond node:crypto, no engine imports.
14
+ */
15
+ import { createHash } from "node:crypto";
16
+ /** sha256 hex of the canonical (recursively sorted-keys) JSON of the plan. */
17
+ export function computePlanHash(plan) {
18
+ return createHash("sha256").update(canonicalPlanJson(plan)).digest("hex");
19
+ }
20
+ /** The canonical JSON string the hash is computed over (also what to persist). */
21
+ export function canonicalPlanJson(plan) {
22
+ return JSON.stringify(sortKeys(plan));
23
+ }
24
+ function sortKeys(value) {
25
+ if (Array.isArray(value))
26
+ return value.map(sortKeys);
27
+ if (value && typeof value === "object") {
28
+ return Object.fromEntries(Object.entries(value)
29
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
30
+ .map(([k, v]) => [k, sortKeys(v)]));
31
+ }
32
+ return value;
33
+ }
@@ -0,0 +1,4 @@
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
+ export const WORKFLOW_IR_VERSION = 2;
@@ -233,7 +233,9 @@ function collectStepBody(subsections, lines, path, stepTitle, errors) {
233
233
  }
234
234
  errors.push({
235
235
  line: sub.headingLine,
236
- message: `Step "${stepTitle}" has an unknown "### ${sub.name}" section. Only "### Instructions" and "### Completion Criteria" are supported.`,
236
+ message: `Step "${stepTitle}" has an unknown "### ${sub.name}" section. Supported sections: ` +
237
+ `"### Instructions", "### Completion Criteria". For orchestrated workflows (runners, ` +
238
+ `fan-out, routing), author a YAML workflow program instead — see \`akm workflow template --yaml\`.`,
237
239
  });
238
240
  }
239
241
  return {