akm-cli 0.9.16 โ†’ 0.9.17-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (403) hide show
  1. package/CHANGELOG.md +2101 -0
  2. package/STABILITY.md +11 -10
  3. package/dist/akm +124 -193
  4. package/dist/akm-migrate +38 -19
  5. package/dist/assets/hints/cli-hints-full.md +6 -7
  6. package/dist/assets/improve-strategies/catchup.json +0 -3
  7. package/dist/assets/improve-strategies/consolidate.json +0 -1
  8. package/dist/assets/improve-strategies/default.json +1 -2
  9. package/dist/assets/improve-strategies/proactive-maintenance.json +1 -2
  10. package/dist/assets/improve-strategies/quick.json +1 -2
  11. package/dist/assets/improve-strategies/reflect-distill.json +1 -2
  12. package/dist/assets/improve-strategies/thorough.json +0 -3
  13. package/dist/assets/prompts/consolidate-pair.md +20 -0
  14. package/dist/assets/prompts/consolidate-system.md +4 -11
  15. package/dist/assets/prompts/retrieval-relevance-judge.md +6 -0
  16. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +20 -20
  17. package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -2
  18. package/dist/assets/templates/html/health.html +3 -5
  19. package/dist/cli/retired-commands.js +1 -1
  20. package/dist/cli/shared.js +6 -2
  21. package/dist/cli/unknown-flags.js +24 -1
  22. package/dist/cli.js +68 -10
  23. package/dist/commands/agent/agent-dispatch.js +1 -1
  24. package/dist/commands/command/command-execution.js +24 -62
  25. package/dist/commands/feedback-cli.js +0 -1
  26. package/dist/commands/health/accept-rate.js +6 -0
  27. package/dist/commands/health/archive-usage.js +92 -0
  28. package/dist/commands/health/checks.js +83 -74
  29. package/dist/commands/health/config-skew.js +38 -0
  30. package/dist/commands/health/data-dir-usage.js +25 -13
  31. package/dist/commands/health/egress.js +54 -0
  32. package/dist/commands/health/html-report.js +1 -42
  33. package/dist/commands/health/improve-metrics.js +136 -591
  34. package/dist/commands/health/md-report.js +1 -6
  35. package/dist/commands/health/plugin-staleness.js +53 -3
  36. package/dist/commands/health/renderers.js +12 -4
  37. package/dist/commands/health/report-view-model.js +14 -120
  38. package/dist/commands/health/types-improve.js +4 -19
  39. package/dist/commands/health/windows.js +64 -74
  40. package/dist/commands/health.js +145 -143
  41. package/dist/commands/improve/consolidate/chunking.js +26 -117
  42. package/dist/commands/improve/consolidate/continuity-check.js +137 -0
  43. package/dist/commands/improve/consolidate/pair-pass.js +791 -0
  44. package/dist/commands/improve/consolidate/sanitize.js +54 -149
  45. package/dist/commands/improve/consolidate.js +589 -1127
  46. package/dist/commands/improve/content-hash.js +16 -24
  47. package/dist/commands/improve/distill/content-repair.js +18 -100
  48. package/dist/commands/improve/distill-guards.js +20 -81
  49. package/dist/commands/improve/distill-promotion-policy.js +23 -243
  50. package/dist/commands/improve/distill.js +608 -1041
  51. package/dist/commands/improve/eligibility.js +126 -390
  52. package/dist/commands/improve/execution.js +8 -10
  53. package/dist/commands/improve/extract-prompt.js +1 -2
  54. package/dist/commands/improve/extract.js +487 -1046
  55. package/dist/commands/improve/feedback-valence.js +0 -25
  56. package/dist/commands/improve/improve-cli.js +75 -169
  57. package/dist/commands/improve/improve-result-file.js +10 -66
  58. package/dist/commands/improve/improve-strategies.js +52 -4
  59. package/dist/commands/improve/improve-usage-report.js +18 -64
  60. package/dist/commands/improve/improve.js +480 -1074
  61. package/dist/commands/improve/ledger.js +119 -0
  62. package/dist/commands/improve/locks.js +2 -8
  63. package/dist/commands/improve/loop-stages.js +415 -1073
  64. package/dist/commands/improve/memory/derived-ref.js +12 -77
  65. package/dist/commands/improve/memory/memory-belief.js +16 -118
  66. package/dist/commands/improve/memory/memory-improve.js +266 -14
  67. package/dist/commands/improve/outcome-loop.js +28 -156
  68. package/dist/commands/improve/planner.js +5 -15
  69. package/dist/commands/improve/preparation.js +779 -2319
  70. package/dist/commands/improve/proactive-maintenance.js +34 -101
  71. package/dist/commands/improve/reflect-noise.js +104 -280
  72. package/dist/commands/improve/reflect.js +642 -1353
  73. package/dist/commands/improve/retrieval-gate.js +127 -0
  74. package/dist/commands/improve/retrieval-scope.js +92 -0
  75. package/dist/commands/improve/salience.js +41 -240
  76. package/dist/commands/improve/session-asset.js +19 -100
  77. package/dist/commands/improve/stage.js +322 -0
  78. package/dist/commands/lint/base-linter.js +37 -15
  79. package/dist/commands/proposal/drain.js +261 -578
  80. package/dist/commands/proposal/proposal-cli.js +19 -20
  81. package/dist/commands/proposal/proposal-types.js +31 -24
  82. package/dist/commands/proposal/proposal.js +38 -8
  83. package/dist/commands/proposal/propose.js +134 -160
  84. package/dist/commands/proposal/repository.js +1097 -1394
  85. package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
  86. package/dist/commands/proposal/validators/proposal-validators.js +1 -1
  87. package/dist/commands/proposal/validators/proposals.js +22 -89
  88. package/dist/commands/read/curate.js +105 -462
  89. package/dist/commands/read/knowledge.js +3 -2
  90. package/dist/commands/read/search-cli.js +16 -33
  91. package/dist/commands/read/search.js +17 -23
  92. package/dist/commands/read/show.js +57 -108
  93. package/dist/commands/sources/bundle-cli.js +25 -2
  94. package/dist/commands/sources/bundle-config-ops.js +4 -0
  95. package/dist/commands/sources/dangerous-env-audit.js +1 -2
  96. package/dist/commands/sources/info.js +127 -29
  97. package/dist/commands/sources/installed-stashes.js +197 -746
  98. package/dist/commands/sources/schema-repair.js +98 -129
  99. package/dist/commands/sources/source-add.js +62 -12
  100. package/dist/commands/sources/source-manage.js +9 -2
  101. package/dist/commands/sources/stash-cli.js +24 -4
  102. package/dist/commands/tasks/explain.js +10 -13
  103. package/dist/commands/tasks/tasks-cli.js +12 -13
  104. package/dist/commands/tasks/tasks.js +350 -936
  105. package/dist/commands/tasks/validate.js +26 -24
  106. package/dist/commands/workflow/plan.js +22 -29
  107. package/dist/commands/workflow-cli.js +4 -4
  108. package/dist/core/adapter/adapters/akm-adapter.js +2 -1
  109. package/dist/core/adapter/adapters/akm-lint.js +2 -3
  110. package/dist/core/adapter/adapters/akm-metadata.js +42 -12
  111. package/dist/core/adapter/adapters/akm-task-adapter.js +29 -8
  112. package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
  113. package/dist/core/adapter/execution-source.js +17 -29
  114. package/dist/core/asset/asset-placement.js +4 -13
  115. package/dist/core/asset/frontmatter.js +106 -1
  116. package/dist/core/asset/resolve-ref.js +1 -1
  117. package/dist/core/bundle-id.js +42 -5
  118. package/dist/core/bundle-rename.js +285 -0
  119. package/dist/core/config/config-io.js +1 -2
  120. package/dist/core/config/config-schema.js +9 -34
  121. package/dist/core/config/config-walker.js +1 -1
  122. package/dist/core/config/config.js +184 -111
  123. package/dist/core/config/engine-semantics.js +0 -2
  124. package/dist/core/config/legacy-source-shape-shim.js +38 -9
  125. package/dist/core/config/schema/embedding.js +20 -5
  126. package/dist/core/config/schema/engines.js +5 -0
  127. package/dist/core/config/schema/execution.js +1 -1
  128. package/dist/core/config/schema/experimental.js +1 -1
  129. package/dist/core/config/schema/improve-processes.js +54 -125
  130. package/dist/core/config/schema/improve.js +4 -42
  131. package/dist/core/config/schema/index-config.js +9 -48
  132. package/dist/core/config/schema/scheduler.js +12 -12
  133. package/dist/core/config/schema/search.js +6 -22
  134. package/dist/core/env-secret-ref.js +0 -1
  135. package/dist/core/errors.js +8 -9
  136. package/dist/core/file-change.js +13 -5
  137. package/dist/core/file-lock.js +76 -173
  138. package/dist/core/improve-result.js +35 -7
  139. package/dist/core/improve-types.js +0 -1
  140. package/dist/core/logs-db.js +2 -2
  141. package/dist/core/loopback.js +7 -12
  142. package/dist/core/non-task-input.js +20 -0
  143. package/dist/core/parse.js +13 -16
  144. package/dist/core/paths.js +0 -24
  145. package/dist/core/redaction.js +109 -2
  146. package/dist/core/run-lock.js +2 -5
  147. package/dist/core/spawn-env.js +1 -1
  148. package/dist/core/state/migrations.js +123 -61
  149. package/dist/core/state-db-scope.js +2 -4
  150. package/dist/core/state-db.js +126 -692
  151. package/dist/core/time.js +0 -20
  152. package/dist/core/type-presentation.js +1 -9
  153. package/dist/core/write-source.js +294 -1005
  154. package/dist/execution/input-contract.js +1 -1
  155. package/dist/execution/resolved-request.js +135 -689
  156. package/dist/execution/source.js +63 -257
  157. package/dist/execution/target-ref.js +1 -1
  158. package/dist/indexer/bundle-identity-guard.js +2 -2
  159. package/dist/indexer/db/llm-cache.js +2 -2
  160. package/dist/indexer/ensure-index.js +77 -73
  161. package/dist/indexer/index-rebuild-lock.js +3 -11
  162. package/dist/indexer/index-writer-lock.js +8 -17
  163. package/dist/indexer/index-written-assets.js +141 -154
  164. package/dist/indexer/indexer.js +400 -1124
  165. package/dist/indexer/links/declared-links.js +90 -0
  166. package/dist/indexer/materialize-embeddings.js +60 -397
  167. package/dist/indexer/passes/memory-inference.js +96 -90
  168. package/dist/indexer/passes/metadata.js +132 -219
  169. package/dist/indexer/read-preflight.js +0 -7
  170. package/dist/indexer/scan/doc-to-entry.js +2 -3
  171. package/dist/indexer/scan/drain-dir.js +1 -1
  172. package/dist/indexer/search/db-search.js +190 -590
  173. package/dist/indexer/search/fts-query.js +30 -41
  174. package/dist/indexer/search/ranking.js +28 -154
  175. package/dist/indexer/search/search-attribution.js +12 -32
  176. package/dist/indexer/search/search-fields.js +11 -15
  177. package/dist/indexer/search/search-hit-enrichers.js +54 -85
  178. package/dist/indexer/search/search-source.js +1 -4
  179. package/dist/indexer/usage/usage-events.js +36 -7
  180. package/dist/indexer/walk/walker.js +3 -4
  181. package/dist/integrations/agent/engine-fallback.js +23 -40
  182. package/dist/integrations/agent/engine-resolution.js +93 -183
  183. package/dist/integrations/agent/execution.js +507 -0
  184. package/dist/integrations/agent/model-map.js +28 -156
  185. package/dist/integrations/agent/request-lowering.js +66 -141
  186. package/dist/integrations/agent/runner-dispatch.js +143 -321
  187. package/dist/integrations/agent/runner.js +54 -14
  188. package/dist/integrations/lockfile.js +53 -101
  189. package/dist/llm/client.js +18 -6
  190. package/dist/llm/embedders/deterministic.js +2 -3
  191. package/dist/llm/embedders/profile.js +71 -0
  192. package/dist/llm/embedders/remote.js +11 -17
  193. package/dist/llm/feature-gate.js +0 -8
  194. package/dist/llm/index-passes.js +3 -5
  195. package/dist/llm/memory-infer.js +1 -2
  196. package/dist/llm/structured-call.js +5 -24
  197. package/dist/output/generic-render.js +23 -11
  198. package/dist/output/html-render.js +13 -10
  199. package/dist/output/render-registry.js +3 -32
  200. package/dist/output/shapes/helpers.js +25 -38
  201. package/dist/output/shapes/passthrough.js +1 -9
  202. package/dist/{indexer/graph/graph-types.js โ†’ output/text/bundle-rename.js} +4 -1
  203. package/dist/output/text/command-format.js +69 -31
  204. package/dist/output/text/helpers.js +1 -1
  205. package/dist/output/text/migrate.js +5 -14
  206. package/dist/output/text/proposal-format.js +48 -3
  207. package/dist/output/text/show-format.js +13 -17
  208. package/dist/output/text/workflow-format.js +0 -32
  209. package/dist/output/text.js +2 -0
  210. package/dist/registry/factory.js +4 -19
  211. package/dist/registry/network.js +66 -220
  212. package/dist/registry/providers/index.js +0 -2
  213. package/dist/registry/providers/skills-sh.js +3 -14
  214. package/dist/registry/providers/static-index.js +24 -26
  215. package/dist/registry/resolve.js +55 -131
  216. package/dist/scripts/akm-migrate-node.js +42948 -92369
  217. package/dist/scripts/akm-migrate.js +42935 -92354
  218. package/dist/setup/registry-stash-loader.js +4 -13
  219. package/dist/setup/semantic-assets.js +3 -44
  220. package/dist/setup/setup.js +1 -1
  221. package/dist/setup/steps/connection.js +5 -6
  222. package/dist/setup/steps/platforms.js +2 -2
  223. package/dist/setup/steps/tasks.js +25 -15
  224. package/dist/sources/provider-factory.js +17 -18
  225. package/dist/sources/providers/filesystem.js +2 -3
  226. package/dist/sources/providers/git-install.js +7 -1
  227. package/dist/sources/providers/git-provider.js +0 -3
  228. package/dist/sources/providers/git-stash.js +83 -21
  229. package/dist/sources/providers/npm.js +2 -4
  230. package/dist/sources/providers/provider-utils.js +5 -10
  231. package/dist/sources/providers/website.js +0 -2
  232. package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
  233. package/dist/sources/website-url.js +2 -2
  234. package/dist/storage/database.js +9 -35
  235. package/dist/storage/repositories/improve-ledger-repository.js +209 -0
  236. package/dist/storage/repositories/index-connection.js +39 -72
  237. package/dist/storage/repositories/index-entries-repository.js +131 -129
  238. package/dist/storage/repositories/index-entry-mapper.js +1 -2
  239. package/dist/storage/repositories/index-entry-schema.js +101 -268
  240. package/dist/storage/repositories/index-fts-repository.js +86 -256
  241. package/dist/storage/repositories/index-links-repository.js +143 -0
  242. package/dist/storage/repositories/index-llm-cache-repository.js +7 -9
  243. package/dist/storage/repositories/index-meta-repository.js +6 -4
  244. package/dist/storage/repositories/index-schema.js +257 -325
  245. package/dist/storage/repositories/index-utility-repository.js +8 -29
  246. package/dist/storage/repositories/index-vec-repository.js +133 -414
  247. package/dist/storage/repositories/outcome-repository.js +2 -1
  248. package/dist/storage/repositories/proposals-repository.js +104 -1
  249. package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
  250. package/dist/storage/repositories/salience-repository.js +1 -19
  251. package/dist/storage/repositories/task-history-repository.js +26 -4
  252. package/dist/storage/repositories/workflow-runs-repository.js +53 -244
  253. package/dist/storage/sqlite-migrations.js +136 -0
  254. package/dist/storage/sqlite-pragmas.js +11 -9
  255. package/dist/storage/sqlite-transaction.js +170 -0
  256. package/dist/storage/state-db-integrity.js +130 -0
  257. package/dist/tasks/activation-config.js +134 -62
  258. package/dist/tasks/backends/cron.js +191 -302
  259. package/dist/tasks/backends/exec-utils.js +2 -5
  260. package/dist/tasks/backends/launchd.js +141 -748
  261. package/dist/tasks/backends/schtasks.js +119 -623
  262. package/dist/tasks/prepare/prepare-support.js +5 -15
  263. package/dist/tasks/prepare/prepare.js +0 -2
  264. package/dist/tasks/resolve-akm-bin.js +20 -79
  265. package/dist/tasks/run/attempt-lifecycle.js +0 -1
  266. package/dist/tasks/run/load-task.js +1 -1
  267. package/dist/tasks/scheduler-binding.js +20 -238
  268. package/dist/tasks/scheduler-invocation.js +136 -244
  269. package/dist/tasks/scheduler-lock.js +53 -0
  270. package/dist/tasks/scheduler-sync.js +368 -679
  271. package/dist/tasks/source/parse-task-source.js +55 -9
  272. package/dist/tasks/source/task-source-v3-frozen.js +3 -4
  273. package/dist/tasks/source/task-to-v4.js +464 -88
  274. package/dist/workflows/authoring/authoring.js +3 -12
  275. package/dist/workflows/compile.js +211 -0
  276. package/dist/workflows/concurrency-policy.js +13 -74
  277. package/dist/workflows/exec/child-invocation.js +3 -17
  278. package/dist/workflows/exec/child-workflow.js +32 -141
  279. package/dist/workflows/exec/dispatch-redaction.js +13 -53
  280. package/dist/workflows/exec/environment.js +98 -0
  281. package/dist/workflows/exec/exec-unit.js +33 -140
  282. package/dist/workflows/exec/frozen-judge.js +7 -59
  283. package/dist/workflows/exec/native-executor.js +82 -341
  284. package/dist/workflows/exec/param-secrets.js +29 -47
  285. package/dist/workflows/exec/run-workflow.js +154 -387
  286. package/dist/workflows/exec/scheduler.js +9 -36
  287. package/dist/workflows/exec/step-work.js +127 -430
  288. package/dist/workflows/exec/unit-dispatch.js +11 -63
  289. package/dist/workflows/exec/unit-writer.js +8 -52
  290. package/dist/workflows/exec/worktree.js +39 -273
  291. package/dist/workflows/freeze/child-output-references.js +4 -15
  292. package/dist/workflows/freeze/environment.js +99 -92
  293. package/dist/workflows/freeze/freeze.js +172 -0
  294. package/dist/workflows/freeze/step-values.js +19 -21
  295. package/dist/workflows/freeze/targets/child-workflow.js +23 -92
  296. package/dist/workflows/freeze/targets/command.js +10 -33
  297. package/dist/workflows/freeze/targets/script.js +5 -12
  298. package/dist/workflows/freeze/targets/shell.js +3 -6
  299. package/dist/workflows/freeze/targets/task.js +25 -80
  300. package/dist/workflows/freeze/task-bindings.js +20 -67
  301. package/dist/workflows/{source-ir/github-yaml.js โ†’ github-yaml.js} +88 -206
  302. package/dist/workflows/ir/params.js +6 -51
  303. package/dist/workflows/ir/plan-hash.js +2 -34
  304. package/dist/workflows/parser.js +140 -43
  305. package/dist/{commands/improve/consolidate/types.js โ†’ workflows/plan.js} +2 -1
  306. package/dist/workflows/renderer.js +36 -69
  307. package/dist/workflows/resource-limits.js +12 -120
  308. package/dist/workflows/runtime/agent-identity.js +8 -40
  309. package/dist/workflows/runtime/run-outputs.js +3 -6
  310. package/dist/workflows/runtime/run-plan.js +316 -0
  311. package/dist/workflows/runtime/runs.js +48 -200
  312. package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
  313. package/dist/workflows/{source-ir/semantics.js โ†’ source-semantics.js} +16 -20
  314. package/dist/workflows/validate-summary.js +2 -7
  315. package/docs/integration/bundling-akm.md +49 -42
  316. package/docs/migration/README.md +1 -0
  317. package/docs/migration/release-notes/0.9.17.md +43 -0
  318. package/docs/migration/v0.9.1-to-v0.9.2.md +23 -7
  319. package/docs/reference/cli.md +232 -135
  320. package/docs/reference/configuration.md +71 -57
  321. package/docs/reference/data-and-telemetry.md +20 -21
  322. package/docs/reference/tasks.md +105 -39
  323. package/docs/reference/workflow-schema.md +14 -18
  324. package/docs/reference/workflows.md +6 -9
  325. package/package.json +1 -1
  326. package/schemas/akm-config.json +115 -738
  327. package/schemas/akm-workflow.json +1 -0
  328. package/dist/assets/improve-strategies/graph-refresh.json +0 -15
  329. package/dist/assets/prompts/contradiction-judge.md +0 -33
  330. package/dist/assets/prompts/graph-extract-system.md +0 -1
  331. package/dist/assets/prompts/graph-extract-user-prompt.md +0 -35
  332. package/dist/assets/prompts/metadata-enhance-system.md +0 -1
  333. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +0 -4
  334. package/dist/commands/health/advisories.js +0 -150
  335. package/dist/commands/health/metrics.js +0 -329
  336. package/dist/commands/health/surfaces.js +0 -102
  337. package/dist/commands/improve/anti-collapse.js +0 -83
  338. package/dist/commands/improve/collapse-detector.js +0 -432
  339. package/dist/commands/improve/consolidate/eligibility.js +0 -48
  340. package/dist/commands/improve/consolidate/merge.js +0 -149
  341. package/dist/commands/improve/distill/promote-memory.js +0 -291
  342. package/dist/commands/improve/distill/quality-gate.js +0 -337
  343. package/dist/commands/improve/eval-cases.js +0 -52
  344. package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
  345. package/dist/commands/improve/proposal-envelope.js +0 -31
  346. package/dist/commands/improve/run-context.js +0 -123
  347. package/dist/commands/improve/shared.js +0 -31
  348. package/dist/commands/improve/source-identity.js +0 -28
  349. package/dist/commands/improve/triage.js +0 -96
  350. package/dist/commands/proposal/drain-policies.js +0 -151
  351. package/dist/commands/sources/update-transaction.js +0 -220
  352. package/dist/core/action-contributors.js +0 -28
  353. package/dist/core/config/config-version-shim.js +0 -101
  354. package/dist/core/fs-txn.js +0 -405
  355. package/dist/core/lexical-score.js +0 -25
  356. package/dist/core/maintenance-barrier.js +0 -167
  357. package/dist/execution/executable-identity.js +0 -105
  358. package/dist/execution/guarded-source.js +0 -427
  359. package/dist/indexer/db/graph-db.js +0 -444
  360. package/dist/indexer/graph/graph-boost.js +0 -427
  361. package/dist/indexer/graph/graph-dedup.js +0 -95
  362. package/dist/indexer/graph/graph-extraction.js +0 -1108
  363. package/dist/indexer/search/name-match.js +0 -35
  364. package/dist/indexer/search/ranking-contributors.js +0 -515
  365. package/dist/indexer/search/ranking-types.js +0 -4
  366. package/dist/indexer/walk/project-context.js +0 -192
  367. package/dist/integrations/agent/execution-cascade.js +0 -566
  368. package/dist/integrations/agent/execution-definitions.js +0 -202
  369. package/dist/integrations/agent/execution-lowering.js +0 -841
  370. package/dist/integrations/agent/execution-preparation.js +0 -98
  371. package/dist/integrations/agent/inline-execution.js +0 -74
  372. package/dist/llm/graph-extract.js +0 -728
  373. package/dist/llm/metadata-enhance.js +0 -96
  374. package/dist/registry/create-provider-registry.js +0 -29
  375. package/dist/registry/pinned-request-helper.js +0 -247
  376. package/dist/registry/pinned-transport.js +0 -717
  377. package/dist/sources/providers/index.js +0 -14
  378. package/dist/storage/engines/sqlite-migrations.js +0 -271
  379. package/dist/storage/repositories/canaries-repository.js +0 -107
  380. package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
  381. package/dist/storage/repositories/registry-cache.js +0 -113
  382. package/dist/tasks/scheduler-sync-preview.js +0 -52
  383. package/dist/tasks/source/task-to-v3.js +0 -507
  384. package/dist/workflows/freeze/resolve-steps.js +0 -86
  385. package/dist/workflows/freeze/source-freeze.js +0 -64
  386. package/dist/workflows/ir/compile.js +0 -321
  387. package/dist/workflows/ir/environment-v4.js +0 -330
  388. package/dist/workflows/ir/freeze-v4.js +0 -153
  389. package/dist/workflows/ir/schema-v4.js +0 -745
  390. package/dist/workflows/ir/schema.js +0 -354
  391. package/dist/workflows/program/schema.js +0 -77
  392. package/dist/workflows/runtime/checkin.js +0 -57
  393. package/dist/workflows/runtime/plan-classifier.js +0 -196
  394. package/dist/workflows/runtime/unit-checkin.js +0 -45
  395. package/dist/workflows/runtime/unit-phases.js +0 -20
  396. package/dist/workflows/schema.js +0 -4
  397. package/dist/workflows/source-ir/compile.js +0 -200
  398. package/dist/workflows/source-ir/program.js +0 -50
  399. package/dist/workflows/source-ir/result.js +0 -26
  400. package/dist/workflows/source-ir/schema.js +0 -786
  401. package/dist/workflows/source-ir/triggers.js +0 -79
  402. package/dist/workflows/source-ir/uses.js +0 -40
  403. package/dist/workflows/validator.js +0 -60
