akm-cli 0.9.17-alpha.2 → 0.9.17-alpha.4

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 (343) hide show
  1. package/CHANGELOG.md +756 -0
  2. package/dist/akm +94 -196
  3. package/dist/cli/shared.js +6 -2
  4. package/dist/cli.js +22 -9
  5. package/dist/commands/agent/agent-dispatch.js +1 -1
  6. package/dist/commands/command/command-execution.js +24 -62
  7. package/dist/commands/feedback-cli.js +0 -1
  8. package/dist/commands/health/accept-rate.js +2 -2
  9. package/dist/commands/health/checks.js +30 -75
  10. package/dist/commands/health/config-skew.js +38 -0
  11. package/dist/commands/health/egress.js +54 -0
  12. package/dist/commands/health/html-report.js +0 -38
  13. package/dist/commands/health/improve-metrics.js +123 -562
  14. package/dist/commands/health/plugin-staleness.js +53 -3
  15. package/dist/commands/health/renderers.js +12 -4
  16. package/dist/commands/health/report-view-model.js +11 -106
  17. package/dist/commands/health/types-improve.js +4 -19
  18. package/dist/commands/health/windows.js +64 -73
  19. package/dist/commands/health.js +122 -143
  20. package/dist/commands/improve/consolidate/chunking.js +25 -100
  21. package/dist/commands/improve/consolidate/sanitize.js +54 -149
  22. package/dist/commands/improve/consolidate.js +538 -1075
  23. package/dist/commands/improve/content-hash.js +16 -24
  24. package/dist/commands/improve/distill/content-repair.js +18 -100
  25. package/dist/commands/improve/distill-guards.js +20 -81
  26. package/dist/commands/improve/distill-promotion-policy.js +23 -243
  27. package/dist/commands/improve/distill.js +608 -1075
  28. package/dist/commands/improve/eligibility.js +126 -400
  29. package/dist/commands/improve/execution.js +3 -5
  30. package/dist/commands/improve/extract.js +487 -1046
  31. package/dist/commands/improve/feedback-valence.js +0 -25
  32. package/dist/commands/improve/improve-cli.js +29 -166
  33. package/dist/commands/improve/improve-result-file.js +10 -66
  34. package/dist/commands/improve/improve-strategies.js +12 -7
  35. package/dist/commands/improve/improve-usage-report.js +18 -64
  36. package/dist/commands/improve/improve.js +443 -1063
  37. package/dist/commands/improve/ledger.js +114 -0
  38. package/dist/commands/improve/locks.js +2 -8
  39. package/dist/commands/improve/loop-stages.js +459 -1172
  40. package/dist/commands/improve/memory/derived-ref.js +12 -77
  41. package/dist/commands/improve/memory/memory-belief.js +14 -118
  42. package/dist/commands/improve/memory/memory-improve.js +4 -3
  43. package/dist/commands/improve/outcome-loop.js +28 -156
  44. package/dist/commands/improve/planner.js +5 -10
  45. package/dist/commands/improve/preparation.js +851 -2339
  46. package/dist/commands/improve/proactive-maintenance.js +34 -101
  47. package/dist/commands/improve/reflect-noise.js +104 -280
  48. package/dist/commands/improve/reflect.js +621 -1367
  49. package/dist/commands/improve/salience.js +46 -232
  50. package/dist/commands/improve/session-asset.js +19 -100
  51. package/dist/commands/improve/stage.js +323 -0
  52. package/dist/commands/proposal/drain.js +251 -644
  53. package/dist/commands/proposal/proposal-cli.js +3 -18
  54. package/dist/commands/proposal/proposal-types.js +20 -41
  55. package/dist/commands/proposal/proposal.js +1 -2
  56. package/dist/commands/proposal/propose.js +134 -160
  57. package/dist/commands/proposal/repository.js +502 -1487
  58. package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
  59. package/dist/commands/proposal/validators/proposal-validators.js +1 -1
  60. package/dist/commands/proposal/validators/proposals.js +13 -89
  61. package/dist/commands/read/curate.js +63 -413
  62. package/dist/commands/read/search-cli.js +16 -33
  63. package/dist/commands/read/search.js +17 -23
  64. package/dist/commands/read/show.js +2 -13
  65. package/dist/commands/sources/bundle-cli.js +25 -2
  66. package/dist/commands/sources/bundle-config-ops.js +7 -0
  67. package/dist/commands/sources/dangerous-env-audit.js +1 -2
  68. package/dist/commands/sources/info.js +2 -11
  69. package/dist/commands/sources/installed-stashes.js +197 -746
  70. package/dist/commands/sources/schema-repair.js +98 -129
  71. package/dist/commands/sources/source-add.js +62 -12
  72. package/dist/commands/sources/stash-cli.js +1 -1
  73. package/dist/commands/tasks/explain.js +10 -13
  74. package/dist/commands/tasks/tasks-cli.js +9 -8
  75. package/dist/commands/tasks/tasks.js +326 -930
  76. package/dist/commands/tasks/validate.js +42 -21
  77. package/dist/commands/workflow/plan.js +22 -29
  78. package/dist/commands/workflow-cli.js +4 -4
  79. package/dist/core/adapter/adapters/akm-adapter.js +0 -1
  80. package/dist/core/adapter/adapters/akm-lint.js +2 -3
  81. package/dist/core/adapter/adapters/akm-metadata.js +11 -12
  82. package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
  83. package/dist/core/adapter/execution-source.js +17 -29
  84. package/dist/core/asset/resolve-ref.js +1 -1
  85. package/dist/core/bundle-id.js +42 -5
  86. package/dist/core/bundle-rename.js +291 -0
  87. package/dist/core/config/config-io.js +1 -2
  88. package/dist/core/config/config-schema.js +1 -33
  89. package/dist/core/config/config-walker.js +1 -1
  90. package/dist/core/config/config.js +163 -68
  91. package/dist/core/config/legacy-source-shape-shim.js +38 -9
  92. package/dist/core/config/schema/embedding.js +20 -5
  93. package/dist/core/config/schema/engines.js +5 -0
  94. package/dist/core/config/schema/execution.js +1 -1
  95. package/dist/core/config/schema/experimental.js +1 -1
  96. package/dist/core/config/schema/improve-processes.js +21 -95
  97. package/dist/core/config/schema/improve.js +4 -42
  98. package/dist/core/config/schema/scheduler.js +12 -12
  99. package/dist/core/config/schema/search.js +6 -22
  100. package/dist/core/env-secret-ref.js +0 -1
  101. package/dist/core/errors.js +8 -9
  102. package/dist/core/file-lock.js +76 -173
  103. package/dist/core/logs-db.js +2 -2
  104. package/dist/core/paths.js +0 -27
  105. package/dist/core/redaction.js +109 -2
  106. package/dist/core/run-lock.js +2 -5
  107. package/dist/core/spawn-env.js +1 -1
  108. package/dist/core/state/migrations.js +108 -61
  109. package/dist/core/state-db-scope.js +2 -4
  110. package/dist/core/state-db.js +126 -692
  111. package/dist/core/type-presentation.js +1 -9
  112. package/dist/core/write-source.js +293 -1012
  113. package/dist/execution/input-contract.js +1 -1
  114. package/dist/execution/resolved-request.js +135 -689
  115. package/dist/execution/source.js +63 -257
  116. package/dist/execution/target-ref.js +1 -1
  117. package/dist/indexer/bundle-identity-guard.js +2 -2
  118. package/dist/indexer/db/graph-db.js +106 -46
  119. package/dist/indexer/ensure-index.js +44 -85
  120. package/dist/indexer/graph/graph-extraction.js +340 -562
  121. package/dist/indexer/graph/graph-related.js +130 -0
  122. package/dist/indexer/index-rebuild-lock.js +3 -11
  123. package/dist/indexer/index-writer-lock.js +8 -17
  124. package/dist/indexer/index-written-assets.js +139 -151
  125. package/dist/indexer/indexer.js +524 -846
  126. package/dist/indexer/materialize-embeddings.js +60 -397
  127. package/dist/indexer/passes/memory-inference.js +81 -90
  128. package/dist/indexer/passes/metadata.js +132 -200
  129. package/dist/indexer/read-preflight.js +0 -7
  130. package/dist/indexer/scan/doc-to-entry.js +1 -3
  131. package/dist/indexer/scan/drain-dir.js +1 -1
  132. package/dist/indexer/search/db-search.js +181 -590
  133. package/dist/indexer/search/fts-query.js +30 -41
  134. package/dist/indexer/search/ranking.js +28 -154
  135. package/dist/indexer/search/search-attribution.js +12 -32
  136. package/dist/indexer/search/search-fields.js +11 -15
  137. package/dist/indexer/search/search-hit-enrichers.js +54 -85
  138. package/dist/indexer/search/search-source.js +1 -4
  139. package/dist/indexer/usage/usage-events.js +2 -7
  140. package/dist/integrations/agent/engine-fallback.js +23 -40
  141. package/dist/integrations/agent/engine-resolution.js +93 -183
  142. package/dist/integrations/agent/execution.js +507 -0
  143. package/dist/integrations/agent/model-map.js +28 -156
  144. package/dist/integrations/agent/request-lowering.js +66 -141
  145. package/dist/integrations/agent/runner-dispatch.js +143 -321
  146. package/dist/integrations/agent/runner.js +54 -14
  147. package/dist/integrations/lockfile.js +53 -101
  148. package/dist/llm/embedders/deterministic.js +2 -3
  149. package/dist/llm/embedders/profile.js +71 -0
  150. package/dist/llm/embedders/remote.js +10 -15
  151. package/dist/llm/graph-extract.js +3 -12
  152. package/dist/llm/index-passes.js +3 -5
  153. package/dist/llm/memory-infer.js +1 -2
  154. package/dist/llm/metadata-enhance.js +1 -2
  155. package/dist/llm/structured-call.js +5 -24
  156. package/dist/output/generic-render.js +23 -11
  157. package/dist/output/html-render.js +13 -10
  158. package/dist/output/render-registry.js +3 -32
  159. package/dist/output/shapes/helpers.js +2 -34
  160. package/dist/output/shapes/passthrough.js +1 -9
  161. package/dist/{indexer/search/ranking-types.js → output/text/bundle-rename.js} +4 -1
  162. package/dist/output/text/command-format.js +60 -23
  163. package/dist/output/text/helpers.js +1 -1
  164. package/dist/output/text/migrate.js +5 -14
  165. package/dist/output/text/proposal-format.js +1 -2
  166. package/dist/output/text/workflow-format.js +0 -32
  167. package/dist/output/text.js +2 -0
  168. package/dist/registry/factory.js +4 -19
  169. package/dist/registry/network.js +66 -220
  170. package/dist/registry/providers/index.js +0 -2
  171. package/dist/registry/providers/skills-sh.js +3 -14
  172. package/dist/registry/providers/static-index.js +24 -26
  173. package/dist/registry/resolve.js +55 -131
  174. package/dist/scripts/akm-migrate-node.js +43937 -93313
  175. package/dist/scripts/akm-migrate.js +43697 -93071
  176. package/dist/setup/registry-stash-loader.js +4 -13
  177. package/dist/setup/semantic-assets.js +3 -44
  178. package/dist/setup/setup.js +1 -1
  179. package/dist/setup/steps/tasks.js +25 -15
  180. package/dist/sources/provider-factory.js +17 -18
  181. package/dist/sources/providers/filesystem.js +2 -3
  182. package/dist/sources/providers/git-install.js +7 -1
  183. package/dist/sources/providers/git-provider.js +0 -3
  184. package/dist/sources/providers/git-stash.js +0 -17
  185. package/dist/sources/providers/npm.js +2 -4
  186. package/dist/sources/providers/provider-utils.js +5 -10
  187. package/dist/sources/providers/website.js +0 -2
  188. package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
  189. package/dist/sources/website-url.js +2 -2
  190. package/dist/storage/database.js +9 -35
  191. package/dist/storage/repositories/improve-ledger-repository.js +168 -0
  192. package/dist/storage/repositories/index-connection.js +34 -70
  193. package/dist/storage/repositories/index-entries-repository.js +69 -111
  194. package/dist/storage/repositories/index-entry-mapper.js +1 -2
  195. package/dist/storage/repositories/index-entry-schema.js +83 -269
  196. package/dist/storage/repositories/index-fts-repository.js +86 -256
  197. package/dist/storage/repositories/index-llm-cache-repository.js +17 -0
  198. package/dist/storage/repositories/index-meta-repository.js +6 -4
  199. package/dist/storage/repositories/index-schema.js +192 -220
  200. package/dist/storage/repositories/index-utility-repository.js +8 -29
  201. package/dist/storage/repositories/index-vec-repository.js +133 -414
  202. package/dist/storage/repositories/outcome-repository.js +2 -1
  203. package/dist/storage/repositories/proposals-repository.js +35 -0
  204. package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
  205. package/dist/storage/repositories/task-history-repository.js +26 -4
  206. package/dist/storage/repositories/workflow-runs-repository.js +53 -244
  207. package/dist/storage/sqlite-migrations.js +136 -0
  208. package/dist/storage/sqlite-pragmas.js +11 -9
  209. package/dist/storage/sqlite-transaction.js +170 -0
  210. package/dist/storage/state-db-integrity.js +34 -27
  211. package/dist/tasks/activation-config.js +134 -62
  212. package/dist/tasks/backends/cron.js +129 -277
  213. package/dist/tasks/backends/exec-utils.js +2 -5
  214. package/dist/tasks/backends/launchd.js +125 -745
  215. package/dist/tasks/backends/schtasks.js +101 -620
  216. package/dist/tasks/prepare/prepare-support.js +5 -15
  217. package/dist/tasks/prepare/prepare.js +0 -2
  218. package/dist/tasks/resolve-akm-bin.js +20 -79
  219. package/dist/tasks/run/attempt-lifecycle.js +0 -1
  220. package/dist/tasks/scheduler-binding.js +18 -238
  221. package/dist/tasks/scheduler-invocation.js +52 -52
  222. package/dist/tasks/scheduler-lock.js +53 -0
  223. package/dist/tasks/scheduler-sync.js +363 -679
  224. package/dist/tasks/source/parse-task-source.js +160 -10
  225. package/dist/tasks/source/task-source-v3-frozen.js +3 -4
  226. package/dist/tasks/source/task-to-v4.js +2 -2
  227. package/dist/workflows/authoring/authoring.js +3 -12
  228. package/dist/workflows/compile.js +211 -0
  229. package/dist/workflows/concurrency-policy.js +13 -74
  230. package/dist/workflows/exec/child-invocation.js +3 -17
  231. package/dist/workflows/exec/child-workflow.js +32 -141
  232. package/dist/workflows/exec/dispatch-redaction.js +13 -53
  233. package/dist/workflows/exec/environment.js +98 -0
  234. package/dist/workflows/exec/exec-unit.js +33 -140
  235. package/dist/workflows/exec/frozen-judge.js +7 -59
  236. package/dist/workflows/exec/native-executor.js +82 -341
  237. package/dist/workflows/exec/param-secrets.js +29 -47
  238. package/dist/workflows/exec/run-workflow.js +154 -387
  239. package/dist/workflows/exec/scheduler.js +9 -36
  240. package/dist/workflows/exec/step-work.js +127 -430
  241. package/dist/workflows/exec/unit-dispatch.js +11 -63
  242. package/dist/workflows/exec/unit-writer.js +8 -52
  243. package/dist/workflows/exec/worktree.js +39 -273
  244. package/dist/workflows/freeze/child-output-references.js +4 -15
  245. package/dist/workflows/freeze/environment.js +99 -92
  246. package/dist/workflows/freeze/freeze.js +172 -0
  247. package/dist/workflows/freeze/step-values.js +19 -21
  248. package/dist/workflows/freeze/targets/child-workflow.js +23 -92
  249. package/dist/workflows/freeze/targets/command.js +10 -33
  250. package/dist/workflows/freeze/targets/script.js +5 -12
  251. package/dist/workflows/freeze/targets/shell.js +3 -6
  252. package/dist/workflows/freeze/targets/task.js +25 -80
  253. package/dist/workflows/freeze/task-bindings.js +20 -67
  254. package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
  255. package/dist/workflows/ir/params.js +6 -51
  256. package/dist/workflows/ir/plan-hash.js +2 -34
  257. package/dist/workflows/parser.js +140 -43
  258. package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
  259. package/dist/workflows/renderer.js +36 -69
  260. package/dist/workflows/resource-limits.js +12 -120
  261. package/dist/workflows/runtime/agent-identity.js +8 -40
  262. package/dist/workflows/runtime/run-outputs.js +3 -6
  263. package/dist/workflows/runtime/run-plan.js +316 -0
  264. package/dist/workflows/runtime/runs.js +48 -200
  265. package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
  266. package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
  267. package/dist/workflows/validate-summary.js +2 -7
  268. package/docs/integration/bundling-akm.md +49 -42
  269. package/docs/migration/README.md +1 -0
  270. package/docs/migration/release-notes/0.9.17.md +41 -0
  271. package/docs/migration/v0.9.1-to-v0.9.2.md +19 -7
  272. package/docs/reference/cli.md +182 -125
  273. package/docs/reference/configuration.md +49 -56
  274. package/docs/reference/data-and-telemetry.md +19 -20
  275. package/docs/reference/tasks.md +86 -38
  276. package/docs/reference/workflow-schema.md +14 -18
  277. package/docs/reference/workflows.md +6 -9
  278. package/package.json +1 -1
  279. package/schemas/akm-config.json +87 -406
  280. package/dist/commands/health/advisories.js +0 -150
  281. package/dist/commands/health/metrics.js +0 -329
  282. package/dist/commands/health/surfaces.js +0 -102
  283. package/dist/commands/improve/anti-collapse.js +0 -83
  284. package/dist/commands/improve/collapse-detector.js +0 -432
  285. package/dist/commands/improve/consolidate/eligibility.js +0 -48
  286. package/dist/commands/improve/consolidate/merge.js +0 -146
  287. package/dist/commands/improve/distill/promote-memory.js +0 -329
  288. package/dist/commands/improve/distill/quality-gate.js +0 -500
  289. package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
  290. package/dist/commands/improve/proposal-envelope.js +0 -31
  291. package/dist/commands/improve/run-context.js +0 -123
  292. package/dist/commands/improve/shared.js +0 -21
  293. package/dist/commands/improve/source-identity.js +0 -28
  294. package/dist/commands/improve/triage.js +0 -96
  295. package/dist/commands/proposal/drain-policies.js +0 -151
  296. package/dist/commands/sources/update-transaction.js +0 -220
  297. package/dist/core/action-contributors.js +0 -28
  298. package/dist/core/config/config-version-shim.js +0 -101
  299. package/dist/core/config/retired-experimental-keys-shim.js +0 -62
  300. package/dist/core/fs-txn.js +0 -405
  301. package/dist/core/lexical-score.js +0 -25
  302. package/dist/core/maintenance-barrier.js +0 -167
  303. package/dist/execution/executable-identity.js +0 -105
  304. package/dist/execution/guarded-source.js +0 -427
  305. package/dist/indexer/graph/graph-boost.js +0 -427
  306. package/dist/indexer/graph/graph-dedup.js +0 -95
  307. package/dist/indexer/search/name-match.js +0 -35
  308. package/dist/indexer/search/ranking-contributors.js +0 -515
  309. package/dist/indexer/walk/project-context.js +0 -192
  310. package/dist/integrations/agent/execution-cascade.js +0 -566
  311. package/dist/integrations/agent/execution-definitions.js +0 -202
  312. package/dist/integrations/agent/execution-lowering.js +0 -841
  313. package/dist/integrations/agent/execution-preparation.js +0 -98
  314. package/dist/integrations/agent/inline-execution.js +0 -74
  315. package/dist/registry/create-provider-registry.js +0 -29
  316. package/dist/registry/pinned-request-helper.js +0 -247
  317. package/dist/registry/pinned-transport.js +0 -717
  318. package/dist/sources/providers/index.js +0 -14
  319. package/dist/storage/engines/sqlite-migrations.js +0 -271
  320. package/dist/storage/repositories/canaries-repository.js +0 -107
  321. package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
  322. package/dist/storage/repositories/registry-cache.js +0 -113
  323. package/dist/tasks/scheduler-sync-preview.js +0 -52
  324. package/dist/workflows/freeze/resolve-steps.js +0 -86
  325. package/dist/workflows/freeze/source-freeze.js +0 -64
  326. package/dist/workflows/ir/compile.js +0 -321
  327. package/dist/workflows/ir/environment-v4.js +0 -330
  328. package/dist/workflows/ir/freeze-v4.js +0 -153
  329. package/dist/workflows/ir/schema-v4.js +0 -745
  330. package/dist/workflows/ir/schema.js +0 -354
  331. package/dist/workflows/program/schema.js +0 -78
  332. package/dist/workflows/runtime/checkin.js +0 -57
  333. package/dist/workflows/runtime/plan-classifier.js +0 -196
  334. package/dist/workflows/runtime/unit-checkin.js +0 -45
  335. package/dist/workflows/runtime/unit-phases.js +0 -20
  336. package/dist/workflows/schema.js +0 -4
  337. package/dist/workflows/source-ir/compile.js +0 -200
  338. package/dist/workflows/source-ir/program.js +0 -50
  339. package/dist/workflows/source-ir/result.js +0 -26
  340. package/dist/workflows/source-ir/schema.js +0 -786
  341. package/dist/workflows/source-ir/triggers.js +0 -79
  342. package/dist/workflows/source-ir/uses.js +0 -40
  343. 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
- }