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
@@ -1,24 +1,14 @@
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
- /**
5
- * File-private helpers prepareTaskV3Execution depends on, moved body-intact
6
- * out of the pre-P1b src/tasks/runtime-v3.ts (spec
7
- * docs/plans/specs/p1b-model-extraction.md §4.1, Lane B / D4 module map).
8
- * None of these was exported at head either; only the subset prepare.ts's
9
- * moved function body calls is exported here.
10
- */
11
- import path from "node:path";
12
4
  import { makeBundleRef, parseBundleRef } from "../../core/asset/asset-ref.js";
13
5
  import { COMPOSITION_INVALID_MULTI_JOB_HINT, ConfigError, NotFoundError, UsageError } from "../../core/errors.js";
14
6
  import { DURATION_UNITS, parseDuration } from "../../core/time.js";
15
7
  import { isPortableExecutionAgentSelector } from "../../execution/source.js";
16
- import { requireAuthorizedExecutionPlan } from "../../integrations/agent/execution-cascade.js";
17
- import { lowerResolvedExecutionRequest } from "../../integrations/agent/execution-lowering.js";
8
+ import { buildExecution } from "../../integrations/agent/execution.js";
18
9
  import { resolveAssetPath } from "../../sources/resolve.js";
10
+ import { checkWorkflowPlan, compileWorkflowSource } from "../../workflows/compile.js";
19
11
  import { detectSecretShapedParams } from "../../workflows/exec/param-secrets.js";
20
- import { compileWorkflowPlan } from "../../workflows/ir/compile.js";
21
- import { compileWorkflowSource } from "../../workflows/source-ir/compile.js";
22
12
  import { isInferredSecretName } from "../log-redaction.js";
23
13
  import { SCHEDULED_TASK_CONTEXT_KEYS } from "../scheduler-invocation.js";
