akm-cli 0.9.1 → 0.9.2-alpha.2

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 (350) hide show
  1. package/CHANGELOG.md +103 -28
  2. package/README.md +3 -1
  3. package/SECURITY.md +1 -1
  4. package/STABILITY.md +1 -1
  5. package/dist/akm +2 -2
  6. package/dist/akm-migrate +2 -2
  7. package/dist/assets/hints/cli-hints-full.md +14 -9
  8. package/dist/assets/improve-strategies/proactive-maintenance.json +1 -1
  9. package/dist/assets/improve-strategies/reflect-distill.json +1 -1
  10. package/dist/assets/models.json +35 -0
  11. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +3 -4
  12. package/dist/assets/stash-skeleton/facts/conventions/organization.md +1 -3
  13. package/dist/assets/tasks/core/extract.yml +6 -5
  14. package/dist/assets/tasks/core/improve.yml +6 -5
  15. package/dist/assets/tasks/core/index-refresh.yml +6 -5
  16. package/dist/assets/tasks/core/sync.yml +6 -5
  17. package/dist/assets/tasks/core/version-check.yml +6 -5
  18. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +6 -5
  19. package/dist/assets/tasks/improve/akm-improve-catchup.yml +6 -5
  20. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +6 -5
  21. package/dist/assets/tasks/improve/akm-improve-frequent.yml +6 -5
  22. package/dist/assets/tasks/improve/akm-improve-nightly.yml +6 -5
  23. package/dist/cli/confirm.js +2 -2
  24. package/dist/cli/parse-args.js +3 -24
  25. package/dist/cli/retired-commands.js +1 -1
  26. package/dist/cli/shared.js +2 -2
  27. package/dist/cli.js +11 -9
  28. package/dist/commands/agent/agent-dispatch.js +55 -89
  29. package/dist/commands/agent/contribute-cli.js +12 -45
  30. package/dist/commands/command/builtin-action.js +32 -0
  31. package/dist/commands/command/command-cli.js +99 -0
  32. package/dist/commands/command/command-execution.js +308 -0
  33. package/dist/commands/command/execution-source-loader.js +176 -0
  34. package/dist/commands/command/portable-template.js +60 -0
  35. package/dist/commands/config-cli.js +10 -4
  36. package/dist/commands/env/env.js +4 -2
  37. package/dist/commands/feedback-cli.js +1 -1
  38. package/dist/commands/health/checks.js +241 -29
  39. package/dist/commands/health/html-report.js +0 -14
  40. package/dist/commands/health/report-view-model.js +0 -1
  41. package/dist/commands/health/surfaces.js +6 -7
  42. package/dist/commands/health/types.js +0 -2
  43. package/dist/commands/health.js +63 -18
  44. package/dist/commands/improve/collapse-detector.js +5 -6
  45. package/dist/commands/improve/consolidate.js +251 -214
  46. package/dist/commands/improve/distill/promote-memory.js +71 -34
  47. package/dist/commands/improve/distill/quality-gate.js +17 -5
  48. package/dist/commands/improve/distill.js +232 -155
  49. package/dist/commands/improve/eligibility.js +112 -79
  50. package/dist/commands/improve/execution.js +57 -0
  51. package/dist/commands/improve/extract-cli.js +5 -5
  52. package/dist/commands/improve/extract-prompt.js +64 -22
  53. package/dist/commands/improve/extract.js +608 -360
  54. package/dist/commands/improve/improve-strategies.js +43 -14
  55. package/dist/commands/improve/improve.js +249 -29
  56. package/dist/commands/improve/loop-stages.js +11 -17
  57. package/dist/commands/improve/memory/memory-contradiction-detect.js +90 -66
  58. package/dist/commands/improve/outcome-loop.js +22 -38
  59. package/dist/commands/improve/planner.js +134 -0
  60. package/dist/commands/improve/preparation.js +730 -409
  61. package/dist/commands/improve/reflect.js +386 -223
  62. package/dist/commands/improve/run-context.js +3 -4
  63. package/dist/commands/improve/salience.js +6 -58
  64. package/dist/commands/improve/session-asset.js +12 -12
  65. package/dist/commands/lint/index.js +101 -29
  66. package/dist/commands/migrate-cli.js +11 -69
  67. package/dist/commands/migration-tool.js +6 -9
  68. package/dist/commands/models-cli.js +27 -0
  69. package/dist/commands/proposal/drain.js +258 -186
  70. package/dist/commands/proposal/proposal-cli.js +32 -10
  71. package/dist/commands/proposal/proposal.js +2 -5
  72. package/dist/commands/proposal/propose.js +192 -172
  73. package/dist/commands/proposal/repository.js +54 -91
  74. package/dist/commands/proposal/validators/proposal-validators.js +9 -7
  75. package/dist/commands/read/curate.js +53 -22
  76. package/dist/commands/read/registry-search.js +25 -9
  77. package/dist/commands/read/remember-cli.js +14 -2
  78. package/dist/commands/read/search.js +10 -4
  79. package/dist/commands/read/show.js +139 -153
  80. package/dist/commands/registry-cli.js +16 -7
  81. package/dist/commands/remember.js +33 -18
  82. package/dist/commands/sources/add-cli.js +19 -178
  83. package/dist/commands/sources/bundle-cli.js +15 -3
  84. package/dist/commands/sources/dangerous-env-audit.js +135 -0
  85. package/dist/commands/sources/info.js +2 -1
  86. package/dist/commands/sources/installed-stashes.js +901 -177
  87. package/dist/commands/sources/schema-repair.js +174 -95
  88. package/dist/commands/sources/self-update.js +30 -74
  89. package/dist/commands/sources/source-add.js +3 -5
  90. package/dist/commands/sources/sources-cli.js +2 -15
  91. package/dist/commands/sources/update-transaction.js +220 -0
  92. package/dist/commands/tasks/tasks-cli.js +3 -3
  93. package/dist/commands/tasks/tasks.js +736 -317
  94. package/dist/commands/workflow-cli.js +2 -2
  95. package/dist/core/adapter/adapters/agent-skills-adapter.js +3 -0
  96. package/dist/core/adapter/adapters/akm-adapter.js +85 -35
  97. package/dist/core/adapter/adapters/akm-lint.js +54 -39
  98. package/dist/core/adapter/adapters/akm-metadata.js +45 -45
  99. package/dist/core/adapter/adapters/akm-task-adapter.js +32 -49
  100. package/dist/core/adapter/adapters/akm-workflow-adapter.js +38 -23
  101. package/dist/core/adapter/adapters/dotenv-adapter.js +30 -1
  102. package/dist/core/adapter/adapters/generic-files-adapter.js +11 -0
  103. package/dist/core/adapter/adapters/index.js +0 -9
  104. package/dist/core/adapter/adapters/llm-wiki-adapter.js +4 -0
  105. package/dist/core/adapter/adapters/okf-adapter.js +4 -0
  106. package/dist/core/adapter/adapters/opencode-adapter.js +5 -8
  107. package/dist/core/adapter/adapters/tool-dir-shared.js +63 -6
  108. package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -0
  109. package/dist/core/adapter/execution-source.js +308 -0
  110. package/dist/core/adapter/recognize-match.js +36 -13
  111. package/dist/core/adapter/registry.js +0 -9
  112. package/dist/core/asset/stash-meta.js +94 -4
  113. package/dist/core/common.js +6 -11
  114. package/dist/core/config/config-io.js +3 -3
  115. package/dist/core/config/config-schema.js +18 -40
  116. package/dist/core/config/config-sources.js +11 -21
  117. package/dist/core/config/config-walker.js +31 -13
  118. package/dist/core/config/config.js +23 -26
  119. package/dist/core/config/schema/engines.js +8 -7
  120. package/dist/core/config/schema/improve-processes.js +29 -5
  121. package/dist/core/config/schema/index-config.js +0 -27
  122. package/dist/core/config/schema/primitives.js +1 -23
  123. package/dist/core/config/schema/sources-bundles.js +13 -16
  124. package/dist/core/errors.js +2 -0
  125. package/dist/core/events.js +68 -32
  126. package/dist/core/extra-params.js +1 -0
  127. package/dist/core/improve-result.js +315 -0
  128. package/dist/core/lesson-lint.js +0 -6
  129. package/dist/core/maintenance-barrier.js +4 -4
  130. package/dist/core/network-policy.js +152 -0
  131. package/dist/core/paths.js +1 -1
  132. package/dist/core/recognition-util.js +4 -4
  133. package/dist/core/registry-url.js +456 -0
  134. package/dist/core/state/migrations.js +161 -47
  135. package/dist/core/state-db.js +453 -80
  136. package/dist/core/system-error.js +32 -0
  137. package/dist/core/time.js +2 -12
  138. package/dist/core/write-source.js +0 -18
  139. package/dist/execution/directory-identity.js +52 -0
  140. package/dist/execution/executable-identity.js +107 -0
  141. package/dist/execution/guarded-source.js +398 -0
  142. package/dist/execution/json.js +95 -0
  143. package/dist/{commands/health/types-session-log.js → execution/limits.js} +2 -1
  144. package/dist/execution/record.js +55 -0
  145. package/dist/execution/resolved-request.js +730 -0
  146. package/dist/execution/source.js +320 -0
  147. package/dist/indexer/bundle-identity-guard.js +5 -4
  148. package/dist/indexer/db/graph-db.js +33 -0
  149. package/dist/indexer/graph/graph-boost.js +3 -4
  150. package/dist/indexer/graph/graph-extraction.js +562 -373
  151. package/dist/indexer/index-written-assets.js +78 -39
  152. package/dist/indexer/indexer.js +471 -432
  153. package/dist/indexer/installations.js +6 -0
  154. package/dist/indexer/lookup/adapter-concept-owner.js +283 -0
  155. package/dist/indexer/materialize-embeddings.js +155 -0
  156. package/dist/indexer/passes/memory-inference.js +227 -174
  157. package/dist/indexer/passes/metadata.js +263 -118
  158. package/dist/indexer/scan/doc-to-entry.js +7 -10
  159. package/dist/indexer/scan/drain-dir.js +51 -23
  160. package/dist/indexer/search/db-search.js +156 -50
  161. package/dist/indexer/search/fts-query.js +40 -40
  162. package/dist/indexer/search/ranking.js +36 -1
  163. package/dist/indexer/search/search-attribution.js +3 -1
  164. package/dist/indexer/search/search-fields.js +23 -14
  165. package/dist/indexer/search/search-hit-enrichers.js +1 -1
  166. package/dist/indexer/search/search-source.js +7 -16
  167. package/dist/indexer/search/semantic-status.js +10 -1
  168. package/dist/indexer/usage/show-usage.js +105 -0
  169. package/dist/indexer/usage/usage-events.js +7 -2
  170. package/dist/indexer/walk/matchers.js +40 -10
  171. package/dist/indexer/walk/path-resolver.js +5 -2
  172. package/dist/indexer/walk/walker.js +20 -2
  173. package/dist/integrations/agent/builder-shared.js +3 -6
  174. package/dist/integrations/agent/conversation-fallback.js +16 -0
  175. package/dist/integrations/agent/engine-resolution.js +87 -87
  176. package/dist/integrations/agent/execution-cascade.js +566 -0
  177. package/dist/integrations/agent/execution-definitions.js +211 -0
  178. package/dist/integrations/agent/execution-lowering.js +811 -0
  179. package/dist/integrations/agent/execution-preparation.js +67 -0
  180. package/dist/integrations/agent/index.js +0 -2
  181. package/dist/integrations/agent/inline-execution.js +74 -0
  182. package/dist/integrations/agent/model-map.js +515 -0
  183. package/dist/integrations/agent/persona-fallback.js +30 -0
  184. package/dist/integrations/agent/request-lowering.js +186 -0
  185. package/dist/integrations/agent/runner-dispatch.js +230 -37
  186. package/dist/integrations/agent/runner.js +12 -83
  187. package/dist/integrations/harnesses/aider/agent-builder.js +8 -0
  188. package/dist/integrations/harnesses/aider/index.js +0 -1
  189. package/dist/integrations/harnesses/amazonq/agent-builder.js +8 -0
  190. package/dist/integrations/harnesses/amazonq/index.js +0 -1
  191. package/dist/integrations/harnesses/claude/agent-builder.js +14 -1
  192. package/dist/integrations/harnesses/claude/index.js +1 -5
  193. package/dist/integrations/harnesses/claude/session-log.js +3 -33
  194. package/dist/integrations/harnesses/codex/agent-builder.js +8 -0
  195. package/dist/integrations/harnesses/codex/index.js +0 -1
  196. package/dist/integrations/harnesses/copilot/agent-builder.js +8 -0
  197. package/dist/integrations/harnesses/copilot/index.js +0 -1
  198. package/dist/integrations/harnesses/gemini/agent-builder.js +8 -0
  199. package/dist/integrations/harnesses/gemini/index.js +0 -1
  200. package/dist/integrations/harnesses/index.js +4 -44
  201. package/dist/integrations/harnesses/opencode/agent-builder.js +16 -9
  202. package/dist/integrations/harnesses/opencode/index.js +0 -2
  203. package/dist/integrations/harnesses/opencode/session-log.js +14 -204
  204. package/dist/integrations/harnesses/opencode-sdk/harness.js +12 -1
  205. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +40 -42
  206. package/dist/integrations/harnesses/openhands/agent-builder.js +8 -0
  207. package/dist/integrations/harnesses/openhands/index.js +0 -1
  208. package/dist/integrations/harnesses/pi/agent-builder.js +8 -0
  209. package/dist/integrations/harnesses/pi/index.js +0 -1
  210. package/dist/integrations/harnesses/shared.js +0 -1
  211. package/dist/integrations/harnesses/types.js +1 -3
  212. package/dist/integrations/lockfile.js +82 -79
  213. package/dist/integrations/session-logs/index.js +6 -17
  214. package/dist/integrations/session-logs/provider-base.js +1 -29
  215. package/dist/llm/client.js +10 -5
  216. package/dist/llm/embedder.js +6 -7
  217. package/dist/llm/embedders/local.js +37 -88
  218. package/dist/llm/embedders/types.js +1 -1
  219. package/dist/llm/graph-extract.js +75 -50
  220. package/dist/llm/index-passes.js +43 -5
  221. package/dist/llm/memory-infer.js +8 -6
  222. package/dist/llm/metadata-enhance.js +5 -3
  223. package/dist/llm/structured-call.js +122 -25
  224. package/dist/output/format-exempt.js +1 -1
  225. package/dist/output/render-registry.js +0 -16
  226. package/dist/output/renderers.js +12 -7
  227. package/dist/output/shapes/curate.js +1 -0
  228. package/dist/output/shapes/helpers.js +10 -2
  229. package/dist/output/shapes/passthrough.js +2 -0
  230. package/dist/output/text/command-format.js +31 -33
  231. package/dist/output/text/health-format.js +1 -29
  232. package/dist/output/text/migrate.js +6 -56
  233. package/dist/output/text/proposal-format.js +16 -1
  234. package/dist/output/text/workflow-format.js +16 -0
  235. package/dist/registry/network.js +279 -0
  236. package/dist/registry/pinned-request-helper.js +247 -0
  237. package/dist/registry/pinned-transport.js +717 -0
  238. package/dist/registry/providers/skills-sh.js +18 -6
  239. package/dist/registry/providers/static-index.js +20 -7
  240. package/dist/registry/resolve.js +53 -28
  241. package/dist/scripts/akm-migrate-node.js +19334 -52269
  242. package/dist/scripts/akm-migrate.js +19270 -51612
  243. package/dist/setup/registry-stash-loader.js +64 -20
  244. package/dist/setup/semantic-assets.js +9 -34
  245. package/dist/setup/setup.js +12 -30
  246. package/dist/setup/source-identity.js +17 -0
  247. package/dist/setup/steps/sources.js +36 -15
  248. package/dist/setup/steps/tasks.js +39 -11
  249. package/dist/sources/providers/git-provider.js +3 -3
  250. package/dist/sources/providers/npm.js +2 -2
  251. package/dist/sources/providers/provider-utils.js +4 -3
  252. package/dist/sources/providers/website.js +11 -7
  253. package/dist/sources/snapshot-fetchers/host-guard.js +9 -136
  254. package/dist/sources/snapshot-fetchers/website-ingest.js +25 -109
  255. package/dist/sources/website-url.js +73 -0
  256. package/dist/storage/engines/sqlite-migrations.js +81 -26
  257. package/dist/storage/managed-db.js +27 -24
  258. package/dist/storage/repositories/events-repository.js +3 -0
  259. package/dist/storage/repositories/index-connection.js +42 -10
  260. package/dist/storage/repositories/index-entries-repository.js +203 -229
  261. package/dist/storage/repositories/index-entry-mapper.js +8 -12
  262. package/dist/storage/repositories/index-entry-schema.js +255 -0
  263. package/dist/storage/repositories/index-fts-repository.js +64 -71
  264. package/dist/storage/repositories/index-llm-cache-repository.js +8 -13
  265. package/dist/storage/repositories/index-meta-repository.js +0 -11
  266. package/dist/storage/repositories/index-schema.js +74 -350
  267. package/dist/storage/repositories/index-utility-repository.js +12 -17
  268. package/dist/storage/repositories/index-vec-repository.js +56 -7
  269. package/dist/storage/repositories/proposals-repository.js +4 -127
  270. package/dist/storage/repositories/registry-cache.js +2 -1
  271. package/dist/storage/repositories/task-history-repository.js +20 -40
  272. package/dist/storage/repositories/workflow-runs-repository.js +228 -129
  273. package/dist/storage/sqlite-read-snapshot.js +148 -0
  274. package/dist/tasks/backends/cron.js +170 -42
  275. package/dist/tasks/backends/index.js +1 -1
  276. package/dist/tasks/backends/launchd.js +787 -202
  277. package/dist/tasks/backends/schtasks.js +282 -83
  278. package/dist/tasks/embedded.js +7 -7
  279. package/dist/tasks/frozen-script.js +50 -0
  280. package/dist/tasks/resolve-akm-bin.js +5 -1
  281. package/dist/tasks/runner.js +239 -251
  282. package/dist/tasks/runtime-v3.js +281 -0
  283. package/dist/tasks/scheduler-binding.js +272 -0
  284. package/dist/tasks/scheduler-invocation.js +57 -43
  285. package/dist/tasks/scheduler-sync.js +654 -0
  286. package/dist/tasks/source-v3.js +752 -0
  287. package/dist/tasks/standalone-script-entry.js +5 -0
  288. package/dist/tasks/task-id.js +29 -0
  289. package/dist/workflows/authoring/authoring.js +15 -32
  290. package/dist/workflows/exec/dispatch-redaction.js +14 -8
  291. package/dist/workflows/exec/exec-unit.js +7 -28
  292. package/dist/workflows/exec/frozen-judge.js +57 -89
  293. package/dist/workflows/exec/lowering-notices.js +23 -0
  294. package/dist/workflows/exec/native-executor.js +301 -458
  295. package/dist/workflows/exec/param-secrets.js +4 -3
  296. package/dist/workflows/exec/run-workflow.js +26 -32
  297. package/dist/workflows/exec/step-work.js +105 -109
  298. package/dist/workflows/exec/unit-dispatch.js +103 -27
  299. package/dist/workflows/exec/unit-writer.js +3 -3
  300. package/dist/workflows/exec/worktree.js +2 -2
  301. package/dist/workflows/ir/compile.js +86 -72
  302. package/dist/workflows/ir/environment-v4.js +328 -0
  303. package/dist/workflows/ir/freeze-v4.js +122 -0
  304. package/dist/workflows/ir/plan-hash.js +13 -7
  305. package/dist/workflows/ir/schema-v4.js +525 -0
  306. package/dist/workflows/ir/schema.js +25 -284
  307. package/dist/workflows/ir/source-freeze-v4.js +506 -0
  308. package/dist/workflows/parser.js +27 -24
  309. package/dist/workflows/program/schema.js +1 -2
  310. package/dist/workflows/renderer.js +42 -29
  311. package/dist/workflows/resource-limits.js +4 -5
  312. package/dist/workflows/runtime/agent-identity.js +11 -13
  313. package/dist/workflows/runtime/plan-classifier.js +8 -8
  314. package/dist/workflows/runtime/runs.js +27 -43
  315. package/dist/workflows/runtime/workflow-asset-loader.js +45 -205
  316. package/dist/workflows/source-files.js +373 -0
  317. package/dist/workflows/source-ir/compile.js +196 -0
  318. package/dist/workflows/source-ir/github-yaml.js +577 -0
  319. package/dist/workflows/source-ir/ordering.js +38 -0
  320. package/dist/workflows/source-ir/program.js +50 -0
  321. package/dist/workflows/source-ir/result.js +26 -0
  322. package/dist/workflows/source-ir/schema.js +772 -0
  323. package/dist/workflows/source-ir/semantics.js +242 -0
  324. package/dist/workflows/source-ir/uses.js +14 -0
  325. package/docs/README.md +2 -0
  326. package/docs/migration/README.md +3 -1
  327. package/docs/migration/release-notes/0.9.2.md +55 -0
  328. package/docs/migration/release-notes/README.md +5 -0
  329. package/docs/migration/v0.8-to-v0.9.md +76 -1077
  330. package/docs/migration/v0.9.0-troubleshooting.md +104 -516
  331. package/docs/migration/v0.9.1-to-v0.9.2.md +150 -0
  332. package/docs/reference/README.md +1 -0
  333. package/docs/reference/cli.md +230 -98
  334. package/docs/reference/configuration.md +159 -36
  335. package/docs/reference/data-and-telemetry.md +19 -1
  336. package/docs/reference/supported-formats.md +23 -3
  337. package/docs/reference/tasks.md +182 -0
  338. package/docs/reference/workflow-schema.md +91 -40
  339. package/docs/reference/workflows.md +33 -6
  340. package/package.json +10 -6
  341. package/schemas/akm-config.json +372 -224
  342. package/schemas/akm-task.json +324 -80
  343. package/schemas/akm-workflow.json +6 -9
  344. package/dist/core/migration-operation.js +0 -75
  345. package/dist/integrations/agent/model-aliases.js +0 -74
  346. package/dist/tasks/parser.js +0 -380
  347. package/dist/tasks/schema.js +0 -123
  348. package/dist/tasks/validator.js +0 -80
  349. package/dist/workflows/ir/freeze.js +0 -320
  350. package/dist/workflows/runtime/document-cache.js +0 -13