@@ -2,18 +2,10 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  /**
5
- * Plan hashing for the frozen-plan contract (redesign addendum, R1).
6
- *
7
- * `workflow run` 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.
5
+ * Plan hashing: sha256 of the plan's canonical JSON (keys recursively sorted),
6
+ * stored beside `plan_json` as information โ€” a stored plan is never gated on it.
14
7
  */
15
8
  import { createHash } from "node:crypto";
16
- import { decodeWorkflowPlanV4, WORKFLOW_IR_V5_VERSION } from "./schema-v4.js";
17
9
  /** sha256 hex of the canonical (recursively sorted-keys) JSON of the plan. */
18
10
  export function computePlanHash(plan) {
19
11
  return createHash("sha256").update(canonicalPlanJson(plan)).digest("hex");
@@ -26,30 +18,6 @@ export function canonicalPlanJson(plan) {
26
18
  export function canonicalJson(value) {
27
19
  return JSON.stringify(sortKeys(value));
28
20
  }
29
- /** Decode, require stored canonical bytes, then verify the stored SHA-256. */
30
- export function decodeCanonicalPlan(runId, planJson, planHash, expectedVersion) {
31
- let parsed;
32
- try {
33
- parsed = JSON.parse(planJson);
34
- }
35
- catch {
36
- throw new Error(`Workflow run ${runId} has corrupt frozen plan JSON.`);
37
- }
38
- const canonicalWire = canonicalJson(parsed);
39
- if (planJson !== canonicalWire)
40
- throw new Error(`Workflow run ${runId} has noncanonical frozen plan JSON.`);
41
- const actual = createHash("sha256").update(planJson).digest("hex");
42
- if (!planHash || !/^[0-9a-f]{64}$/.test(planHash) || actual !== planHash)
43
- throw new Error(`Workflow run ${runId} frozen plan integrity check failed.`);
44
- if (expectedVersion !== undefined && expectedVersion !== null && expectedVersion !== WORKFLOW_IR_V5_VERSION) {
45
- throw new Error(`Workflow run ${runId} uses unsupported workflow IR version ${expectedVersion}; this runtime supports only workflow IR version 5.`);
46
- }
47
- const plan = decodeWorkflowPlanV4(parsed);
48
- const canonical = canonicalPlanJson(plan);
49
- if (planJson !== canonical)
50
- throw new Error(`Workflow run ${runId} has noncanonical frozen plan JSON.`);
51
- return plan;
52
- }
53
21
  function sortKeys(value) {
54
22
  if (value === null || typeof value === "string" || typeof value === "boolean")
55
23
  return value;
@@ -10,11 +10,12 @@
10
10
  * parsed with the `yaml` package's `parseDocument` + `LineCounter` (best-effort
11
11
  * per-key line anchoring), the body's heading list with `parseMarkdownToc`
12
12
  * (already fence-aware) โ€” both already in the codebase. The parser
13
- * accumulates `WorkflowError`s rather than throwing.
13
+ * accumulates `WorkflowError`s rather than throwing, and emits a compiled
14
+ * {@link WorkflowPlan} directly (`plan.ts`).
14
15
  *
15
16
  * Frontmatter carries the orchestration graph (params/defaults/budget/steps);
16
17
  * the body carries per-step prose, joined to the graph by step id. Body rules
17
- * (spec ยง2.2), exactly three:
18
+ *, exactly three:
18
19
  *
19
20
  * 1. Every level-2 heading must be `## <step-id>` for a DECLARED step,
20
21
  * exactly (fenced code blocks are skipped when scanning for headings).
@@ -31,16 +32,45 @@
31
32
  * (`program/expressions.ts`): `map.over`, `route.input`, `inputs[]`.
32
33
  */
33
34
  import { LineCounter, parseDocument } from "yaml";
35
+ import { bundleRefToString, parseBundleRef } from "../core/asset/asset-ref.js";
34
36
  import { parseFrontmatterBlock } from "../core/asset/frontmatter.js";
35
37
  import { parseMarkdownToc } from "../core/asset/markdown.js";
36
- import { isContainedRelativePath, isRecord } from "../core/common.js";
38
+ import { compareCodePoints, isContainedRelativePath, isRecord } from "../core/common.js";
37
39
  import { formatExtraParamsIssue, validateExtraParams } from "../core/extra-params.js";
38
40
  import { checkJsonSchemaDefinition, JSON_SCHEMA_SUBSET_SUPPORTED_KEYWORDS } from "../core/json-schema.js";
41
+ import { INPUT_NAME_PATTERN } from "../execution/input-contract.js";
42
+ import { WORKFLOW_PLAN_VERSION, } from "./plan.js";
39
43
  import { parseReference } from "./program/expressions.js";
40
- import { PROGRAM_ISOLATION_KINDS, PROGRAM_ON_ERROR, PROGRAM_PARAM_NAME_PATTERN, PROGRAM_REDUCERS, PROGRAM_RETRY_REASONS, PROGRAM_STEP_ID_PATTERN, } from "./program/schema.js";
41
- import { jsonBytes, utf8Bytes, WORKFLOW_ENGINE_NAME_PATTERN, WORKFLOW_ENV_VAR_NAME_PATTERN, WORKFLOW_MAX_CONCURRENCY, WORKFLOW_MAX_ENGINE_NAME_LENGTH, WORKFLOW_MAX_EXTRA_PARAMS_BYTES, WORKFLOW_MAX_SCHEMA_BYTES, WORKFLOW_MAX_SOURCE_BYTES, WORKFLOW_MAX_TIMEOUT_MS, } from "./resource-limits.js";
42
- import { WORKFLOW_SCHEMA_VERSION, } from "./schema.js";
43
- import { runSemanticChecks } from "./validator.js";
44
+ import { jsonBytes, utf8Bytes, WORKFLOW_ENGINE_NAME_PATTERN, WORKFLOW_ENV_VAR_NAME_PATTERN, WORKFLOW_MAX_CONCURRENCY, WORKFLOW_MAX_ENGINE_NAME_LENGTH, WORKFLOW_MAX_EXTRA_PARAMS_BYTES, WORKFLOW_MAX_INSTRUCTION_BYTES, WORKFLOW_MAX_SCHEMA_BYTES, WORKFLOW_MAX_SOURCE_BYTES, WORKFLOW_MAX_TIMEOUT_MS, } from "./resource-limits.js";
45
+ // โ”€โ”€ The Markdown grammar's vocabulary (pinned against schemas/akm-workflow.json) โ”€โ”€
46
+ export const PROGRAM_REDUCERS = ["collect", "vote"];
47
+ export const PROGRAM_ON_ERROR = ["fail", "continue"];
48
+ export const PROGRAM_ISOLATION_KINDS = ["none", "worktree"];
49
+ /** `retry.on`: exactly the persisted `AgentFailureReason` taxonomy (the `satisfies` fails typecheck on drift). */
50
+ const RETRY_REASON_SET = {
51
+ timeout: true,
52
+ spawn_failed: true,
53
+ non_zero_exit: true,
54
+ parse_error: true,
55
+ cooldown: true,
56
+ llm_rate_limit: true,
57
+ llm_content_filter: true,
58
+ llm_invalid_json: true,
59
+ content_policy_reject: true,
60
+ unsupported_type: true,
61
+ no_change: true,
62
+ quality_rejected: true,
63
+ aborted: true,
64
+ };
65
+ export const PROGRAM_RETRY_REASONS = Object.keys(RETRY_REASON_SET);
66
+ /**
67
+ * Step ids are exactly the `<ident>` grammar `steps.<id>.output` references
68
+ * accept: no dots, so every step is addressable and `<stepId>.gate` can never
69
+ * collide with a real step id.
70
+ */
71
+ export const PROGRAM_STEP_ID_PATTERN = /^[A-Za-z_][A-Za-z0-9_-]*$/;
72
+ /** Param (and output) names: plain `params.<ident>`-addressable identifiers, shared with task inputs. */
73
+ export const PROGRAM_PARAM_NAME_PATTERN = INPUT_NAME_PATTERN;
44
74
  /** Envelope keys every AKM markdown asset carries ($ref'd from schemas/akm-asset-envelope.json). */
45
75
  const ENVELOPE_KEYS = [
46
76
  "type",
@@ -174,7 +204,7 @@ export function parseWorkflow(markdown, source) {
174
204
  checkUnknownKeys(ctx, root, [], TOP_LEVEL_KEYS, "workflow frontmatter");
175
205
  checkEnvelopeFields(ctx, root, frontmatterEndLine);
176
206
  const description = typeof root.description === "string" ? root.description : undefined;
177
- const tags = readTags(ctx, root.tags, frontmatterEndLine);
207
+ readTags(ctx, root.tags, frontmatterEndLine);
178
208
  const params = parseParams(ctx, root.params);
179
209
  const outputs = parseOutputs(ctx, root.outputs);
180
210
  const defaults = parseDefaults(ctx, root.defaults);
@@ -194,46 +224,113 @@ export function parseWorkflow(markdown, source) {
194
224
  });
195
225
  }
196
226
  }
197
- else {
198
- if (step.route === undefined && !section.instructions) {
199
- errors.push({
200
- line: section.headingLine,
201
- message: `Step "${step.id}" section ("## ${step.id}") is empty. Add the step's instructions below the heading.`,
202
- });
227
+ else if (step.route === undefined && !section.instructions) {
228
+ errors.push({
229
+ line: section.headingLine,
230
+ message: `Step "${step.id}" section ("## ${step.id}") is empty. Add the step's instructions below the heading.`,
231
+ });
232
+ }
233
+ for (const [block, what] of [
234
+ [section?.instructions, "instructions exceed"],
235
+ [section?.gateRubric, "gate rubric exceeds"],
236
+ ]) {
237
+ if (block && utf8Bytes(block.text) > WORKFLOW_MAX_INSTRUCTION_BYTES) {
238
+ errors.push({ line: block.source.start, message: `Step "${step.id}" ${what} the 256 KiB resource limit.` });
203
239
  }
204
240
  }
205
- const gate = step.gate ?? (section?.gateRubric ? {} : undefined);
206
- const out = {
207
- id: step.id,
241
+ const rubric = section?.gateRubric?.text;
242
+ return {
243
+ stepId: step.id,
244
+ title: step.id,
208
245
  sequenceIndex: index,
209
- ...(step.unit ? { unit: step.unit } : {}),
210
- ...(step.map ? { map: step.map } : {}),
211
- ...(step.route ? { route: step.route } : {}),
212
- ...(step.inputs ? { inputs: step.inputs } : {}),
213
- ...(step.output !== undefined ? { output: step.output } : {}),
214
- ...(gate ? { gate } : {}),
215
- ...(section?.instructions ? { instructions: section.instructions } : {}),
216
- ...(section?.gateRubric ? { gateRubric: section.gateRubric } : {}),
217
- source: step.source,
246
+ spec: stepSpec(step, section),
247
+ ...(step.route
248
+ ? {
249
+ route: {
250
+ input: step.route.input,
251
+ when: Object.fromEntries(step.route.branches.map((branch) => [branch.match, branch.stepId])),
252
+ ...(step.route.defaultStepId !== undefined ? { defaultStepId: step.route.defaultStepId } : {}),
253
+ },
254
+ }
255
+ : {}),
256
+ ...(step.output !== undefined ? { outputSchema: step.output } : {}),
257
+ gate: {
258
+ kind: "gate",
259
+ id: `${step.id}.gate`,
260
+ stepId: step.id,
261
+ criteria: rubric?.trim() ? [rubric] : [],
262
+ maxLoops: step.gate?.maxLoops ?? 1,
263
+ frozenJudge: null,
264
+ },
218
265
  };
219
- return out;
220
266
  });
221
- const draft = {
222
- schemaVersion: WORKFLOW_SCHEMA_VERSION,
223
- ...(description ? { description } : {}),
224
- ...(tags ? { tags } : {}),
225
- ...(params ? { params } : {}),
226
- ...(outputs ? { outputs } : {}),
227
- ...(defaults ? { defaults } : {}),
267
+ checkCanonicalXrefs(root.xrefs, frontmatterEndLine, errors);
268
+ if (errors.length > 0)
269
+ return { ok: false, errors: sortErrors(errors) };
270
+ const paramNames = params ? Object.keys(params) : [];
271
+ const plan = {
272
+ irVersion: WORKFLOW_PLAN_VERSION,
273
+ title: source.title ?? path.replace(/^.*[\\/]/, "").replace(/\.[^.]*$/, ""),
274
+ ...(params && paramNames.length > 0 ? { params: paramNames, paramSchemas: params } : {}),
275
+ ...(outputs ? { outputs: sortedByName(outputs) } : {}),
228
276
  ...(budget ? { budget } : {}),
229
- steps,
277
+ ...(defaults ? { defaults } : {}),
278
+ ...(description ? { description } : {}),
230
279
  ...(preamble ? { preamble } : {}),
231
- source: { path, lineCount: totalLines },
280
+ steps,
232
281
  };
233
- runSemanticChecks(draft, root, frontmatterEndLine, errors);
234
- if (errors.length > 0)
235
- return { ok: false, errors: sortErrors(errors) };
236
- return { ok: true, document: draft };
282
+ return { ok: true, plan };
283
+ }
284
+ /** The authored step as the plan carries it. A prose step is inline `akm/command` literal content. */
285
+ function stepSpec(step, section) {
286
+ const prose = section?.instructions?.text;
287
+ if (step.route)
288
+ return { ...(prose?.trim() ? { instructions: prose } : {}), source: step.source };
289
+ const dispatchUnit = step.map?.unit ?? step.unit;
290
+ const { exec, source: _unitSource, ...unit } = dispatchUnit ?? { source: step.source };
291
+ return {
292
+ ...(exec
293
+ ? { exec: { ...exec }, ...(prose?.trim() ? { instructions: prose } : {}) }
294
+ : { uses: "akm/command", commandMode: "literal", with: { content: prose ?? "" } }),
295
+ ...(Object.keys(unit).length > 0 ? { unit } : {}),
296
+ ...(step.map
297
+ ? {
298
+ map: {
299
+ over: step.map.over,
300
+ ...(step.map.concurrency !== undefined ? { concurrency: step.map.concurrency } : {}),
301
+ ...(step.map.reducer !== undefined ? { reducer: step.map.reducer } : {}),
302
+ },
303
+ }
304
+ : {}),
305
+ ...(step.inputs ? { inputs: [...step.inputs] } : {}),
306
+ source: step.source,
307
+ };
308
+ }
309
+ /** `outputs:` in canonical wire order (code-point ascending by name). */
310
+ function sortedByName(entries) {
311
+ return Object.fromEntries(Object.keys(entries)
312
+ .sort(compareCodePoints)
313
+ .map((name) => [name, entries[name]]));
314
+ }
315
+ /** `xrefs` entries must be canonical asset refs. */
316
+ function checkCanonicalXrefs(value, line, errors) {
317
+ if (!Array.isArray(value))
318
+ return; // shape already flagged by checkXrefs
319
+ for (const ref of value) {
320
+ try {
321
+ if (typeof ref !== "string")
322
+ throw new Error("non-canonical ref");
323
+ const parsed = parseBundleRef(ref);
324
+ if (parsed.conceptId.includes(":") || ref !== bundleRefToString(parsed))
325
+ throw new Error("non-canonical ref");
326
+ }
327
+ catch {
328
+ errors.push({
329
+ line,
330
+ message: `Workflow frontmatter "xrefs" contains an invalid or non-canonical ref: ${String(ref)}.`,
331
+ });
332
+ }
333
+ }
237
334
  }
238
335
  function bindStepSections(headings, lines, bodyStartLine, totalLines, path, declaredIds, errors) {
239
336
  const sections = new Map();
@@ -425,9 +522,9 @@ function parseParams(ctx, raw) {
425
522
  return Object.keys(params).length > 0 ? params : undefined;
426
523
  }
427
524
  /**
428
- * `outputs:` (P3b, spec ยง4.2): named, optionally schema-validated projections
525
+ * `outputs:`: named, optionally schema-validated projections
429
526
  * of step artifacts, exported when the run completes. Symmetrical with
430
- * `parseParams` above (B-N4) โ€” same authoring surface, same name grammar,
527
+ * `parseParams` above โ€” same authoring surface, same name grammar,
431
528
  * same schema-subset validator, same per-schema byte bound โ€” but each entry
432
529
  * is a STRUCTURED `{from, schema?}` mapping rather than a bare JSON Schema.
433
530
  *
@@ -435,7 +532,7 @@ function parseParams(ctx, raw) {
435
532
  * `steps.<id>.output(.<seg>)*` reference (never `params.<name>` โ€” an output
436
533
  * projects a step artifact, never a param, B-07). Whether the named step is
437
534
  * actually DECLARED in this document is a semantic, cross-step check left to
438
- * `ir/compile.ts`'s reference validation (B-06), mirroring how `inputs[]` /
535
+ * `compile.ts`'s `checkWorkflowPlan`, mirroring how `inputs[]` /
439
536
  * `map.over` / `route.input` already split "syntax here, semantics there".
440
537
  */
441
538
  function parseOutputs(ctx, raw) {
@@ -1,4 +1,5 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- export {};
4
+ /** Stored plans record this; earlier releases wrote 4 and 5, which still decode. */
5
+ export const WORKFLOW_PLAN_VERSION = 6;
@@ -2,17 +2,15 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  /**
5
- * Show + indexing renderer for peer workflow sources. `.md` and `.yml` both
6
- * compile through `compileWorkflowSource` into source IR v1, which is projected
7
- * down to the public `ShowResponse` shape and into search hints for the indexer,
8
- * including a compact per-step orchestration summary (engine/model or an exec
9
- * unit's argv, `map.over` reference, route table) when the step declares one.
5
+ * Show renderer for peer workflow sources. `.md` and `.yml` both compile
6
+ * through `compileWorkflowSource` into a plan, which is projected down to the
7
+ * public `ShowResponse` shape, including a compact per-step orchestration
8
+ * summary (engine/model or an exec unit's argv, `map.over` reference, route
9
+ * table) when the step declares one.
10
10
  */
11
11
  import { displayRef } from "../core/asset/resolve-ref.js";
12
12
  import { UsageError } from "../core/errors.js";
13
- import { projectExecCore } from "./program/schema.js";
14
- import { compileWorkflowSource } from "./source-ir/compile.js";
15
- import { sourceStepInstructions, workflowShellCommand } from "./source-ir/program.js";
13
+ import { compileWorkflowSource, routeDescription, workflowStepInstructions } from "./compile.js";
16
14
  function shellQuote(value) {
17
15
  return `'${value.replace(/'/g, `'\\''`)}'`;
18
16
  }
@@ -26,36 +24,18 @@ function deriveName(ctx) {
26
24
  const ext = ctx.relPath.lastIndexOf(".");
27
25
  return ext > 0 ? ctx.relPath.slice(0, ext) : ctx.relPath;
28
26
  }
29
- function loadSourceIr(ctx) {
27
+ function loadPlan(ctx) {
30
28
  const result = compileWorkflowSource(ctx.content(), { path: ctx.relPath, workspaceRoot: ctx.stashRoot });
31
29
  if (result.ok)
32
- return result.ir;
30
+ return result.plan;
33
31
  const summary = result.errors.map((e) => `${e.path}:${e.line} โ€” ${e.message}`).join("\n");
34
32
  throw new UsageError(`Workflow has errors:\n${summary}`);
35
33
  }
36
- /**
37
- * The instruction text a step contributes to the flat step projection. A
38
- * route step has no body requirement, so a deterministic description of the
39
- * routing table stands in when it declares no section (the spine still needs
40
- * a non-empty instructions string).
41
- */
42
- function stepInstructions(step) {
43
- const instructions = sourceStepInstructions(step);
44
- if (instructions)
45
- return instructions;
46
- if (step.route) {
47
- const branches = step.route.branches.map((b) => `"${b.match}" -> ${b.stepId}`);
48
- if (step.route.defaultStepId !== undefined)
49
- branches.push(`default -> ${step.route.defaultStepId}`);
50
- return `Route on ${step.route.input}: ${branches.join(", ")}.`;
51
- }
52
- return "";
53
- }
54
34
  /** Project the `params` block into the flat `WorkflowParameter` list. */
55
- function projectParameters(sourceIr) {
56
- if (!sourceIr.params)
35
+ function projectParameters(plan) {
36
+ if (!plan.paramSchemas)
57
37
  return undefined;
58
- const parameters = Object.entries(sourceIr.params).map(([name, schema]) => {
38
+ const parameters = Object.entries(plan.paramSchemas).map(([name, schema]) => {
59
39
  const description = schema.description;
60
40
  return { name, ...(typeof description === "string" && description !== "" ? { description } : {}) };
61
41
  });
@@ -91,15 +71,9 @@ function projectParameters(sourceIr) {
91
71
  * already carries whole.
92
72
  */
93
73
  function summarizeStepOrchestration(step, defaults) {
94
- const unit = step.unit;
95
- const exec = step.exec
96
- ? step.exec
97
- : step.run !== undefined
98
- ? {
99
- command: workflowShellCommand(step.shell ?? "sh", step.run),
100
- ...(step.workingDirectory ? { cwd: step.workingDirectory } : {}),
101
- }
102
- : undefined;
74
+ const spec = step.spec;
75
+ const unit = spec?.unit;
76
+ const exec = spec?.exec;
103
77
  const engine = exec ? undefined : (unit?.engine ?? defaults?.engine);
104
78
  const model = exec ? undefined : (unit?.model ?? defaults?.model);
105
79
  const timeoutMs = unit?.timeoutMs !== undefined ? unit.timeoutMs : defaults?.timeoutMs;
@@ -107,25 +81,24 @@ function summarizeStepOrchestration(step, defaults) {
107
81
  ...(engine !== undefined ? { engine } : {}),
108
82
  ...(model !== undefined ? { model } : {}),
109
83
  ...(timeoutMs !== undefined ? { timeoutMs } : {}),
110
- // Same projection the draft and the frozen plan use, so what `show` prints
111
- // cannot drift from what runs.
112
- ...(exec ? { exec: projectExecCore(exec) } : {}),
113
- ...(step.map
84
+ // Same projection the frozen plan uses, so what `show` prints cannot drift from what runs.
85
+ ...(exec ? { exec: { ...exec } } : {}),
86
+ ...(spec?.map
114
87
  ? {
115
88
  fanOut: {
116
- over: step.map.over,
117
- ...(step.map.concurrency !== undefined ? { concurrency: step.map.concurrency } : {}),
118
- reducer: step.map.reducer ?? "collect",
89
+ over: spec.map.over,
90
+ ...(spec.map.concurrency !== undefined ? { concurrency: spec.map.concurrency } : {}),
91
+ reducer: spec.map.reducer ?? "collect",
119
92
  },
120
93
  }
121
94
  : {}),
122
- ...(unit?.output !== undefined || step.output !== undefined ? { hasSchema: true } : {}),
95
+ ...(unit?.output !== undefined || step.outputSchema !== undefined ? { hasSchema: true } : {}),
123
96
  ...(unit?.env !== undefined ? { env: [...unit.env] } : {}),
124
97
  ...(step.route
125
98
  ? {
126
99
  route: {
127
100
  input: step.route.input,
128
- branches: step.route.branches.map((b) => ({ match: b.match, stepId: b.stepId })),
101
+ branches: Object.entries(step.route.when).map(([match, stepId]) => ({ match, stepId })),
129
102
  ...(step.route.defaultStepId !== undefined ? { defaultStepId: step.route.defaultStepId } : {}),
130
103
  },
131
104
  }
@@ -133,20 +106,15 @@ function summarizeStepOrchestration(step, defaults) {
133
106
  };
134
107
  return Object.keys(summary).length > 0 ? summary : undefined;
135
108
  }
136
- function projectStepDefinitions(sourceIr) {
137
- const flattened = sourceIr.jobs.flatMap((job) => job.steps.map((step) => ({ jobId: job.id, step })));
138
- const counts = new Map();
139
- for (const { step } of flattened)
140
- counts.set(step.id, (counts.get(step.id) ?? 0) + 1);
141
- return flattened.map(({ jobId, step }, sequenceIndex) => {
142
- const id = (counts.get(step.id) ?? 0) > 1 ? `${jobId}-${step.id}` : step.id;
143
- const orchestration = summarizeStepOrchestration(step, sourceIr.defaults);
109
+ function projectStepDefinitions(plan) {
110
+ return plan.steps.map((step, sequenceIndex) => {
111
+ const orchestration = summarizeStepOrchestration(step, plan.defaults);
112
+ const instructions = workflowStepInstructions(step);
144
113
  return {
145
- id,
146
- // No titles in the shared source IR โ€” a step IS its id.
147
- title: step.id,
148
- instructions: stepInstructions(step),
149
- ...(step.gate?.rubric?.trim() ? { completionCriteria: [step.gate.rubric] } : {}),
114
+ id: step.stepId,
115
+ title: step.stepId,
116
+ instructions: instructions || (step.route ? routeDescription(step.route) : ""),
117
+ ...(step.gate.criteria.length > 0 ? { completionCriteria: [...step.gate.criteria] } : {}),
150
118
  sequenceIndex,
151
119
  ...(orchestration ? { orchestration } : {}),
152
120
  };
@@ -156,26 +124,25 @@ export const workflowMdRenderer = {
156
124
  name: "workflow-md",
157
125
  buildShowResponse(ctx) {
158
126
  const name = deriveName(ctx);
159
- const sourceIr = loadSourceIr(ctx);
127
+ const plan = loadPlan(ctx);
160
128
  // WI-8.5b (display flip): the `akm workflow run <ref>` action is DISPLAY
161
129
  // output โ€” its spelling follows the D-R5 display rule (`displayRef`). A
162
130
  // primary/default-bundle workflow renders the SHORT conceptId
163
131
  // (`workflows/<name>`); a named source qualifies it as
164
132
  // (`<bundle>//workflows/<name>`).
165
133
  const ref = displayRef({ type: "workflow", name, bundleId: ctx.origin }, ctx.defaultBundle);
166
- const parameters = projectParameters(sourceIr);
134
+ const parameters = projectParameters(plan);
167
135
  return {
168
136
  type: "workflow",
169
137
  name,
170
138
  path: ctx.absPath,
171
139
  action: buildWorkflowAction(ref),
172
- ...(sourceIr.preamble ? { content: sourceIr.preamble } : {}),
173
- description: sourceIr.description,
174
- // No authored title in the shared source IR โ€” the asset's human name is
175
- // its `description`/H1 like any other asset; this is its canonical name.
140
+ ...(plan.preamble ? { content: plan.preamble } : {}),
141
+ description: plan.description,
142
+ // No authored title โ€” the asset's human name is its `description`/H1; this is its canonical name.
176
143
  workflowTitle: name,
177
144
  ...(parameters ? { parameters: parameters.map((p) => p.name), workflowParameters: parameters } : {}),
178
- steps: projectStepDefinitions(sourceIr),
145
+ steps: projectStepDefinitions(plan),
179
146
  };
180
147
  },
181
148
  };
@@ -6,18 +6,8 @@ export const WORKFLOW_MAX_SOURCE_BYTES = 1024 * 1024;
6
6
  export const WORKFLOW_MAX_INSTRUCTION_BYTES = 256 * 1024;
7
7
  export const WORKFLOW_MAX_SCHEMA_BYTES = 256 * 1024;
8
8
  export const WORKFLOW_MAX_EXTRA_PARAMS_BYTES = 64 * 1024;
9
- // โ”€โ”€ Dispatch-significant bounds shared across validation layers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
10
- //
11
- // Defined ONCE here so the enforcement layers cannot drift:
12
- // 1. the parser (`../parser.ts`) โ€” line-anchored authoring-time errors,
13
- // 2. the published JSON Schema (`schemas/akm-workflow.json`) โ€” mirrored
14
- // `maximum`/`pattern`/`maxLength` values, pinned against these constants
15
- // by `tests/integration/workflows/schema-drift.test.ts`,
16
- // 3. the strict frozen-plan decoder (`./ir/schema.ts`) โ€” the corruption
17
- // gate for persisted plans.
18
- // A bound enforced only by the decoder surfaces as a terse, unlocated
19
- // "Invalid frozen workflow plan" at `workflow run` โ€” after lint and
20
- // `workflow create` already said the document was fine.
9
+ // โ”€โ”€ Bounds the parser enforces, mirrored by schemas/akm-workflow.json โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
10
+ // (pinned by tests/workflows/schema-drift.test.ts)
21
11
  /** Max per-step map fan-out concurrency (also the run-level concurrency ceiling). */
22
12
  export const WORKFLOW_MAX_CONCURRENCY = 64;
23
13
  /** Max timeout in milliseconds (setTimeout's 32-bit signed ceiling: 2^31-1, ~24.8 days). */
@@ -26,69 +16,21 @@ export const WORKFLOW_MAX_TIMEOUT_MS = EXECUTION_MAX_TIMEOUT_MS;
26
16
  export const WORKFLOW_ENGINE_NAME_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
27
17
  export const WORKFLOW_MAX_ENGINE_NAME_LENGTH = 63;
28
18
  // โ”€โ”€ exec (shell) unit bounds โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
29
- /**
30
- * Grammar for an env var NAME in `pass_env:`. Matches the frozen-plan
31
- * `envPassthrough` grammar in `ir/schema.ts` so both allowlist surfaces accept
32
- * exactly the same identifiers.
33
- */
19
+ /** Grammar for an env var NAME (`pass_env:`, step `env:` keys, task env). */
34
20
  export const WORKFLOW_ENV_VAR_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
35
21
  /**
36
- * Default wall-clock timeout for an exec unit that declares no `timeout:` and
37
- * inherits no document `defaults.timeout`.
38
- *
39
- * 10 minutes matches `DEFAULT_LLM_TIMEOUT_MS`. Unlike an agent harness (which
40
- * owns its own lifetime, hence `DEFAULT_AGENT_TIMEOUT_MS === null`), a shell
41
- * command has NO lifetime discipline of its own: an unbounded default would let
42
- * a hung `npm install` or an interactive prompt wedge a workflow run forever.
43
- * Authors who genuinely need an unbounded command write `timeout: none`.
22
+ * Default timeout for an exec unit with no `timeout:` of its own or in
23
+ * `defaults` (a command has no lifetime discipline; `timeout: none` opts out).
44
24
  */
45
25
  export const DEFAULT_EXEC_TIMEOUT_MS = 600_000;
46
26
  /**
47
- * Max BYTES of ONE captured pipe an exec unit RETAINS in memory (stdout and
48
- * stderr are retained separately).
49
- *
50
- * This is a RETENTION cap, not a permission to run. Without it the capture is
51
- * bounded only by the command's exit or the wall timeout, so a command that
52
- * writes continuously (`yes`, a verbose test loop) grows a string in the akm
53
- * process until the host runs out of memory โ€” and the default budget gives it
54
- * ten minutes to do so. What the cap buys is a BOUND where there was none: the
55
- * retained prefix is promoted into the unit's outcome text and every outcome is
56
- * held until the step reduces, so the worst case is (units in the STEP ร— this
57
- * cap) โ€” the step's width, not the in-flight width, is what sizes it.
58
- *
59
- * On reaching the cap the reader switches to DRAIN-AND-DISCARD: it keeps
60
- * pulling from the pipe (so the child never blocks on backpressure) and stops
61
- * RETAINING. The command therefore runs to completion and its real exit code
62
- * stands โ€” a passing-but-chatty test suite is no longer failed over log volume.
63
- * What overflow costs is honesty about the artifact, and that is paid two ways
64
- * in `exec/exec-unit.ts`:
65
- *
66
- * - no declared `output:` schema โ†’ the unit succeeds and its artifact carries
67
- * an unmistakable {@link WORKFLOW_EXEC_OUTPUT_TRUNCATED_MARKER} block naming
68
- * the total and retained byte counts, so truncated text can never be
69
- * mistaken for the whole output;
70
- * - a declared `output:` schema โ†’ the unit fails `exec_output_limit`, because
71
- * validating a truncated JSON prefix is meaningless and promoting it would
72
- * corrupt every downstream reference. That is the residual failure the cap
73
- * genuinely justifies.
74
- *
75
- * 8 MiB is deliberately generous, so any output a step is likely to produce
76
- * fits many times over and an ordinary full test/build log is nowhere near
77
- * it.
27
+ * Max bytes of one captured pipe an exec unit retains in memory. Past it the
28
+ * reader drains and discards, so the command still runs to its real exit
29
+ * code; the artifact gets a {@link WORKFLOW_EXEC_OUTPUT_TRUNCATED_MARKER}
30
+ * block, or the unit fails `exec_output_limit` if it declared an `output:` schema.
78
31
  */
79
32
  export const WORKFLOW_MAX_EXEC_OUTPUT_BYTES = 8 * 1024 * 1024;
80
- /**
81
- * Marker stamped on an exec artifact that was RETAINED ONLY IN PART because the
82
- * command wrote past {@link WORKFLOW_MAX_EXEC_OUTPUT_BYTES}.
83
- *
84
- * Deliberately ugly and unique: a truncated value must NEVER be mistakable
85
- * for a complete one by a downstream `steps.<id>.output` reference, by a gate
86
- * judge, by `akm workflow status`, or by a human reading the row. The
87
- * artifact is TEXT here rather than a JSON value, so the marker is appended
88
- * as a trailing block instead of replacing the value with an envelope: the
89
- * retained prefix is still genuinely useful (it is the head of a real log),
90
- * and the block says exactly how much is missing.
91
- */
33
+ /** Appended to an exec artifact retained only in part, so it is never mistaken for complete output. */
92
34
  export const WORKFLOW_EXEC_OUTPUT_TRUNCATED_MARKER = "__akm_exec_output_truncated__";
93
35
  // Per-var: Win32 `SetEnvironmentVariable` caps one variable at 32 767 UTF-16
94
36
  // code units; measuring UTF-8 bytes is conservative in the right direction.
@@ -116,65 +58,15 @@ const EXEC_CONTEXT_LIMITS_POSIX = {
116
58
  export function execContextLimits(platform = process.platform) {
117
59
  return platform === "win32" ? EXEC_CONTEXT_LIMITS_WIN32 : EXEC_CONTEXT_LIMITS_POSIX;
118
60
  }
119
- /**
120
- * Max characters of the per-unit human diagnostic โ€” the `error`/stderr text
121
- * journaled on a failed unit row and rendered by `akm workflow status --units`.
122
- *
123
- * ONE constant for the write side (`exec/native-executor.ts`, which clips before
124
- * journaling) and the read side (`runtime/runs.ts`, which clips whatever a row
125
- * already holds), so a diagnostic can never be stored larger than the surface
126
- * that displays it. Long enough for a real stack trace or a compiler's error
127
- * block; short enough that a runaway command cannot turn the journal into its
128
- * log file.
129
- */
61
+ /** Max characters of a unit's journaled diagnostic, on both the write and the display side. */
130
62
  export const WORKFLOW_UNIT_DIAGNOSTIC_CLIP = 2_000;
131
- /**
132
- * Truncate to `max` chars with an ellipsis marker.
133
- *
134
- * Lives with the bounds rather than with either caller: the write side
135
- * (`exec/step-work.ts`) and the read side (`runtime/runs.ts`) clip against the
136
- * same constants, and `runtime/runs.ts` cannot take the helper from
137
- * `exec/step-work.ts` โ€” that module imports `runtime/runs.ts`.
138
- */
63
+ /** Truncate to `max` chars with an ellipsis marker. */
139
64
  export function clip(text, max) {
140
65
  return text.length > max ? `${text.slice(0, max)}โ€ฆ` : text;
141
66
  }
142
- // โ”€โ”€ Persistence bounds โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
143
- //
144
- // `workflow_run_steps.evidence_json` is persisted WHOLE and unclipped. It used
145
- // to be capped at 1 MiB, past which the row was replaced by a marked
146
- // truncation envelope โ€” but the run still looked successful, and the NEXT
147
- // invocation (a resume, or any later step referencing the artifact) failed
148
- // permanently: the value was gone from the only place a resumed run can read
149
- // it from, so every prior paid step had to be re-run from scratch. SQLite has
150
- // no practical row-size problem here (its own ceiling is ~1 GB), so there is
151
- // nothing this cap protected that a full write does not already handle
152
- // correctly. `JSON.stringify` throwing on genuinely unserializable evidence
153
- // is unchanged.
154
67
  export function utf8Bytes(value) {
155
68
  return Buffer.byteLength(value, "utf8");
156
69
  }
157
70
  export function jsonBytes(value) {
158
71
  return utf8Bytes(JSON.stringify(value));
159
72
  }
160
- // โ”€โ”€ Recursive child-workflow composition bounds (spec docs/plans/specs/
161
- // โ”€โ”€ p3a-plan-v5-child-freeze.md ยง4.5, A-N6) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
162
- //
163
- // Composition DEPTH is unbounded โ€” `assertNoCompositionCycle` (freeze/targets/
164
- // child-workflow.ts) already makes infinite composition mathematically
165
- // impossible, so a depth ceiling on top of it only bounded how many
166
- // legitimately distinct workflows an author could nest.
167
- //
168
- // This section used to also cap the AGGREGATE canonical-JSON bytes of every
169
- // embedded child plan in one root freeze (`WORKFLOW_MAX_EMBEDDED_CHILD_PLAN_BYTES`,
170
- // enforced in `freeze/targets/child-workflow.ts` and re-checked on every
171
- // decode in `ir/schema-v4.ts`'s `decodeChildWorkflowTarget`), alongside a
172
- // standalone cap on any one frozen plan's own bytes
173
- // (`WORKFLOW_MAX_PLAN_BYTES`, enforced in `ir/plan-hash.ts` and
174
- // `ir/schema.ts`). A large plan is not a wrong plan: composing several
175
- // substantial workflows together is a legitimate, deliberate authoring
176
- // choice, and SQLite has no practical row-size problem here (its own
177
- // ceiling is ~1 GB) โ€” there was nothing left for either cap to protect that
178
- // `planHash`/`contentHash` verification does not already cover. Both caps
179
- // are removed; the hash/canonical-JSON integrity checks they sat next to
180
- // are unchanged.