24
14
  function own(value, key) {
@@ -118,14 +108,14 @@ export function defaultTaskShell(platform) {
118
108
  return platform === "win32" ? "powershell" : "sh";
119
109
  }
120
110
  export function validatePreparedCommand(invocation, context) {
121
- const request = requireAuthorizedExecutionPlan(invocation.plan);
111
+ const { request } = invocation;
122
112
  if (!request.engine.name) {
123
113
  throw new ConfigError(`Task ${JSON.stringify(context.taskRef)} has no resolved execution engine. Configure defaults.engine or akm.engine before running it.`, "INVALID_CONFIG_FILE");
124
114
  }
125
115
  // Lowering is pure. Running it before the durable-attempt boundary proves
126
116
  // the selected target is transport-projectable; dispatch repeats the same
127
117
  // deterministic projection from this frozen request/config snapshot.
128
- lowerResolvedExecutionRequest(request, invocation.config);
118
+ buildExecution(request, invocation.runner);
129
119
  return invocation;
130
120
  }
131
121
  export function validateWorkflowRuntimeSource(file, workspaceRoot, readFile) {
@@ -141,7 +131,7 @@ export function validateWorkflowRuntimeSource(file, workspaceRoot, readFile) {
141
131
  const code = isMultiJob ? "COMPOSITION_INVALID" : "WORKFLOW_SOURCE_INVALID";
142
132
  throw new UsageError(`Task workflow target is not projectable: ${detail}`, code, isMultiJob ? COMPOSITION_INVALID_MULTI_JOB_HINT : undefined);
143
133
  }
144
- const planned = compileWorkflowPlan(compiled.ir, path.basename(file, path.extname(file)));
134
+ const planned = checkWorkflowPlan(compiled.plan);
145
135
  if (!planned.ok) {
146
136
  // Same mapping applied for consistency; `compiled.ir` is already
147
137
  // guaranteed exactly one job here, so this arm always resolves to
@@ -54,7 +54,6 @@ export async function prepareTaskV3Execution(document, context) {
54
54
  const invocation = validatePreparedCommand(await (context.prepareCommand ?? prepareCommandInvocation)({
55
55
  action,
56
56
  config: context.config,
57
- invocationKind: "task",
58
57
  current: currentExecutionValues(document, context, commandEnvironment),
59
58
  ...(context.commandSourceLoader ? { sourceLoader: context.commandSourceLoader } : {}),
60
59
  }), context);
@@ -71,7 +70,6 @@ export async function prepareTaskV3Execution(document, context) {
71
70
  const invocation = validatePreparedCommand(await (context.prepareCommand ?? prepareCommandInvocation)({
72
71
  action: { ref: qualified },
73
72
  config: context.config,
74
- invocationKind: "task",
75
73
  current: currentExecutionValues(document, context, commandEnvironment),
76
74
  ...(context.commandSourceLoader ? { sourceLoader: context.commandSourceLoader } : {}),
77
75
  }), context);
@@ -10,17 +10,16 @@
10
10
  * Resolution order:
11
11
  *
12
12
  * 1. `process.execPath` alone for a Bun standalone executable.
13
- * 2. Absolute Node plus the public `dist/akm` package launcher — eligible
14
- * when it is the active npm global install, or when this process
15
- * cannot write to the directory containing it (a read-only mount, e.g.
16
- * an image-baked install, gives the same "won't change out from under
17
- * the scheduler" guarantee npm-global ownership does).
18
- * 3. Absolute runtime plus the source/build CLI entry, classified as a
19
- * checkout that requires explicit `--rebind` for scheduler writes.
13
+ * 2. Absolute Node plus the public `dist/akm` package launcher.
14
+ * 3. Absolute runtime plus the source/build CLI entry of a checkout.
15
+ *
16
+ * `via` names which one was used. `checkout` — a package launcher inside a
17
+ * git work tree, or a source/build entry — runs whatever the checkout holds
18
+ * when the scheduler fires; `task sync` says so once when it writes one.
20
19
  *
21
20
  * Returns the argv array the scheduler should execute (e.g.
22
- * `["/usr/local/bin/node", "/repo/dist/cli-node.mjs"]`). The caller appends
23
- * subcommand args (`"task", "run", "<id>"`).
21
+ * `["/usr/local/bin/node", "/usr/lib/node_modules/akm-cli/dist/akm"]`). The
22
+ * caller appends subcommand args (`"task", "run", "<id>"`).
24
23
  */
25
24
  import { spawnSync } from "node:child_process";
26
25
  import fs from "node:fs";
@@ -28,6 +27,8 @@ import path from "node:path";
28
27
  import { fileURLToPath } from "node:url";
29
28
  import { ConfigError } from "../core/errors.js";
30
29
  import { mainPath as runtimeMainPath } from "../runtime.js";
30
+ /** A source entry or local build run by a runtime: `src/cli.ts`, `dist/cli.js`, `dist/cli-node.mjs`. */
31
+ const CHECKOUT_ENTRY = /(?:^|[\\/])src[\\/]cli\.ts$|(?:^|[\\/])dist[\\/](?:cli\.js|cli-node\.mjs)$/i;
31
32
  /** True only for Bun's virtual main path inside a compiled standalone executable. */
32
33
  export function isBunStandaloneMain(mainPath = runtimeMainPath) {
33
34
  return (mainPath?.startsWith("/$bunfs/") === true || (mainPath !== undefined && /^[A-Za-z]:[\\/]~BUN[\\/]/i.test(mainPath)));
@@ -37,44 +38,27 @@ export function resolveAkmInvocation(options = {}) {
37
38
  const runtime = options.runtime ?? (process.versions.bun ? "bun" : "node");
38
39
  const execPath = options.execPath ?? process.execPath;
39
40
  const mainPath = options.mainPath ?? runtimeMainPath;
40
- const isStandaloneMain = isBunStandaloneMain(mainPath);
41
- if (runtime === "bun" && isStandaloneMain && execPath) {
42
- return { argv: [absoluteInvocationPath(execPath)], via: "standalone", kind: "standalone", eligible: true };
41
+ if (runtime === "bun" && isBunStandaloneMain(mainPath) && execPath) {
42
+ return { argv: [absoluteInvocationPath(execPath)], via: "standalone" };
43
43
  }
44
44
  const launcherPath = options.launcherPath ?? env.AKM_LAUNCHER_PATH?.trim();
45
45
  const nodePath = options.nodePath ?? env.AKM_LAUNCHER_NODE?.trim() ?? (runtime === "node" ? execPath : undefined);
46
46
  if (launcherPath && nodePath && isPublicPackageLauncher(launcherPath)) {
47
- const checkout = isCheckoutLauncher(launcherPath);
48
- let npmGlobalRoot;
49
- if (!checkout) {
50
- try {
51
- npmGlobalRoot = (options.resolveNpmGlobalRoot ?? ((node) => resolveNpmGlobalRoot(node, env)))(nodePath);
52
- }
53
- catch {
54
- // An unprovable package installation is intentionally ineligible.
55
- }
56
- }
57
- const npmGlobal = !checkout && packageBelongsToNpmGlobalRoot(launcherPath, npmGlobalRoot);
58
- const readOnlyInstall = !checkout && !npmGlobal && !(options.isPathWritable ?? isPathWritable)(path.dirname(launcherPath));
59
- const kind = checkout ? "checkout" : npmGlobal ? "npm" : "package-local";
60
47
  return {
61
48
  argv: [absoluteInvocationPath(nodePath), absoluteInvocationPath(launcherPath)],
62
- via: kind,
63
- kind,
64
- eligible: npmGlobal || readOnlyInstall,
49
+ via: isCheckoutLauncher(launcherPath) ? "checkout" : "npm",
65
50
  };
66
51
  }
67
52
  const checkoutEntry = resolveCheckoutEntry(options.cliEntryUrl ?? import.meta.url, runtime, mainPath);
68
53
  if (checkoutEntry && execPath) {
69
- return {
70
- argv: [absoluteInvocationPath(execPath), absoluteInvocationPath(checkoutEntry)],
71
- via: "checkout",
72
- kind: "checkout",
73
- eligible: false,
74
- };
54
+ return { argv: [absoluteInvocationPath(execPath), absoluteInvocationPath(checkoutEntry)], via: "checkout" };
75
55
  }
76
56
  throw new ConfigError("Cannot resolve absolute path to the akm binary for scheduler registration.", "INVALID_CONFIG_FILE", "Run the npm-global launcher or a standalone akm executable.");
77
57
  }
58
+ /** Whether an installed launcher argv runs akm out of a source checkout. */
59
+ export function isCheckoutInvocation(argv) {
60
+ return argv.some((part) => CHECKOUT_ENTRY.test(part) || (isPublicPackageLauncher(part) && isCheckoutLauncher(part)));
61
+ }
78
62
  function resolveCheckoutEntry(moduleUrl, runtime, mainPath) {
79
63
  try {
80
64
  const modulePath = fileURLToPath(moduleUrl);
@@ -111,6 +95,7 @@ function isPublicPackageLauncher(file) {
111
95
  path.basename(path.dirname(file)).toLowerCase() === "dist" &&
112
96
  fs.existsSync(file));
113
97
  }
98
+ /** A package launcher whose package root is a git work tree (`npm link`, a local clone). */
114
99
  function isCheckoutLauncher(file) {
115
100
  let launcher = path.resolve(file);
116
101
  try {
@@ -122,52 +107,8 @@ function isCheckoutLauncher(file) {
122
107
  const packageRoot = path.dirname(path.dirname(launcher));
123
108
  return fs.existsSync(path.join(packageRoot, ".git"));
124
109
  }
125
- /** Whether this process can write to `dir` — false also covers a read-only mount. */
126
- function isPathWritable(dir) {
127
- try {
128
- fs.accessSync(dir, fs.constants.W_OK);
129
- return true;
130
- }
131
- catch {
132
- return false;
133
- }
134
- }
135
- function packageBelongsToNpmGlobalRoot(launcherPath, npmGlobalRoot) {
136
- if (!npmGlobalRoot)
137
- return false;
138
- try {
139
- const packageRoot = path.dirname(path.dirname(fs.realpathSync(launcherPath)));
140
- const globalRoot = fs.realpathSync(npmGlobalRoot);
141
- const metadata = JSON.parse(fs.readFileSync(path.join(packageRoot, "package.json"), "utf8"));
142
- return metadata.name === "akm-cli" && samePath(path.dirname(packageRoot), globalRoot);
143
- }
144
- catch {
145
- return false;
146
- }
147
- }
148
- function samePath(left, right) {
149
- const normalize = (value) => {
150
- const resolved = path.resolve(value);
151
- return process.platform === "win32" ? resolved.toLowerCase() : resolved;
152
- };
153
- return normalize(left) === normalize(right);
154
- }
155
- // #901: the global root can't change within a process lifetime, and every
156
- // `resolveAkmInvocation()` call in a scheduler-sync process re-derives the
157
- // same `nodePath` — so this spawns `npm root --global` at most once per
158
- // process instead of once per call. Keyed by nodePath (rather than a bare
159
- // once-only flag) so a differently-invoked probe later in the same process
160
- // still gets its own answer instead of a stale one.
161
- let cachedNpmGlobalRoot;
110
+ /** `npm root --global` for the npm that ships with `nodePath`; `akm upgrade` uses it to detect a global install. */
162
111
  export function resolveNpmGlobalRoot(nodePath, env) {
163
- if (cachedNpmGlobalRoot && cachedNpmGlobalRoot.nodePath === nodePath) {
164
- return cachedNpmGlobalRoot.value;
165
- }
166
- const value = resolveNpmGlobalRootUncached(nodePath, env);
167
- cachedNpmGlobalRoot = { nodePath, value };
168
- return value;
169
- }
170
- function resolveNpmGlobalRootUncached(nodePath, env) {
171
112
  const npmCli = resolveAssociatedNpmCli(nodePath);
172
113
  if (!npmCli)
173
114
  return undefined;
@@ -105,7 +105,6 @@ const SAFE_TASK_ATTEMPT_ERROR_CODES = new Set([
105
105
  "STASH_DIR_UNREADABLE",
106
106
  "LLM_NOT_CONFIGURED",
107
107
  "INVALID_CONFIG_FILE",
108
- "UNSUPPORTED_CONFIG_VERSION",
109
108
  "TEST_ISOLATION_MISSING",
110
109
  "INVALID_FLAG_VALUE",
111
110
  "MISSING_REQUIRED_ARGUMENT",
@@ -100,7 +100,7 @@ export async function loadPreparedTask(id, options) {
100
100
  bundleRoot: bundleDir,
101
101
  config,
102
102
  // Agent profiles build child env from an allowlist, so freeze the closed
103
- // scheduler-restored AKM directory context before command preparation.
103
+ // AKM directory context the scheduled row set before command preparation.
104
104
  ...(options.scheduled ? { schedulerContext: scheduledTaskContextEnv() } : {}),
105
105
  resolveAsset: async ({ bundle, type, name }) => {
106
106
  if (bundle === bundleName) {
@@ -2,12 +2,14 @@
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
- * Secret-free input to every native scheduler backend.
5
+ * Secret-free input to every native scheduler backend, and the backend
6
+ * contract itself.
6
7
  *
7
- * The binding deliberately contains only stable source identity, trigger
8
- * identity, and the public CLI tail. Source content, action inputs,
9
- * environment values, resolved requests, and credentials must never cross
10
- * this boundary or be persisted by an OS scheduler.
8
+ * A binding carries only stable source identity, trigger identity, and the
9
+ * public CLI tail; its install options add the launcher and the AKM
10
+ * directory environment the row sets inline. Source content, action inputs,
11
+ * task environment values, and credentials never cross this boundary or
12
+ * reach an OS scheduler.
11
13
  */
12
14
  import { createHash } from "node:crypto";
13
15
  import { bundleRefToString, parseBundleRef } from "../core/asset/asset-ref.js";
@@ -20,20 +22,8 @@ export function compileTaskSchedulerBindings(input) {
20
22
  const bundle = parseBundleRef(ref).bundle;
21
23
  if (!bundle)
22
24
  throw new Error("invariant: qualified scheduler task ref lost its bundle");
23
- // P2b Lane B (B-N3): the invocation is compiled PER schedule entry now —
24
- // each entry's own `inputs` produces its own trailing flag tail, so it can
25
- // no longer be hoisted as one binding shared by every entry.
26
25
  return Object.freeze(input.schedules.map((schedule) => {
27
26
  const bindingId = schedule.ordinal === 0 ? id : digestBindingId("task", ref, schedule.ordinal);
28
- const invocation = Object.freeze([
29
- "task",
30
- "run",
31
- id,
32
- "--bundle",
33
- bundle,
34
- "--scheduled",
35
- ...schedulerInputFlagTail(schedule.inputs),
36
- ]);
37
27
  return freezeBinding({
38
28
  id: bindingId,
39
29
  nativeId: schedulerNativeBindingId(bindingId),
@@ -42,39 +32,21 @@ export function compileTaskSchedulerBindings(input) {
42
32
  source: schedule.source,
43
33
  ordinal: schedule.ordinal,
44
34
  enabled: true,
45
- invocation,
35
+ invocation: ["task", "run", id, "--bundle", bundle, "--scheduled", ...schedulerInputFlagTail(schedule.inputs)],
46
36
  });
47
37
  }));
48
38
  }
49
39
  /**
50
40
  * The canonically-sorted `--<name> <value>` flag tail for one schedule
51
- * entry's `inputs` (spec §1.7 B-N3). Empty/absent `inputs` yields an empty
52
- * tail — the fixed six-token invocation, byte-identical to every schedule
53
- * entry before P2b (B-03).
54
- *
55
- * Code-review finding (scheduler-binding.ts:536): a value whose exact text
56
- * begins with `-` (a negative number, or a string that just happens to
57
- * start with a dash) is indistinguishable from a NEW flag in the two-token
58
- * `--<name> <value>` form — `isValidSchedulerInputFlagTail`
59
- * (scheduler-invocation.ts) refuses it outright, and even a looser parser
60
- * would still be wrong for a non-numeric dash-leading string: the real `akm
61
- * task run` flag parser (`parseTaskInputFlags`, tasks-cli.ts) only
62
- * special-cases a dash-DIGIT lead, so it would silently treat `--scope
63
- * -urgent` as the boolean flag `--scope` followed by an orphaned,
64
- * dropped `-urgent` token. The inline `--<name>=<value>` form has no such
65
- * ambiguity on EITHER side — `isValidSchedulerInputFlagTail` accepts it
66
- * unconditionally, and `parseTaskInputFlags`'s own inline-`=` branch splits
67
- * on the first `=` without ever inspecting the value's leading character —
68
- * so it is used whenever the value's exact text would otherwise be
69
- * ambiguous. Every other value keeps the existing two-token form
70
- * byte-identical to before this fix (B-03/B-45).
41
+ * entry's `inputs`. A value whose text starts with `-` uses the inline
42
+ * `--<name>=<value>` form, the only spelling `parseTaskInputFlags` cannot
43
+ * mistake for a flag.
71
44
  */
72
45
  function schedulerInputFlagTail(inputs) {
73
46
  if (!inputs)
74
47
  return [];
75
- const names = Object.keys(inputs).sort();
76
48
  const tail = [];
77
- for (const name of names) {
49
+ for (const name of Object.keys(inputs).sort()) {
78
50
  const text = schedulerInputFlagValueText(inputs[name]);
79
51
  if (text.startsWith("-"))
80
52
  tail.push(`--${name}=${text}`);
@@ -83,14 +55,6 @@ function schedulerInputFlagTail(inputs) {
83
55
  }
84
56
  return tail;
85
57
  }
86
- /**
87
- * One input value's argv text. A scalar is its exact text — `String(value)`
88
- * for a number/boolean (a `true` boolean is `"true"`, never a bare flag, so
89
- * the tail round-trips through one parser), the string itself for a string.
90
- * An object/array value is its `canonicalInputJson` text, which
91
- * `materializeInputFlags`'s JSON-shorthand path already coerces back through
92
- * the declaration.
93
- */
94
58
  function schedulerInputFlagValueText(value) {
95
59
  if (typeof value === "string")
96
60
  return value;
@@ -100,7 +64,6 @@ function schedulerInputFlagValueText(value) {
100
64
  }
101
65
  export function compileWorkflowSchedulerBindings(input) {
102
66
  const ref = assertQualifiedRef(input.qualifiedRef, "workflow");
103
- const invocation = Object.freeze(["workflow", "run", ref]);
104
67
  return Object.freeze(input.schedules.map((schedule) => {
105
68
  const bindingId = digestBindingId("workflow", ref, schedule.ordinal);
106
69
  return freezeBinding({
@@ -111,23 +74,14 @@ export function compileWorkflowSchedulerBindings(input) {
111
74
  source: schedule.source,
112
75
  ordinal: schedule.ordinal,
113
76
  enabled: true,
114
- invocation,
115
- ...(input.executionEvidenceDigest !== undefined
116
- ? { executionEvidenceDigest: assertSchedulerExecutionEvidenceDigest(input.executionEvidenceDigest) }
117
- : {}),
77
+ invocation: ["workflow", "run", ref],
118
78
  });
119
79
  }));
120
80
  }
121
- export function assertSchedulerExecutionEvidenceDigest(value) {
122
- if (!/^[a-f0-9]{64}$/u.test(value)) {
123
- throw new UsageError("Scheduler workflow execution evidence must be a lowercase SHA-256 digest.", "INVALID_FLAG_VALUE");
124
- }
125
- return value;
126
- }
127
81
  /**
128
82
  * Map a logical binding id to the flat portable token persisted by native
129
- * schedulers. Existing flat ids are byte-for-byte stable; only standalone
130
- * component-relative ids need an encoded native spelling.
83
+ * schedulers. Flat ids are byte-for-byte stable; only nested standalone
84
+ * component ids need an encoded native spelling.
131
85
  */
132
86
  export function schedulerNativeBindingId(id) {
133
87
  if (!id.includes("/"))
@@ -138,183 +92,17 @@ export function schedulerNativeBindingId(id) {
138
92
  .slice(0, 32);
139
93
  return `task-${digest}`;
140
94
  }
141
- /** Portable collision key for scheduler namespaces with Windows semantics. */
142
- export function schedulerNativeArtifactKey(nativeId) {
143
- return nativeId.toLowerCase().replace(/\.+$/u, "");
144
- }
145
- export function schedulerNativeArtifactsForKey(artifacts, nativeId) {
146
- const key = schedulerNativeArtifactKey(nativeId);
147
- return artifacts.filter((artifact) => schedulerNativeArtifactKey(artifact.nativeId) === key);
148
- }
149
- export function assertSchedulerNativeArtifactCardinality(artifacts, nativeId, expectedCount) {
150
- const matches = schedulerNativeArtifactsForKey(artifacts, nativeId);
151
- if (matches.length !== expectedCount) {
152
- const expectedState = expectedCount === 0 ? "absence" : "one present owner";
153
- throw new UsageError(`Native scheduler artifact ${JSON.stringify(nativeId)} changed: normalized cardinality ${matches.length} violates the expected ${expectedState} before mutation.`, "RESOURCE_ALREADY_EXISTS");
154
- }
155
- return matches[0];
156
- }
157
- /** Return a logical owner only when the public invocation proves the mapping. */
158
- export function schedulerLogicalBindingOwner(nativeId, invocation) {
159
- return schedulerNativeArtifactOwner(nativeId, invocation)?.logicalId;
160
- }
161
- export function schedulerNativeArtifactOwner(nativeId, invocation) {
162
- if (invocation[0] === "workflow" && invocation[1] === "run" && invocation.length === 3) {
163
- const ref = invocation[2];
164
- if (ref && workflowRefDigestsToNativeId(ref, nativeId)) {
165
- return { logicalId: nativeId, logicalKind: "workflow" };
166
- }
167
- return undefined;
168
- }
169
- const taskId = invocation[0] === "task" && invocation[1] === "run" ? invocation[2] : undefined;
170
- if (!taskId)
171
- return undefined;
172
- return {
173
- logicalId: schedulerNativeBindingId(taskId) === nativeId ? taskId : nativeId,
174
- logicalKind: "task",
175
- };
176
- }
177
- export function assertSchedulerNativeArtifactOwner(nativeId, intended, invocation) {
178
- const intendedNativeId = intended.nativeId ?? schedulerNativeBindingId(intended.id);
179
- if (nativeId === intendedNativeId && invocation && sameInvocation(invocation, intended.invocation))
180
- return;
181
- const description = invocation ? JSON.stringify(invocation) : "an unproven or malformed invocation";
182
- throw new UsageError(`Native scheduler artifact ${JSON.stringify(nativeId)} belongs to ${description}, not the exact ${intended.logicalSource.kind} owner ${JSON.stringify(intended.logicalSource.ref)} with binding ${JSON.stringify(intended.id)}.`, "RESOURCE_ALREADY_EXISTS");
183
- }
184
- /** Recover binding identity without treating the native hash as source ownership. */
185
- export function schedulerLogicalBindingId(nativeId, invocation) {
186
- return schedulerLogicalBindingOwner(nativeId, invocation) ?? nativeId;
187
- }
188
95
  export function schedulerBindingNativeId(binding) {
189
96
  return binding.nativeId ?? schedulerNativeBindingId(binding.id);
190
97
  }
191
- export function assertSchedulerRemovalArtifact(nativeId, expected, invocation, fingerprint) {
192
- const normalized = normalizeRemovalExpectation(expected);
193
- assertSchedulerExpectationIdentity(normalized);
194
- const fingerprintMatches = normalized.fingerprint === undefined || normalized.fingerprint === fingerprint;
195
- if (nativeId === normalized.nativeId &&
196
- invocation !== undefined &&
197
- sameInvocation(invocation, normalized.invocation) &&
198
- fingerprintMatches) {
199
- return;
200
- }
201
- throw new UsageError(`Native scheduler artifact ${JSON.stringify(nativeId)} changed owner or fingerprint; refusing to remove an unverified ${normalized.logicalSource.kind} owner ${JSON.stringify(normalized.logicalSource.ref)}.`, "RESOURCE_ALREADY_EXISTS");
202
- }
203
- export function assertSchedulerExpectationIdentity(expected, binding) {
204
- const identity = canonicalSchedulerIdentity(expected.logicalSource, expected.ordinal, expected.invocation);
205
- if (identity.bindingId !== expected.bindingId ||
206
- identity.nativeId !== expected.nativeId ||
207
- !sameInvocation(identity.invocation, expected.invocation) ||
208
- (binding !== undefined &&
209
- (binding.id !== expected.bindingId ||
210
- schedulerBindingNativeId(binding) !== expected.nativeId ||
211
- binding.ordinal !== expected.ordinal ||
212
- binding.logicalSource.kind !== expected.logicalSource.kind ||
213
- binding.logicalSource.ref !== expected.logicalSource.ref ||
214
- !sameInvocation(binding.invocation, expected.invocation)))) {
215
- throw new UsageError("Scheduler mutation expectation has a forged or inconsistent binding identity.", "INVALID_FLAG_VALUE");
216
- }
217
- if (expected.state === "absent" && expected.fingerprint !== undefined) {
218
- throw new UsageError("An absent scheduler expectation cannot carry prior artifact state.", "INVALID_FLAG_VALUE");
219
- }
220
- }
221
- export function assertSchedulerMutationArtifact(artifact, expected) {
222
- assertSchedulerExpectationIdentity(expected);
223
- if (expected.state === "absent") {
224
- if (artifact === undefined)
225
- return;
226
- }
227
- else if (artifact !== undefined &&
228
- artifact.nativeId === expected.nativeId &&
229
- artifact.bindingId === expected.bindingId &&
230
- artifact.invocation !== undefined &&
231
- expected.fingerprint !== undefined &&
232
- artifact.fingerprint === expected.fingerprint) {
233
- return;
234
- }
235
- throw new UsageError(`Native scheduler artifact ${JSON.stringify(expected.nativeId)} changed from its frozen ${expected.state} state; refusing mutation.`, "RESOURCE_ALREADY_EXISTS");
236
- }
237
- export function assertSchedulerRollbackArtifact(artifact, expected) {
238
- const matches = expected.allowed.some((state) => {
239
- if (state.state === "absent")
240
- return artifact === undefined;
241
- if (!artifact || artifact.nativeId !== expected.nativeId)
242
- return false;
243
- if (artifact.fingerprint !== state.fingerprint || artifact.bindingId !== state.bindingId)
244
- return false;
245
- return state.invocation === undefined
246
- ? artifact.invocation === undefined
247
- : artifact.invocation !== undefined && sameInvocation(artifact.invocation, state.invocation);
248
- });
249
- if (matches)
250
- return;
251
- throw new UsageError(`Native scheduler artifact ${JSON.stringify(expected.nativeId)} changed after the transaction began; refusing rollback over a concurrent owner or fingerprint.`, "RESOURCE_ALREADY_EXISTS");
252
- }
253
98
  /**
254
- * Validate a rollback target from one complete native inventory. Rollback
255
- * guards may allow either the transaction-written state or the prior state,
256
- * but neither state permits two portable-key-equivalent artifacts.
99
+ * Recover the logical id of an installed row from its native spelling and
100
+ * public invocation: an ordinal-zero task row is its task id (possibly a
101
+ * nested one behind a digest spelling); every other row is its native id.
257
102
  */
258
- export function assertSchedulerRollbackArtifactCardinality(artifacts, expected) {
259
- const matches = schedulerNativeArtifactsForKey(artifacts, expected.nativeId);
260
- if (matches.length > 1) {
261
- throw new UsageError(`Native scheduler artifact ${JSON.stringify(expected.nativeId)} changed after the transaction began: normalized rollback cardinality ${matches.length} exceeds one.`, "RESOURCE_ALREADY_EXISTS");
262
- }
263
- const artifact = matches[0];
264
- assertSchedulerRollbackArtifact(artifact, expected);
265
- return artifact;
266
- }
267
- export function canonicalSchedulerIdentity(logicalSource, ordinal, invocation) {
268
- const parsed = parseBundleRef(logicalSource.ref);
269
- if (!parsed.bundle || parsed.fragment !== undefined || bundleRefToString(parsed) !== logicalSource.ref) {
270
- throw new UsageError("Scheduler expectation requires one canonical fully-qualified source.", "INVALID_FLAG_VALUE");
271
- }
272
- if (!Number.isSafeInteger(ordinal) || ordinal < 0) {
273
- throw new UsageError("Scheduler expectation ordinal must be a non-negative integer.", "INVALID_FLAG_VALUE");
274
- }
275
- if (logicalSource.kind === "workflow") {
276
- const canonicalInvocation = ["workflow", "run", logicalSource.ref];
277
- if (!sameInvocation(invocation, canonicalInvocation)) {
278
- throw new UsageError("Workflow scheduler expectation invocation does not match its qualified source.", "INVALID_FLAG_VALUE");
279
- }
280
- const bindingId = digestBindingId("workflow", logicalSource.ref, ordinal);
281
- return Object.freeze({ bindingId, nativeId: bindingId, invocation: Object.freeze(canonicalInvocation) });
282
- }
103
+ export function schedulerLogicalBindingId(nativeId, invocation) {
283
104
  const taskId = invocation[0] === "task" && invocation[1] === "run" ? invocation[2] : undefined;
284
- if (!taskId || normaliseTaskConceptId(taskId) !== taskId) {
285
- throw new UsageError("Task scheduler expectation has an invalid public task id.", "INVALID_FLAG_VALUE");
286
- }
287
- const canonicalInvocation = ["task", "run", taskId, "--bundle", parsed.bundle, "--scheduled"];
288
- if (!sameInvocation(invocation, canonicalInvocation)) {
289
- throw new UsageError(`Task scheduler expectation invocation does not match its qualified source: expected ${JSON.stringify(canonicalInvocation)}, got ${JSON.stringify(invocation)}.`, "INVALID_FLAG_VALUE");
290
- }
291
- if (parsed.conceptId !== taskId && parsed.conceptId !== `tasks/${taskId}`) {
292
- throw new UsageError("Task scheduler expectation id does not match its qualified source.", "INVALID_FLAG_VALUE");
293
- }
294
- const bindingId = ordinal === 0 ? taskId : digestBindingId("task", logicalSource.ref, ordinal);
295
- return Object.freeze({
296
- bindingId,
297
- nativeId: schedulerNativeBindingId(bindingId),
298
- invocation: Object.freeze(canonicalInvocation),
299
- });
300
- }
301
- /** Recover the authored schedule ordinal from the exact source/binding identity. */
302
- export function schedulerBindingOrdinal(bindingId, logicalSource, invocation) {
303
- if (logicalSource.kind === "task" && bindingId === invocation[2])
304
- return 0;
305
- for (let ordinal = 0; ordinal < 4096; ordinal += 1) {
306
- if (digestBindingId(logicalSource.kind, logicalSource.ref, ordinal) === bindingId)
307
- return ordinal;
308
- }
309
- return undefined;
310
- }
311
- /** Whether some schedule ordinal on `ref` would digest to `nativeId` (mirrors schedulerBindingOrdinal). */
312
- function workflowRefDigestsToNativeId(ref, nativeId) {
313
- for (let ordinal = 0; ordinal < 4096; ordinal += 1) {
314
- if (digestBindingId("workflow", ref, ordinal) === nativeId)
315
- return true;
316
- }
317
- return false;
105
+ return taskId !== undefined && schedulerNativeBindingId(taskId) === nativeId ? taskId : nativeId;
318
106
  }
319
107
  function digestBindingId(kind, ref, ordinal) {
320
108
  const prefix = kind === "workflow" ? "wf" : "task";
@@ -338,9 +126,3 @@ function freezeBinding(binding) {
338
126
  invocation: Object.freeze([...binding.invocation]),
339
127
  });
340
128
  }
341
- function sameInvocation(left, right) {
342
- return left.length === right.length && left.every((value, index) => value === right[index]);
343
- }
344
- function normalizeRemovalExpectation(expected) {
345
- return { ...expected, state: "present" };
346
- }