akm-cli 0.9.17-alpha.1 → 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 (399) hide show
  1. package/CHANGELOG.md +1623 -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/retrieval-relevance-judge.md +6 -0
  15. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +20 -20
  16. package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -2
  17. package/dist/assets/templates/html/health.html +3 -5
  18. package/dist/cli/retired-commands.js +1 -1
  19. package/dist/cli/shared.js +6 -2
  20. package/dist/cli/unknown-flags.js +24 -1
  21. package/dist/cli.js +68 -10
  22. package/dist/commands/agent/agent-dispatch.js +1 -1
  23. package/dist/commands/command/command-execution.js +24 -62
  24. package/dist/commands/feedback-cli.js +0 -1
  25. package/dist/commands/health/accept-rate.js +2 -2
  26. package/dist/commands/health/archive-usage.js +92 -0
  27. package/dist/commands/health/checks.js +30 -75
  28. package/dist/commands/health/config-skew.js +38 -0
  29. package/dist/commands/health/data-dir-usage.js +25 -13
  30. package/dist/commands/health/egress.js +54 -0
  31. package/dist/commands/health/html-report.js +1 -42
  32. package/dist/commands/health/improve-metrics.js +136 -587
  33. package/dist/commands/health/md-report.js +1 -6
  34. package/dist/commands/health/plugin-staleness.js +53 -3
  35. package/dist/commands/health/renderers.js +12 -4
  36. package/dist/commands/health/report-view-model.js +14 -119
  37. package/dist/commands/health/types-improve.js +4 -19
  38. package/dist/commands/health/windows.js +64 -74
  39. package/dist/commands/health.js +135 -143
  40. package/dist/commands/improve/consolidate/chunking.js +25 -100
  41. package/dist/commands/improve/consolidate/continuity-check.js +137 -0
  42. package/dist/commands/improve/consolidate/pair-pass.js +791 -0
  43. package/dist/commands/improve/consolidate/sanitize.js +54 -149
  44. package/dist/commands/improve/consolidate.js +573 -1124
  45. package/dist/commands/improve/content-hash.js +16 -24
  46. package/dist/commands/improve/distill/content-repair.js +18 -100
  47. package/dist/commands/improve/distill-guards.js +20 -81
  48. package/dist/commands/improve/distill-promotion-policy.js +23 -243
  49. package/dist/commands/improve/distill.js +608 -1075
  50. package/dist/commands/improve/eligibility.js +126 -400
  51. package/dist/commands/improve/execution.js +8 -10
  52. package/dist/commands/improve/extract-prompt.js +1 -2
  53. package/dist/commands/improve/extract.js +487 -1046
  54. package/dist/commands/improve/feedback-valence.js +0 -25
  55. package/dist/commands/improve/improve-cli.js +54 -171
  56. package/dist/commands/improve/improve-result-file.js +10 -66
  57. package/dist/commands/improve/improve-strategies.js +35 -9
  58. package/dist/commands/improve/improve-usage-report.js +18 -64
  59. package/dist/commands/improve/improve.js +451 -1082
  60. package/dist/commands/improve/ledger.js +119 -0
  61. package/dist/commands/improve/locks.js +2 -8
  62. package/dist/commands/improve/loop-stages.js +401 -1192
  63. package/dist/commands/improve/memory/derived-ref.js +12 -77
  64. package/dist/commands/improve/memory/memory-belief.js +16 -118
  65. package/dist/commands/improve/memory/memory-improve.js +266 -14
  66. package/dist/commands/improve/outcome-loop.js +28 -156
  67. package/dist/commands/improve/planner.js +5 -15
  68. package/dist/commands/improve/preparation.js +776 -2349
  69. package/dist/commands/improve/proactive-maintenance.js +34 -101
  70. package/dist/commands/improve/reflect-noise.js +104 -280
  71. package/dist/commands/improve/reflect.js +642 -1364
  72. package/dist/commands/improve/retrieval-gate.js +127 -0
  73. package/dist/commands/improve/retrieval-scope.js +92 -0
  74. package/dist/commands/improve/salience.js +41 -240
  75. package/dist/commands/improve/session-asset.js +19 -100
  76. package/dist/commands/improve/stage.js +322 -0
  77. package/dist/commands/lint/base-linter.js +37 -15
  78. package/dist/commands/proposal/drain.js +258 -644
  79. package/dist/commands/proposal/proposal-cli.js +19 -20
  80. package/dist/commands/proposal/proposal-types.js +27 -41
  81. package/dist/commands/proposal/proposal.js +38 -8
  82. package/dist/commands/proposal/propose.js +134 -160
  83. package/dist/commands/proposal/repository.js +1099 -1475
  84. package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
  85. package/dist/commands/proposal/validators/proposal-validators.js +1 -1
  86. package/dist/commands/proposal/validators/proposals.js +22 -89
  87. package/dist/commands/read/curate.js +105 -462
  88. package/dist/commands/read/knowledge.js +3 -2
  89. package/dist/commands/read/search-cli.js +16 -33
  90. package/dist/commands/read/search.js +17 -23
  91. package/dist/commands/read/show.js +57 -108
  92. package/dist/commands/sources/bundle-cli.js +25 -2
  93. package/dist/commands/sources/bundle-config-ops.js +4 -0
  94. package/dist/commands/sources/dangerous-env-audit.js +1 -2
  95. package/dist/commands/sources/info.js +127 -29
  96. package/dist/commands/sources/installed-stashes.js +197 -746
  97. package/dist/commands/sources/schema-repair.js +98 -129
  98. package/dist/commands/sources/source-add.js +62 -12
  99. package/dist/commands/sources/source-manage.js +9 -2
  100. package/dist/commands/sources/stash-cli.js +24 -4
  101. package/dist/commands/tasks/explain.js +10 -13
  102. package/dist/commands/tasks/tasks-cli.js +12 -13
  103. package/dist/commands/tasks/tasks.js +350 -936
  104. package/dist/commands/tasks/validate.js +26 -24
  105. package/dist/commands/workflow/plan.js +22 -29
  106. package/dist/commands/workflow-cli.js +4 -4
  107. package/dist/core/adapter/adapters/akm-adapter.js +2 -1
  108. package/dist/core/adapter/adapters/akm-lint.js +2 -3
  109. package/dist/core/adapter/adapters/akm-metadata.js +42 -12
  110. package/dist/core/adapter/adapters/akm-task-adapter.js +29 -8
  111. package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
  112. package/dist/core/adapter/execution-source.js +17 -29
  113. package/dist/core/asset/asset-placement.js +4 -13
  114. package/dist/core/asset/resolve-ref.js +1 -1
  115. package/dist/core/bundle-id.js +42 -5
  116. package/dist/core/bundle-rename.js +285 -0
  117. package/dist/core/config/config-io.js +1 -2
  118. package/dist/core/config/config-schema.js +9 -34
  119. package/dist/core/config/config-walker.js +1 -1
  120. package/dist/core/config/config.js +184 -111
  121. package/dist/core/config/engine-semantics.js +0 -2
  122. package/dist/core/config/legacy-source-shape-shim.js +38 -9
  123. package/dist/core/config/schema/embedding.js +20 -5
  124. package/dist/core/config/schema/engines.js +5 -0
  125. package/dist/core/config/schema/execution.js +1 -1
  126. package/dist/core/config/schema/experimental.js +1 -1
  127. package/dist/core/config/schema/improve-processes.js +37 -135
  128. package/dist/core/config/schema/improve.js +4 -42
  129. package/dist/core/config/schema/index-config.js +9 -48
  130. package/dist/core/config/schema/scheduler.js +12 -12
  131. package/dist/core/config/schema/search.js +6 -22
  132. package/dist/core/env-secret-ref.js +0 -1
  133. package/dist/core/errors.js +8 -9
  134. package/dist/core/file-change.js +13 -5
  135. package/dist/core/file-lock.js +76 -173
  136. package/dist/core/improve-result.js +26 -7
  137. package/dist/core/improve-types.js +0 -1
  138. package/dist/core/logs-db.js +2 -2
  139. package/dist/core/loopback.js +7 -12
  140. package/dist/core/non-task-input.js +20 -0
  141. package/dist/core/parse.js +13 -16
  142. package/dist/core/paths.js +0 -31
  143. package/dist/core/redaction.js +109 -2
  144. package/dist/core/run-lock.js +2 -5
  145. package/dist/core/spawn-env.js +1 -1
  146. package/dist/core/state/migrations.js +123 -61
  147. package/dist/core/state-db-scope.js +2 -4
  148. package/dist/core/state-db.js +126 -692
  149. package/dist/core/time.js +0 -20
  150. package/dist/core/type-presentation.js +1 -9
  151. package/dist/core/write-source.js +294 -1005
  152. package/dist/execution/input-contract.js +1 -1
  153. package/dist/execution/resolved-request.js +135 -689
  154. package/dist/execution/source.js +63 -257
  155. package/dist/execution/target-ref.js +1 -1
  156. package/dist/indexer/bundle-identity-guard.js +2 -2
  157. package/dist/indexer/db/llm-cache.js +2 -2
  158. package/dist/indexer/ensure-index.js +46 -87
  159. package/dist/indexer/index-rebuild-lock.js +3 -11
  160. package/dist/indexer/index-writer-lock.js +8 -17
  161. package/dist/indexer/index-written-assets.js +141 -154
  162. package/dist/indexer/indexer.js +400 -1124
  163. package/dist/indexer/links/declared-links.js +90 -0
  164. package/dist/indexer/materialize-embeddings.js +60 -397
  165. package/dist/indexer/passes/memory-inference.js +81 -90
  166. package/dist/indexer/passes/metadata.js +132 -219
  167. package/dist/indexer/read-preflight.js +0 -7
  168. package/dist/indexer/scan/doc-to-entry.js +2 -3
  169. package/dist/indexer/scan/drain-dir.js +1 -1
  170. package/dist/indexer/search/db-search.js +190 -590
  171. package/dist/indexer/search/fts-query.js +30 -41
  172. package/dist/indexer/search/ranking.js +28 -154
  173. package/dist/indexer/search/search-attribution.js +12 -32
  174. package/dist/indexer/search/search-fields.js +11 -15
  175. package/dist/indexer/search/search-hit-enrichers.js +54 -85
  176. package/dist/indexer/search/search-source.js +1 -4
  177. package/dist/indexer/usage/usage-events.js +36 -7
  178. package/dist/indexer/walk/walker.js +3 -4
  179. package/dist/integrations/agent/engine-fallback.js +23 -40
  180. package/dist/integrations/agent/engine-resolution.js +93 -183
  181. package/dist/integrations/agent/execution.js +507 -0
  182. package/dist/integrations/agent/model-map.js +28 -156
  183. package/dist/integrations/agent/request-lowering.js +66 -141
  184. package/dist/integrations/agent/runner-dispatch.js +143 -321
  185. package/dist/integrations/agent/runner.js +54 -14
  186. package/dist/integrations/lockfile.js +53 -101
  187. package/dist/llm/client.js +8 -10
  188. package/dist/llm/embedders/deterministic.js +2 -3
  189. package/dist/llm/embedders/profile.js +71 -0
  190. package/dist/llm/embedders/remote.js +11 -17
  191. package/dist/llm/feature-gate.js +0 -8
  192. package/dist/llm/index-passes.js +3 -5
  193. package/dist/llm/memory-infer.js +1 -2
  194. package/dist/llm/structured-call.js +5 -24
  195. package/dist/output/generic-render.js +23 -11
  196. package/dist/output/html-render.js +13 -10
  197. package/dist/output/render-registry.js +3 -32
  198. package/dist/output/shapes/helpers.js +25 -38
  199. package/dist/output/shapes/passthrough.js +1 -9
  200. package/dist/{indexer/graph/graph-types.js → output/text/bundle-rename.js} +4 -1
  201. package/dist/output/text/command-format.js +69 -31
  202. package/dist/output/text/helpers.js +1 -1
  203. package/dist/output/text/migrate.js +5 -14
  204. package/dist/output/text/proposal-format.js +48 -3
  205. package/dist/output/text/show-format.js +13 -17
  206. package/dist/output/text/workflow-format.js +0 -32
  207. package/dist/output/text.js +2 -0
  208. package/dist/registry/factory.js +4 -19
  209. package/dist/registry/network.js +66 -220
  210. package/dist/registry/providers/index.js +0 -2
  211. package/dist/registry/providers/skills-sh.js +3 -14
  212. package/dist/registry/providers/static-index.js +24 -26
  213. package/dist/registry/resolve.js +55 -131
  214. package/dist/scripts/akm-migrate-node.js +42938 -92375
  215. package/dist/scripts/akm-migrate.js +42930 -92365
  216. package/dist/setup/registry-stash-loader.js +4 -13
  217. package/dist/setup/semantic-assets.js +3 -44
  218. package/dist/setup/setup.js +1 -1
  219. package/dist/setup/steps/connection.js +5 -6
  220. package/dist/setup/steps/platforms.js +2 -2
  221. package/dist/setup/steps/tasks.js +25 -15
  222. package/dist/sources/provider-factory.js +17 -18
  223. package/dist/sources/providers/filesystem.js +2 -3
  224. package/dist/sources/providers/git-install.js +7 -1
  225. package/dist/sources/providers/git-provider.js +0 -3
  226. package/dist/sources/providers/git-stash.js +83 -21
  227. package/dist/sources/providers/npm.js +2 -4
  228. package/dist/sources/providers/provider-utils.js +5 -10
  229. package/dist/sources/providers/website.js +0 -2
  230. package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
  231. package/dist/sources/website-url.js +2 -2
  232. package/dist/storage/database.js +9 -35
  233. package/dist/storage/repositories/improve-ledger-repository.js +209 -0
  234. package/dist/storage/repositories/index-connection.js +39 -72
  235. package/dist/storage/repositories/index-entries-repository.js +88 -129
  236. package/dist/storage/repositories/index-entry-mapper.js +1 -2
  237. package/dist/storage/repositories/index-entry-schema.js +101 -268
  238. package/dist/storage/repositories/index-fts-repository.js +86 -256
  239. package/dist/storage/repositories/index-links-repository.js +143 -0
  240. package/dist/storage/repositories/index-llm-cache-repository.js +7 -9
  241. package/dist/storage/repositories/index-meta-repository.js +6 -4
  242. package/dist/storage/repositories/index-schema.js +257 -325
  243. package/dist/storage/repositories/index-utility-repository.js +8 -29
  244. package/dist/storage/repositories/index-vec-repository.js +133 -414
  245. package/dist/storage/repositories/outcome-repository.js +2 -1
  246. package/dist/storage/repositories/proposals-repository.js +100 -0
  247. package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
  248. package/dist/storage/repositories/salience-repository.js +1 -19
  249. package/dist/storage/repositories/task-history-repository.js +26 -4
  250. package/dist/storage/repositories/workflow-runs-repository.js +53 -244
  251. package/dist/storage/sqlite-migrations.js +136 -0
  252. package/dist/storage/sqlite-pragmas.js +11 -9
  253. package/dist/storage/sqlite-transaction.js +170 -0
  254. package/dist/storage/state-db-integrity.js +34 -27
  255. package/dist/tasks/activation-config.js +134 -62
  256. package/dist/tasks/backends/cron.js +191 -302
  257. package/dist/tasks/backends/exec-utils.js +2 -5
  258. package/dist/tasks/backends/launchd.js +141 -748
  259. package/dist/tasks/backends/schtasks.js +119 -623
  260. package/dist/tasks/prepare/prepare-support.js +5 -15
  261. package/dist/tasks/prepare/prepare.js +0 -2
  262. package/dist/tasks/resolve-akm-bin.js +20 -79
  263. package/dist/tasks/run/attempt-lifecycle.js +0 -1
  264. package/dist/tasks/run/load-task.js +1 -1
  265. package/dist/tasks/scheduler-binding.js +20 -238
  266. package/dist/tasks/scheduler-invocation.js +136 -244
  267. package/dist/tasks/scheduler-lock.js +53 -0
  268. package/dist/tasks/scheduler-sync.js +368 -679
  269. package/dist/tasks/source/parse-task-source.js +55 -9
  270. package/dist/tasks/source/task-source-v3-frozen.js +3 -4
  271. package/dist/tasks/source/task-to-v4.js +464 -88
  272. package/dist/workflows/authoring/authoring.js +3 -12
  273. package/dist/workflows/compile.js +211 -0
  274. package/dist/workflows/concurrency-policy.js +13 -74
  275. package/dist/workflows/exec/child-invocation.js +3 -17
  276. package/dist/workflows/exec/child-workflow.js +32 -141
  277. package/dist/workflows/exec/dispatch-redaction.js +13 -53
  278. package/dist/workflows/exec/environment.js +98 -0
  279. package/dist/workflows/exec/exec-unit.js +33 -140
  280. package/dist/workflows/exec/frozen-judge.js +7 -59
  281. package/dist/workflows/exec/native-executor.js +82 -341
  282. package/dist/workflows/exec/param-secrets.js +29 -47
  283. package/dist/workflows/exec/run-workflow.js +154 -387
  284. package/dist/workflows/exec/scheduler.js +9 -36
  285. package/dist/workflows/exec/step-work.js +127 -430
  286. package/dist/workflows/exec/unit-dispatch.js +11 -63
  287. package/dist/workflows/exec/unit-writer.js +8 -52
  288. package/dist/workflows/exec/worktree.js +39 -273
  289. package/dist/workflows/freeze/child-output-references.js +4 -15
  290. package/dist/workflows/freeze/environment.js +99 -92
  291. package/dist/workflows/freeze/freeze.js +172 -0
  292. package/dist/workflows/freeze/step-values.js +19 -21
  293. package/dist/workflows/freeze/targets/child-workflow.js +23 -92
  294. package/dist/workflows/freeze/targets/command.js +10 -33
  295. package/dist/workflows/freeze/targets/script.js +5 -12
  296. package/dist/workflows/freeze/targets/shell.js +3 -6
  297. package/dist/workflows/freeze/targets/task.js +25 -80
  298. package/dist/workflows/freeze/task-bindings.js +20 -67
  299. package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
  300. package/dist/workflows/ir/params.js +6 -51
  301. package/dist/workflows/ir/plan-hash.js +2 -34
  302. package/dist/workflows/parser.js +140 -43
  303. package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
  304. package/dist/workflows/renderer.js +36 -69
  305. package/dist/workflows/resource-limits.js +12 -120
  306. package/dist/workflows/runtime/agent-identity.js +8 -40
  307. package/dist/workflows/runtime/run-outputs.js +3 -6
  308. package/dist/workflows/runtime/run-plan.js +316 -0
  309. package/dist/workflows/runtime/runs.js +48 -200
  310. package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
  311. package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
  312. package/dist/workflows/validate-summary.js +2 -7
  313. package/docs/integration/bundling-akm.md +49 -42
  314. package/docs/migration/README.md +1 -0
  315. package/docs/migration/release-notes/0.9.17.md +43 -0
  316. package/docs/migration/v0.9.1-to-v0.9.2.md +23 -7
  317. package/docs/reference/cli.md +229 -133
  318. package/docs/reference/configuration.md +71 -57
  319. package/docs/reference/data-and-telemetry.md +19 -21
  320. package/docs/reference/tasks.md +105 -39
  321. package/docs/reference/workflow-schema.md +14 -18
  322. package/docs/reference/workflows.md +6 -9
  323. package/package.json +1 -1
  324. package/schemas/akm-config.json +87 -754
  325. package/dist/assets/improve-strategies/graph-refresh.json +0 -15
  326. package/dist/assets/prompts/contradiction-judge.md +0 -33
  327. package/dist/assets/prompts/graph-extract-system.md +0 -1
  328. package/dist/assets/prompts/graph-extract-user-prompt.md +0 -35
  329. package/dist/assets/prompts/metadata-enhance-system.md +0 -1
  330. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +0 -4
  331. package/dist/commands/health/advisories.js +0 -150
  332. package/dist/commands/health/metrics.js +0 -329
  333. package/dist/commands/health/surfaces.js +0 -102
  334. package/dist/commands/improve/anti-collapse.js +0 -83
  335. package/dist/commands/improve/collapse-detector.js +0 -432
  336. package/dist/commands/improve/consolidate/eligibility.js +0 -48
  337. package/dist/commands/improve/consolidate/merge.js +0 -146
  338. package/dist/commands/improve/distill/promote-memory.js +0 -329
  339. package/dist/commands/improve/distill/quality-gate.js +0 -500
  340. package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
  341. package/dist/commands/improve/proposal-envelope.js +0 -31
  342. package/dist/commands/improve/run-context.js +0 -123
  343. package/dist/commands/improve/shared.js +0 -21
  344. package/dist/commands/improve/source-identity.js +0 -28
  345. package/dist/commands/improve/triage.js +0 -96
  346. package/dist/commands/proposal/drain-policies.js +0 -151
  347. package/dist/commands/sources/update-transaction.js +0 -220
  348. package/dist/core/action-contributors.js +0 -28
  349. package/dist/core/config/config-version-shim.js +0 -101
  350. package/dist/core/fs-txn.js +0 -405
  351. package/dist/core/lexical-score.js +0 -25
  352. package/dist/core/maintenance-barrier.js +0 -167
  353. package/dist/execution/executable-identity.js +0 -105
  354. package/dist/execution/guarded-source.js +0 -427
  355. package/dist/indexer/db/graph-db.js +0 -444
  356. package/dist/indexer/graph/graph-boost.js +0 -427
  357. package/dist/indexer/graph/graph-dedup.js +0 -95
  358. package/dist/indexer/graph/graph-extraction.js +0 -1182
  359. package/dist/indexer/search/name-match.js +0 -35
  360. package/dist/indexer/search/ranking-contributors.js +0 -515
  361. package/dist/indexer/search/ranking-types.js +0 -4
  362. package/dist/indexer/walk/project-context.js +0 -192
  363. package/dist/integrations/agent/execution-cascade.js +0 -566
  364. package/dist/integrations/agent/execution-definitions.js +0 -202
  365. package/dist/integrations/agent/execution-lowering.js +0 -841
  366. package/dist/integrations/agent/execution-preparation.js +0 -98
  367. package/dist/integrations/agent/inline-execution.js +0 -74
  368. package/dist/llm/graph-extract.js +0 -872
  369. package/dist/llm/metadata-enhance.js +0 -96
  370. package/dist/registry/create-provider-registry.js +0 -29
  371. package/dist/registry/pinned-request-helper.js +0 -247
  372. package/dist/registry/pinned-transport.js +0 -717
  373. package/dist/sources/providers/index.js +0 -14
  374. package/dist/storage/engines/sqlite-migrations.js +0 -271
  375. package/dist/storage/repositories/canaries-repository.js +0 -107
  376. package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
  377. package/dist/storage/repositories/registry-cache.js +0 -113
  378. package/dist/tasks/scheduler-sync-preview.js +0 -52
  379. package/dist/tasks/source/task-to-v3.js +0 -507
  380. package/dist/workflows/freeze/resolve-steps.js +0 -86
  381. package/dist/workflows/freeze/source-freeze.js +0 -64
  382. package/dist/workflows/ir/compile.js +0 -321
  383. package/dist/workflows/ir/environment-v4.js +0 -330
  384. package/dist/workflows/ir/freeze-v4.js +0 -153
  385. package/dist/workflows/ir/schema-v4.js +0 -745
  386. package/dist/workflows/ir/schema.js +0 -354
  387. package/dist/workflows/program/schema.js +0 -78
  388. package/dist/workflows/runtime/checkin.js +0 -57
  389. package/dist/workflows/runtime/plan-classifier.js +0 -196
  390. package/dist/workflows/runtime/unit-checkin.js +0 -45
  391. package/dist/workflows/runtime/unit-phases.js +0 -20
  392. package/dist/workflows/schema.js +0 -4
  393. package/dist/workflows/source-ir/compile.js +0 -200
  394. package/dist/workflows/source-ir/program.js +0 -50
  395. package/dist/workflows/source-ir/result.js +0 -26
  396. package/dist/workflows/source-ir/schema.js +0 -786
  397. package/dist/workflows/source-ir/triggers.js +0 -79
  398. package/dist/workflows/source-ir/uses.js +0 -40
  399. package/dist/workflows/validator.js +0 -60