@@ -0,0 +1,654 @@
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
+ /** Pure whole-set scheduler reconciliation planning. */
5
+ import { createHash } from "node:crypto";
6
+ import path from "node:path";
7
+ import { loadAdapterExecutionSource } from "../commands/command/execution-source-loader.js";
8
+ import { makeBundleRef } from "../core/asset/asset-ref.js";
9
+ import { UsageError } from "../core/errors.js";
10
+ import { canonicalizeWorkflowName, WORKFLOW_EXTENSIONS } from "../core/recognition-util.js";
11
+ import { captureGuardedDirectoryManifest, captureGuardedExecutionSource, GuardedExecutionSourceCollector, } from "../execution/guarded-source.js";
12
+ import { compileWorkflowPlan } from "../workflows/ir/compile.js";
13
+ import { compileResolveFreezeWorkflowV4 } from "../workflows/ir/freeze-v4.js";
14
+ import { canonicalJson, computePlanHash } from "../workflows/ir/plan-hash.js";
15
+ import { WorkflowSourceCollisionError, WorkflowSourceNameError, WorkflowSourceRejectionError, workflowNameForSourcePath, } from "../workflows/source-files.js";
16
+ import { compileWorkflowSource } from "../workflows/source-ir/compile.js";
17
+ import { prepareTaskV3Execution } from "./runtime-v3.js";
18
+ import { parseSchedule } from "./schedule.js";
19
+ import { assertSchedulerNativeArtifactCardinality, compileTaskSchedulerBindings, compileWorkflowSchedulerBindings, schedulerBindingNativeId, schedulerBindingOrdinal, schedulerNativeArtifactKey, schedulerNativeBindingId, } from "./scheduler-binding.js";
20
+ import { parseTaskV3Yaml, taskV3SourceErrorDetail } from "./source-v3.js";
21
+ export function computeSchedulerExecutionEvidenceDigest(planHash, sourceReadSet) {
22
+ const envelope = canonicalJson({
23
+ version: 1,
24
+ planHash,
25
+ sourceReadSet: sourceReadSet.map((snapshot) => ({
26
+ identity: snapshot.identity,
27
+ containmentPhysicalIdentity: snapshot.containmentPhysicalIdentity,
28
+ physicalIdentity: snapshot.physicalIdentity,
29
+ size: snapshot.size,
30
+ })),
31
+ });
32
+ return createHash("sha256").update("akm.scheduler.workflow-evidence\0v1\0").update(envelope).digest("hex");
33
+ }
34
+ const SCHEDULER_PROJECTION_CONFIG = Object.freeze({
35
+ configVersion: "0.9.0",
36
+ semanticSearchMode: "off",
37
+ });
38
+ export async function prepareSchedulerSyncSourceSet(input) {
39
+ const collector = new SchedulerSourceCollector(input);
40
+ const compiled = await compileDesiredSourceSet(input, collector);
41
+ const sourceSnapshot = collector.snapshot();
42
+ assertSchedulerSourceSnapshot(sourceSnapshot);
43
+ return Object.freeze({
44
+ desired: compiled.desired,
45
+ sourceSnapshot,
46
+ executableWorkflows: compiled.executableWorkflows,
47
+ });
48
+ }
49
+ export function finalizeSchedulerSyncPlan(input, prepared) {
50
+ const inspection = inspectionForPlan(input);
51
+ const coherentInput = {
52
+ ...input,
53
+ installed: inspection.installed,
54
+ nativeArtifacts: inspection.artifacts,
55
+ };
56
+ const desired = prepared.desired;
57
+ assertUniqueDesiredIds(desired);
58
+ assertCoherentInspection(inspection, input.inspection !== undefined);
59
+ assertUniqueInstalledIds(coherentInput.installed);
60
+ assertNoForeignIds(desired, coherentInput);
61
+ assertSchedulerNativeArtifactOwnership(desired, inspection.artifacts);
62
+ const scopedInstalled = coherentInput.installed.filter((entry) => belongsToBundle(entry, coherentInput));
63
+ const present = new Map(scopedInstalled.map((entry) => [entry.id, entry]));
64
+ const installed = [];
65
+ const updated = [];
66
+ const unchanged = [];
67
+ const operations = [];
68
+ for (const binding of desired) {
69
+ const current = present.get(binding.id);
70
+ const options = installOptionsFor(coherentInput, current);
71
+ const resultFingerprint = coherentInput.expectedSignature?.(binding, options);
72
+ if (!current) {
73
+ installed.push(binding.id);
74
+ operations.push(freezeOperation({
75
+ kind: "install",
76
+ binding,
77
+ expected: freezeMutationExpectation(expectationForBinding(binding, "absent")),
78
+ ...(resultFingerprint !== undefined ? { resultFingerprint } : {}),
79
+ ...(options ? { options } : {}),
80
+ }));
81
+ continue;
82
+ }
83
+ if (current.signature !== undefined && resultFingerprint !== undefined && current.signature === resultFingerprint) {
84
+ unchanged.push(binding.id);
85
+ continue;
86
+ }
87
+ const artifact = exactInstalledArtifact(binding.id, current, inspection.artifacts);
88
+ const priorFingerprint = artifact?.fingerprint ?? current.signature;
89
+ if (artifact === undefined || priorFingerprint === undefined) {
90
+ throw new UsageError(`Installed scheduler binding ${JSON.stringify(binding.id)} has no exact native fingerprint; refusing update.`, "RESOURCE_ALREADY_EXISTS");
91
+ }
92
+ updated.push(binding.id);
93
+ operations.push(freezeOperation({
94
+ kind: "update",
95
+ binding,
96
+ expected: freezeMutationExpectation(expectationForBinding(binding, "present", priorFingerprint)),
97
+ ...(resultFingerprint !== undefined ? { resultFingerprint } : {}),
98
+ ...(options ? { options } : {}),
99
+ }));
100
+ }
101
+ const desiredIds = new Set(desired.map(({ id }) => id));
102
+ const removed = scopedInstalled
103
+ .map(({ id }) => id)
104
+ .filter((id) => !desiredIds.has(id))
105
+ .sort(compareCodePoints);
106
+ for (const id of removed) {
107
+ const current = present.get(id);
108
+ if (!current?.invocation) {
109
+ throw nativeArtifactCollision({ nativeId: current?.nativeId ?? schedulerNativeBindingId(id), bindingId: id }, { nativeId: current?.nativeId ?? schedulerNativeBindingId(id) });
110
+ }
111
+ const nativeId = exactInstalledNativeId(id, current, inspection.artifacts);
112
+ const artifact = inspection.artifacts.find((candidate) => candidate.nativeId === nativeId && candidate.bindingId === id);
113
+ const priorFingerprint = current.signature ?? artifact?.fingerprint;
114
+ if (!artifact || priorFingerprint === undefined) {
115
+ throw new UsageError(`Installed scheduler binding ${JSON.stringify(id)} has no exact native fingerprint; refusing removal.`, "RESOURCE_ALREADY_EXISTS");
116
+ }
117
+ const logicalSource = installedLogicalSource(current.invocation, coherentInput);
118
+ const ordinal = schedulerBindingOrdinal(id, logicalSource, current.invocation);
119
+ if (ordinal === undefined) {
120
+ throw new UsageError(`Installed scheduler binding ${JSON.stringify(id)} cannot be attributed to an exact schedule ordinal; refusing removal.`, "RESOURCE_ALREADY_EXISTS");
121
+ }
122
+ operations.push(Object.freeze({
123
+ kind: "remove",
124
+ id,
125
+ nativeId,
126
+ expected: freezeRemovalExpectation({
127
+ state: "present",
128
+ bindingId: id,
129
+ nativeId,
130
+ logicalSource,
131
+ ordinal,
132
+ invocation: current.invocation,
133
+ fingerprint: priorFingerprint,
134
+ }),
135
+ }));
136
+ }
137
+ return Object.freeze({
138
+ desired,
139
+ installed: Object.freeze(installed),
140
+ updated: Object.freeze(updated),
141
+ removed: Object.freeze(removed),
142
+ unchanged: Object.freeze(unchanged),
143
+ operations: Object.freeze(operations),
144
+ sourceSnapshot: prepared.sourceSnapshot,
145
+ });
146
+ }
147
+ function exactInstalledNativeId(logicalId, current, artifacts) {
148
+ const exact = artifacts.find((artifact) => artifact.bindingId === logicalId);
149
+ return exact?.nativeId ?? current?.nativeId ?? schedulerNativeBindingId(logicalId);
150
+ }
151
+ function exactInstalledArtifact(bindingId, current, artifacts) {
152
+ const nativeId = current.nativeId ?? schedulerNativeBindingId(bindingId);
153
+ return artifacts.find((artifact) => artifact.nativeId === nativeId && (artifact.bindingId === bindingId || artifact.bindingId === undefined));
154
+ }
155
+ function nativeArtifactsForPlan(input) {
156
+ return (input.nativeArtifacts ??
157
+ input.installed.map((entry) => ({
158
+ nativeId: entry.nativeId ?? schedulerNativeBindingId(entry.id),
159
+ bindingId: entry.id,
160
+ ...(entry.invocation ? { invocation: Object.freeze([...entry.invocation]) } : {}),
161
+ ...(entry.signature !== undefined ? { fingerprint: entry.signature } : {}),
162
+ })));
163
+ }
164
+ function inspectionForPlan(input) {
165
+ return input.inspection ?? Object.freeze({ installed: input.installed, artifacts: nativeArtifactsForPlan(input) });
166
+ }
167
+ export function assertSchedulerNativeArtifactOwnership(desired, installed) {
168
+ const desiredByKey = new Map();
169
+ for (const binding of desired) {
170
+ const nativeId = schedulerBindingNativeId(binding);
171
+ const key = schedulerNativeArtifactKey(nativeId);
172
+ const prior = desiredByKey.get(key);
173
+ if (prior && !sameDesiredArtifact(prior, binding)) {
174
+ throw nativeArtifactCollision(desiredArtifact(prior), desiredArtifact(binding));
175
+ }
176
+ desiredByKey.set(key, binding);
177
+ }
178
+ const installedByKey = new Map();
179
+ for (const artifact of installed) {
180
+ const key = schedulerNativeArtifactKey(artifact.nativeId);
181
+ const prior = installedByKey.get(key);
182
+ if (prior) {
183
+ throw nativeArtifactCollision(prior, artifact);
184
+ }
185
+ installedByKey.set(key, artifact);
186
+ const wanted = desiredByKey.get(key);
187
+ if (!wanted)
188
+ continue;
189
+ if (artifact.nativeId !== schedulerBindingNativeId(wanted) ||
190
+ artifact.bindingId !== wanted.id ||
191
+ artifact.invocation === undefined ||
192
+ !sameInvocation(artifact.invocation, wanted.invocation)) {
193
+ throw nativeArtifactCollision(desiredArtifact(wanted), artifact);
194
+ }
195
+ }
196
+ }
197
+ function assertCoherentInspection(inspection, requireCompleteFingerprint = false) {
198
+ const seenNativeKeys = new Set();
199
+ for (const artifact of inspection.artifacts) {
200
+ const key = schedulerNativeArtifactKey(artifact.nativeId);
201
+ if (seenNativeKeys.has(key)) {
202
+ throw new UsageError(`Scheduler inspection has duplicate normalized native artifact ${JSON.stringify(artifact.nativeId)}; expected cardinality one.`, "RESOURCE_ALREADY_EXISTS");
203
+ }
204
+ seenNativeKeys.add(key);
205
+ }
206
+ for (const installed of inspection.installed) {
207
+ const nativeId = installed.nativeId ?? schedulerNativeBindingId(installed.id);
208
+ const artifact = assertSchedulerNativeArtifactCardinality(inspection.artifacts, nativeId, 1);
209
+ if (!artifact ||
210
+ (installed.signature !== undefined &&
211
+ (artifact.fingerprint !== undefined
212
+ ? installed.signature !== artifact.fingerprint
213
+ : requireCompleteFingerprint)) ||
214
+ (artifact.bindingId !== undefined && artifact.bindingId !== installed.id)) {
215
+ throw new UsageError(`Scheduler inspection is not coherent for ${JSON.stringify(nativeId)}: installed and native fingerprints differ.`, "RESOURCE_ALREADY_EXISTS");
216
+ }
217
+ if (installed.invocation !== undefined &&
218
+ (artifact.invocation === undefined || !sameInvocation(installed.invocation, artifact.invocation))) {
219
+ throw new UsageError(`Scheduler inspection is not coherent for ${JSON.stringify(nativeId)}: installed and native owners differ.`, "RESOURCE_ALREADY_EXISTS");
220
+ }
221
+ }
222
+ }
223
+ function nativeArtifactCollision(left, right) {
224
+ const owner = (value) => value.bindingId === undefined || value.invocation === undefined
225
+ ? `${JSON.stringify(value.nativeId)} (unproven owner)`
226
+ : `binding ${JSON.stringify(value.bindingId)} invoking ${JSON.stringify(value.invocation)}`;
227
+ return new UsageError(`Native scheduler artifact collision between ${owner(left)} and ${owner(right)}; refusing to overwrite an existing or ambiguous native owner.`, "RESOURCE_ALREADY_EXISTS");
228
+ }
229
+ function desiredArtifact(binding) {
230
+ return {
231
+ nativeId: schedulerBindingNativeId(binding),
232
+ bindingId: binding.id,
233
+ invocation: binding.invocation,
234
+ };
235
+ }
236
+ function sameDesiredArtifact(left, right) {
237
+ return (schedulerBindingNativeId(left) === schedulerBindingNativeId(right) &&
238
+ left.id === right.id &&
239
+ left.logicalSource.kind === right.logicalSource.kind &&
240
+ left.logicalSource.ref === right.logicalSource.ref &&
241
+ left.ordinal === right.ordinal &&
242
+ left.executionEvidenceDigest === right.executionEvidenceDigest &&
243
+ sameInvocation(left.invocation, right.invocation));
244
+ }
245
+ async function compileDesiredSourceSet(input, collector) {
246
+ const bindings = [];
247
+ const executableWorkflows = [];
248
+ const failures = [];
249
+ await compileTaskSources(input, collector, bindings, failures);
250
+ await compileWorkflowSources(input, collector, bindings, executableWorkflows, failures);
251
+ if (failures.length > 0) {
252
+ throw new UsageError(`Scheduler sync rejected the desired source set before mutation:\n${failures.map((failure) => `- ${failure}`).join("\n")}`, "INVALID_FLAG_VALUE");
253
+ }
254
+ return Object.freeze({
255
+ desired: Object.freeze(bindings),
256
+ executableWorkflows: Object.freeze(executableWorkflows.sort((left, right) => compareCodePoints(left.ref, right.ref))),
257
+ });
258
+ }
259
+ async function compileTaskSources(input, collector, out, failures) {
260
+ if (input.adapterId !== "akm" && input.adapterId !== "akm-task")
261
+ return;
262
+ const physicalOwners = new Map();
263
+ for (const guarded of collector.authoredTaskSources(input.adapterId)) {
264
+ const sourcePath = guarded.sourcePath;
265
+ const relative = guarded.relativePath;
266
+ const conceptId = relative.slice(0, -4);
267
+ const id = input.adapterId === "akm-task" ? conceptId : path.basename(sourcePath, ".yml");
268
+ try {
269
+ const physicalIdentity = guarded.physicalIdentity;
270
+ const priorOwner = physicalOwners.get(physicalIdentity);
271
+ if (priorOwner !== undefined && priorOwner !== sourcePath) {
272
+ throw new UsageError(`Task sources ${JSON.stringify(priorOwner)} and ${JSON.stringify(sourcePath)} resolve to the same physical source identity; refusing canonical task identity collision.`, "RESOURCE_ALREADY_EXISTS");
273
+ }
274
+ physicalOwners.set(physicalIdentity, sourcePath);
275
+ const document = parseTaskV3Yaml({
276
+ yaml: guarded.content,
277
+ filePath: sourcePath,
278
+ workspaceRoot: input.sourceRoot,
279
+ });
280
+ const qualifiedRef = makeBundleRef(input.bundleName, conceptId);
281
+ await prepareTaskV3Execution(document, {
282
+ taskId: id,
283
+ taskRef: qualifiedRef,
284
+ bundleName: input.bundleName,
285
+ bundleRoot: input.sourceRoot,
286
+ config: input.config ?? SCHEDULER_PROJECTION_CONFIG,
287
+ ...(input.resolveAsset ? { resolveAsset: input.resolveAsset } : {}),
288
+ readFile: (file, bundleRoot) => collector.readBytes(file, bundleRoot ?? input.sourceRoot),
289
+ commandSourceLoader: (ref, kind, options) => {
290
+ const guardedOptions = {
291
+ ...options,
292
+ fileContext: (root, file) => collector.fileContext(root, file),
293
+ };
294
+ return kind === "command"
295
+ ? loadAdapterExecutionSource(ref, "command", guardedOptions)
296
+ : loadAdapterExecutionSource(ref, "persona", guardedOptions);
297
+ },
298
+ });
299
+ const sourceBindings = compileTaskSchedulerBindings({
300
+ id,
301
+ qualifiedRef,
302
+ ...(input.bundleTarget ? { bundleTarget: input.bundleTarget } : {}),
303
+ enabled: document.akm?.enabled !== false,
304
+ schedules: document.triggers.schedules.map((schedule) => ({
305
+ ...schedule,
306
+ source: `${toPosix(path.relative(input.sourceRoot, sourcePath))}:${schedule.source}`,
307
+ })),
308
+ });
309
+ for (const binding of sourceBindings) {
310
+ parseSchedule(binding.cron, input.backend);
311
+ out.push(binding);
312
+ }
313
+ }
314
+ catch (cause) {
315
+ failures.push(taskFailure(sourcePath, cause));
316
+ }
317
+ }
318
+ }
319
+ async function compileWorkflowSources(input, collector, out, evidence, failures) {
320
+ if (input.adapterId !== "akm" && input.adapterId !== "akm-workflow")
321
+ return;
322
+ const lookups = enumerateWorkflowLookups(input, collector, failures);
323
+ for (const [canonicalName, sources] of lookups) {
324
+ try {
325
+ if (sources.length > 1) {
326
+ throw new WorkflowSourceCollisionError(input.adapterId === "akm" ? `workflows/${canonicalName}` : canonicalName, sources.map((source) => source.relativePath));
327
+ }
328
+ const guarded = sources[0];
329
+ if (!guarded)
330
+ continue;
331
+ const compiled = compileWorkflowSource(guarded.content, {
332
+ path: guarded.relativePath,
333
+ workspaceRoot: input.sourceRoot,
334
+ });
335
+ if (!compiled.ok) {
336
+ throw new UsageError(compiled.errors
337
+ .map((error) => `${error.path}:${error.line ?? 1} [${error.code}] ${error.message}`)
338
+ .join("; "), "INVALID_FLAG_VALUE");
339
+ }
340
+ const planDraft = compileWorkflowPlan(compiled.ir, canonicalName);
341
+ if (!planDraft.ok) {
342
+ throw new UsageError(planDraft.errors.map((error) => `${guarded.relativePath}:${error.line} ${error.message}`).join("; "), "INVALID_FLAG_VALUE");
343
+ }
344
+ const conceptId = input.adapterId === "akm" ? `workflows/${canonicalName}` : canonicalName;
345
+ const qualifiedRef = makeBundleRef(input.bundleName, conceptId);
346
+ const asset = {
347
+ ref: qualifiedRef,
348
+ path: guarded.sourcePath,
349
+ sourcePath: input.sourceRoot,
350
+ adapterId: input.adapterId,
351
+ title: canonicalName,
352
+ steps: [],
353
+ sourceIr: compiled.ir,
354
+ };
355
+ const frozen = await compileResolveFreezeWorkflowV4(asset, input.config ?? schedulerProjectionConfig(input), {
356
+ sourceCollector: collector.executionCollector(),
357
+ });
358
+ const planHash = computePlanHash(frozen.plan);
359
+ const executionEvidenceDigest = computeSchedulerExecutionEvidenceDigest(planHash, frozen.plan.sourceReadSet);
360
+ evidence.push(Object.freeze({
361
+ ref: qualifiedRef,
362
+ irVersion: 4,
363
+ planHash,
364
+ sourceReadSet: frozen.plan.sourceReadSet,
365
+ executionEvidenceDigest,
366
+ }));
367
+ const schedules = compiled.ir.triggers.flatMap((trigger) => trigger.kind === "schedule"
368
+ ? [
369
+ {
370
+ cron: trigger.cron,
371
+ source: `${trigger.source.path}:${trigger.source.start}`,
372
+ ordinal: trigger.ordinal,
373
+ },
374
+ ]
375
+ : []);
376
+ for (const binding of compileWorkflowSchedulerBindings({
377
+ qualifiedRef,
378
+ schedules,
379
+ executionEvidenceDigest,
380
+ })) {
381
+ parseSchedule(binding.cron, input.backend);
382
+ out.push(binding);
383
+ }
384
+ }
385
+ catch (cause) {
386
+ failures.push(errorMessage(cause));
387
+ }
388
+ }
389
+ }
390
+ function schedulerProjectionConfig(input) {
391
+ return Object.freeze({
392
+ ...SCHEDULER_PROJECTION_CONFIG,
393
+ defaultBundle: input.bundleName,
394
+ bundles: {
395
+ [input.bundleName]: {
396
+ path: input.sourceRoot,
397
+ components: { main: { root: ".", adapter: input.adapterId } },
398
+ },
399
+ },
400
+ });
401
+ }
402
+ function enumerateWorkflowLookups(input, collector, failures) {
403
+ const lookups = new Map();
404
+ for (const guarded of collector.authoredWorkflowSources(input.adapterId)) {
405
+ const sourcePath = guarded.sourcePath;
406
+ if (path.basename(sourcePath).toLowerCase() === "readme.md")
407
+ continue;
408
+ const authoredName = workflowNameForSourcePath(input.sourceRoot, input.adapterId, sourcePath);
409
+ if (authoredName === undefined)
410
+ continue;
411
+ const extension = path.posix.extname(authoredName).toLowerCase();
412
+ const stem = authoredName.slice(0, -extension.length).toLowerCase();
413
+ const nestedSuffix = WORKFLOW_EXTENSIONS.find((suffix) => stem.endsWith(suffix));
414
+ if (nestedSuffix) {
415
+ failures.push(errorMessage(new WorkflowSourceNameError(guarded.relativePath, nestedSuffix)));
416
+ continue;
417
+ }
418
+ const canonicalName = canonicalizeWorkflowName(authoredName);
419
+ const owners = lookups.get(canonicalName) ?? [];
420
+ owners.push(guarded);
421
+ lookups.set(canonicalName, owners);
422
+ }
423
+ return new Map([...lookups]
424
+ .sort(([left], [right]) => compareCodePoints(left, right))
425
+ .map(([name, sources]) => [name, Object.freeze(sources.sort(compareGuardedSources))]));
426
+ }
427
+ function installOptionsFor(input, current) {
428
+ if (current && !input.rebind) {
429
+ return Object.freeze({
430
+ ...(input.bundleTarget ? { target: input.bundleTarget } : {}),
431
+ binding: Object.freeze([...current.binding]),
432
+ contextPath: current.contextPath,
433
+ });
434
+ }
435
+ return input.installOptions ? Object.freeze({ ...input.installOptions }) : undefined;
436
+ }
437
+ function belongsToBundle(entry, input) {
438
+ if (entry.target === input.bundleName || entry.target === input.bundleTarget)
439
+ return true;
440
+ return false;
441
+ }
442
+ function assertNoForeignIds(desired, input) {
443
+ const wanted = new Set(desired.map(({ id }) => id));
444
+ const foreign = input.installed.find((entry) => wanted.has(entry.id) && !belongsToBundle(entry, input));
445
+ if (!foreign)
446
+ return;
447
+ const where = foreign.target ? `bundle ${JSON.stringify(foreign.target)}` : "the default bundle";
448
+ throw new UsageError(`Scheduler id ${JSON.stringify(foreign.id)} is already scheduled from ${where}; desired source ids must not collide across bundles.`, "RESOURCE_ALREADY_EXISTS");
449
+ }
450
+ function assertUniqueDesiredIds(desired) {
451
+ const seen = new Set();
452
+ for (const binding of desired) {
453
+ if (seen.has(binding.id)) {
454
+ throw new UsageError(`Desired scheduler id collision for ${JSON.stringify(binding.id)}; no native definitions were changed.`, "RESOURCE_ALREADY_EXISTS");
455
+ }
456
+ seen.add(binding.id);
457
+ }
458
+ }
459
+ function assertUniqueInstalledIds(installed) {
460
+ const seen = new Set();
461
+ for (const binding of installed) {
462
+ if (seen.has(binding.id)) {
463
+ throw new UsageError(`Installed scheduler id collision for ${JSON.stringify(binding.id)}; refusing whole-set reconciliation.`, "RESOURCE_ALREADY_EXISTS");
464
+ }
465
+ seen.add(binding.id);
466
+ }
467
+ }
468
+ function taskFailure(file, cause) {
469
+ const detail = taskV3SourceErrorDetail(cause);
470
+ return detail === errorMessage(cause) ? `${file}: ${detail}` : detail;
471
+ }
472
+ function errorMessage(cause) {
473
+ return cause instanceof Error ? cause.message : String(cause);
474
+ }
475
+ export function assertSchedulerSourceSnapshot(snapshot) {
476
+ try {
477
+ for (const source of snapshot.files) {
478
+ const current = captureGuardedExecutionSource(source.sourcePath, source.containmentRoot, {
479
+ authored: source.authored,
480
+ ...(source.identity ? { identity: source.identity } : {}),
481
+ });
482
+ if (JSON.stringify(current) !== JSON.stringify(source)) {
483
+ throw new Error(`source identity changed: ${source.sourcePath}`);
484
+ }
485
+ }
486
+ for (const manifest of snapshot.directoryManifests) {
487
+ const current = captureGuardedDirectoryManifest(manifest.directoryPath, manifest.containmentRoot);
488
+ if (JSON.stringify(current) !== JSON.stringify(manifest)) {
489
+ throw new Error(`directory manifest changed: ${manifest.directoryPath}`);
490
+ }
491
+ }
492
+ }
493
+ catch (cause) {
494
+ throw new UsageError(`Scheduler desired source read set changed after projection; refusing native mutation: ${errorMessage(cause)}`, "RESOURCE_ALREADY_EXISTS");
495
+ }
496
+ }
497
+ class SchedulerSourceCollector {
498
+ #adapterId;
499
+ #sourceRoot;
500
+ #collector = new GuardedExecutionSourceCollector();
501
+ constructor(input) {
502
+ this.#adapterId = input.adapterId;
503
+ this.#sourceRoot = path.resolve(input.sourceRoot);
504
+ const root = this.#collector.trackDirectory(this.#sourceRoot, this.#sourceRoot);
505
+ const rootDirectories = new Set(root.entries.filter((entry) => entry.kind === "directory").map((entry) => entry.name));
506
+ const candidates = [];
507
+ if (input.adapterId === "akm") {
508
+ if (rootDirectories.has("tasks")) {
509
+ const taskRoot = path.join(this.#sourceRoot, "tasks");
510
+ const taskManifest = this.#collector.trackDirectory(taskRoot, this.#sourceRoot);
511
+ for (const entry of taskManifest.entries) {
512
+ if (entry.kind === "file" && entry.name.endsWith(".yml")) {
513
+ candidates.push(path.join(taskRoot, entry.name));
514
+ }
515
+ }
516
+ }
517
+ if (rootDirectories.has("workflows")) {
518
+ candidates.push(...this.#collector.enumerateTree(path.join(this.#sourceRoot, "workflows"), this.#sourceRoot));
519
+ }
520
+ }
521
+ else if (input.adapterId === "akm-task") {
522
+ candidates.push(...this.#collector.enumerateTree(this.#sourceRoot, this.#sourceRoot).filter((file) => file.endsWith(".yml")));
523
+ }
524
+ else if (input.adapterId === "akm-workflow") {
525
+ candidates.push(...this.#collector.enumerateTree(this.#sourceRoot, this.#sourceRoot));
526
+ }
527
+ for (const file of candidates.sort(compareCodePoints)) {
528
+ this.#collector.capture(file, this.#sourceRoot, { authored: true });
529
+ }
530
+ }
531
+ executionCollector() {
532
+ return this.#collector;
533
+ }
534
+ authoredTaskSources(adapterId) {
535
+ return this.#collector
536
+ .snapshot()
537
+ .sources.filter((file) => {
538
+ if (!file.authored || !file.relativePath.endsWith(".yml"))
539
+ return false;
540
+ if (adapterId === "akm-task")
541
+ return true;
542
+ return path.posix.dirname(file.relativePath) === "tasks";
543
+ })
544
+ .sort(compareGuardedSources);
545
+ }
546
+ authoredWorkflowSources(adapterId) {
547
+ return this.#collector
548
+ .snapshot()
549
+ .sources.filter((file) => {
550
+ if (!file.authored)
551
+ return false;
552
+ if (adapterId === "akm-workflow")
553
+ return true;
554
+ return file.relativePath.startsWith("workflows/");
555
+ })
556
+ .sort(compareGuardedSources);
557
+ }
558
+ readBytes(file, containmentRoot) {
559
+ this.#trackAncestors(file, containmentRoot);
560
+ return this.#collector.readBytes(file, containmentRoot);
561
+ }
562
+ fileContext(root, file) {
563
+ this.#trackAncestors(file, root);
564
+ return this.#collector.fileContext(root, file);
565
+ }
566
+ snapshot() {
567
+ const guarded = this.#collector.snapshot();
568
+ const root = guarded.directoryManifests.find((manifest) => manifest.directoryPath === this.#sourceRoot && manifest.containmentRoot === this.#sourceRoot);
569
+ if (!root)
570
+ throw new Error("scheduler source collector lost its guarded root manifest");
571
+ return Object.freeze({
572
+ adapterId: this.#adapterId,
573
+ sourceRoot: this.#sourceRoot,
574
+ sourceRealPath: root.realPath,
575
+ sourcePhysicalIdentity: root.physicalIdentity,
576
+ sourceDirectoryVersion: root.version,
577
+ files: Object.freeze([...guarded.sources].sort(compareGuardedSources)),
578
+ directoryManifests: guarded.directoryManifests,
579
+ });
580
+ }
581
+ #trackAncestors(file, containmentRoot) {
582
+ const root = path.resolve(containmentRoot);
583
+ const parent = path.dirname(path.resolve(file));
584
+ const relative = path.relative(root, parent);
585
+ if (relative.startsWith("..") || path.isAbsolute(relative))
586
+ return;
587
+ this.#collector.trackDirectory(root, root);
588
+ if (relative === "")
589
+ return;
590
+ let current = root;
591
+ for (const segment of relative.split(path.sep)) {
592
+ current = path.join(current, segment);
593
+ this.#collector.trackDirectory(current, root);
594
+ }
595
+ }
596
+ }
597
+ function compareGuardedSources(left, right) {
598
+ return compareCodePoints(left.sourcePath, right.sourcePath);
599
+ }
600
+ function installedLogicalSource(invocation, input) {
601
+ if (invocation[0] === "workflow" && invocation[1] === "run" && invocation.length === 3) {
602
+ return Object.freeze({ kind: "workflow", ref: invocation[2] });
603
+ }
604
+ if (invocation[0] === "task" && invocation[1] === "run" && invocation[2]) {
605
+ const bundleIndex = invocation.indexOf("--bundle", 3);
606
+ const bundle = bundleIndex === -1 ? input.bundleName : invocation[bundleIndex + 1];
607
+ if (!bundle) {
608
+ throw new UsageError("Installed task invocation has no resolvable bundle owner.", "RESOURCE_ALREADY_EXISTS");
609
+ }
610
+ const conceptId = input.adapterId === "akm" ? `tasks/${invocation[2]}` : invocation[2];
611
+ return Object.freeze({ kind: "task", ref: makeBundleRef(bundle, conceptId) });
612
+ }
613
+ throw new UsageError("Installed scheduler invocation has no exact canonical source owner.", "RESOURCE_ALREADY_EXISTS");
614
+ }
615
+ function freezeRemovalExpectation(expectation) {
616
+ return Object.freeze({
617
+ ...expectation,
618
+ logicalSource: Object.freeze({ ...expectation.logicalSource }),
619
+ invocation: Object.freeze([...expectation.invocation]),
620
+ });
621
+ }
622
+ function expectationForBinding(binding, state, fingerprint) {
623
+ return {
624
+ state,
625
+ bindingId: binding.id,
626
+ nativeId: schedulerBindingNativeId(binding),
627
+ logicalSource: binding.logicalSource,
628
+ ordinal: binding.ordinal,
629
+ invocation: binding.invocation,
630
+ ...(fingerprint !== undefined ? { fingerprint } : {}),
631
+ };
632
+ }
633
+ function freezeMutationExpectation(expectation) {
634
+ return Object.freeze({
635
+ ...expectation,
636
+ logicalSource: Object.freeze({ ...expectation.logicalSource }),
637
+ invocation: Object.freeze([...expectation.invocation]),
638
+ });
639
+ }
640
+ function freezeOperation(operation) {
641
+ return Object.freeze(operation);
642
+ }
643
+ function sameInvocation(left, right) {
644
+ return left.length === right.length && left.every((value, index) => value === right[index]);
645
+ }
646
+ function compareCodePoints(left, right) {
647
+ return left < right ? -1 : left > right ? 1 : 0;
648
+ }
649
+ function toPosix(value) {
650
+ return value.replaceAll("\\", "/");
651
+ }
652
+ // Retain the concrete error in this module's public dependency graph so callers
653
+ // can continue to identify ownership failures without importing an adapter.
654
+ export { WorkflowSourceRejectionError };