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,105 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { createHash } from "node:crypto";
5
- import fs from "node:fs";
6
- import path from "node:path";
7
- import { isRecord } from "../core/common.js";
8
- import { UsageError } from "../core/errors.js";
9
- export function freezeExecutableIdentity(requested, options = {}) {
10
- const absolutePath = resolveExecutable(requested, options.cwd ?? process.cwd(), options.path ?? process.env.PATH ?? "");
11
- let realPath;
12
- let stat;
13
- let bytes;
14
- try {
15
- fs.accessSync(absolutePath, fs.constants.X_OK);
16
- realPath = fs.realpathSync(absolutePath);
17
- stat = fs.lstatSync(realPath, { bigint: true });
18
- if (!stat.isFile() || stat.isSymbolicLink())
19
- throw new Error("not a regular executable file");
20
- bytes = fs.readFileSync(realPath);
21
- }
22
- catch {
23
- throw new UsageError(`Executable ${JSON.stringify(requested)} could not be frozen.`, "INVALID_FLAG_VALUE");
24
- }
25
- return Object.freeze({
26
- requested,
27
- absolutePath,
28
- realPath,
29
- device: stat.dev.toString(),
30
- inode: stat.ino.toString(),
31
- size: bytes.byteLength,
32
- sha256: createHash("sha256").update(bytes).digest("hex"),
33
- });
34
- }
35
- export function decodeFrozenExecutableIdentity(value, label = "executable") {
36
- if (!isRecord(value))
37
- throw invalid(label);
38
- const allowed = new Set(["requested", "absolutePath", "realPath", "device", "inode", "size", "sha256"]);
39
- for (const key of Object.keys(value))
40
- if (!allowed.has(key))
41
- throw invalid(label);
42
- if (typeof value.requested !== "string" ||
43
- typeof value.absolutePath !== "string" ||
44
- !path.isAbsolute(value.absolutePath) ||
45
- typeof value.realPath !== "string" ||
46
- !path.isAbsolute(value.realPath) ||
47
- typeof value.device !== "string" ||
48
- typeof value.inode !== "string" ||
49
- !Number.isSafeInteger(value.size) ||
50
- value.size < 0 ||
51
- typeof value.sha256 !== "string" ||
52
- !/^[0-9a-f]{64}$/.test(value.sha256)) {
53
- throw invalid(label);
54
- }
55
- const decoded = Object.freeze({
56
- requested: value.requested,
57
- absolutePath: value.absolutePath,
58
- realPath: value.realPath,
59
- device: value.device,
60
- inode: value.inode,
61
- size: value.size,
62
- sha256: value.sha256,
63
- });
64
- assertFrozenExecutableIdentity(decoded, label);
65
- return decoded;
66
- }
67
- export function assertFrozenExecutableIdentity(identity, label = "executable") {
68
- let actual;
69
- try {
70
- actual = freezeExecutableIdentity(identity.absolutePath, { cwd: path.dirname(identity.absolutePath) });
71
- }
72
- catch {
73
- throw changed(label);
74
- }
75
- for (const key of ["absolutePath", "realPath", "device", "inode", "size", "sha256"]) {
76
- if (actual[key] !== identity[key])
77
- throw changed(label);
78
- }
79
- }
80
- function resolveExecutable(requested, cwd, pathValue) {
81
- if (requested.includes("/") || requested.includes("\\"))
82
- return path.resolve(cwd, requested);
83
- const extensions = process.platform === "win32" ? (process.env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";") : [""];
84
- for (const directory of pathValue.split(path.delimiter)) {
85
- if (!directory)
86
- continue;
87
- for (const extension of extensions) {
88
- const candidate = path.resolve(directory, `${requested}${extension}`);
89
- try {
90
- fs.accessSync(candidate, fs.constants.X_OK);
91
- return candidate;
92
- }
93
- catch {
94
- // Continue through the frozen search path.
95
- }
96
- }
97
- }
98
- throw new UsageError(`Executable ${JSON.stringify(requested)} was not found.`, "INVALID_FLAG_VALUE");
99
- }
100
- function invalid(label) {
101
- return new UsageError(`Frozen ${label} identity is invalid.`, "INVALID_FLAG_VALUE");
102
- }
103
- function changed(label) {
104
- return new UsageError(`Frozen ${label} changed after publication.`, "RESOURCE_ALREADY_EXISTS");
105
- }
@@ -1,427 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { createHash } from "node:crypto";
5
- import fs from "node:fs";
6
- import path from "node:path";
7
- import { parseFrontmatter } from "../core/asset/frontmatter.js";
8
- import { compareCodePoints, toPosix } from "../core/common.js";
9
- import { UsageError } from "../core/errors.js";
10
- import { createExecutionSourceIdentity } from "./source.js";
11
- function errorMessage(cause) {
12
- return cause instanceof Error ? cause.message : String(cause);
13
- }
14
- function physicalIdentity(realPath, stat) {
15
- return stat.ino === 0n ? `path:${realPath}` : `inode:${stat.dev}:${stat.ino}`;
16
- }
17
- function statVersion(stat) {
18
- return `${stat.size}:${stat.mtimeNs}:${stat.ctimeNs}`;
19
- }
20
- function sameBigIntStat(left, right) {
21
- return (left.dev === right.dev &&
22
- left.ino === right.ino &&
23
- left.mode === right.mode &&
24
- left.size === right.size &&
25
- left.mtimeNs === right.mtimeNs &&
26
- left.ctimeNs === right.ctimeNs);
27
- }
28
- function containedRelative(root, candidate, allowRoot) {
29
- const relative = path.relative(root, candidate);
30
- if ((!allowRoot && relative === "") || relative.startsWith("..") || path.isAbsolute(relative)) {
31
- throw new UsageError(`${candidate} resolves outside its guarded containment root.`, "PATH_ESCAPE_VIOLATION");
32
- }
33
- return relative;
34
- }
35
- function requireContainmentRoot(containmentRootInput) {
36
- const containmentRoot = path.resolve(containmentRootInput);
37
- const containmentRealPath = fs.realpathSync(containmentRoot);
38
- const containmentStat = fs.statSync(containmentRealPath, { bigint: true });
39
- if (!containmentStat.isDirectory()) {
40
- throw new UsageError(`${containmentRootInput} is not a guarded source directory.`, "INVALID_FLAG_VALUE");
41
- }
42
- return { containmentRoot, containmentRealPath, containmentStat };
43
- }
44
- function numberStat(stat) {
45
- return new Proxy(stat, {
46
- get(target, property, receiver) {
47
- const value = Reflect.get(target, property, receiver);
48
- return typeof value === "bigint" ? Number(value) : value;
49
- },
50
- });
51
- }
52
- function decodeUtf8(bytes, sourcePath) {
53
- try {
54
- return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
55
- }
56
- catch {
57
- throw new UsageError(`${sourcePath} contains invalid UTF-8 bytes.`, "INVALID_FLAG_VALUE");
58
- }
59
- }
60
- function freezeSource(source) {
61
- const identity = source.identity ? createExecutionSourceIdentity(source.identity) : undefined;
62
- return Object.freeze({ ...source, ...(identity ? { identity } : {}) });
63
- }
64
- function captureRecord(sourcePathInput, containmentRootInput, options = {}) {
65
- const sourcePath = path.resolve(sourcePathInput);
66
- const { containmentRoot, containmentRealPath, containmentStat } = requireContainmentRoot(containmentRootInput);
67
- const lexicalRelative = containedRelative(containmentRoot, sourcePath, false);
68
- const noFollow = typeof fs.constants.O_NOFOLLOW === "number" ? fs.constants.O_NOFOLLOW : 0;
69
- let descriptor;
70
- try {
71
- descriptor = fs.openSync(sourcePath, fs.constants.O_RDONLY | noFollow);
72
- const before = fs.fstatSync(descriptor, { bigint: true });
73
- if (!before.isFile()) {
74
- throw new UsageError(`${sourcePath} is not a regular guarded source file.`, "INVALID_FLAG_VALUE");
75
- }
76
- const bytes = fs.readFileSync(descriptor);
77
- const after = fs.fstatSync(descriptor, { bigint: true });
78
- if (!sameBigIntStat(before, after) || BigInt(bytes.byteLength) !== before.size) {
79
- throw new UsageError(`${sourcePath} changed while its guarded bytes were read.`, "RESOURCE_ALREADY_EXISTS");
80
- }
81
- const pathnameStat = fs.lstatSync(sourcePath, { bigint: true });
82
- if (pathnameStat.isSymbolicLink()) {
83
- throw new UsageError(`${sourcePath} is a symbolic source; guarded reads require a regular no-follow owner.`, "RESOURCE_ALREADY_EXISTS");
84
- }
85
- if (!pathnameStat.isFile() || pathnameStat.dev !== before.dev || pathnameStat.ino !== before.ino) {
86
- throw new UsageError(`${sourcePath} changed physical identity during its guarded read.`, "RESOURCE_ALREADY_EXISTS");
87
- }
88
- const realPath = fs.realpathSync(sourcePath);
89
- containedRelative(containmentRealPath, realPath, false);
90
- const content = decodeUtf8(bytes, sourcePath);
91
- const sha256 = createHash("sha256").update(bytes).digest("hex");
92
- if (options.identity && options.identity.hash !== sha256) {
93
- throw new UsageError(`${sourcePath} adapter identity hash does not match its guarded bytes.`, "RESOURCE_ALREADY_EXISTS");
94
- }
95
- if (options.identity && options.identity.file !== toPosix(lexicalRelative)) {
96
- throw new UsageError(`${sourcePath} adapter identity file does not match its guarded relative path.`, "RESOURCE_ALREADY_EXISTS");
97
- }
98
- return {
99
- source: freezeSource({
100
- sourcePath,
101
- relativePath: toPosix(lexicalRelative),
102
- realPath,
103
- containmentRoot,
104
- containmentRealPath,
105
- containmentPhysicalIdentity: physicalIdentity(containmentRealPath, containmentStat),
106
- physicalIdentity: physicalIdentity(realPath, before),
107
- size: bytes.byteLength,
108
- mtimeNs: String(before.mtimeNs),
109
- ctimeNs: String(before.ctimeNs),
110
- sha256,
111
- bytesBase64: bytes.toString("base64"),
112
- content,
113
- authored: options.authored ?? false,
114
- ...(options.identity ? { identity: options.identity } : {}),
115
- }),
116
- stat: numberStat(before),
117
- };
118
- }
119
- catch (cause) {
120
- if (cause instanceof UsageError)
121
- throw cause;
122
- const code = cause.code;
123
- if (code === "ELOOP") {
124
- let linked;
125
- try {
126
- linked = fs.realpathSync(sourcePath);
127
- }
128
- catch {
129
- // The no-follow failure itself is sufficient when the link is broken.
130
- }
131
- if (linked) {
132
- const relative = path.relative(containmentRealPath, linked);
133
- if (relative.startsWith("..") || path.isAbsolute(relative)) {
134
- throw new UsageError(`${sourcePath} resolves outside its containment root through a symbolic source.`, "PATH_ESCAPE_VIOLATION");
135
- }
136
- }
137
- throw new UsageError(`${sourcePath} is a symbolic source; guarded reads require a regular no-follow owner.`, "RESOURCE_ALREADY_EXISTS");
138
- }
139
- throw new UsageError(`${sourcePath} could not be guarded as a contained regular source: ${errorMessage(cause)}`, code === "ENOENT" ? "RESOURCE_ALREADY_EXISTS" : "PATH_ESCAPE_VIOLATION");
140
- }
141
- finally {
142
- if (descriptor !== undefined)
143
- fs.closeSync(descriptor);
144
- }
145
- }
146
- export function captureGuardedExecutionSource(sourcePath, containmentRoot, options = {}) {
147
- return captureRecord(sourcePath, containmentRoot, options).source;
148
- }
149
- export function captureGuardedDirectoryManifest(directoryPathInput, containmentRootInput) {
150
- const directoryPath = path.resolve(directoryPathInput);
151
- const { containmentRoot, containmentRealPath, containmentStat } = requireContainmentRoot(containmentRootInput);
152
- const lexicalRelative = containedRelative(containmentRoot, directoryPath, true);
153
- try {
154
- const before = fs.lstatSync(directoryPath, { bigint: true });
155
- if (before.isSymbolicLink()) {
156
- throw new UsageError(`${directoryPath} is a symbolic directory with ambiguous guarded identity.`, "RESOURCE_ALREADY_EXISTS");
157
- }
158
- if (!before.isDirectory()) {
159
- throw new UsageError(`${directoryPath} is not a guarded directory.`, "INVALID_FLAG_VALUE");
160
- }
161
- const realPath = fs.realpathSync(directoryPath);
162
- containedRelative(containmentRealPath, realPath, true);
163
- const entries = fs
164
- .readdirSync(directoryPath, { withFileTypes: true })
165
- .sort((left, right) => compareCodePoints(left.name, right.name))
166
- .map((entry) => {
167
- const entryPath = path.join(directoryPath, entry.name);
168
- const entryStat = fs.lstatSync(entryPath, { bigint: true });
169
- if (entry.isSymbolicLink() || entryStat.isSymbolicLink()) {
170
- let linked;
171
- try {
172
- linked = fs.realpathSync(entryPath);
173
- }
174
- catch {
175
- // Broken symbolic entries still have ambiguous ownership.
176
- }
177
- if (linked) {
178
- const relative = path.relative(containmentRealPath, linked);
179
- if (relative.startsWith("..") || path.isAbsolute(relative)) {
180
- throw new UsageError(`${entryPath} resolves outside the bundle root through a symbolic source.`, "PATH_ESCAPE_VIOLATION");
181
- }
182
- }
183
- throw new UsageError(`${entryPath} is a symbolic source with a physical source identity collision; guarded reads require one no-follow owner.`, "RESOURCE_ALREADY_EXISTS");
184
- }
185
- const kind = entry.isDirectory() && entryStat.isDirectory()
186
- ? "directory"
187
- : entry.isFile() && entryStat.isFile()
188
- ? "file"
189
- : undefined;
190
- if (!kind) {
191
- throw new UsageError(`${entryPath} is neither a regular file nor directory.`, "INVALID_FLAG_VALUE");
192
- }
193
- const entryRealPath = fs.realpathSync(entryPath);
194
- containedRelative(containmentRealPath, entryRealPath, false);
195
- return Object.freeze({
196
- name: entry.name,
197
- kind,
198
- physicalIdentity: physicalIdentity(entryRealPath, entryStat),
199
- version: statVersion(entryStat),
200
- });
201
- });
202
- const after = fs.lstatSync(directoryPath, { bigint: true });
203
- if (!sameBigIntStat(before, after)) {
204
- throw new UsageError(`${directoryPath} changed while its guarded directory manifest was read.`, "RESOURCE_ALREADY_EXISTS");
205
- }
206
- return Object.freeze({
207
- directoryPath,
208
- relativePath: lexicalRelative === "" ? "." : toPosix(lexicalRelative),
209
- realPath,
210
- containmentRoot,
211
- containmentRealPath,
212
- containmentPhysicalIdentity: physicalIdentity(containmentRealPath, containmentStat),
213
- physicalIdentity: physicalIdentity(realPath, before),
214
- version: statVersion(before),
215
- entries: Object.freeze(entries),
216
- });
217
- }
218
- catch (cause) {
219
- if (cause instanceof UsageError)
220
- throw cause;
221
- throw new UsageError(`${directoryPath} could not be captured as a guarded directory manifest: ${errorMessage(cause)}`, cause.code === "ENOENT" ? "RESOURCE_ALREADY_EXISTS" : "PATH_ESCAPE_VIOLATION");
222
- }
223
- }
224
- function sameSnapshotValue(left, right) {
225
- return JSON.stringify(left) === JSON.stringify(right);
226
- }
227
- function sourceSortKey(source) {
228
- const identity = source.identity;
229
- return identity
230
- ? `${identity.ref}\0${identity.adapter}\0${identity.file}`
231
- : `${source.containmentRealPath}\0${source.relativePath}`;
232
- }
233
- function directorySortKey(manifest) {
234
- return `${manifest.containmentRealPath}\0${manifest.relativePath}`;
235
- }
236
- export class GuardedExecutionSourceCollector {
237
- #sources = new Map();
238
- #directories = new Map();
239
- capture(sourcePath, containmentRoot, options = {}) {
240
- const key = path.resolve(sourcePath);
241
- const existing = this.#sources.get(key);
242
- if (existing) {
243
- if (options.identity)
244
- return this.bindIdentity(sourcePath, containmentRoot, options.identity);
245
- return existing.source;
246
- }
247
- const record = captureRecord(sourcePath, containmentRoot, options);
248
- this.#assertNoPhysicalOwnerAlias(record.source);
249
- this.#sources.set(key, record);
250
- return record.source;
251
- }
252
- readBytes(sourcePath, containmentRoot, options = {}) {
253
- return Buffer.from(this.capture(sourcePath, containmentRoot, options).bytesBase64, "base64");
254
- }
255
- fileContext(root, file, options = {}) {
256
- const source = this.capture(file, root, options);
257
- const record = this.#sources.get(path.resolve(file));
258
- if (!record)
259
- throw new Error("guarded source collector lost a captured file");
260
- const relPath = source.relativePath;
261
- const ext = path.extname(file).toLowerCase();
262
- const fileName = path.basename(file);
263
- const parentDirAbs = path.dirname(path.resolve(file));
264
- const relDir = path.posix.dirname(relPath);
265
- const ancestorDirs = relDir === "." ? [] : relDir.split("/").filter(Boolean);
266
- let frontmatter;
267
- let parsed = false;
268
- return {
269
- absPath: path.resolve(file),
270
- relPath,
271
- ext,
272
- fileName,
273
- parentDir: path.basename(parentDirAbs),
274
- parentDirAbs,
275
- ancestorDirs,
276
- stashRoot: path.resolve(root),
277
- content: () => source.content,
278
- frontmatter: () => {
279
- if (!parsed) {
280
- const result = parseFrontmatter(source.content);
281
- frontmatter = Object.keys(result.data).length > 0 ? result.data : null;
282
- parsed = true;
283
- }
284
- return frontmatter ?? null;
285
- },
286
- stat: () => record.stat,
287
- };
288
- }
289
- bindIdentity(sourcePath, containmentRoot, identityInput) {
290
- const key = path.resolve(sourcePath);
291
- const existing = this.#sources.get(key) ?? captureRecord(sourcePath, containmentRoot);
292
- const identity = createExecutionSourceIdentity(identityInput);
293
- if (identity.file !== existing.source.relativePath || identity.hash !== existing.source.sha256) {
294
- throw new UsageError(`${sourcePath} adapter identity does not match its guarded file owner or bytes.`, "RESOURCE_ALREADY_EXISTS");
295
- }
296
- if (existing.source.identity) {
297
- if (!sameSnapshotValue(existing.source.identity, identity)) {
298
- throw new UsageError(`${sourcePath} already has a different guarded logical owner identity.`, "RESOURCE_ALREADY_EXISTS");
299
- }
300
- return existing.source;
301
- }
302
- const source = freezeSource({ ...existing.source, identity });
303
- this.#assertNoPhysicalOwnerAlias(source, key);
304
- this.#sources.set(key, { ...existing, source });
305
- return source;
306
- }
307
- trackDirectory(directoryPath, containmentRoot) {
308
- const manifest = captureGuardedDirectoryManifest(directoryPath, containmentRoot);
309
- const key = path.resolve(directoryPath);
310
- const existing = this.#directories.get(key);
311
- if (existing && !sameSnapshotValue(existing, manifest)) {
312
- throw new UsageError(`${directoryPath} changed between guarded directory reads.`, "RESOURCE_ALREADY_EXISTS");
313
- }
314
- if (!existing)
315
- this.#directories.set(key, manifest);
316
- return existing ?? manifest;
317
- }
318
- enumerateTree(directoryPath, containmentRoot) {
319
- const files = [];
320
- const visit = (directory) => {
321
- const manifest = this.trackDirectory(directory, containmentRoot);
322
- for (const entry of manifest.entries) {
323
- const candidate = path.join(directory, entry.name);
324
- if (entry.kind === "directory")
325
- visit(candidate);
326
- else
327
- files.push(candidate);
328
- }
329
- };
330
- visit(path.resolve(directoryPath));
331
- return Object.freeze(files.sort(compareCodePoints));
332
- }
333
- snapshot() {
334
- return Object.freeze({
335
- sources: Object.freeze([...this.#sources.values()]
336
- .map((record) => record.source)
337
- .sort((left, right) => compareCodePoints(sourceSortKey(left), sourceSortKey(right)))),
338
- directoryManifests: Object.freeze([...this.#directories.values()].sort((left, right) => compareCodePoints(directorySortKey(left), directorySortKey(right)))),
339
- });
340
- }
341
- /**
342
- * Merge another collector's captured sources and directory manifests into
343
- * this one (A-N7, spec docs/plans/specs/p3a-plan-v5-child-freeze.md §4.2
344
- * step 6). The recursive child-workflow freeze gives each child its OWN
345
- * fresh collector, so a child's plan (and therefore its `planHash`) is a
346
- * pure function of its own source, independent of its position in the
347
- * parent (A-N7's rejected alternative: sharing the parent's collector,
348
- * which would make an identical child hash differently depending on what
349
- * the parent had already captured). The parent then absorbs the child's
350
- * records so its own final pre-publication CAS ({@link revalidate}) covers
351
- * every child file too.
352
- *
353
- * Re-runs `#assertNoPhysicalOwnerAlias` for each newly-absorbed source
354
- * record, so the shared-physical-owner authority holds ACROSS the
355
- * composition, not just within one workflow's own freeze. A record whose
356
- * key (resolved source path) is already present is required to be
357
- * byte-identical to the one already held — two DISJOINT branches
358
- * composing the SAME child (a diamond, not a cycle) absorb the same file
359
- * twice with identical content and pass silently; two branches that
360
- * somehow captured the same path with different content fail closed.
361
- */
362
- absorb(other) {
363
- for (const [key, record] of other.#sources) {
364
- const existing = this.#sources.get(key);
365
- if (existing) {
366
- if (!sameSnapshotValue(existing.source, record.source)) {
367
- throw new UsageError(`${record.source.sourcePath} was captured with conflicting content across a composed workflow freeze.`, "RESOURCE_ALREADY_EXISTS");
368
- }
369
- continue;
370
- }
371
- this.#assertNoPhysicalOwnerAlias(record.source);
372
- this.#sources.set(key, record);
373
- }
374
- for (const [key, manifest] of other.#directories) {
375
- const existing = this.#directories.get(key);
376
- if (existing) {
377
- if (!sameSnapshotValue(existing, manifest)) {
378
- throw new UsageError(`${manifest.directoryPath} changed between guarded directory reads across a composed workflow freeze.`, "RESOURCE_ALREADY_EXISTS");
379
- }
380
- continue;
381
- }
382
- this.#directories.set(key, manifest);
383
- }
384
- }
385
- revalidate() {
386
- for (const record of this.#sources.values()) {
387
- let current;
388
- try {
389
- current = captureRecord(record.source.sourcePath, record.source.containmentRoot, {
390
- authored: record.source.authored,
391
- ...(record.source.identity ? { identity: record.source.identity } : {}),
392
- }).source;
393
- }
394
- catch (cause) {
395
- throw new UsageError(`Guarded execution source read set changed before publication: ${errorMessage(cause)}`, "RESOURCE_ALREADY_EXISTS");
396
- }
397
- if (!sameSnapshotValue(record.source, current)) {
398
- throw new UsageError("Guarded execution source read set changed before publication.", "RESOURCE_ALREADY_EXISTS");
399
- }
400
- }
401
- for (const manifest of this.#directories.values()) {
402
- let current;
403
- try {
404
- current = captureGuardedDirectoryManifest(manifest.directoryPath, manifest.containmentRoot);
405
- }
406
- catch (cause) {
407
- throw new UsageError(`Guarded execution source directory manifest changed before publication: ${errorMessage(cause)}`, "RESOURCE_ALREADY_EXISTS");
408
- }
409
- if (!sameSnapshotValue(manifest, current)) {
410
- throw new UsageError("Guarded execution source directory manifest changed before publication.", "RESOURCE_ALREADY_EXISTS");
411
- }
412
- }
413
- }
414
- #assertNoPhysicalOwnerAlias(candidate, selfKey) {
415
- if (!candidate.identity)
416
- return;
417
- for (const [key, record] of this.#sources) {
418
- if (key === selfKey || !record.source.identity)
419
- continue;
420
- if (record.source.containmentPhysicalIdentity === candidate.containmentPhysicalIdentity &&
421
- record.source.physicalIdentity === candidate.physicalIdentity &&
422
- !sameSnapshotValue(record.source.identity, candidate.identity)) {
423
- throw new UsageError(`${candidate.sourcePath} aliases the same physical source and root under a different logical owner.`, "RESOURCE_ALREADY_EXISTS");
424
- }
425
- }
426
- }
427
- }