@@ -1,354 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { isContainedRelativePath, isRecord } from "../../core/common.js";
5
- import { UsageError } from "../../core/errors.js";
6
- import { parseReference } from "../program/expressions.js";
7
- import { PROGRAM_PARAM_NAME_PATTERN, PROGRAM_RETRY_REASONS, PROGRAM_STEP_ID_PATTERN } from "../program/schema.js";
8
- import { jsonBytes, utf8Bytes, WORKFLOW_ENV_VAR_NAME_PATTERN, WORKFLOW_MAX_CONCURRENCY, WORKFLOW_MAX_INSTRUCTION_BYTES, WORKFLOW_MAX_SCHEMA_BYTES, WORKFLOW_MAX_TIMEOUT_MS, } from "../resource-limits.js";
9
- // Shared dispatch-significant bounds now live in `../resource-limits` so the
10
- // parser, the published JSON Schema, and this decoder enforce identical
11
- // values. Re-exported here for existing importers (e.g. `commands/workflow-cli.ts`).
12
- export { WORKFLOW_MAX_CONCURRENCY, WORKFLOW_MAX_TIMEOUT_MS };
13
- const MAX_LIST_ITEMS = 1024;
14
- const MAX_STRING_LENGTH = 1_000_000;
15
- /** Validate the current durable execution graph. */
16
- export function validateWorkflowPlanStructure(input, options) {
17
- if (!isRecord(input) || input.irVersion !== options.expectedVersion) {
18
- fail(`irVersion must be ${options.expectedVersion}`);
19
- }
20
- assertJson(input);
21
- const plan = input;
22
- assertKeys(input, ["irVersion", "title", "params", "paramSchemas", "budget", "execution", "steps", ...(options.planExtraKeys ?? [])], "plan");
23
- assertString(plan.title, "title");
24
- validateParams(plan.params, plan.paramSchemas);
25
- validateBudget(plan.budget);
26
- if (!isRecord(plan.execution) ||
27
- !Number.isInteger(plan.execution.maxConcurrency) ||
28
- plan.execution.maxConcurrency < 1 ||
29
- plan.execution.maxConcurrency > WORKFLOW_MAX_CONCURRENCY) {
30
- fail(`execution.maxConcurrency must be an integer from 1 through ${WORKFLOW_MAX_CONCURRENCY}`);
31
- }
32
- assertKeys(plan.execution, ["maxConcurrency"], "execution");
33
- if (!Array.isArray(plan.steps) || plan.steps.length === 0)
34
- fail("steps must be a non-empty array");
35
- const stepIds = new Set();
36
- const nodeIds = new Set();
37
- for (let index = 0; index < plan.steps.length; index++) {
38
- const step = plan.steps[index];
39
- if (!isRecord(step) ||
40
- typeof step.stepId !== "string" ||
41
- !PROGRAM_STEP_ID_PATTERN.test(step.stepId) ||
42
- stepIds.has(step.stepId))
43
- fail("step ids must be unique non-empty strings");
44
- stepIds.add(step.stepId);
45
- if (step.sequenceIndex !== index)
46
- fail("step sequence indices must be contiguous and unique");
47
- assertString(step.title, `step ${step.stepId} title`);
48
- if (!!step.root === !!step.route)
49
- fail(`step ${step.stepId} must contain exactly one of root or route`);
50
- assertKeys(step, ["stepId", "title", "sequenceIndex", "root", "route", "outputSchema", "gate"], `step ${step.stepId}`);
51
- if (step.outputSchema !== undefined)
52
- validateSchema(step.outputSchema, `step ${step.stepId} outputSchema`);
53
- if (step.root)
54
- validateNode(step.root, step.stepId, nodeIds, options.unitExtraKeys ?? []);
55
- if (step.route)
56
- validateRoute(step.route, step.stepId);
57
- validateGate(step.gate, step.stepId, nodeIds, options.gateExtraKeys ?? []);
58
- }
59
- const stepIndex = new Map(plan.steps.map((step, index) => [step.stepId, index]));
60
- for (const [index, step] of plan.steps.entries()) {
61
- for (const target of step.route
62
- ? [...Object.values(step.route.when), ...(step.route.defaultStepId ? [step.route.defaultStepId] : [])]
63
- : []) {
64
- const targetIndex = stepIndex.get(target);
65
- if (targetIndex === undefined)
66
- fail(`route target ${target} does not name a step`);
67
- if (targetIndex <= index)
68
- fail(`route target ${target} must come after step ${step.stepId}`);
69
- }
70
- validateStepExpressions(step, index, stepIndex);
71
- }
72
- }
73
- function validateNode(node, stepId, nodeIds, unitExtraKeys) {
74
- if (!isRecord(node) ||
75
- (node.kind !== "unit" && node.kind !== "map") ||
76
- typeof node.id !== "string" ||
77
- !node.id ||
78
- nodeIds.has(node.id))
79
- fail("node ids must be unique non-empty strings");
80
- nodeIds.add(node.id);
81
- if (node.kind === "map") {
82
- assertKeys(node, ["kind", "id", "over", "template", "concurrency", "reducer", "source"], `map ${node.id}`);
83
- if (typeof node.over !== "string" ||
84
- !node.over ||
85
- !Number.isInteger(node.concurrency) ||
86
- node.concurrency < 1 ||
87
- node.concurrency > WORKFLOW_MAX_CONCURRENCY ||
88
- (node.reducer !== "collect" && node.reducer !== "vote"))
89
- fail(`map ${node.id} is invalid`);
90
- if (node.id !== `${stepId}.map`)
91
- fail(`map ${node.id} does not match step ${stepId}`);
92
- validateSource(node.source, `map ${node.id} source`);
93
- validateNode(node.template, stepId, nodeIds, unitExtraKeys);
94
- if (!isRecord(node.template) || node.template.kind !== "unit")
95
- fail(`map ${node.id} template must be a unit`);
96
- if (node.template.id !== `${stepId}.unit`)
97
- fail(`map ${node.id} template id is invalid`);
98
- return;
99
- }
100
- assertKeys(node, [
101
- "kind",
102
- "id",
103
- "instructions",
104
- "inputs",
105
- "schema",
106
- "retry",
107
- "onError",
108
- "env",
109
- "isolation",
110
- "source",
111
- ...unitExtraKeys,
112
- ], `unit ${node.id}`);
113
- if (typeof node.instructions !== "string" ||
114
- !node.instructions ||
115
- (node.onError !== "fail" && node.onError !== "continue") ||
116
- (node.isolation !== "none" && node.isolation !== "worktree"))
117
- fail(`unit ${node.id} is invalid`);
118
- if (node.id !== stepId && node.id !== `${stepId}.unit`)
119
- fail(`unit ${node.id} does not belong to step ${stepId}`);
120
- if (utf8Bytes(node.instructions) > WORKFLOW_MAX_INSTRUCTION_BYTES)
121
- fail(`unit ${node.id} instructions exceed the 256 KiB resource limit`);
122
- if (node.schema !== undefined)
123
- validateSchema(node.schema, `unit ${node.id} schema`);
124
- validateRetry(node.retry, node.id);
125
- validateStringArray(node.env, `unit ${node.id} env`, MAX_LIST_ITEMS, true);
126
- validateStringArray(node.inputs, `unit ${node.id} inputs`, Infinity, true);
127
- validateSource(node.source, `unit ${node.id} source`);
128
- }
129
- /**
130
- * Strictly decode a frozen {@link IrExecSpec}. This is the corruption gate for
131
- * a persisted plan: the argv bounds, the relative-and-contained `cwd`, and the
132
- * timeout range are all re-checked here, because `plan_json` may have been
133
- * hand-edited between freeze and dispatch.
134
- */
135
- function validateExecSpec(value, label) {
136
- if (!isRecord(value))
137
- fail(`${label} must be an object`);
138
- assertKeys(value, ["command", "cwd", "passEnv", "timeoutMs"], label);
139
- validateExecEnvScope(value, label);
140
- const command = value.command;
141
- if (!Array.isArray(command) ||
142
- command.length === 0 ||
143
- !command.every((arg) => typeof arg === "string" && arg.length > 0)) {
144
- fail(`${label}.command must be an argv array of non-empty strings`);
145
- }
146
- if (value.cwd !== undefined) {
147
- if (typeof value.cwd !== "string" || value.cwd.length === 0 || !isContainedRelativePath(value.cwd)) {
148
- fail(`${label}.cwd must be a relative path contained in the unit working directory`);
149
- }
150
- }
151
- if (!(value.timeoutMs === null ||
152
- (Number.isSafeInteger(value.timeoutMs) &&
153
- value.timeoutMs >= 1 &&
154
- value.timeoutMs <= WORKFLOW_MAX_TIMEOUT_MS))) {
155
- fail(`${label}.timeoutMs must be null or an integer from 1 through ${WORKFLOW_MAX_TIMEOUT_MS}`);
156
- }
157
- }
158
- /** Decode one current frozen exec spec. */
159
- export function decodeWorkflowExecSpec(value, label) {
160
- validateExecSpec(value, label);
161
- return value;
162
- }
163
- /**
164
- * The child's ENVIRONMENT SCOPE half of a frozen exec spec. Split out so
165
- * {@link validateExecSpec} keeps its shape (and the src-fn-size ratchet stays
166
- * shrink-only).
167
- *
168
- * `passEnv` is canonical-form-only and may only be a non-empty deduplicated
169
- * name list. A persisted `[]` means exactly what absence means, and admitting a
170
- * second spelling of the default would give the same unit two different input
171
- * hashes.
172
- */
173
- function validateExecEnvScope(value, label) {
174
- if (value.passEnv === undefined)
175
- return;
176
- const passEnv = value.passEnv;
177
- if (!Array.isArray(passEnv) ||
178
- passEnv.length === 0 ||
179
- !passEnv.every((name) => typeof name === "string" && WORKFLOW_ENV_VAR_NAME_PATTERN.test(name)) ||
180
- new Set(passEnv).size !== passEnv.length) {
181
- fail(`${label}.passEnv must be a non-empty list of distinct environment variable names matching ` +
182
- `${WORKFLOW_ENV_VAR_NAME_PATTERN.source}`);
183
- }
184
- }
185
- function validateGate(gate, stepId, nodeIds, gateExtraKeys) {
186
- if (!isRecord(gate) ||
187
- gate.kind !== "gate" ||
188
- gate.id !== `${stepId}.gate` ||
189
- gate.stepId !== stepId ||
190
- !Array.isArray(gate.criteria) ||
191
- gate.criteria.length > MAX_LIST_ITEMS ||
192
- !gate.criteria.every((x) => typeof x === "string" && x.length > 0 && x.length <= MAX_STRING_LENGTH) ||
193
- !Number.isInteger(gate.maxLoops) ||
194
- gate.maxLoops < 1)
195
- fail(`gate for step ${stepId} is invalid`);
196
- if (nodeIds.has(gate.id))
197
- fail(`gate id ${gate.id} collides with a node`);
198
- assertKeys(gate, ["kind", "id", "stepId", "criteria", "maxLoops", ...gateExtraKeys], `gate ${stepId}`);
199
- nodeIds.add(gate.id);
200
- }
201
- function validateRoute(route, stepId) {
202
- if (!isRecord(route) ||
203
- typeof route.input !== "string" ||
204
- !route.input ||
205
- !isRecord(route.when) ||
206
- Object.keys(route.when).length === 0 ||
207
- !Object.keys(route.when).every((match) => match.length > 0 && match.length <= MAX_STRING_LENGTH) ||
208
- !Object.values(route.when).every((target) => typeof target === "string" && target))
209
- fail(`route for step ${stepId} is invalid`);
210
- assertKeys(route, ["input", "when", "defaultStepId"], `route ${stepId}`);
211
- if (route.defaultStepId !== undefined && (typeof route.defaultStepId !== "string" || !route.defaultStepId))
212
- fail(`route for step ${stepId} has an invalid default target`);
213
- }
214
- function assertKeys(value, allowed, label) {
215
- for (const key of Object.keys(value))
216
- if (!allowed.includes(key))
217
- fail(`${label} contains unknown key ${key}`);
218
- }
219
- function assertJson(value) {
220
- if (value === null || typeof value === "boolean")
221
- return;
222
- if (typeof value === "string") {
223
- if (value.length > MAX_STRING_LENGTH)
224
- fail("plan contains an oversized string");
225
- return;
226
- }
227
- if (typeof value === "number") {
228
- if (!Number.isFinite(value))
229
- fail("plan contains a non-finite number");
230
- return;
231
- }
232
- if (Array.isArray(value)) {
233
- for (const item of value)
234
- assertJson(item);
235
- return;
236
- }
237
- if (isRecord(value)) {
238
- for (const item of Object.values(value))
239
- assertJson(item);
240
- return;
241
- }
242
- fail("plan contains a non-JSON value");
243
- }
244
- function validateParams(params, schemas) {
245
- validateStringArray(params, "params", Infinity, true);
246
- if (params?.some((name) => !PROGRAM_PARAM_NAME_PATTERN.test(name)))
247
- fail("params contains an invalid name");
248
- if (schemas !== undefined) {
249
- if (!isRecord(schemas))
250
- fail("paramSchemas must be an object");
251
- for (const [name, schema] of Object.entries(schemas)) {
252
- if (!PROGRAM_PARAM_NAME_PATTERN.test(name))
253
- fail(`paramSchemas.${name} is invalid`);
254
- validateSchema(schema, `paramSchemas.${name}`);
255
- }
256
- }
257
- const names = params ?? [];
258
- if (schemas && (names.length !== Object.keys(schemas).length || names.some((name) => !Object.hasOwn(schemas, name))))
259
- fail("params and paramSchemas must name the same parameters");
260
- if (!schemas && names.length > 0) {
261
- // Markdown workflows have named parameters but no schemas, which is valid.
262
- return;
263
- }
264
- }
265
- function validateBudget(budget) {
266
- if (budget === undefined)
267
- return;
268
- if (!isRecord(budget))
269
- fail("budget must be an object");
270
- assertKeys(budget, ["maxTokens", "maxUnits"], "budget");
271
- if (budget.maxTokens === undefined && budget.maxUnits === undefined)
272
- fail("budget must declare a ceiling");
273
- validateOptionalPositiveInteger(budget.maxTokens, "budget.maxTokens");
274
- const maxUnits = budget.maxUnits;
275
- if (maxUnits !== undefined && (!Number.isSafeInteger(maxUnits) || maxUnits < 1))
276
- fail("budget.maxUnits must be a positive integer");
277
- }
278
- function validateRetry(retry, nodeId) {
279
- if (retry === undefined)
280
- return;
281
- if (!isRecord(retry))
282
- fail(`unit ${nodeId} retry must be an object`);
283
- assertKeys(retry, ["max", "on"], `unit ${nodeId} retry`);
284
- if (!Number.isSafeInteger(retry.max) || retry.max < 0)
285
- fail(`unit ${nodeId} retry.max is invalid`);
286
- validateStringArray(retry.on, `unit ${nodeId} retry.on`, PROGRAM_RETRY_REASONS.length, true);
287
- if (retry.on === undefined ||
288
- retry.on.length === 0 ||
289
- retry.on.some((reason) => !PROGRAM_RETRY_REASONS.includes(reason)))
290
- fail(`unit ${nodeId} retry.on is invalid`);
291
- }
292
- function validateSchema(value, label) {
293
- if (!isRecord(value))
294
- fail(`${label} must be an object`);
295
- if (jsonBytes(value) > WORKFLOW_MAX_SCHEMA_BYTES)
296
- fail(`${label} exceeds the 256 KiB resource limit`);
297
- }
298
- function validateStepExpressions(step, index, steps) {
299
- const validateReference = (text, label, paramsAllowed) => {
300
- const parsed = parseReference(text);
301
- if (!parsed.ok)
302
- fail(`${label} contains an invalid reference`);
303
- if (parsed.expr.kind === "param" && !paramsAllowed)
304
- fail(`${label} must reference a step output`);
305
- if (parsed.expr.kind === "stepOutput") {
306
- const referenced = steps.get(parsed.expr.stepId);
307
- if (referenced === undefined || referenced >= index)
308
- fail(`${label} references a non-earlier step`);
309
- }
310
- };
311
- if (step.root) {
312
- const unit = step.root.kind === "map" ? step.root.template : step.root;
313
- if (step.root.kind === "map")
314
- validateReference(step.root.over, `map ${step.root.id} over`, true);
315
- for (const reference of unit.inputs ?? [])
316
- validateReference(reference, `unit ${unit.id} inputs`, false);
317
- }
318
- if (step.route)
319
- validateReference(step.route.input, `route ${step.stepId} input`, true);
320
- }
321
- function validateSource(value, label) {
322
- if (value === undefined)
323
- return;
324
- if (!isRecord(value))
325
- fail(`${label} must be an object`);
326
- assertKeys(value, ["path", "start", "end"], label);
327
- if (typeof value.path !== "string" ||
328
- !value.path ||
329
- !Number.isSafeInteger(value.start) ||
330
- !Number.isSafeInteger(value.end) ||
331
- value.start < 1 ||
332
- value.end < value.start)
333
- fail(`${label} is invalid`);
334
- }
335
- function validateStringArray(value, label, max, unique) {
336
- if (value === undefined)
337
- return;
338
- if (!Array.isArray(value) ||
339
- value.length > max ||
340
- !value.every((item) => typeof item === "string" && item.length > 0 && item.length <= MAX_STRING_LENGTH) ||
341
- (unique && new Set(value).size !== value.length))
342
- fail(`${label} is invalid`);
343
- }
344
- function validateOptionalPositiveInteger(value, label) {
345
- if (value !== undefined && (!Number.isSafeInteger(value) || value < 1))
346
- fail(`${label} must be a positive safe integer`);
347
- }
348
- function assertString(value, label) {
349
- if (typeof value !== "string" || value.length === 0 || value.length > MAX_STRING_LENGTH)
350
- fail(`${label} must be a non-empty bounded string`);
351
- }
352
- function fail(message) {
353
- throw new UsageError(`Invalid frozen workflow plan: ${message}.`);
354
- }
@@ -1,78 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- /** How a map step folds its per-item unit results into the step artifact. */
5
- export const PROGRAM_REDUCERS = ["collect", "vote"];
6
- /** Failure policy: fail the step on first unit failure, or record and go on. */
7
- export const PROGRAM_ON_ERROR = ["fail", "continue"];
8
- /** Filesystem isolation for file-mutating units. */
9
- export const PROGRAM_ISOLATION_KINDS = ["none", "worktree"];
10
- /**
11
- * `retry.on` vocabulary — exactly the persisted `AgentFailureReason` taxonomy
12
- * from `src/integrations/agent/spawn.ts`. The `satisfies` clause fails the
13
- * typecheck if spawn.ts adds/renames a reason without this list (and the JSON
14
- * Schema, via the drift test) being updated.
15
- */
16
- const RETRY_REASON_SET = {
17
- timeout: true,
18
- spawn_failed: true,
19
- non_zero_exit: true,
20
- parse_error: true,
21
- cooldown: true,
22
- llm_rate_limit: true,
23
- llm_content_filter: true,
24
- llm_invalid_json: true,
25
- content_policy_reject: true,
26
- unsupported_type: true,
27
- no_change: true,
28
- quality_rejected: true,
29
- aborted: true,
30
- };
31
- export const PROGRAM_RETRY_REASONS = Object.keys(RETRY_REASON_SET);
32
- /**
33
- * Step ids: `[A-Za-z_][A-Za-z0-9_-]*` (also pinned in the JSON Schema) — the
34
- * ONE id grammar for the shared source IR (workflow-format-unification, spec
35
- * §2.2). This is EXACTLY the `<ident>` grammar `readIdent` accepts in
36
- * `program/expressions.ts` for `steps.<id>.output` references: a
37
- * letter/underscore first char, then letters/digits/underscores/dashes, and
38
- * NO dots (the expression parser treats `.` as the `.output` path separator,
39
- * so a dotted id could never be addressed). Keeping step ids inside the
40
- * addressable grammar guarantees every step can be referenced from map
41
- * inputs, routes, and `inputs:` without renaming.
42
- *
43
- * Forbidding dots additionally keeps the engine's internal gate-row node id
44
- * `<stepId>.gate` collision-free: no user step id can contain a dot, so it can
45
- * never equal another step's `<stepId>.gate` synthetic id.
46
- */
47
- export const PROGRAM_STEP_ID_PATTERN = /^[A-Za-z_][A-Za-z0-9_-]*$/;
48
- /**
49
- * Param names must be `params.<ident>`-addressable, so they are plain
50
- * identifiers (no dots/dashes). Re-exported from the shared input contract
51
- * (`src/execution/input-contract.ts`'s `INPUT_NAME_PATTERN`) so task source
52
- * v4's `inputs:` declarations share the exact same name pattern rather than a
53
- * second, hand-maintained copy (P2a, D3-N1).
54
- */
55
- export { INPUT_NAME_PATTERN as PROGRAM_PARAM_NAME_PATTERN } from "../../execution/input-contract.js";
56
- /**
57
- * The ONE structural projection of an exec spec — ONE encoding per state.
58
- *
59
- * Every layer that carries an exec forward derives from this: the compiled
60
- * draft, the frozen plan (which layers `timeoutMs` on top), and the summary
61
- * `akm workflow show` prints. Written out per layer instead, a field added to
62
- * {@link ProgramExec} reaches whichever copies were remembered and silently
63
- * vanishes from the rest — and nothing catches it, because every key here is
64
- * optional, so an omitted spread is not a type error. What it would cost:
65
- * either the frozen plan loses a field the author wrote (and the canonical
66
- * hash preimage stops matching the authored intent), or `show` describes
67
- * something other than what runs.
68
- *
69
- * The ABSENCE of both env keys is the default allowlist. The parser rejects an
70
- * empty `pass_env` outright, so no layer has to distinguish absent from empty.
71
- */
72
- export function projectExecCore(exec) {
73
- return {
74
- command: [...exec.command],
75
- ...(exec.cwd ? { cwd: exec.cwd } : {}),
76
- ...(exec.passEnv && exec.passEnv.length > 0 ? { passEnv: [...exec.passEnv] } : {}),
77
- };
78
- }
@@ -1,57 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- /**
5
- * Agent check-in: a no-background-thread "continue" nudge for stalled workflow
6
- * runs (#506).
7
- *
8
- * The design decision (the workflow-agent check-in ADR)
9
- * reconciles #506 (file/command-loop signal) with #501 (background thread) in
10
- * favour of the former. There is intentionally NO timer or resident process
11
- * here. Arming a check-in writes a timestamp (`checkin_armed_at`) on the run
12
- * row; the next time the agent polls the engine via `workflow run`/`status`,
13
- * {@link evaluateCheckin} is called to decide — purely from timestamps — whether
14
- * the run looks stalled and a strong `continue` directive should be surfaced
15
- * through the normal command output.
16
- *
17
- * @module workflows/checkin
18
- */
19
- /**
20
- * Default stall window. If a run has been active and untouched for at least
21
- * this long since the later of its last update and its armed timestamp, the
22
- * next poll surfaces a check-in directive.
23
- */
24
- export const CHECKIN_STALL_MS = 90_000;
25
- function parseIso(value) {
26
- if (!value)
27
- return null;
28
- const ms = Date.parse(value);
29
- return Number.isNaN(ms) ? null : ms;
30
- }
31
- /**
32
- * Pure check-in evaluator. Returns a `continue` directive when an *active* run
33
- * has been idle past the stall window, otherwise `null`. Deterministic in
34
- * `now`, so it is trivially unit-testable and free of timer flakiness.
35
- */
36
- export function evaluateCheckin(run, now = Date.now(), stallMs = CHECKIN_STALL_MS) {
37
- if (run.status !== "active")
38
- return null;
39
- const updated = parseIso(run.updatedAt);
40
- const armed = parseIso(run.checkinArmedAt);
41
- // Never armed → no check-in (opt-in per run via startWorkflowRun).
42
- if (armed === null)
43
- return null;
44
- const last = Math.max(updated ?? armed, armed);
45
- const idleMs = now - last;
46
- if (idleMs < stallMs)
47
- return null;
48
- return {
49
- signal: "continue",
50
- directive: "CONTINUE: this workflow run has stalled with no progress. Resume immediately — " +
51
- "inspect its status, then call `akm workflow run` with the run id to finish the outstanding work. " +
52
- "Do not stop until the run reaches a terminal state or reports a verification rejection.",
53
- idleMs,
54
- agentHarness: run.agentHarness ?? null,
55
- agentSessionId: run.agentSessionId ?? null,
56
- };
57
- }