@mysten-incubation/devstack 0.0.1 → 0.1.1
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.
- package/README.md +8 -4
- package/dashboard-ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dashboard-ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dashboard-ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dashboard-ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-cyrillic-ext-wght-normal-I4S5GZfc.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-cyrillic-wght-normal-BmXc_FBt.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-latin-ext-wght-normal-DrnZ1wKl.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-latin-wght-normal-B_7UjwxQ.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-symbols2-wght-normal-GZpp1pK2.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-vietnamese-wght-normal-D8KDMBhC.woff2 +0 -0
- package/dashboard-ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dashboard-ui/assets/index-Bmi1UtAg.js +1356 -0
- package/dashboard-ui/assets/index-D5EShVt4.js +3 -0
- package/dashboard-ui/assets/index-Deml9drg.css +1 -0
- package/dashboard-ui/index.html +13 -0
- package/dist/api/define-capabilities.d.mts +14 -3
- package/dist/api/define-capabilities.mjs +18 -1
- package/dist/api/define-capabilities.mjs.map +1 -1
- package/dist/api/define-devstack.d.mts +1 -1
- package/dist/api/define-devstack.mjs +6 -26
- package/dist/api/define-devstack.mjs.map +1 -1
- package/dist/api/define-plugin.d.mts +1 -0
- package/dist/api/define-plugin.mjs +2 -0
- package/dist/api/inference-network.d.mts +132 -0
- package/dist/api/inference-network.mjs +105 -16
- package/dist/api/inference-network.mjs.map +1 -1
- package/dist/api/plugin-errors.d.mts +7 -0
- package/dist/api/run-stack.d.mts +20 -9
- package/dist/api/run-stack.mjs +56 -29
- package/dist/api/run-stack.mjs.map +1 -1
- package/dist/build-integrations/playwright/config.d.mts +6 -4
- package/dist/build-integrations/playwright/config.mjs +5 -3
- package/dist/build-integrations/playwright/config.mjs.map +1 -1
- package/dist/build-integrations/playwright/errors.d.mts +1 -1
- package/dist/build-integrations/playwright/global-setup.d.mts +43 -17
- package/dist/build-integrations/playwright/global-setup.mjs +250 -13
- package/dist/build-integrations/playwright/global-setup.mjs.map +1 -1
- package/dist/build-integrations/playwright/index.d.mts +5 -3
- package/dist/build-integrations/playwright/index.mjs +4 -2
- package/dist/build-integrations/playwright/stack-context.d.mts +0 -1
- package/dist/build-integrations/playwright/stack-context.mjs +24 -63
- package/dist/build-integrations/playwright/stack-context.mjs.map +1 -1
- package/dist/build-integrations/playwright/wallet-context.d.mts +7 -10
- package/dist/build-integrations/playwright/wallet-context.mjs +8 -13
- package/dist/build-integrations/playwright/wallet-context.mjs.map +1 -1
- package/dist/build-integrations/runtime/cold-start-url.d.mts +5 -0
- package/dist/build-integrations/runtime/cold-start-url.mjs +4 -3
- package/dist/build-integrations/runtime/cold-start-url.mjs.map +1 -1
- package/dist/build-integrations/runtime/conventional-routes.d.mts +51 -0
- package/dist/build-integrations/runtime/conventional-routes.mjs +92 -0
- package/dist/build-integrations/runtime/conventional-routes.mjs.map +1 -0
- package/dist/build-integrations/runtime/discover.d.mts +38 -30
- package/dist/build-integrations/runtime/discover.mjs +73 -70
- package/dist/build-integrations/runtime/discover.mjs.map +1 -1
- package/dist/build-integrations/runtime/endpoint-registry.d.mts +3 -1
- package/dist/build-integrations/runtime/endpoint-registry.mjs +3 -1
- package/dist/build-integrations/runtime/endpoint-registry.mjs.map +1 -1
- package/dist/build-integrations/runtime/index.d.mts +7 -2
- package/dist/build-integrations/runtime/index.mjs +9 -2
- package/dist/build-integrations/runtime/manifest-types.d.mts +2 -0
- package/dist/build-integrations/runtime/manifest-types.mjs +3 -0
- package/dist/build-integrations/runtime/playwright-stack-context-slot.d.mts +29 -0
- package/dist/build-integrations/runtime/playwright-stack-context-slot.mjs +10 -0
- package/dist/build-integrations/runtime/playwright-stack-context-slot.mjs.map +1 -0
- package/dist/build-integrations/runtime/read-stack-context.d.mts +1 -1
- package/dist/build-integrations/runtime/read-stack-context.mjs +10 -4
- package/dist/build-integrations/runtime/read-stack-context.mjs.map +1 -1
- package/dist/build-integrations/runtime/resolve-discovery-env.d.mts +48 -0
- package/dist/build-integrations/runtime/resolve-discovery-env.mjs +42 -0
- package/dist/build-integrations/runtime/resolve-discovery-env.mjs.map +1 -0
- package/dist/build-integrations/runtime/stack-context.d.mts +1 -1
- package/dist/build-integrations/runtime/wallet-paths.mjs +2 -0
- package/dist/build-integrations/vite/index.d.mts +51 -0
- package/dist/build-integrations/vite/index.mjs +73 -0
- package/dist/build-integrations/vite/index.mjs.map +1 -0
- package/dist/build-integrations/vitest/env.d.mts +4 -3
- package/dist/build-integrations/vitest/env.mjs +6 -4
- package/dist/build-integrations/vitest/env.mjs.map +1 -1
- package/dist/build-integrations/vitest/errors.d.mts +25 -4
- package/dist/build-integrations/vitest/errors.mjs +15 -2
- package/dist/build-integrations/vitest/errors.mjs.map +1 -1
- package/dist/build-integrations/vitest/index.d.mts +2 -2
- package/dist/build-integrations/vitest/index.mjs +3 -3
- package/dist/build-integrations/vitest/setup.d.mts +4 -2
- package/dist/build-integrations/vitest/setup.mjs +2 -2
- package/dist/build-integrations/vitest/setup.mjs.map +1 -1
- package/dist/build-integrations/vitest/stack-context.d.mts +0 -1
- package/dist/build-integrations/vitest/stack-context.mjs +33 -13
- package/dist/build-integrations/vitest/stack-context.mjs.map +1 -1
- package/dist/cli/bail.mjs +23 -0
- package/dist/cli/bail.mjs.map +1 -0
- package/dist/{surfaces/cli/commands → cli}/doctor-probes.mjs +26 -16
- package/dist/cli/doctor-probes.mjs.map +1 -0
- package/dist/cli/main.d.mts +15 -1
- package/dist/cli/main.mjs +166 -482
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/prune-direct.mjs +31 -201
- package/dist/cli/prune-direct.mjs.map +1 -1
- package/dist/cli/snapshot-reader.mjs +14 -11
- package/dist/cli/snapshot-reader.mjs.map +1 -1
- package/dist/cli/up-lifecycle.mjs +4 -1
- package/dist/cli/up-lifecycle.mjs.map +1 -1
- package/dist/cli/wirings/apply.mjs +95 -0
- package/dist/cli/wirings/apply.mjs.map +1 -0
- package/dist/cli/wirings/build-verb-layers.mjs +42 -0
- package/dist/cli/wirings/build-verb-layers.mjs.map +1 -0
- package/dist/cli/wirings/config-loader.mjs +69 -0
- package/dist/cli/wirings/config-loader.mjs.map +1 -0
- package/dist/cli/wirings/engine-command.mjs +30 -0
- package/dist/cli/wirings/engine-command.mjs.map +1 -0
- package/dist/cli/wirings/identity.mjs +72 -0
- package/dist/cli/wirings/identity.mjs.map +1 -0
- package/dist/cli/wirings/provide-file-system.mjs +7 -0
- package/dist/cli/wirings/provide-file-system.mjs.map +1 -0
- package/dist/cli/wirings/snapshot.mjs +177 -0
- package/dist/cli/wirings/snapshot.mjs.map +1 -0
- package/dist/cli/wirings/up.mjs +287 -0
- package/dist/cli/wirings/up.mjs.map +1 -0
- package/dist/cli/wirings/wipe.mjs +40 -0
- package/dist/cli/wirings/wipe.mjs.map +1 -0
- package/dist/contracts/capability-decl.d.mts +0 -2
- package/dist/contracts/codegenable.d.mts +43 -0
- package/dist/contracts/container-runtime.d.mts +26 -1
- package/dist/contracts/faucet-strategy.d.mts +25 -0
- package/dist/contracts/funding-strategy.d.mts +42 -0
- package/dist/contracts/plugin-expander.mjs +60 -0
- package/dist/contracts/plugin-expander.mjs.map +1 -0
- package/dist/contracts/projection.d.mts +5 -3
- package/dist/contracts/renderer.d.mts +23 -0
- package/dist/contracts/routable.d.mts +14 -1
- package/dist/contracts/snapshotable.d.mts +25 -3
- package/dist/contracts/wallet-protocol.d.mts +52 -0
- package/dist/contracts/wallet-protocol.mjs +52 -0
- package/dist/contracts/wallet-protocol.mjs.map +1 -0
- package/dist/index.d.mts +26 -25
- package/dist/index.mjs +20 -13
- package/dist/{runtime → orchestrators}/built-in-plugin-layers.mjs +10 -5
- package/dist/orchestrators/built-in-plugin-layers.mjs.map +1 -0
- package/dist/orchestrators/codegen/bindings.d.mts +1 -2
- package/dist/orchestrators/codegen/bindings.mjs +52 -186
- package/dist/orchestrators/codegen/bindings.mjs.map +1 -1
- package/dist/orchestrators/codegen/emit.mjs +19 -1
- package/dist/orchestrators/codegen/emit.mjs.map +1 -1
- package/dist/orchestrators/codegen/errors.mjs +8 -3
- package/dist/orchestrators/codegen/errors.mjs.map +1 -1
- package/dist/orchestrators/codegen/format.mjs +47 -39
- package/dist/orchestrators/codegen/format.mjs.map +1 -1
- package/dist/orchestrators/codegen/gitignore.mjs +3 -1
- package/dist/orchestrators/codegen/gitignore.mjs.map +1 -1
- package/dist/orchestrators/codegen/output-location.mjs +41 -0
- package/dist/orchestrators/codegen/output-location.mjs.map +1 -0
- package/dist/orchestrators/codegen/paths.d.mts +1 -1
- package/dist/orchestrators/codegen/paths.mjs +40 -14
- package/dist/orchestrators/codegen/paths.mjs.map +1 -1
- package/dist/orchestrators/codegen/permissions.mjs +3 -1
- package/dist/orchestrators/codegen/permissions.mjs.map +1 -1
- package/dist/orchestrators/codegen/service.mjs +157 -105
- package/dist/orchestrators/codegen/service.mjs.map +1 -1
- package/dist/orchestrators/lifecycle-prune/errors.mjs +31 -0
- package/dist/orchestrators/lifecycle-prune/errors.mjs.map +1 -0
- package/dist/orchestrators/lifecycle-prune/index.mjs +350 -0
- package/dist/orchestrators/lifecycle-prune/index.mjs.map +1 -0
- package/dist/orchestrators/router/cleanup.mjs +26 -27
- package/dist/orchestrators/router/cleanup.mjs.map +1 -1
- package/dist/orchestrators/router/entrypoints.mjs +2 -2
- package/dist/orchestrators/router/entrypoints.mjs.map +1 -1
- package/dist/orchestrators/router/file-provider.mjs +14 -5
- package/dist/orchestrators/router/file-provider.mjs.map +1 -1
- package/dist/orchestrators/router/hostname.mjs +19 -55
- package/dist/orchestrators/router/hostname.mjs.map +1 -1
- package/dist/orchestrators/router/index.mjs +11 -0
- package/dist/orchestrators/router/profile.mjs +2 -2
- package/dist/orchestrators/router/sentinels.mjs +26 -0
- package/dist/orchestrators/router/sentinels.mjs.map +1 -0
- package/dist/orchestrators/router/service.mjs +40 -37
- package/dist/orchestrators/router/service.mjs.map +1 -1
- package/dist/orchestrators/router/traefik-container.mjs +27 -16
- package/dist/orchestrators/router/traefik-container.mjs.map +1 -1
- package/dist/{substrate/runtime → orchestrators}/run.mjs +26 -21
- package/dist/orchestrators/run.mjs.map +1 -0
- package/dist/orchestrators/runtime-composition.d.mts +1 -1
- package/dist/orchestrators/runtime-composition.mjs +123 -39
- package/dist/orchestrators/runtime-composition.mjs.map +1 -1
- package/dist/orchestrators/snapshot/capture-command.d.mts +1 -0
- package/dist/orchestrators/snapshot/capture-command.mjs +25 -0
- package/dist/orchestrators/snapshot/capture-command.mjs.map +1 -0
- package/dist/orchestrators/snapshot/capture.mjs +42 -28
- package/dist/orchestrators/snapshot/capture.mjs.map +1 -1
- package/dist/orchestrators/snapshot/descriptor.mjs +35 -10
- package/dist/orchestrators/snapshot/descriptor.mjs.map +1 -1
- package/dist/orchestrators/snapshot/identity-guard.mjs +1 -1
- package/dist/orchestrators/snapshot/index.mjs +13 -0
- package/dist/orchestrators/snapshot/integrity.d.mts +1 -1
- package/dist/orchestrators/snapshot/integrity.mjs +73 -17
- package/dist/orchestrators/snapshot/integrity.mjs.map +1 -1
- package/dist/orchestrators/snapshot/pending-marker.d.mts +1 -0
- package/dist/orchestrators/snapshot/pending-marker.mjs +99 -0
- package/dist/orchestrators/snapshot/pending-marker.mjs.map +1 -0
- package/dist/orchestrators/snapshot/phase-error.mjs +23 -0
- package/dist/orchestrators/snapshot/phase-error.mjs.map +1 -0
- package/dist/orchestrators/snapshot/prune.mjs +20 -55
- package/dist/orchestrators/snapshot/prune.mjs.map +1 -1
- package/dist/orchestrators/snapshot/recover-pending.d.mts +1 -0
- package/dist/orchestrators/snapshot/recover-pending.mjs +223 -0
- package/dist/orchestrators/snapshot/recover-pending.mjs.map +1 -0
- package/dist/orchestrators/snapshot/restore.mjs +118 -84
- package/dist/orchestrators/snapshot/restore.mjs.map +1 -1
- package/dist/orchestrators/snapshot/service.mjs +53 -56
- package/dist/orchestrators/snapshot/service.mjs.map +1 -1
- package/dist/orchestrators/snapshot/state-document.d.mts +1 -0
- package/dist/orchestrators/snapshot/state-document.mjs +47 -7
- package/dist/orchestrators/snapshot/state-document.mjs.map +1 -1
- package/dist/orchestrators/snapshot/wipe.mjs +67 -10
- package/dist/orchestrators/snapshot/wipe.mjs.map +1 -1
- package/dist/plugins/account/codegen.mjs +9 -8
- package/dist/plugins/account/codegen.mjs.map +1 -1
- package/dist/plugins/account/errors.d.mts +33 -6
- package/dist/plugins/account/errors.mjs.map +1 -1
- package/dist/plugins/account/funding.d.mts +29 -19
- package/dist/plugins/account/funding.mjs +84 -66
- package/dist/plugins/account/funding.mjs.map +1 -1
- package/dist/plugins/account/index.d.mts +2 -4
- package/dist/plugins/account/index.mjs +64 -31
- package/dist/plugins/account/index.mjs.map +1 -1
- package/dist/plugins/account/keypair.mjs +6 -9
- package/dist/plugins/account/keypair.mjs.map +1 -1
- package/dist/plugins/account/lease.mjs +1 -0
- package/dist/plugins/account/lease.mjs.map +1 -1
- package/dist/plugins/account/registry.d.mts +14 -1
- package/dist/plugins/account/registry.mjs +18 -18
- package/dist/plugins/account/registry.mjs.map +1 -1
- package/dist/plugins/account/service.d.mts +23 -4
- package/dist/plugins/account/service.mjs +83 -45
- package/dist/plugins/account/service.mjs.map +1 -1
- package/dist/plugins/account/snapshot.mjs +2 -5
- package/dist/plugins/account/snapshot.mjs.map +1 -1
- package/dist/plugins/account/spans.mjs +16 -0
- package/dist/plugins/account/spans.mjs.map +1 -0
- package/dist/plugins/account/variants/keystore.mjs +6 -8
- package/dist/plugins/account/variants/keystore.mjs.map +1 -1
- package/dist/plugins/action/build-context.d.mts +3 -2
- package/dist/plugins/action/errors.d.mts +16 -12
- package/dist/plugins/action/errors.mjs.map +1 -1
- package/dist/plugins/action/execute.mjs +65 -103
- package/dist/plugins/action/execute.mjs.map +1 -1
- package/dist/plugins/action/index.d.mts +0 -2
- package/dist/plugins/action/index.mjs +17 -13
- package/dist/plugins/action/index.mjs.map +1 -1
- package/dist/plugins/action/service.mjs +38 -35
- package/dist/plugins/action/service.mjs.map +1 -1
- package/dist/plugins/action/spans.mjs +11 -0
- package/dist/plugins/action/spans.mjs.map +1 -0
- package/dist/plugins/coin/codegen.mjs +9 -8
- package/dist/plugins/coin/codegen.mjs.map +1 -1
- package/dist/plugins/coin/discovery.mjs +8 -4
- package/dist/plugins/coin/discovery.mjs.map +1 -1
- package/dist/plugins/coin/index.d.mts +11 -29
- package/dist/plugins/coin/index.mjs +56 -27
- package/dist/plugins/coin/index.mjs.map +1 -1
- package/dist/plugins/coin/metadata.mjs +8 -15
- package/dist/plugins/coin/metadata.mjs.map +1 -1
- package/dist/plugins/coin/mint.d.mts +30 -11
- package/dist/plugins/coin/mint.mjs +78 -74
- package/dist/plugins/coin/mint.mjs.map +1 -1
- package/dist/plugins/coin/registry.mjs +4 -7
- package/dist/plugins/coin/registry.mjs.map +1 -1
- package/dist/plugins/coin/service.d.mts +39 -1
- package/dist/plugins/coin/service.mjs +11 -4
- package/dist/plugins/coin/service.mjs.map +1 -1
- package/dist/plugins/coin/spans.mjs +20 -0
- package/dist/plugins/coin/spans.mjs.map +1 -0
- package/dist/plugins/dashboard/domain.mjs +402 -0
- package/dist/plugins/dashboard/domain.mjs.map +1 -0
- package/dist/plugins/dashboard/index.d.mts +29 -0
- package/dist/plugins/dashboard/index.mjs +91 -0
- package/dist/plugins/dashboard/index.mjs.map +1 -0
- package/dist/plugins/dashboard/origin-policy.mjs +36 -0
- package/dist/plugins/dashboard/origin-policy.mjs.map +1 -0
- package/dist/plugins/dashboard/routable.mjs +27 -0
- package/dist/plugins/dashboard/routable.mjs.map +1 -0
- package/dist/plugins/dashboard/schema/builder.mjs +21 -0
- package/dist/plugins/dashboard/schema/builder.mjs.map +1 -0
- package/dist/plugins/dashboard/schema/enums.mjs +72 -0
- package/dist/plugins/dashboard/schema/enums.mjs.map +1 -0
- package/dist/plugins/dashboard/schema/root.mjs +351 -0
- package/dist/plugins/dashboard/schema/root.mjs.map +1 -0
- package/dist/plugins/dashboard/schema/types.mjs +508 -0
- package/dist/plugins/dashboard/schema/types.mjs.map +1 -0
- package/dist/plugins/dashboard/schema.mjs +11 -0
- package/dist/plugins/dashboard/schema.mjs.map +1 -0
- package/dist/plugins/dashboard/server.mjs +166 -0
- package/dist/plugins/dashboard/server.mjs.map +1 -0
- package/dist/plugins/deepbook/deploy.mjs +53 -115
- package/dist/plugins/deepbook/deploy.mjs.map +1 -1
- package/dist/plugins/deepbook/errors.mjs +1 -0
- package/dist/plugins/deepbook/errors.mjs.map +1 -1
- package/dist/plugins/deepbook/faucet-strategy.mjs +47 -34
- package/dist/plugins/deepbook/faucet-strategy.mjs.map +1 -1
- package/dist/plugins/deepbook/hash.mjs +9 -0
- package/dist/plugins/deepbook/hash.mjs.map +1 -0
- package/dist/plugins/deepbook/index.d.mts +1 -10
- package/dist/plugins/deepbook/index.mjs +25 -22
- package/dist/plugins/deepbook/index.mjs.map +1 -1
- package/dist/plugins/deepbook/pyth/index.mjs +26 -55
- package/dist/plugins/deepbook/pyth/index.mjs.map +1 -1
- package/dist/plugins/deepbook/snapshot.mjs +17 -29
- package/dist/plugins/deepbook/snapshot.mjs.map +1 -1
- package/dist/plugins/deepbook/spans.mjs +18 -0
- package/dist/plugins/deepbook/spans.mjs.map +1 -0
- package/dist/plugins/deepbook/type-strings.mjs +65 -0
- package/dist/plugins/deepbook/type-strings.mjs.map +1 -0
- package/dist/plugins/deepbook/types.d.mts +2 -3
- package/dist/plugins/deepbook/types.mjs.map +1 -1
- package/dist/plugins/faucet/dispatcher.d.mts +21 -2
- package/dist/plugins/faucet/dispatcher.mjs +1 -2
- package/dist/plugins/faucet/dispatcher.mjs.map +1 -1
- package/dist/plugins/faucet/errors.d.mts +11 -24
- package/dist/plugins/faucet/errors.mjs.map +1 -1
- package/dist/plugins/faucet/http.mjs +33 -14
- package/dist/plugins/faucet/http.mjs.map +1 -1
- package/dist/plugins/faucet/index.d.mts +15 -5
- package/dist/plugins/faucet/index.mjs +3 -0
- package/dist/plugins/faucet/index.mjs.map +1 -1
- package/dist/plugins/faucet/spans.mjs +12 -0
- package/dist/plugins/faucet/spans.mjs.map +1 -0
- package/dist/plugins/host-service/errors.d.mts +1 -1
- package/dist/plugins/host-service/index.mjs +34 -8
- package/dist/plugins/host-service/index.mjs.map +1 -1
- package/dist/plugins/host-service/routable.mjs +2 -1
- package/dist/plugins/host-service/routable.mjs.map +1 -1
- package/dist/plugins/host-service/service.d.mts +21 -0
- package/dist/plugins/host-service/service.mjs +136 -81
- package/dist/plugins/host-service/service.mjs.map +1 -1
- package/dist/plugins/internal/acquire-on-chain-artifact.mjs +23 -0
- package/dist/plugins/internal/acquire-on-chain-artifact.mjs.map +1 -0
- package/dist/plugins/internal/codegen-helpers.mjs +18 -0
- package/dist/plugins/internal/codegen-helpers.mjs.map +1 -0
- package/dist/plugins/internal/funding-failure-error.mjs +32 -0
- package/dist/plugins/internal/funding-failure-error.mjs.map +1 -0
- package/dist/plugins/package/build.mjs +1 -1
- package/dist/plugins/package/build.mjs.map +1 -1
- package/dist/plugins/package/codegen.mjs +26 -0
- package/dist/plugins/package/codegen.mjs.map +1 -1
- package/dist/plugins/package/errors.d.mts +16 -6
- package/dist/plugins/package/errors.mjs.map +1 -1
- package/dist/plugins/package/index.d.mts +0 -4
- package/dist/plugins/package/index.mjs +27 -21
- package/dist/plugins/package/index.mjs.map +1 -1
- package/dist/plugins/package/mode-known.mjs +26 -12
- package/dist/plugins/package/mode-known.mjs.map +1 -1
- package/dist/plugins/package/mode-local.mjs +47 -41
- package/dist/plugins/package/mode-local.mjs.map +1 -1
- package/dist/plugins/package/publish-executor.mjs +55 -114
- package/dist/plugins/package/publish-executor.mjs.map +1 -1
- package/dist/plugins/package/registry.mjs +2 -1
- package/dist/plugins/package/registry.mjs.map +1 -1
- package/dist/plugins/package/service.mjs.map +1 -1
- package/dist/plugins/package/spans.mjs +14 -0
- package/dist/plugins/package/spans.mjs.map +1 -0
- package/dist/plugins/postgres/db-ensure.mjs +19 -12
- package/dist/plugins/postgres/db-ensure.mjs.map +1 -1
- package/dist/plugins/postgres/errors.d.mts +5 -0
- package/dist/plugins/postgres/errors.mjs.map +1 -1
- package/dist/plugins/postgres/index.mjs +10 -17
- package/dist/plugins/postgres/index.mjs.map +1 -1
- package/dist/plugins/postgres/service.mjs +58 -24
- package/dist/plugins/postgres/service.mjs.map +1 -1
- package/dist/plugins/postgres/snapshot.mjs.map +1 -1
- package/dist/plugins/postgres/spans.mjs +11 -0
- package/dist/plugins/postgres/spans.mjs.map +1 -0
- package/dist/plugins/router-entrypoints.mjs +4 -4
- package/dist/plugins/router-entrypoints.mjs.map +1 -1
- package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs +15 -13
- package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs.map +1 -1
- package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs +15 -19
- package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs.map +1 -1
- package/dist/plugins/seal/codegen.d.mts +2 -3
- package/dist/plugins/seal/codegen.mjs.map +1 -1
- package/dist/plugins/seal/config-render.mjs +35 -8
- package/dist/plugins/seal/config-render.mjs.map +1 -1
- package/dist/plugins/seal/deploy.mjs +31 -39
- package/dist/plugins/seal/deploy.mjs.map +1 -1
- package/dist/plugins/seal/errors.d.mts +1 -3
- package/dist/plugins/seal/errors.mjs +7 -1
- package/dist/plugins/seal/errors.mjs.map +1 -1
- package/dist/plugins/seal/index.d.mts +1 -6
- package/dist/plugins/seal/index.mjs +40 -14
- package/dist/plugins/seal/index.mjs.map +1 -1
- package/dist/plugins/seal/key-manager.d.mts +1 -9
- package/dist/plugins/seal/key-manager.mjs +2 -18
- package/dist/plugins/seal/key-manager.mjs.map +1 -1
- package/dist/plugins/seal/key-server.mjs +37 -36
- package/dist/plugins/seal/key-server.mjs.map +1 -1
- package/dist/plugins/seal/keygen.mjs +16 -17
- package/dist/plugins/seal/keygen.mjs.map +1 -1
- package/dist/plugins/seal/mode/fork-known.mjs +36 -14
- package/dist/plugins/seal/mode/fork-known.mjs.map +1 -1
- package/dist/plugins/seal/mode/live.d.mts +6 -4
- package/dist/plugins/seal/mode/live.mjs +14 -21
- package/dist/plugins/seal/mode/live.mjs.map +1 -1
- package/dist/plugins/seal/mode/local-keygen.mjs +57 -21
- package/dist/plugins/seal/mode/local-keygen.mjs.map +1 -1
- package/dist/plugins/seal/registry-publish.mjs +1 -0
- package/dist/plugins/seal/registry-publish.mjs.map +1 -1
- package/dist/plugins/seal/routable.mjs.map +1 -1
- package/dist/plugins/seal/service.mjs.map +1 -1
- package/dist/plugins/seal/spans.mjs +18 -0
- package/dist/plugins/seal/spans.mjs.map +1 -0
- package/dist/plugins/sui/auto-tick.mjs +17 -23
- package/dist/plugins/sui/auto-tick.mjs.map +1 -1
- package/dist/plugins/sui/chain-build-container.mjs +18 -0
- package/dist/plugins/sui/chain-build-container.mjs.map +1 -0
- package/dist/plugins/sui/chain-probe.d.mts +5 -5
- package/dist/plugins/sui/chain-probe.mjs +28 -58
- package/dist/plugins/sui/chain-probe.mjs.map +1 -1
- package/dist/plugins/sui/codegen.mjs +26 -0
- package/dist/plugins/sui/codegen.mjs.map +1 -1
- package/dist/plugins/sui/errors.d.mts +2 -29
- package/dist/plugins/sui/errors.mjs +1 -3
- package/dist/plugins/sui/errors.mjs.map +1 -1
- package/dist/plugins/sui/fork-faucet-strategy.d.mts +1 -0
- package/dist/plugins/sui/fork-faucet-strategy.mjs +55 -0
- package/dist/plugins/sui/fork-faucet-strategy.mjs.map +1 -0
- package/dist/plugins/sui/fork-orchestration.d.mts +1 -0
- package/dist/plugins/sui/fork-orchestration.mjs +170 -2
- package/dist/plugins/sui/fork-orchestration.mjs.map +1 -1
- package/dist/plugins/sui/fork-transaction.d.mts +2 -0
- package/dist/plugins/sui/fork-transaction.mjs +92 -28
- package/dist/plugins/sui/fork-transaction.mjs.map +1 -1
- package/dist/plugins/sui/index.d.mts +33 -70
- package/dist/plugins/sui/index.mjs +58 -35
- package/dist/plugins/sui/index.mjs.map +1 -1
- package/dist/plugins/{faucet/strategies/sui-local.mjs → sui/local-faucet-strategy.mjs} +10 -7
- package/dist/plugins/sui/local-faucet-strategy.mjs.map +1 -0
- package/dist/plugins/sui/mode/external.mjs +7 -13
- package/dist/plugins/sui/mode/external.mjs.map +1 -1
- package/dist/plugins/sui/mode/fork.mjs +136 -59
- package/dist/plugins/sui/mode/fork.mjs.map +1 -1
- package/dist/plugins/sui/mode/live.mjs +10 -16
- package/dist/plugins/sui/mode/live.mjs.map +1 -1
- package/dist/plugins/sui/mode/local.mjs +37 -36
- package/dist/plugins/sui/mode/local.mjs.map +1 -1
- package/dist/plugins/sui/mode/shared-boot.mjs +38 -115
- package/dist/plugins/sui/mode/shared-boot.mjs.map +1 -1
- package/dist/plugins/sui/mode/shared.d.mts +1 -5
- package/dist/plugins/sui/mode/shared.mjs.map +1 -1
- package/dist/plugins/sui/mode/spec.d.mts +18 -0
- package/dist/plugins/sui/move-summary-runner.mjs +207 -0
- package/dist/plugins/sui/move-summary-runner.mjs.map +1 -0
- package/dist/plugins/sui/network-resolver.d.mts +4 -3
- package/dist/plugins/sui/service.mjs.map +1 -1
- package/dist/plugins/sui/snapshot.mjs +3 -0
- package/dist/plugins/sui/snapshot.mjs.map +1 -1
- package/dist/plugins/sui/spans.mjs +17 -0
- package/dist/plugins/sui/spans.mjs.map +1 -0
- package/dist/plugins/wallet/codegen.d.mts +0 -1
- package/dist/plugins/wallet/codegen.mjs +8 -9
- package/dist/plugins/wallet/codegen.mjs.map +1 -1
- package/dist/plugins/wallet/index.d.mts +6 -8
- package/dist/plugins/wallet/index.mjs +46 -35
- package/dist/plugins/wallet/index.mjs.map +1 -1
- package/dist/plugins/wallet/origin-policy.mjs +12 -28
- package/dist/plugins/wallet/origin-policy.mjs.map +1 -1
- package/dist/plugins/wallet/pairing.mjs +6 -4
- package/dist/plugins/wallet/pairing.mjs.map +1 -1
- package/dist/plugins/wallet/protocol.d.mts +1 -0
- package/dist/plugins/wallet/protocol.mjs +5 -44
- package/dist/plugins/wallet/protocol.mjs.map +1 -1
- package/dist/plugins/wallet/routable.mjs +2 -8
- package/dist/plugins/wallet/routable.mjs.map +1 -1
- package/dist/plugins/wallet/server.mjs +36 -44
- package/dist/plugins/wallet/server.mjs.map +1 -1
- package/dist/plugins/wallet/service.d.mts +1 -5
- package/dist/plugins/wallet/service.mjs +22 -18
- package/dist/plugins/wallet/service.mjs.map +1 -1
- package/dist/plugins/wallet/spans.mjs +22 -0
- package/dist/plugins/wallet/spans.mjs.map +1 -0
- package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs +33 -8
- package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs.map +1 -1
- package/dist/plugins/walrus/codegen.d.mts +3 -3
- package/dist/plugins/walrus/codegen.mjs.map +1 -1
- package/dist/plugins/walrus/deploy-paths.mjs +21 -5
- package/dist/plugins/walrus/deploy-paths.mjs.map +1 -1
- package/dist/plugins/walrus/deploy.mjs +67 -69
- package/dist/plugins/walrus/deploy.mjs.map +1 -1
- package/dist/plugins/walrus/errors.mjs +1 -0
- package/dist/plugins/walrus/errors.mjs.map +1 -1
- package/dist/plugins/walrus/faucet-strategy.mjs +12 -7
- package/dist/plugins/walrus/faucet-strategy.mjs.map +1 -1
- package/dist/plugins/walrus/index.d.mts +2 -13
- package/dist/plugins/walrus/index.mjs +18 -23
- package/dist/plugins/walrus/index.mjs.map +1 -1
- package/dist/plugins/walrus/mode/known-deploy.mjs +7 -5
- package/dist/plugins/walrus/mode/known-deploy.mjs.map +1 -1
- package/dist/plugins/walrus/mode/local-cluster.mjs +26 -7
- package/dist/plugins/walrus/mode/local-cluster.mjs.map +1 -1
- package/dist/plugins/walrus/registry-publish.mjs.map +1 -1
- package/dist/plugins/walrus/routable.mjs +7 -23
- package/dist/plugins/walrus/routable.mjs.map +1 -1
- package/dist/plugins/walrus/service.mjs.map +1 -1
- package/dist/plugins/walrus/spans.mjs +18 -0
- package/dist/plugins/walrus/spans.mjs.map +1 -0
- package/dist/plugins/walrus/storage-nodes.d.mts +6 -2
- package/dist/plugins/walrus/storage-nodes.mjs +15 -8
- package/dist/plugins/walrus/storage-nodes.mjs.map +1 -1
- package/dist/plugins/walrus/wal-swap.mjs +58 -15
- package/dist/plugins/walrus/wal-swap.mjs.map +1 -1
- package/dist/primitives/artifact-publisher.d.mts +1 -1
- package/dist/primitives/artifact-publisher.mjs +15 -0
- package/dist/primitives/artifact-publisher.mjs.map +1 -0
- package/dist/runtime/docker/client.mjs +17 -4
- package/dist/runtime/docker/client.mjs.map +1 -1
- package/dist/runtime/docker/container.mjs +219 -132
- package/dist/runtime/docker/container.mjs.map +1 -1
- package/dist/runtime/docker/errors.mjs +0 -6
- package/dist/runtime/docker/errors.mjs.map +1 -1
- package/dist/runtime/docker/exec.mjs +21 -18
- package/dist/runtime/docker/exec.mjs.map +1 -1
- package/dist/runtime/docker/image.mjs +36 -13
- package/dist/runtime/docker/image.mjs.map +1 -1
- package/dist/runtime/docker/index.mjs +14 -0
- package/dist/runtime/docker/inspect-and-decode.mjs +51 -0
- package/dist/runtime/docker/inspect-and-decode.mjs.map +1 -0
- package/dist/runtime/docker/inventory.mjs +14 -11
- package/dist/runtime/docker/inventory.mjs.map +1 -1
- package/dist/runtime/docker/labels.mjs +38 -5
- package/dist/runtime/docker/labels.mjs.map +1 -1
- package/dist/runtime/docker/logs.d.mts +1 -1
- package/dist/runtime/docker/logs.mjs.map +1 -1
- package/dist/runtime/docker/network.mjs +83 -47
- package/dist/runtime/docker/network.mjs.map +1 -1
- package/dist/runtime/docker/render-run-args.mjs +82 -0
- package/dist/runtime/docker/render-run-args.mjs.map +1 -0
- package/dist/runtime/docker/service.d.mts +1 -1
- package/dist/runtime/docker/service.mjs +12 -7
- package/dist/runtime/docker/service.mjs.map +1 -1
- package/dist/runtime/docker/sweep.mjs +118 -43
- package/dist/runtime/docker/sweep.mjs.map +1 -1
- package/dist/runtime/docker/volume.mjs +2 -0
- package/dist/runtime/docker/volume.mjs.map +1 -1
- package/dist/runtime/docker/wrap.mjs +30 -1
- package/dist/runtime/docker/wrap.mjs.map +1 -1
- package/dist/substrate/cross-process.mjs +14 -8
- package/dist/substrate/cross-process.mjs.map +1 -1
- package/dist/substrate/event-time.mjs +33 -0
- package/dist/substrate/event-time.mjs.map +1 -0
- package/dist/substrate/events.d.mts +28 -8
- package/dist/substrate/identity.d.mts +2 -1
- package/dist/substrate/manifest.d.mts +68 -5
- package/dist/substrate/manifest.mjs +34 -5
- package/dist/substrate/manifest.mjs.map +1 -1
- package/dist/substrate/network.d.mts +3 -5
- package/dist/substrate/options.d.mts +0 -2
- package/dist/substrate/plugin.d.mts +13 -0
- package/dist/substrate/plugin.mjs +4 -2
- package/dist/substrate/plugin.mjs.map +1 -1
- package/dist/substrate/projection.d.mts +35 -3
- package/dist/substrate/runtime/artifact-publisher/index.mjs +19 -9
- package/dist/substrate/runtime/artifact-publisher/index.mjs.map +1 -1
- package/dist/substrate/runtime/atomic-write.mjs +97 -32
- package/dist/substrate/runtime/atomic-write.mjs.map +1 -1
- package/dist/substrate/runtime/cache/index.mjs +3 -0
- package/dist/substrate/runtime/cache/schema.mjs +2 -2
- package/dist/substrate/runtime/cache/schema.mjs.map +1 -1
- package/dist/substrate/runtime/cache/service.mjs +9 -7
- package/dist/substrate/runtime/cache/service.mjs.map +1 -1
- package/dist/substrate/runtime/capability-sinks/index.d.mts +1 -1
- package/dist/substrate/runtime/capability-sinks/index.mjs +3 -0
- package/dist/substrate/runtime/capability-sinks/layer.mjs +1 -1
- package/dist/substrate/runtime/capability-sinks/service.d.mts +61 -2
- package/dist/substrate/runtime/capability-sinks/service.mjs +21 -26
- package/dist/substrate/runtime/capability-sinks/service.mjs.map +1 -1
- package/dist/substrate/runtime/config-validation.d.mts +1 -13
- package/dist/substrate/runtime/config-validation.mjs +2 -91
- package/dist/substrate/runtime/config-validation.mjs.map +1 -1
- package/dist/substrate/runtime/container-runtime.d.mts +1 -0
- package/dist/substrate/runtime/container-runtime.mjs +2 -0
- package/dist/substrate/runtime/control-plane/domain.mjs +101 -0
- package/dist/substrate/runtime/control-plane/domain.mjs.map +1 -0
- package/dist/substrate/runtime/control-plane/service.mjs +7 -0
- package/dist/substrate/runtime/control-plane/service.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/command-channel/channel.mjs +46 -19
- package/dist/substrate/runtime/cross-process/command-channel/channel.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs +30 -12
- package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/command-channel/index.mjs +5 -0
- package/dist/substrate/runtime/cross-process/command-channel/protocol.mjs +11 -2
- package/dist/substrate/runtime/cross-process/command-channel/protocol.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/command-channel/runtime-control-lock.mjs +1 -1
- package/dist/substrate/runtime/cross-process/index.mjs +11 -0
- package/dist/substrate/runtime/cross-process/live-clock.mjs +34 -0
- package/dist/substrate/runtime/cross-process/live-clock.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/liveness.mjs +52 -10
- package/dist/substrate/runtime/cross-process/liveness.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/lock.d.mts +1 -0
- package/dist/substrate/runtime/cross-process/lock.mjs +23 -0
- package/dist/substrate/runtime/cross-process/lock.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs +64 -0
- package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/roster.mjs +97 -83
- package/dist/substrate/runtime/cross-process/roster.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/self-pid.mjs +8 -0
- package/dist/substrate/runtime/cross-process/self-pid.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs +24 -28
- package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/stack-lock.mjs +41 -20
- package/dist/substrate/runtime/cross-process/stack-lock.mjs.map +1 -1
- package/dist/substrate/runtime/current-plugin.mjs +2 -2
- package/dist/substrate/runtime/current-plugin.mjs.map +1 -1
- package/dist/substrate/runtime/errors.mjs +12 -6
- package/dist/substrate/runtime/errors.mjs.map +1 -1
- package/dist/substrate/runtime/format-unknown-error.mjs +30 -0
- package/dist/substrate/runtime/format-unknown-error.mjs.map +1 -0
- package/dist/substrate/runtime/host-bind-mount-owner.mjs +10 -0
- package/dist/substrate/runtime/host-bind-mount-owner.mjs.map +1 -0
- package/dist/substrate/runtime/host-gateway.mjs +20 -0
- package/dist/substrate/runtime/host-gateway.mjs.map +1 -0
- package/dist/substrate/runtime/host-tree-tar/index.mjs +61 -50
- package/dist/substrate/runtime/host-tree-tar/index.mjs.map +1 -1
- package/dist/substrate/runtime/http-probe.d.mts +1 -1
- package/dist/substrate/runtime/index.mjs +14 -0
- package/dist/substrate/runtime/lease-broker/index.d.mts +1 -1
- package/dist/substrate/runtime/lease-broker/index.mjs +2 -0
- package/dist/substrate/runtime/lease-broker/service.d.mts +1 -64
- package/dist/substrate/runtime/lease-broker/service.mjs +1 -1
- package/dist/substrate/runtime/lease-broker/service.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/dep-graph.mjs +22 -3
- package/dist/substrate/runtime/lifecycle/dep-graph.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/index.mjs +9 -0
- package/dist/substrate/runtime/lifecycle/lifecycle-fact.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/plugin-registry.mjs +20 -3
- package/dist/substrate/runtime/lifecycle/plugin-registry.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/selective-restart.mjs +1 -1
- package/dist/substrate/runtime/lifecycle/signals.mjs +5 -5
- package/dist/substrate/runtime/lifecycle/signals.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/state-machine.mjs +1 -1
- package/dist/substrate/runtime/managed-container.d.mts +19 -1
- package/dist/substrate/runtime/managed-container.mjs +20 -1
- package/dist/substrate/runtime/managed-container.mjs.map +1 -1
- package/dist/substrate/runtime/manifest/index.mjs +3 -0
- package/dist/substrate/runtime/manifest/manifest.mjs +15 -11
- package/dist/substrate/runtime/manifest/manifest.mjs.map +1 -1
- package/dist/substrate/runtime/mode-errors.mjs +20 -0
- package/dist/substrate/runtime/mode-errors.mjs.map +1 -0
- package/dist/substrate/runtime/observability/cascade-formatter.mjs +9 -13
- package/dist/substrate/runtime/observability/cascade-formatter.mjs.map +1 -1
- package/dist/substrate/runtime/observability/formatter-registry.mjs +19 -36
- package/dist/substrate/runtime/observability/formatter-registry.mjs.map +1 -1
- package/dist/substrate/runtime/observability/ignore-with-log.d.mts +1 -0
- package/dist/substrate/runtime/observability/ignore-with-log.mjs +17 -0
- package/dist/substrate/runtime/observability/ignore-with-log.mjs.map +1 -0
- package/dist/substrate/runtime/observability/index.d.mts +1 -1
- package/dist/substrate/runtime/observability/index.mjs +13 -0
- package/dist/substrate/runtime/observability/log-store.d.mts +1 -0
- package/dist/substrate/runtime/observability/log-store.mjs +175 -0
- package/dist/substrate/runtime/observability/log-store.mjs.map +1 -0
- package/dist/substrate/runtime/observability/logger.d.mts +2 -1
- package/dist/substrate/runtime/observability/logger.mjs +5 -9
- package/dist/substrate/runtime/observability/logger.mjs.map +1 -1
- package/dist/substrate/runtime/observability/output-truncate.mjs +35 -0
- package/dist/substrate/runtime/observability/output-truncate.mjs.map +1 -0
- package/dist/substrate/runtime/observability/pretty-error.mjs +9 -12
- package/dist/substrate/runtime/observability/pretty-error.mjs.map +1 -1
- package/dist/substrate/runtime/observability/redaction.d.mts +2 -13
- package/dist/substrate/runtime/observability/redaction.mjs +8 -14
- package/dist/substrate/runtime/observability/redaction.mjs.map +1 -1
- package/dist/substrate/runtime/observability/span-store.d.mts +1 -0
- package/dist/substrate/runtime/observability/span-store.mjs +110 -0
- package/dist/substrate/runtime/observability/span-store.mjs.map +1 -0
- package/dist/substrate/runtime/observability/spans.mjs +14 -14
- package/dist/substrate/runtime/observability/spans.mjs.map +1 -1
- package/dist/substrate/runtime/observability/subprocess-capture.mjs +1 -1
- package/dist/substrate/runtime/passthrough-or-wrap.mjs +33 -0
- package/dist/substrate/runtime/passthrough-or-wrap.mjs.map +1 -0
- package/dist/substrate/runtime/paths.d.mts +1 -1
- package/dist/substrate/runtime/paths.mjs +4 -3
- package/dist/substrate/runtime/paths.mjs.map +1 -1
- package/dist/substrate/runtime/phase-preserving-produce.mjs +40 -0
- package/dist/substrate/runtime/phase-preserving-produce.mjs.map +1 -0
- package/dist/substrate/runtime/port-broker/index.mjs +3 -0
- package/dist/substrate/runtime/port-broker/service.mjs +170 -126
- package/dist/substrate/runtime/port-broker/service.mjs.map +1 -1
- package/dist/substrate/runtime/post-acquire-tasks.mjs +1 -1
- package/dist/substrate/runtime/post-acquire-tasks.mjs.map +1 -1
- package/dist/substrate/runtime/probes.d.mts +7 -5
- package/dist/substrate/runtime/probes.mjs +3 -1
- package/dist/substrate/runtime/probes.mjs.map +1 -1
- package/dist/substrate/runtime/projection/index.mjs +4 -0
- package/dist/substrate/runtime/projection/operational-endpoints.mjs +1 -2
- package/dist/substrate/runtime/projection/operational-endpoints.mjs.map +1 -1
- package/dist/substrate/runtime/projection/persisted.mjs +33 -15
- package/dist/substrate/runtime/projection/persisted.mjs.map +1 -1
- package/dist/substrate/runtime/projection/state-ref.mjs +26 -2
- package/dist/substrate/runtime/projection/state-ref.mjs.map +1 -1
- package/dist/substrate/runtime/projection/update.mjs +88 -24
- package/dist/substrate/runtime/projection/update.mjs.map +1 -1
- package/dist/substrate/runtime/random-suffix.mjs +11 -0
- package/dist/substrate/runtime/random-suffix.mjs.map +1 -0
- package/dist/substrate/runtime/retry-policy.d.mts +59 -1
- package/dist/substrate/runtime/retry-policy.mjs +66 -1
- package/dist/substrate/runtime/retry-policy.mjs.map +1 -1
- package/dist/substrate/runtime/routed-url.d.mts +1 -0
- package/dist/substrate/runtime/routed-url.mjs +79 -0
- package/dist/substrate/runtime/routed-url.mjs.map +1 -0
- package/dist/substrate/runtime/runtime-decode.d.mts +1 -1
- package/dist/substrate/runtime/runtime-decode.mjs.map +1 -1
- package/dist/substrate/runtime/scoped-http-server.mjs +2 -3
- package/dist/substrate/runtime/scoped-http-server.mjs.map +1 -1
- package/dist/substrate/runtime/scoped-multimap/index.mjs +2 -0
- package/dist/substrate/runtime/scoped-multimap/service.mjs +52 -0
- package/dist/substrate/runtime/scoped-multimap/service.mjs.map +1 -0
- package/dist/substrate/runtime/scoped-ref-map/index.mjs +2 -0
- package/dist/substrate/runtime/scoped-ref-map/service.mjs +2 -2
- package/dist/substrate/runtime/scoped-ref-map/service.mjs.map +1 -1
- package/dist/substrate/runtime/stage-and-swap/index.mjs +72 -4
- package/dist/substrate/runtime/stage-and-swap/index.mjs.map +1 -1
- package/dist/substrate/runtime/state-store/index.d.mts +1 -0
- package/dist/substrate/runtime/state-store/index.mjs +3 -0
- package/dist/substrate/runtime/state-store/schema.d.mts +1 -0
- package/dist/substrate/runtime/state-store/schema.mjs +19 -14
- package/dist/substrate/runtime/state-store/schema.mjs.map +1 -1
- package/dist/substrate/runtime/state-store/service.d.mts +1 -0
- package/dist/substrate/runtime/state-store/service.mjs +145 -0
- package/dist/substrate/runtime/state-store/service.mjs.map +1 -0
- package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.d.mts +1 -0
- package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.mjs +33 -0
- package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.mjs.map +1 -0
- package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs +1 -1
- package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs.map +1 -1
- package/dist/substrate/runtime/strategy-registry/index.mjs +4 -0
- package/dist/substrate/runtime/strategy-registry/service.mjs +19 -33
- package/dist/substrate/runtime/strategy-registry/service.mjs.map +1 -1
- package/dist/substrate/runtime/subnet-broker.mjs +60 -0
- package/dist/substrate/runtime/subnet-broker.mjs.map +1 -0
- package/dist/substrate/runtime/sui-execute/index.d.mts +21 -1
- package/dist/substrate/runtime/sui-execute/index.mjs +84 -20
- package/dist/substrate/runtime/sui-execute/index.mjs.map +1 -1
- package/dist/substrate/runtime/sui-execute/sign-and-dispatch.d.mts +1 -0
- package/dist/substrate/runtime/sui-execute/sign-and-dispatch.mjs +32 -0
- package/dist/substrate/runtime/sui-execute/sign-and-dispatch.mjs.map +1 -0
- package/dist/substrate/runtime/sui-ledger/object-ref.mjs +32 -0
- package/dist/substrate/runtime/sui-ledger/object-ref.mjs.map +1 -0
- package/dist/substrate/runtime/sui-move-build/index.mjs +93 -19
- package/dist/substrate/runtime/sui-move-build/index.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/acquire-node.mjs +181 -0
- package/dist/substrate/runtime/supervisor/acquire-node.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/background-tasks.mjs +144 -0
- package/dist/substrate/runtime/supervisor/background-tasks.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/command-loop.mjs +68 -0
- package/dist/substrate/runtime/supervisor/command-loop.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs +151 -0
- package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/errors.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/errors.mjs +9 -0
- package/dist/substrate/runtime/supervisor/errors.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/index.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/index.mjs +3 -0
- package/dist/substrate/runtime/supervisor/shutdown.mjs +51 -0
- package/dist/substrate/runtime/supervisor/shutdown.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/start-supervisor.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/start-supervisor.mjs +250 -0
- package/dist/substrate/runtime/supervisor/start-supervisor.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/state.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/state.mjs +22 -0
- package/dist/substrate/runtime/supervisor/state.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/teardown.mjs +57 -0
- package/dist/substrate/runtime/supervisor/teardown.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/types.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/wiring.mjs +133 -0
- package/dist/substrate/runtime/supervisor/wiring.mjs.map +1 -0
- package/dist/substrate/runtime/typed-env.mjs +8 -0
- package/dist/substrate/runtime/typed-env.mjs.map +1 -0
- package/dist/substrate/state-store.d.mts +1 -0
- package/dist/substrate/versioned-doc-schema.mjs +17 -0
- package/dist/substrate/versioned-doc-schema.mjs.map +1 -0
- package/dist/substrate/versioned-doc-sync.mjs +94 -0
- package/dist/substrate/versioned-doc-sync.mjs.map +1 -0
- package/dist/surfaces/cli/command-tree.mjs.map +1 -1
- package/dist/surfaces/cli/commands/index.mjs +9 -0
- package/dist/surfaces/cli/commands/prune-picker-entry.mjs +13 -0
- package/dist/surfaces/cli/commands/prune-picker-entry.mjs.map +1 -0
- package/dist/surfaces/cli/commands/prune-picker.mjs +3 -2
- package/dist/surfaces/cli/commands/prune-picker.mjs.map +1 -1
- package/dist/surfaces/cli/commands/prune.mjs +34 -17
- package/dist/surfaces/cli/commands/prune.mjs.map +1 -1
- package/dist/surfaces/cli/commands/status.mjs +2 -2
- package/dist/surfaces/cli/commands/status.mjs.map +1 -1
- package/dist/surfaces/cli/commands/supervisor-presence.mjs +5 -3
- package/dist/surfaces/cli/commands/supervisor-presence.mjs.map +1 -1
- package/dist/surfaces/cli/commands/wipe.mjs +38 -4
- package/dist/surfaces/cli/commands/wipe.mjs.map +1 -1
- package/dist/surfaces/cli/errors.mjs +1 -1
- package/dist/surfaces/cli/errors.mjs.map +1 -1
- package/dist/surfaces/cli/flags.mjs +0 -1
- package/dist/surfaces/cli/flags.mjs.map +1 -1
- package/dist/surfaces/cli/index.mjs +98 -18
- package/dist/surfaces/cli/index.mjs.map +1 -1
- package/dist/surfaces/cli/output.mjs +1 -0
- package/dist/surfaces/cli/output.mjs.map +1 -1
- package/dist/surfaces/cli/sysexits.mjs +2 -1
- package/dist/surfaces/cli/sysexits.mjs.map +1 -1
- package/dist/surfaces/tui/app.mjs +25 -3
- package/dist/surfaces/tui/app.mjs.map +1 -1
- package/dist/surfaces/tui/display-derivation.mjs +23 -74
- package/dist/surfaces/tui/display-derivation.mjs.map +1 -1
- package/dist/surfaces/tui/event-log.mjs +35 -23
- package/dist/surfaces/tui/event-log.mjs.map +1 -1
- package/dist/surfaces/tui/input.mjs +5 -1
- package/dist/surfaces/tui/input.mjs.map +1 -1
- package/dist/surfaces/tui/plain-renderer.mjs +70 -34
- package/dist/surfaces/tui/plain-renderer.mjs.map +1 -1
- package/package.json +24 -4
- package/dist/contracts/liveness-classifier.d.mts +0 -19
- package/dist/contracts/network-resolver.d.mts +0 -15
- package/dist/contracts/network-resolver.mjs +0 -7
- package/dist/contracts/network-resolver.mjs.map +0 -1
- package/dist/orchestrators/codegen/extras.mjs +0 -16
- package/dist/orchestrators/codegen/extras.mjs.map +0 -1
- package/dist/plugins/deepbook/routable.mjs +0 -21
- package/dist/plugins/deepbook/routable.mjs.map +0 -1
- package/dist/plugins/faucet/service.d.mts +0 -20
- package/dist/plugins/faucet/strategies/sui-local.d.mts +0 -23
- package/dist/plugins/faucet/strategies/sui-local.mjs.map +0 -1
- package/dist/plugins/sui/seed-objects.d.mts +0 -18
- package/dist/plugins/sui/seed-objects.mjs +0 -25
- package/dist/plugins/sui/seed-objects.mjs.map +0 -1
- package/dist/runtime/built-in-plugin-layers.mjs.map +0 -1
- package/dist/substrate/runtime/context-helpers.mjs +0 -32
- package/dist/substrate/runtime/context-helpers.mjs.map +0 -1
- package/dist/substrate/runtime/run.mjs.map +0 -1
- package/dist/substrate/runtime/strategy-registry/faucet-capability-for.mjs +0 -30
- package/dist/substrate/runtime/strategy-registry/faucet-capability-for.mjs.map +0 -1
- package/dist/substrate/runtime/supervisor.d.mts +0 -1
- package/dist/substrate/runtime/supervisor.mjs +0 -831
- package/dist/substrate/runtime/supervisor.mjs.map +0 -1
- package/dist/surfaces/cli/commands/doctor-probes.mjs.map +0 -1
- /package/dist/{substrate/runtime/strategy-registry/faucet-capability-for.d.mts → plugins/faucet/http.d.mts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container.mjs","names":[],"sources":["../../../src/runtime/docker/container.ts"],"sourcesContent":["// Container lifecycle state machine.\n//\n// Architecture § Lifecycle states. The (missing | running-match |\n// running-mismatch | stopped-clean | stopped-unclean | stopped-\n// mismatch) input states map to (adopt | resume | recreate | fresh)\n// actions. The output handle is the running container.\n//\n// Architecture invariants encoded here:\n//\n// §1 Name-atomic create — `docker create --name <stable>` collision\n// triggers `docker start <name>` adopt-fallback (single shot;\n// second collision = typed failure, no infinite loop).\n// §2 Label-driven inventory — we use `docker container inspect <name>`\n// for the single-container probe path (cheaper than label-filtered\n// `ps`, and type-specific when container/network names collide), but\n// the labels are still STAMPED on create so sweep can find us by\n// labels later.\n// §5 Async network-connect — `network.ts::waitForIp` is called\n// after attach and before we declare ready.\n// §9 RecreatePolicy enum routed in — `never` refuses to recreate;\n// `on-failure` recreates on unclean shutdown + image mismatch;\n// `on-config-change` recreates on image mismatch, port mismatch,\n// or caller-supplied config hash mismatch.\n\nimport { Deferred, Effect, Ref, Scope, Schema } from 'effect';\n\nimport type {\n\tContainerHandle,\n\tContainerPortPublish,\n\tEnsureContainerSpec,\n\tPortBindingReconciliation,\n\tRecreatePolicy,\n} from '../../contracts/container-runtime.ts';\nimport { addClaim, removeClaim } from '../../substrate/runtime/cross-process/roster.ts';\nimport { StackPathsService } from '../../substrate/runtime/paths.ts';\nimport { decodeJsonArrayElementSync } from '../../substrate/runtime/runtime-decode.ts';\nimport { DockerHost, DockerSpawner, dockerRun, dockerRunOk } from './client.ts';\nimport {\n\tContainerCreateFailed,\n\tContainerNameCollisionUnrecoverable,\n\tDaemonUnreachable,\n\tDockerInspectDecodeFailed,\n\tDockerInspectFailed,\n\ttype DockerRuntimeError,\n\tForeignDockerResource,\n\tRecreateRefused,\n} from './errors.ts';\nimport {\n\texpectedContainerOwnershipLabels,\n\tLabelKey,\n\townershipMismatchDetail,\n\trenderContainerLabels,\n} from './labels.ts';\nimport { connect, readIps, waitForIp } from './network.ts';\nimport {\n\tclassifyExit,\n\tisDaemonUnreachableStderr,\n\tisNameCollisionStderr,\n\tisNoSuchContainerStderr,\n\twrapCreateError,\n\twrapGeneric,\n} from './wrap.ts';\n\n// -----------------------------------------------------------------------------\n// State machine — pure decision (testable independently)\n// -----------------------------------------------------------------------------\n\nexport type InspectLifecycleState =\n\t| { readonly kind: 'running'; readonly exitCode: number }\n\t| { readonly kind: 'paused'; readonly exitCode: number }\n\t| { readonly kind: 'stopped'; readonly exitCode: number }\n\t| { readonly kind: 'unknown' };\n\n/** What `docker container inspect <name>` told us. Lifecycle facts are explicit:\n * Docker may omit `State`, and absence means we cannot prove running,\n * paused, or stopped state. */\nexport interface InspectFacts {\n\treadonly id: string;\n\treadonly lifecycle: InspectLifecycleState;\n\treadonly running: boolean;\n\treadonly paused: boolean;\n\treadonly exitCode: number | null;\n\t/** Create-time image ref recorded by Docker. For tagged builds this is\n\t * usually the tag passed to `docker run`. */\n\treadonly image: string;\n\t/** Resolved image id from Docker inspect's top-level `Image` field. */\n\treadonly imageDigest?: string;\n\treadonly mounts?: ReadonlyArray<InspectMount>;\n\treadonly portBindings?: ReadonlyArray<string>;\n\treadonly ports?: ReadonlyArray<ContainerPortPublish>;\n\treadonly effectivePortBindings?: ReadonlyArray<string>;\n\treadonly effectivePorts?: ReadonlyArray<ContainerPortPublish>;\n\treadonly command?: ReadonlyArray<string>;\n\treadonly labels?: Readonly<Record<string, string>>;\n\treadonly networks?: ReadonlyArray<string>;\n}\n\nexport interface InspectMount {\n\treadonly source: string;\n\treadonly target: string;\n\treadonly readOnly?: boolean;\n}\n\n/** The closed set of actions the state machine can decide. */\nexport type RunAction =\n\t| { readonly kind: 'adopt'; readonly id: string }\n\t| { readonly kind: 'unpause-adopt'; readonly id: string }\n\t| { readonly kind: 'resume'; readonly id: string }\n\t| { readonly kind: 'recreate'; readonly id: string; readonly reason: RecreateReason }\n\t| { readonly kind: 'fresh' }\n\t| { readonly kind: 'refuse'; readonly reason: RecreateReason };\n\nexport type RecreateReason =\n\t| 'image-mismatch'\n\t| 'config-mismatch'\n\t| 'unclean-shutdown'\n\t| 'resume-failed'\n\t| 'unknown-state';\n\n/** Pure decision: given the inspect facts (or null = missing), the\n * desired image + host port bindings, and the policy, what action\n * do we take?\n *\n * Tested directly without the subprocess seam. */\nexport const decideRunAction = (\n\tfacts: InspectFacts | null,\n\tdesiredImage: string,\n\tpolicy: RecreatePolicy,\n\tdesiredPortBindings: ReadonlyArray<string> = [],\n\tportBindingReconciliation: PortBindingReconciliation = 'exact',\n\tdesiredConfigHash?: string,\n\tdesiredImageDigest?: string,\n): RunAction => {\n\tif (facts === null) return { kind: 'fresh' };\n\tconst imageMatches =\n\t\tfacts.image === desiredImage ||\n\t\t(desiredImageDigest !== undefined &&\n\t\t\t(facts.image === desiredImageDigest || facts.imageDigest === desiredImageDigest));\n\tconst portsMatch = sameBindings(facts.portBindings ?? [], desiredPortBindings);\n\tconst portsCompatible =\n\t\tportsMatch ||\n\t\t(portBindingReconciliation === 'adopt-existing' &&\n\t\t\tsameBindingContainerPorts(facts.portBindings ?? [], desiredPortBindings));\n\tconst configMatches =\n\t\tdesiredConfigHash === undefined || facts.labels?.[LabelKey.configHash] === desiredConfigHash;\n\tif (facts.lifecycle.kind === 'unknown') {\n\t\treturn routeRecreate({ kind: 'recreate', id: facts.id, reason: 'unknown-state' }, policy);\n\t}\n\tif (facts.lifecycle.kind === 'paused') {\n\t\treturn imageMatches && portsCompatible && configMatches\n\t\t\t? { kind: 'unpause-adopt', id: facts.id }\n\t\t\t: routeRecreate(\n\t\t\t\t\t{\n\t\t\t\t\t\tkind: 'recreate',\n\t\t\t\t\t\tid: facts.id,\n\t\t\t\t\t\treason: imageMatches ? 'config-mismatch' : 'image-mismatch',\n\t\t\t\t\t},\n\t\t\t\t\tpolicy,\n\t\t\t\t);\n\t}\n\tif (facts.lifecycle.kind === 'running') {\n\t\treturn imageMatches && portsCompatible && configMatches\n\t\t\t? { kind: 'adopt', id: facts.id }\n\t\t\t: routeRecreate(\n\t\t\t\t\t{\n\t\t\t\t\t\tkind: 'recreate',\n\t\t\t\t\t\tid: facts.id,\n\t\t\t\t\t\treason: imageMatches ? 'config-mismatch' : 'image-mismatch',\n\t\t\t\t\t},\n\t\t\t\t\tpolicy,\n\t\t\t\t);\n\t}\n\tif (!imageMatches) {\n\t\t// Image mismatch ALWAYS wins (architecture §11).\n\t\treturn routeRecreate({ kind: 'recreate', id: facts.id, reason: 'image-mismatch' }, policy);\n\t}\n\tif (!portsCompatible) {\n\t\treturn routeRecreate({ kind: 'recreate', id: facts.id, reason: 'config-mismatch' }, policy);\n\t}\n\tif (!configMatches) {\n\t\treturn routeRecreate({ kind: 'recreate', id: facts.id, reason: 'config-mismatch' }, policy);\n\t}\n\tif (facts.lifecycle.exitCode === 137) {\n\t\t// Unclean shutdown — see architecture §G1 / §13.\n\t\t// `on-failure`: recreate. `never`: refuse. `on-config-change`:\n\t\t// resume — caller wants stopped container kept until config\n\t\t// changes, even if the prior exit was unclean.\n\t\tif (policy === 'on-failure') {\n\t\t\treturn { kind: 'recreate', id: facts.id, reason: 'unclean-shutdown' };\n\t\t}\n\t\tif (policy === 'never') {\n\t\t\treturn { kind: 'refuse', reason: 'unclean-shutdown' };\n\t\t}\n\t\treturn { kind: 'resume', id: facts.id };\n\t}\n\treturn { kind: 'resume', id: facts.id };\n};\n\n/** Route a recreate-class decision through the policy. */\nconst routeRecreate = (\n\taction: RunAction & { kind: 'recreate' },\n\tpolicy: RecreatePolicy,\n): RunAction => {\n\tif (policy === 'never') return { kind: 'refuse', reason: action.reason };\n\treturn action;\n};\n\nconst canonicalPortBindings = (\n\tports: ReadonlyArray<ContainerPortPublish> | undefined,\n): ReadonlyArray<string> =>\n\t[...(ports ?? [])]\n\t\t.map((p) => `${p.containerPort}/tcp=${normalizeHostIp(p.hostIp)}:${p.hostPort}`)\n\t\t.sort();\n\nconst sameBindings = (left: ReadonlyArray<string>, right: ReadonlyArray<string>): boolean =>\n\tleft.length === right.length && left.every((value, index) => value === right[index]);\n\nconst sameBindingContainerPorts = (\n\tleft: ReadonlyArray<string>,\n\tright: ReadonlyArray<string>,\n): boolean => {\n\tconst leftContainers = left.map(bindingContainerKey).sort();\n\tconst rightContainers = right.map(bindingContainerKey).sort();\n\treturn sameBindings(leftContainers, rightContainers);\n};\n\nconst bindingContainerKey = (binding: string): string => binding.split('=')[0] ?? binding;\n\nconst normalizeHostIp = (hostIp: string | undefined): string =>\n\thostIp === undefined || hostIp === '' ? '0.0.0.0' : hostIp;\n\nconst readPublishedPorts = (raw: unknown): ReadonlyArray<ContainerPortPublish> => {\n\tif (raw === null || typeof raw !== 'object') return [];\n\tconst out: ContainerPortPublish[] = [];\n\tfor (const [container, bindings] of Object.entries(raw)) {\n\t\tconst containerPort = Number(container.split('/')[0]);\n\t\tif (!Number.isInteger(containerPort) || containerPort <= 0) continue;\n\t\tif (!Array.isArray(bindings)) continue;\n\t\tfor (const binding of bindings) {\n\t\t\tif (binding === null || typeof binding !== 'object') continue;\n\t\t\tconst hostPort = (binding as { HostPort?: unknown }).HostPort;\n\t\t\tif (typeof hostPort !== 'string') continue;\n\t\t\tconst hostPortNumber = Number(hostPort);\n\t\t\tif (!Number.isInteger(hostPortNumber) || hostPortNumber <= 0) continue;\n\t\t\tconst hostIp = (binding as { HostIp?: unknown }).HostIp;\n\t\t\tout.push({\n\t\t\t\tcontainerPort,\n\t\t\t\thostPort: hostPortNumber,\n\t\t\t\t...(typeof hostIp === 'string' ? { hostIp: normalizeHostIp(hostIp) } : {}),\n\t\t\t});\n\t\t}\n\t}\n\treturn out.sort((a, b) => {\n\t\tif (a.containerPort !== b.containerPort) return a.containerPort - b.containerPort;\n\t\tconst hostIp = normalizeHostIp(a.hostIp).localeCompare(normalizeHostIp(b.hostIp));\n\t\treturn hostIp !== 0 ? hostIp : a.hostPort - b.hostPort;\n\t});\n};\n\nconst readMounts = (raw: unknown): ReadonlyArray<InspectMount> => {\n\tif (!Array.isArray(raw)) return [];\n\tconst out: InspectMount[] = [];\n\tfor (const mount of raw) {\n\t\tif (mount === null || typeof mount !== 'object') continue;\n\t\tconst source = (mount as { Source?: unknown }).Source;\n\t\tconst target = (mount as { Destination?: unknown }).Destination;\n\t\tif (typeof source !== 'string' || typeof target !== 'string') continue;\n\t\tconst rw = (mount as { RW?: unknown }).RW;\n\t\tout.push({\n\t\t\tsource,\n\t\t\ttarget,\n\t\t\t...(typeof rw === 'boolean' ? { readOnly: !rw } : {}),\n\t\t});\n\t}\n\treturn out;\n};\n\nconst readStringArray = (raw: unknown): ReadonlyArray<string> => {\n\tif (!Array.isArray(raw)) return [];\n\treturn raw.filter((value): value is string => typeof value === 'string');\n};\n\nconst readLabels = (raw: unknown): Readonly<Record<string, string>> => {\n\tif (raw === null || typeof raw !== 'object') return {};\n\tconst out: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(raw)) {\n\t\tif (typeof value === 'string') out[key] = value;\n\t}\n\treturn out;\n};\n\nconst readNetworks = (raw: unknown): ReadonlyArray<string> => {\n\tif (raw === null || typeof raw !== 'object') return [];\n\treturn Object.keys(raw).sort();\n};\n\nconst readLifecycleState = (\n\tstate:\n\t\t| {\n\t\t\t\treadonly Running: boolean;\n\t\t\t\treadonly Paused: boolean;\n\t\t\t\treadonly ExitCode: number;\n\t\t }\n\t\t| undefined,\n): InspectLifecycleState => {\n\tif (state === undefined) return { kind: 'unknown' };\n\tif (state.Paused) return { kind: 'paused', exitCode: state.ExitCode };\n\tif (state.Running) return { kind: 'running', exitCode: state.ExitCode };\n\treturn { kind: 'stopped', exitCode: state.ExitCode };\n};\n\n// -----------------------------------------------------------------------------\n// Inspect — `docker container inspect <name>`\n// -----------------------------------------------------------------------------\n\nconst InspectSchema = Schema.Struct({\n\tId: Schema.String,\n\tImage: Schema.optional(Schema.String),\n\tMounts: Schema.optional(Schema.Unknown),\n\tHostConfig: Schema.optional(\n\t\tSchema.Struct({\n\t\t\tPortBindings: Schema.Unknown,\n\t\t}),\n\t),\n\tState: Schema.optional(\n\t\tSchema.Struct({\n\t\t\tRunning: Schema.Boolean,\n\t\t\tPaused: Schema.Boolean,\n\t\t\tExitCode: Schema.Number,\n\t\t}),\n\t),\n\tConfig: Schema.Struct({\n\t\tImage: Schema.String,\n\t\tCmd: Schema.optional(Schema.Unknown),\n\t\tLabels: Schema.optional(Schema.Unknown),\n\t}),\n\tNetworkSettings: Schema.Struct({\n\t\tNetworks: Schema.Unknown,\n\t\tPorts: Schema.optional(Schema.Unknown),\n\t}),\n});\n\nexport const inspectContainer = (\n\tname: string,\n): Effect.Effect<InspectFacts | null, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst res = yield* dockerRunOk('container', ['inspect', name]).pipe(\n\t\t\tEffect.mapError(wrapGeneric('docker.container.inspect')),\n\t\t);\n\t\tif (res.exitCode !== 0) {\n\t\t\tif (isNoSuchContainerStderr(res.stderr)) return null;\n\t\t\tif (isDaemonUnreachableStderr(res.stderr)) {\n\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\tnew DaemonUnreachable({\n\t\t\t\t\t\top: 'docker.container.inspect',\n\t\t\t\t\t\tdetail: 'docker daemon unreachable',\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew DockerInspectFailed({\n\t\t\t\t\tresource: 'container',\n\t\t\t\t\tname,\n\t\t\t\t\tstderr: res.stderr,\n\t\t\t\t\texitCode: res.exitCode,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\ttry {\n\t\t\tconst decoded = decodeJsonArrayElementSync(InspectSchema, res.stdout, {\n\t\t\t\tsource: `docker container inspect ${name}`,\n\t\t\t\tmissingMessage: 'inspect returned an empty result',\n\t\t\t\tmkError: (issue) =>\n\t\t\t\t\tnew DockerInspectDecodeFailed({\n\t\t\t\t\t\tresource: 'container',\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdetail:\n\t\t\t\t\t\t\tissue.message === 'inspect returned an empty result'\n\t\t\t\t\t\t\t\t? issue.message\n\t\t\t\t\t\t\t\t: 'inspect returned malformed container JSON',\n\t\t\t\t\t\tcause: issue.cause,\n\t\t\t\t\t}),\n\t\t\t});\n\t\t\tconst lifecycle = readLifecycleState(decoded.State);\n\t\t\tconst effectivePorts = readPublishedPorts(decoded.NetworkSettings.Ports);\n\t\t\tconst ports =\n\t\t\t\tdecoded.HostConfig === undefined\n\t\t\t\t\t? effectivePorts\n\t\t\t\t\t: readPublishedPorts(decoded.HostConfig.PortBindings);\n\t\t\tconst mounts = readMounts(decoded.Mounts);\n\t\t\tconst command = readStringArray(decoded.Config.Cmd);\n\t\t\tconst labels = readLabels(decoded.Config.Labels);\n\t\t\tconst networks = readNetworks(decoded.NetworkSettings.Networks);\n\t\t\treturn {\n\t\t\t\tid: decoded.Id,\n\t\t\t\tlifecycle,\n\t\t\t\trunning: lifecycle.kind === 'running' || lifecycle.kind === 'paused',\n\t\t\t\tpaused: lifecycle.kind === 'paused',\n\t\t\t\texitCode: lifecycle.kind === 'unknown' ? null : lifecycle.exitCode,\n\t\t\t\t// The container's recorded image. Docker may omit the\n\t\t\t\t// top-level digest field, but lifecycle decisions need the\n\t\t\t\t// create-time ref from Config.Image.\n\t\t\t\timage: decoded.Config.Image,\n\t\t\t\t...(decoded.Image !== undefined ? { imageDigest: decoded.Image } : {}),\n\t\t\t\tmounts,\n\t\t\t\tportBindings: canonicalPortBindings(ports),\n\t\t\t\tports,\n\t\t\t\teffectivePortBindings: canonicalPortBindings(effectivePorts),\n\t\t\t\teffectivePorts,\n\t\t\t\tcommand,\n\t\t\t\tlabels,\n\t\t\t\tnetworks,\n\t\t\t};\n\t\t} catch (cause) {\n\t\t\treturn yield* Effect.fail(cause as DockerRuntimeError);\n\t\t}\n\t}).pipe(Effect.withSpan('runtime.docker.container.inspect'));\n\n// -----------------------------------------------------------------------------\n// Argv construction\n// -----------------------------------------------------------------------------\n\nconst createArgv = (\n\tspec: EnsureContainerSpec,\n\tcycle: number,\n\timageRef: string,\n): ReadonlyArray<string> => {\n\tconst args: Array<string> = ['-d', '--name', spec.name];\n\tconst configLabels: Readonly<Record<string, string>> | undefined =\n\t\tspec.configHash === undefined ? undefined : { [LabelKey.configHash]: spec.configHash };\n\tfor (const label of renderContainerLabels(spec.labels, cycle, configLabels)) {\n\t\targs.push('--label', label);\n\t}\n\tif (spec.env) {\n\t\tfor (const [k, v] of Object.entries(spec.env)) {\n\t\t\targs.push('--env', `${k}=${v}`);\n\t\t}\n\t}\n\tif (spec.ports) {\n\t\tfor (const p of spec.ports) {\n\t\t\tconst hostPrefix = p.hostIp === undefined ? '' : `${p.hostIp}:`;\n\t\t\targs.push('-p', `${hostPrefix}${p.hostPort}:${p.containerPort}`);\n\t\t}\n\t}\n\tif (spec.mounts) {\n\t\tfor (const m of spec.mounts) {\n\t\t\tconst ro = m.readonly ? ',readonly' : '';\n\t\t\targs.push('--mount', `type=bind,source=${m.source},target=${m.target}${ro}`);\n\t\t}\n\t}\n\tif (spec.networkAttach && spec.networkAttach.length > 0) {\n\t\t// First attach goes via --network; subsequent attaches via\n\t\t// post-start `network connect` so we can wait for IP readback.\n\t\targs.push('--network', spec.networkAttach[0]!);\n\t}\n\tif (spec.extraHosts) {\n\t\tfor (const [host, ip] of Object.entries(spec.extraHosts)) {\n\t\t\targs.push('--add-host', `${host}:${ip}`);\n\t\t}\n\t}\n\tif (spec.entrypoint) {\n\t\targs.push('--entrypoint', spec.entrypoint);\n\t}\n\targs.push(imageRef);\n\tif (spec.command) {\n\t\targs.push(...spec.command);\n\t}\n\treturn args;\n};\n\n// -----------------------------------------------------------------------------\n// Apply the state machine\n// -----------------------------------------------------------------------------\n\nconst handleOf = (\n\tid: string,\n\tname: string,\n\timageName: string,\n\tstatus: ContainerHandle['status'],\n\tips: ReadonlyArray<string>,\n\tports?: ReadonlyArray<ContainerPortPublish>,\n\tlabels?: EnsureContainerSpec['labels'],\n): ContainerHandle => ({\n\tid,\n\tname,\n\t...(labels !== undefined ? { labels } : {}),\n\timageName,\n\tstatus,\n\tips,\n\t...(ports !== undefined ? { ports } : {}),\n});\n\n/** Force-remove by name. Used by recreate. Idempotent on\n * \"no such container\". */\nconst forceRemove = (\n\tname: string,\n): Effect.Effect<void, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst res = yield* dockerRunOk('rm', ['-f', name]).pipe(\n\t\t\tEffect.mapError(wrapGeneric('docker.rm')),\n\t\t);\n\t\tif (res.exitCode !== 0 && !isNoSuchContainerStderr(res.stderr)) {\n\t\t\t// best-effort; we surface as a span event but do not fail\n\t\t\t// the rm step (the next create will collision-recover).\n\t\t\tyield* Effect.annotateCurrentSpan({ 'docker.rm.warning': res.stderr });\n\t\t}\n\t}).pipe(Effect.withSpan('runtime.docker.container.forceRemove'));\n\nconst ownershipFailure = (\n\tname: string,\n\texpected: Readonly<Record<string, string>>,\n\tactual: Readonly<Record<string, string>>,\n\tdetail: string,\n): ForeignDockerResource =>\n\tnew ForeignDockerResource({\n\t\tresource: 'container',\n\t\tname,\n\t\texpected,\n\t\tactual,\n\t\tdetail,\n\t});\n\nconst assertOwnedFacts = (\n\tname: string,\n\tfacts: InspectFacts,\n\tlabels: EnsureContainerSpec['labels'],\n): Effect.Effect<void, DockerRuntimeError> =>\n\tEffect.gen(function* () {\n\t\tconst expected = expectedContainerOwnershipLabels(labels);\n\t\tconst actual = facts.labels ?? {};\n\t\tconst mismatch = ownershipMismatchDetail(expected, actual);\n\t\tif (mismatch !== null) {\n\t\t\treturn yield* Effect.fail(ownershipFailure(name, expected, actual, mismatch));\n\t\t}\n\t});\n\nconst failUnknownCollisionLifecycle = (\n\tname: string,\n\tstage: 'before-start' | 'after-start',\n): Effect.Effect<never, DockerRuntimeError> =>\n\tEffect.fail(\n\t\tnew ContainerNameCollisionUnrecoverable({\n\t\t\tname,\n\t\t\tdetail: `name collision recovery refused unknown lifecycle state ${stage}`,\n\t\t}),\n\t);\n\nexport const assertContainerHandleOwned = (\n\thandle: ContainerHandle,\n): Effect.Effect<void, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tif (handle.labels === undefined) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\townershipFailure(handle.name, {}, {}, 'container handle has no ownership labels'),\n\t\t\t);\n\t\t}\n\t\tconst facts = yield* inspectContainer(handle.name);\n\t\tconst expected = expectedContainerOwnershipLabels(handle.labels);\n\t\tif (facts === null) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\townershipFailure(handle.name, expected, {}, 'container is missing'),\n\t\t\t);\n\t\t}\n\t\tif (facts.id !== handle.id) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\townershipFailure(handle.name, expected, facts.labels ?? {}, `id changed to ${facts.id}`),\n\t\t\t);\n\t\t}\n\t\tyield* assertOwnedFacts(handle.name, facts, handle.labels);\n\t}).pipe(Effect.withSpan('runtime.docker.container.assertOwned'));\n\nconst forceRemoveOwned = (\n\tname: string,\n\tid: string,\n\tlabels: EnsureContainerSpec['labels'],\n): Effect.Effect<void, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst current = yield* inspectContainer(name);\n\t\tif (current === null) return;\n\t\tif (current.id !== id) {\n\t\t\tconst expected = expectedContainerOwnershipLabels(labels);\n\t\t\treturn yield* Effect.fail(\n\t\t\t\townershipFailure(name, expected, current.labels ?? {}, `id changed to ${current.id}`),\n\t\t\t);\n\t\t}\n\t\tyield* assertOwnedFacts(name, current, labels);\n\t\tyield* forceRemove(name);\n\t});\n\n/** Single-shot start-and-adopt fallback after `docker create` exit-125\n * with name-collision. Architecture §1 / G10 — one attempt; second\n * collision is a typed failure. */\nconst startAndAdopt = (\n\tname: string,\n\tlabels: EnsureContainerSpec['labels'],\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst beforeStart = yield* inspectContainer(name);\n\t\tif (beforeStart === null) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew ContainerNameCollisionUnrecoverable({\n\t\t\t\t\tname,\n\t\t\t\t\tdetail: 'name collision but inspect found no container',\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tyield* assertOwnedFacts(name, beforeStart, labels);\n\t\tif (beforeStart.lifecycle.kind === 'unknown') {\n\t\t\treturn yield* failUnknownCollisionLifecycle(name, 'before-start');\n\t\t}\n\t\tconst res = yield* dockerRunOk('start', [name]).pipe(\n\t\t\tEffect.mapError(wrapGeneric('docker.start')),\n\t\t);\n\t\tconst cls = classifyExit(res);\n\t\tif (cls.ok) {\n\t\t\tconst facts = yield* inspectContainer(name);\n\t\t\tif (facts === null) {\n\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\tnew ContainerNameCollisionUnrecoverable({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdetail: 'peer collision + start succeeded + inspect missed',\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\tyield* assertOwnedFacts(name, facts, labels);\n\t\t\tif (facts.lifecycle.kind === 'unknown') {\n\t\t\t\treturn yield* failUnknownCollisionLifecycle(name, 'after-start');\n\t\t\t}\n\t\t\treturn facts.id;\n\t\t}\n\t\tif (isNoSuchContainerStderr(cls.stderr)) {\n\t\t\t// Peer rm'd between our collision and the start. The caller's\n\t\t\t// outer loop will see this as \"missing\" and promote to fresh.\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew ContainerNameCollisionUnrecoverable({\n\t\t\t\t\tname,\n\t\t\t\t\tdetail: 'TOCTOU: start after collision found no container',\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn yield* Effect.fail(\n\t\t\tnew ContainerNameCollisionUnrecoverable({\n\t\t\t\tname,\n\t\t\t\tdetail: `start-and-adopt failed: ${cls.stderr}`,\n\t\t\t}),\n\t\t);\n\t});\n\nconst freshCreate = (\n\tspec: EnsureContainerSpec,\n\tcycle: number,\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst args = createArgv(spec, cycle, spec.image.tag ?? spec.image.digest);\n\t\tconst created = yield* dockerRun('run', args).pipe(Effect.mapError(wrapCreateError(spec.name)));\n\t\treturn created.stdout.trim();\n\t});\n\nconst resumeStart = (\n\tname: string,\n): Effect.Effect<\n\t{ readonly ok: true } | { readonly ok: false; readonly stderr: string },\n\tDockerRuntimeError,\n\tDockerHost | DockerSpawner\n> =>\n\tEffect.gen(function* () {\n\t\tconst res = yield* dockerRunOk('start', [name]).pipe(\n\t\t\tEffect.mapError(wrapGeneric('docker.start')),\n\t\t);\n\t\tif (res.exitCode === 0) return { ok: true as const };\n\t\tif (isDaemonUnreachableStderr(res.stderr)) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew DaemonUnreachable({\n\t\t\t\t\top: 'docker.start',\n\t\t\t\t\tdetail: 'docker daemon unreachable',\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn { ok: false as const, stderr: res.stderr };\n\t});\n\nconst recreateAfterResumeFailure = (\n\tid: string,\n\tspec: EnsureContainerSpec,\n\tdeps: EnsureContainerDeps,\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst routed = routeRecreate({ kind: 'recreate', id, reason: 'resume-failed' }, spec.recreate);\n\t\tif (routed.kind === 'refuse') {\n\t\t\treturn yield* Effect.fail(new RecreateRefused({ name: spec.name, reason: routed.reason }));\n\t\t}\n\t\tyield* forceRemoveOwned(spec.name, id, spec.labels);\n\t\treturn yield* createWithCollisionRecovery(spec, deps);\n\t});\n\nconst effectivePortsCompatible = (facts: InspectFacts, spec: EnsureContainerSpec): boolean => {\n\tconst desired = canonicalPortBindings(spec.ports);\n\tif (desired.length === 0) return true;\n\tconst actual = facts.effectivePortBindings ?? [];\n\tif (sameBindings(actual, desired)) return true;\n\treturn (\n\t\t(spec.portBindingReconciliation ?? 'exact') === 'adopt-existing' &&\n\t\tsameBindingContainerPorts(actual, desired)\n\t);\n};\n\nconst ensureEffectivePublishedPorts = (\n\tid: string,\n\tspec: EnsureContainerSpec,\n\tdeps: EnsureContainerDeps,\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tif ((spec.ports ?? []).length === 0) return id;\n\t\tconst facts = yield* inspectContainer(spec.name);\n\t\tif (facts === null || facts.id !== id || facts.lifecycle.kind !== 'running') return id;\n\t\tyield* assertOwnedFacts(spec.name, facts, spec.labels);\n\t\tif (effectivePortsCompatible(facts, spec)) return id;\n\t\tconst repairedId = yield* recreateAfterResumeFailure(id, spec, deps);\n\t\tconst repairedFacts = yield* inspectContainer(spec.name);\n\t\tif (\n\t\t\trepairedFacts !== null &&\n\t\t\trepairedFacts.id === repairedId &&\n\t\t\trepairedFacts.lifecycle.kind === 'running' &&\n\t\t\teffectivePortsCompatible(repairedFacts, spec)\n\t\t) {\n\t\t\treturn repairedId;\n\t\t}\n\t\treturn yield* Effect.fail(\n\t\t\tnew ContainerCreateFailed({\n\t\t\t\tname: spec.name,\n\t\t\t\tstderr: `container is running but Docker did not publish requested ports: desired=${JSON.stringify(\n\t\t\t\t\tcanonicalPortBindings(spec.ports),\n\t\t\t\t)} actual=${JSON.stringify(repairedFacts?.effectivePortBindings ?? [])}`,\n\t\t\t\texitCode: 0,\n\t\t\t}),\n\t\t);\n\t});\n\nconst stopWithGrace = (\n\tname: string,\n\tgraceSeconds: number,\n\tsignal?: string,\n): Effect.Effect<void, never, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst args: Array<string> = [];\n\t\tif (signal !== undefined) args.push('--signal', signal);\n\t\targs.push('--time', String(Math.max(0, Math.floor(graceSeconds))));\n\t\targs.push(name);\n\t\tyield* dockerRunOk('stop', args).pipe(\n\t\t\tEffect.catch(() => Effect.void),\n\t\t\tEffect.asVoid,\n\t\t);\n\t});\n\n// -----------------------------------------------------------------------------\n// Public surface\n// -----------------------------------------------------------------------------\n\n/** Per-name lock state. Map entry present = name is held; the value is\n * the FIFO queue of waiter deferreds. Empty queue = held with no\n * waiters. Map entry absent = free. */\nexport type PerNameLockState = ReadonlyMap<string, ReadonlyArray<Deferred.Deferred<void>>>;\n\nexport interface EnsureContainerDeps {\n\t/** Current engine cycle id; stamped as the `devstack.cycle` label. */\n\treadonly cycle: number;\n\t/** Process-local lock holder to serialize per-name actions within\n\t * one Node process. Cross-process safety is the docker daemon's\n\t * `--name` atomicity. */\n\treadonly perNameLock: Ref.Ref<PerNameLockState>;\n}\n\n/** Per-name lock acquire/release. The in-process serialization is the\n * inspect→action window's invariant: two concurrent ensureContainer\n * calls for the same name must not race between the read (inspect)\n * and the write (create / start / recreate). Cross-process safety is\n * separately the docker daemon's `--name` atomicity.\n *\n * Implementation: a `Ref<Map<name, Deferred[]>>`. Acquire atomically\n * claims the slot (free → enter with empty queue) or enqueues a fresh\n * Deferred at the tail and awaits it. Release pops the head of the\n * queue and completes that waiter — transferring ownership without a\n * free intermediate window. Empty-queue release deletes the entry.\n * No wall-clock polling: contention parks fibers on Deferred.await\n * rather than spinning, so tests can use `it.effect` (TestClock) and\n * contended-acquire ordering is FIFO by construction.\n *\n * Exported for direct testing. */\nexport const acquirePerNameLock = (\n\tlock: Ref.Ref<PerNameLockState>,\n\tname: string,\n): Effect.Effect<void> =>\n\tEffect.gen(function* () {\n\t\tconst waiter = yield* Deferred.make<void>();\n\t\tconst claimed = yield* Ref.modify(lock, (m) => {\n\t\t\tconst queue = m.get(name);\n\t\t\tconst next = new Map(m);\n\t\t\tif (queue === undefined) {\n\t\t\t\t// Free → claim with empty waiter queue.\n\t\t\t\tnext.set(name, []);\n\t\t\t\treturn [true, next as PerNameLockState] as const;\n\t\t\t}\n\t\t\t// Held → enqueue and await.\n\t\t\tnext.set(name, [...queue, waiter]);\n\t\t\treturn [false, next as PerNameLockState] as const;\n\t\t});\n\t\tif (claimed) return;\n\t\t// Park until the current holder releases and completes our\n\t\t// deferred. Interrupt-cleanup: if we're interrupted while\n\t\t// queued, drop our deferred from the queue so a future\n\t\t// release doesn't transfer ownership to a dead waiter.\n\t\tyield* Deferred.await(waiter).pipe(\n\t\t\tEffect.onInterrupt(() =>\n\t\t\t\tRef.update(lock, (m) => {\n\t\t\t\t\tconst queue = m.get(name);\n\t\t\t\t\tif (queue === undefined) return m;\n\t\t\t\t\tconst filtered = queue.filter((d) => d !== waiter);\n\t\t\t\t\tif (filtered.length === queue.length) return m;\n\t\t\t\t\tconst next = new Map(m);\n\t\t\t\t\tnext.set(name, filtered);\n\t\t\t\t\treturn next as PerNameLockState;\n\t\t\t\t}),\n\t\t\t),\n\t\t);\n\t});\n\nexport const releasePerNameLock = (\n\tlock: Ref.Ref<PerNameLockState>,\n\tname: string,\n): Effect.Effect<void> =>\n\tEffect.gen(function* () {\n\t\tconst head = yield* Ref.modify(lock, (m) => {\n\t\t\tconst queue = m.get(name);\n\t\t\tif (queue === undefined) return [undefined, m] as const;\n\t\t\tconst next = new Map(m);\n\t\t\tif (queue.length === 0) {\n\t\t\t\tnext.delete(name);\n\t\t\t\treturn [undefined, next as PerNameLockState] as const;\n\t\t\t}\n\t\t\tconst [first, ...rest] = queue;\n\t\t\tnext.set(name, rest);\n\t\t\treturn [first, next as PerNameLockState] as const;\n\t\t});\n\t\tif (head !== undefined) {\n\t\t\tyield* Deferred.succeed(head, undefined);\n\t\t}\n\t});\n\n/** Idempotent ensure: apply the state machine, register a scope\n * finalizer that stops the container + releases the cross-process\n * claim.\n *\n * Returns the running container handle (id + name + status + ips). */\nexport const ensureContainer = (\n\tspec: EnsureContainerSpec,\n\tdeps: EnsureContainerDeps,\n): Effect.Effect<\n\tContainerHandle,\n\tDockerRuntimeError,\n\tDockerHost | DockerSpawner | StackPathsService | Scope.Scope\n> =>\n\tEffect.gen(function* () {\n\t\t// Per-name lock holds the inspect → applyAction window. We release\n\t\t// immediately after applyAction returns (success or typed failure)\n\t\t// so concurrent callers for the SAME name serialize at the\n\t\t// \"decide what to do\" step, but the lock does not outlive the\n\t\t// state-machine resolution. `acquireUseRelease` ensures the\n\t\t// release fires on interrupt/defect too.\n\t\tconst desiredImageRef = spec.image.tag ?? spec.image.digest;\n\t\tconst id = yield* Effect.acquireUseRelease(\n\t\t\tacquirePerNameLock(deps.perNameLock, spec.name),\n\t\t\t() =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst facts = yield* inspectContainer(spec.name);\n\t\t\t\t\tif (facts !== null) {\n\t\t\t\t\t\tyield* assertOwnedFacts(spec.name, facts, spec.labels);\n\t\t\t\t\t}\n\t\t\t\t\tconst action = decideRunAction(\n\t\t\t\t\t\tfacts,\n\t\t\t\t\t\tdesiredImageRef,\n\t\t\t\t\t\tspec.recreate,\n\t\t\t\t\t\tcanonicalPortBindings(spec.ports),\n\t\t\t\t\t\tspec.portBindingReconciliation ?? 'exact',\n\t\t\t\t\t\tspec.configHash,\n\t\t\t\t\t\tspec.image.digest,\n\t\t\t\t\t);\n\t\t\t\t\tconst id = yield* applyAction(action, spec, deps);\n\t\t\t\t\treturn yield* ensureEffectivePublishedPorts(id, spec, deps);\n\t\t\t\t}),\n\t\t\t() => releasePerNameLock(deps.perNameLock, spec.name),\n\t\t);\n\t\tyield* assertContainerHandleOwned({\n\t\t\tid,\n\t\t\tname: spec.name,\n\t\t\tlabels: spec.labels,\n\t\t\timageName: spec.image.tag ?? spec.image.digest,\n\t\t\tstatus: 'running',\n\t\t\tips: [],\n\t\t});\n\n\t\t// Architecture §5 — secondary network attaches (any beyond the\n\t\t// first, which is wired in via `--network` on create) must wait\n\t\t// for IP allocation before we declare ready.\n\t\tconst secondaries = (spec.networkAttach ?? []).slice(1);\n\t\tfor (const net of secondaries) {\n\t\t\tyield* connect(spec.name, net);\n\t\t\tyield* waitForIp(spec.name, net);\n\t\t}\n\n\t\tconst ips = yield* readIps(spec.name);\n\t\tconst refreshedFacts = yield* inspectContainer(spec.name);\n\t\tconst ports = refreshedFacts?.effectivePorts ?? refreshedFacts?.ports ?? spec.ports;\n\n\t\t// Register cross-process claim and scope-bound release. The\n\t\t// stop finalizer fires on scope close if the same container id\n\t\t// still owns the stable name. Restore may deliberately remove a\n\t\t// claimed container and a later acquire may reuse the name before\n\t\t// this scope closes; the old finalizer must not stop that newer\n\t\t// container. Architecture §13: stop is uninterruptible.\n\t\tconst paths = yield* StackPathsService;\n\t\tconst mapSubstrateError = (cause: unknown): DockerRuntimeError =>\n\t\t\tnew DaemonUnreachable({\n\t\t\t\top: 'cross-process.claim',\n\t\t\t\tdetail: `cross-process claim mutation failed: ${String(cause)}`,\n\t\t\t\tcause,\n\t\t\t});\n\t\tyield* addClaim(\n\t\t\t{ stackLockFile: paths.stackLockFile, rosterFile: paths.rosterFile },\n\t\t\tspec.name,\n\t\t).pipe(Effect.mapError(mapSubstrateError));\n\n\t\tyield* Effect.addFinalizer(() =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst current = yield* inspectContainer(spec.name).pipe(\n\t\t\t\t\tEffect.catch(() => Effect.succeed(null)),\n\t\t\t\t);\n\t\t\t\tif (current?.id === id) {\n\t\t\t\t\tyield* stopWithGrace(spec.name, spec.stopGraceSeconds ?? 10);\n\t\t\t\t}\n\t\t\t\tyield* removeClaim(\n\t\t\t\t\t{ stackLockFile: paths.stackLockFile, rosterFile: paths.rosterFile },\n\t\t\t\t\tspec.name,\n\t\t\t\t).pipe(Effect.catch(() => Effect.succeed({ lastClaimReleased: false })));\n\t\t\t}).pipe(Effect.uninterruptible),\n\t\t);\n\n\t\treturn handleOf(\n\t\t\tid,\n\t\t\tspec.name,\n\t\t\tspec.image.tag ?? spec.image.digest,\n\t\t\t'running',\n\t\t\tips,\n\t\t\tports,\n\t\t\tspec.labels,\n\t\t);\n\t}).pipe(Effect.withSpan('runtime.docker.container.ensure'));\n\n/** Apply the decided action. Recovers from name-collision via\n * one-shot start-and-adopt; second collision surfaces typed. */\nconst applyAction = (\n\taction: RunAction,\n\tspec: EnsureContainerSpec,\n\tdeps: EnsureContainerDeps,\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner | Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tswitch (action.kind) {\n\t\t\tcase 'adopt':\n\t\t\t\treturn action.id;\n\t\t\tcase 'unpause-adopt':\n\t\t\t\tyield* assertContainerHandleOwned({\n\t\t\t\t\tid: action.id,\n\t\t\t\t\tname: spec.name,\n\t\t\t\t\tlabels: spec.labels,\n\t\t\t\t\timageName: spec.image.tag ?? spec.image.digest,\n\t\t\t\t\tstatus: 'paused',\n\t\t\t\t\tips: [],\n\t\t\t\t});\n\t\t\t\tyield* unpause(spec.name);\n\t\t\t\treturn action.id;\n\t\t\tcase 'resume': {\n\t\t\t\tyield* assertContainerHandleOwned({\n\t\t\t\t\tid: action.id,\n\t\t\t\t\tname: spec.name,\n\t\t\t\t\tlabels: spec.labels,\n\t\t\t\t\timageName: spec.image.tag ?? spec.image.digest,\n\t\t\t\t\tstatus: 'exited',\n\t\t\t\t\tips: [],\n\t\t\t\t});\n\t\t\t\tconst started = yield* resumeStart(spec.name);\n\t\t\t\tif (!started.ok) {\n\t\t\t\t\treturn yield* recreateAfterResumeFailure(action.id, spec, deps);\n\t\t\t\t}\n\t\t\t\treturn action.id;\n\t\t\t}\n\t\t\tcase 'recreate': {\n\t\t\t\tyield* forceRemoveOwned(spec.name, action.id, spec.labels);\n\t\t\t\treturn yield* createWithCollisionRecovery(spec, deps);\n\t\t\t}\n\t\t\tcase 'fresh':\n\t\t\t\treturn yield* createWithCollisionRecovery(spec, deps);\n\t\t\tcase 'refuse':\n\t\t\t\treturn yield* Effect.fail(new RecreateRefused({ name: spec.name, reason: action.reason }));\n\t\t}\n\t});\n\n/** `docker run -d` with single-shot start-and-adopt fallback on\n * name-collision. */\nconst createWithCollisionRecovery = (\n\tspec: EnsureContainerSpec,\n\tdeps: EnsureContainerDeps,\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tfreshCreate(spec, deps.cycle).pipe(\n\t\tEffect.catchTag('ContainerNameCollisionUnrecoverable', () =>\n\t\t\tstartAndAdopt(spec.name, spec.labels),\n\t\t),\n\t\t// If the original create surfaced a typed `ContainerCreateFailed`\n\t\t// where stderr was name-collision (sometimes the create variant\n\t\t// surfaces with that), attempt the same start-and-adopt.\n\t\tEffect.catchTag('ContainerCreateFailed', (err) =>\n\t\t\tisNameCollisionStderr(err.stderr) ? startAndAdopt(spec.name, spec.labels) : Effect.fail(err),\n\t\t),\n\t);\n\n// -----------------------------------------------------------------------------\n// Stop / commit / pause — used by the snapshot orchestrator\n// -----------------------------------------------------------------------------\n\nexport const stop = (\n\tname: string,\n\tgraceSeconds: number,\n\tsignal?: string,\n): Effect.Effect<void, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tstopWithGrace(name, graceSeconds, signal).pipe(Effect.asVoid);\n\nexport const pause = (\n\tname: string,\n): Effect.Effect<void, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tyield* dockerRun('pause', [name]).pipe(Effect.mapError(wrapGeneric('docker.pause')));\n\t}).pipe(Effect.withSpan('runtime.docker.container.pause'));\n\nexport const unpause = (\n\tname: string,\n): Effect.Effect<void, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tyield* dockerRun('unpause', [name]).pipe(Effect.mapError(wrapGeneric('docker.unpause')));\n\t}).pipe(Effect.withSpan('runtime.docker.container.unpause'));\n\n/** `docker commit <name> <tag>` — writable layer → image. Used by\n * snapshot capture. */\nexport const commit = (\n\tname: string,\n\ttag: string,\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst res = yield* dockerRun('commit', [name, tag]).pipe(\n\t\t\tEffect.mapError(wrapGeneric('docker.commit')),\n\t\t);\n\t\tconst digest = res.stdout.trim();\n\t\tif (digest.length === 0) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew ContainerCreateFailed({\n\t\t\t\t\tname,\n\t\t\t\t\tstderr: 'commit returned empty digest',\n\t\t\t\t\texitCode: 0,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn digest;\n\t}).pipe(Effect.withSpan('runtime.docker.container.commit'));\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"container.mjs","names":[],"sources":["../../../src/runtime/docker/container.ts"],"sourcesContent":["// Container lifecycle state machine.\n//\n// Architecture § Lifecycle states. The (missing | running-match |\n// running-mismatch | stopped-clean | stopped-unclean | stopped-\n// mismatch) input states map to (adopt | resume | recreate | fresh)\n// actions. The output handle is the running container.\n//\n// Architecture invariants encoded here:\n//\n// §1 Name-atomic create — `docker create --name <stable>` collision\n// triggers `docker start <name>` adopt-fallback (single shot;\n// second collision = typed failure, no infinite loop).\n// §2 Label-driven inventory — we use `docker container inspect <name>`\n// for the single-container probe path (cheaper than label-filtered\n// `ps`, and type-specific when container/network names collide), but\n// the labels are still STAMPED on create so sweep can find us by\n// labels later.\n// §5 Async network-connect — `network.ts::waitForIp` is called\n// after attach and before we declare ready.\n// §9 RecreatePolicy enum routed in — `never` refuses to recreate;\n// `on-failure` recreates on unclean shutdown + image mismatch;\n// `on-config-change` recreates on image mismatch, port mismatch,\n// or caller-supplied config hash mismatch.\n\nimport { Deferred, Effect, Ref, Scope, Schema } from 'effect';\n\nimport type {\n\tContainerHandle,\n\tContainerPortPublish,\n\tEnsureContainerSpec,\n\tNetworkAttachment,\n\tPortBindingReconciliation,\n\tRecreatePolicy,\n} from '../../contracts/container-runtime.ts';\nimport {\n\taddClaim,\n\tremoveClaim,\n\ttype RosterError,\n} from '../../substrate/runtime/cross-process/roster.ts';\nimport type { StackLockError } from '../../substrate/runtime/cross-process/stack-lock.ts';\nimport { StackPathsService } from '../../substrate/runtime/paths.ts';\nimport { DockerHost, DockerSpawner, dockerRun, dockerRunOk } from './client.ts';\nimport {\n\tContainerCreateFailed,\n\tContainerNameCollisionUnrecoverable,\n\tDaemonUnreachable,\n\ttype DockerRuntimeError,\n\tForeignDockerResource,\n\tRecreateRefused,\n} from './errors.ts';\nimport { dockerInspectAndDecode } from './inspect-and-decode.ts';\nimport {\n\texpectedContainerOwnershipLabels,\n\tLabelKey,\n\townershipMismatchDetail,\n\treadLabels,\n\trenderContainerLabels,\n} from './labels.ts';\nimport { connect, readIps, waitForIp } from './network.ts';\nimport { renderCreateArgs } from './render-run-args.ts';\nimport {\n\tclassifyExit,\n\tisDaemonUnreachableStderr,\n\tisNameCollisionStderr,\n\tisNoSuchContainerStderr,\n\twrapCreateError,\n\twrapGeneric,\n} from './wrap.ts';\n\n// -----------------------------------------------------------------------------\n// State machine — pure decision (testable independently)\n// -----------------------------------------------------------------------------\n\nexport type InspectLifecycleState =\n\t| { readonly kind: 'running'; readonly exitCode: number }\n\t| { readonly kind: 'paused'; readonly exitCode: number }\n\t| { readonly kind: 'stopped'; readonly exitCode: number }\n\t| { readonly kind: 'unknown' };\n\n/** What `docker container inspect <name>` told us. Lifecycle facts are explicit:\n * Docker may omit `State`, and absence means we cannot prove running,\n * paused, or stopped state. */\nexport interface InspectFacts {\n\treadonly id: string;\n\treadonly lifecycle: InspectLifecycleState;\n\treadonly running: boolean;\n\treadonly paused: boolean;\n\treadonly exitCode: number | null;\n\t/** Create-time image ref recorded by Docker. For tagged builds this is\n\t * usually the tag passed to `docker run`. */\n\treadonly image: string;\n\t/** Resolved image id from Docker inspect's top-level `Image` field. */\n\treadonly imageDigest?: string;\n\treadonly mounts?: ReadonlyArray<InspectMount>;\n\treadonly portBindings?: ReadonlyArray<string>;\n\treadonly ports?: ReadonlyArray<ContainerPortPublish>;\n\treadonly effectivePortBindings?: ReadonlyArray<string>;\n\treadonly effectivePorts?: ReadonlyArray<ContainerPortPublish>;\n\treadonly command?: ReadonlyArray<string>;\n\treadonly labels?: Readonly<Record<string, string>>;\n\treadonly networks?: ReadonlyArray<string>;\n\treadonly networkAttachments?: ReadonlyArray<InspectNetworkAttachment>;\n}\n\nexport interface InspectMount {\n\treadonly source: string;\n\treadonly target: string;\n\treadonly readOnly?: boolean;\n}\n\nexport interface InspectNetworkAttachment {\n\treadonly name: string;\n\treadonly aliases: ReadonlyArray<string>;\n}\n\n/** The closed set of actions the state machine can decide. */\nexport type RunAction =\n\t| { readonly kind: 'adopt'; readonly id: string }\n\t| { readonly kind: 'unpause-adopt'; readonly id: string }\n\t| { readonly kind: 'resume'; readonly id: string }\n\t| { readonly kind: 'recreate'; readonly id: string; readonly reason: RecreateReason }\n\t| { readonly kind: 'fresh' }\n\t| { readonly kind: 'refuse'; readonly reason: RecreateReason };\n\nexport type RecreateReason =\n\t| 'image-mismatch'\n\t| 'config-mismatch'\n\t| 'unclean-shutdown'\n\t| 'resume-failed'\n\t| 'unknown-state';\n\n/** Pure decision: given the inspect facts (or null = missing), the\n * desired image + host port bindings, and the policy, what action\n * do we take?\n *\n * Tested directly without the subprocess seam. */\nexport const decideRunAction = (\n\tfacts: InspectFacts | null,\n\tdesiredImage: string,\n\tpolicy: RecreatePolicy,\n\tdesiredPortBindings: ReadonlyArray<string> = [],\n\tportBindingReconciliation: PortBindingReconciliation = 'exact',\n\tdesiredConfigHash?: string,\n\tdesiredImageDigest?: string,\n\tdesiredNetworkAttachments: ReadonlyArray<string | NetworkAttachment> = [],\n): RunAction => {\n\tif (facts === null) return { kind: 'fresh' };\n\tconst imageMatches =\n\t\tfacts.image === desiredImage ||\n\t\t(desiredImageDigest !== undefined &&\n\t\t\t(facts.image === desiredImageDigest || facts.imageDigest === desiredImageDigest));\n\tconst portsMatch = sameBindings(facts.portBindings ?? [], desiredPortBindings);\n\tconst portsCompatible =\n\t\tportsMatch ||\n\t\t(portBindingReconciliation === 'adopt-existing' &&\n\t\t\tsameBindingContainerPorts(facts.portBindings ?? [], desiredPortBindings));\n\tconst networksCompatible = desiredNetworkAttachmentsCompatible(\n\t\tfacts.networkAttachments ?? [],\n\t\tdesiredNetworkAttachments,\n\t);\n\tconst configMatches =\n\t\tnetworksCompatible &&\n\t\t(desiredConfigHash === undefined || facts.labels?.[LabelKey.configHash] === desiredConfigHash);\n\tif (facts.lifecycle.kind === 'unknown') {\n\t\treturn routeRecreate({ kind: 'recreate', id: facts.id, reason: 'unknown-state' }, policy);\n\t}\n\tif (facts.lifecycle.kind === 'paused') {\n\t\treturn imageMatches && portsCompatible && configMatches\n\t\t\t? { kind: 'unpause-adopt', id: facts.id }\n\t\t\t: routeRecreate(\n\t\t\t\t\t{\n\t\t\t\t\t\tkind: 'recreate',\n\t\t\t\t\t\tid: facts.id,\n\t\t\t\t\t\treason: imageMatches ? 'config-mismatch' : 'image-mismatch',\n\t\t\t\t\t},\n\t\t\t\t\tpolicy,\n\t\t\t\t);\n\t}\n\tif (facts.lifecycle.kind === 'running') {\n\t\treturn imageMatches && portsCompatible && configMatches\n\t\t\t? { kind: 'adopt', id: facts.id }\n\t\t\t: routeRecreate(\n\t\t\t\t\t{\n\t\t\t\t\t\tkind: 'recreate',\n\t\t\t\t\t\tid: facts.id,\n\t\t\t\t\t\treason: imageMatches ? 'config-mismatch' : 'image-mismatch',\n\t\t\t\t\t},\n\t\t\t\t\tpolicy,\n\t\t\t\t);\n\t}\n\tif (!imageMatches) {\n\t\t// Image mismatch ALWAYS wins (architecture §11).\n\t\treturn routeRecreate({ kind: 'recreate', id: facts.id, reason: 'image-mismatch' }, policy);\n\t}\n\tif (!portsCompatible) {\n\t\treturn routeRecreate({ kind: 'recreate', id: facts.id, reason: 'config-mismatch' }, policy);\n\t}\n\tif (!configMatches) {\n\t\treturn routeRecreate({ kind: 'recreate', id: facts.id, reason: 'config-mismatch' }, policy);\n\t}\n\tif (facts.lifecycle.exitCode === 137) {\n\t\t// Unclean shutdown — see architecture §G1 / §13.\n\t\t// `on-failure`: recreate. `never`: refuse. `on-config-change`:\n\t\t// resume — caller wants stopped container kept until config\n\t\t// changes, even if the prior exit was unclean.\n\t\tif (policy === 'on-failure') {\n\t\t\treturn { kind: 'recreate', id: facts.id, reason: 'unclean-shutdown' };\n\t\t}\n\t\tif (policy === 'never') {\n\t\t\treturn { kind: 'refuse', reason: 'unclean-shutdown' };\n\t\t}\n\t\treturn { kind: 'resume', id: facts.id };\n\t}\n\treturn { kind: 'resume', id: facts.id };\n};\n\n/** Route a recreate-class decision through the policy. */\nconst routeRecreate = (\n\taction: RunAction & { kind: 'recreate' },\n\tpolicy: RecreatePolicy,\n): RunAction => {\n\tif (policy === 'never') return { kind: 'refuse', reason: action.reason };\n\treturn action;\n};\n\nconst canonicalPortBindings = (\n\tports: ReadonlyArray<ContainerPortPublish> | undefined,\n): ReadonlyArray<string> =>\n\t[...(ports ?? [])]\n\t\t.map((p) => `${p.containerPort}/tcp=${normalizeHostIp(p.hostIp)}:${p.hostPort}`)\n\t\t.sort();\n\nconst sameBindings = (left: ReadonlyArray<string>, right: ReadonlyArray<string>): boolean =>\n\tleft.length === right.length && left.every((value, index) => value === right[index]);\n\nconst sameBindingContainerPorts = (\n\tleft: ReadonlyArray<string>,\n\tright: ReadonlyArray<string>,\n): boolean => {\n\tconst leftContainers = left.map(bindingContainerKey).sort();\n\tconst rightContainers = right.map(bindingContainerKey).sort();\n\treturn sameBindings(leftContainers, rightContainers);\n};\n\nconst bindingContainerKey = (binding: string): string => binding.split('=')[0] ?? binding;\n\nconst normalizeHostIp = (hostIp: string | undefined): string =>\n\thostIp === undefined || hostIp === '' ? '0.0.0.0' : hostIp;\n\nconst desiredNetworkAttachmentsCompatible = (\n\tactual: ReadonlyArray<InspectNetworkAttachment>,\n\tdesired: ReadonlyArray<string | NetworkAttachment>,\n): boolean => {\n\tconst actualByName = new Map(actual.map((network) => [network.name, network]));\n\treturn desired.every((entry, index) => {\n\t\tconst normalized = normalizeNetworkAttachment(entry);\n\t\tconst actualNetwork = actualByName.get(normalized.name);\n\t\tif (actualNetwork === undefined) {\n\t\t\treturn index !== 0;\n\t\t}\n\t\tif (normalized.aliases === undefined || normalized.aliases.length === 0) return true;\n\t\tconst actualAliases = new Set(actualNetwork.aliases);\n\t\treturn normalized.aliases.every((alias) => actualAliases.has(alias));\n\t});\n};\n\nconst readPublishedPorts = (raw: unknown): ReadonlyArray<ContainerPortPublish> => {\n\tif (raw === null || typeof raw !== 'object') return [];\n\tconst out: ContainerPortPublish[] = [];\n\tfor (const [container, bindings] of Object.entries(raw)) {\n\t\tconst containerPort = Number(container.split('/')[0]);\n\t\tif (!Number.isInteger(containerPort) || containerPort <= 0) continue;\n\t\tif (!Array.isArray(bindings)) continue;\n\t\tfor (const binding of bindings) {\n\t\t\tif (binding === null || typeof binding !== 'object') continue;\n\t\t\tconst hostPort = (binding as { HostPort?: unknown }).HostPort;\n\t\t\tif (typeof hostPort !== 'string') continue;\n\t\t\tconst hostPortNumber = Number(hostPort);\n\t\t\tif (!Number.isInteger(hostPortNumber) || hostPortNumber <= 0) continue;\n\t\t\tconst hostIp = (binding as { HostIp?: unknown }).HostIp;\n\t\t\tout.push({\n\t\t\t\tcontainerPort,\n\t\t\t\thostPort: hostPortNumber,\n\t\t\t\t...(typeof hostIp === 'string' ? { hostIp: normalizeHostIp(hostIp) } : {}),\n\t\t\t});\n\t\t}\n\t}\n\treturn out.sort((a, b) => {\n\t\tif (a.containerPort !== b.containerPort) return a.containerPort - b.containerPort;\n\t\tconst hostIp = normalizeHostIp(a.hostIp).localeCompare(normalizeHostIp(b.hostIp));\n\t\treturn hostIp !== 0 ? hostIp : a.hostPort - b.hostPort;\n\t});\n};\n\nconst readMounts = (raw: unknown): ReadonlyArray<InspectMount> => {\n\tif (!Array.isArray(raw)) return [];\n\tconst out: InspectMount[] = [];\n\tfor (const mount of raw) {\n\t\tif (mount === null || typeof mount !== 'object') continue;\n\t\tconst source = (mount as { Source?: unknown }).Source;\n\t\tconst target = (mount as { Destination?: unknown }).Destination;\n\t\tif (typeof source !== 'string' || typeof target !== 'string') continue;\n\t\tconst rw = (mount as { RW?: unknown }).RW;\n\t\tout.push({\n\t\t\tsource,\n\t\t\ttarget,\n\t\t\t...(typeof rw === 'boolean' ? { readOnly: !rw } : {}),\n\t\t});\n\t}\n\treturn out;\n};\n\nconst readStringArray = (raw: unknown): ReadonlyArray<string> => {\n\tif (!Array.isArray(raw)) return [];\n\treturn raw.filter((value): value is string => typeof value === 'string');\n};\n\nconst readNetworks = (raw: unknown): ReadonlyArray<string> => {\n\tif (raw === null || typeof raw !== 'object') return [];\n\treturn Object.keys(raw).sort();\n};\n\nconst readNetworkAttachments = (raw: unknown): ReadonlyArray<InspectNetworkAttachment> => {\n\tif (raw === null || typeof raw !== 'object') return [];\n\treturn Object.entries(raw)\n\t\t.map(([name, value]): InspectNetworkAttachment => {\n\t\t\tconst aliases =\n\t\t\t\tvalue !== null && typeof value === 'object'\n\t\t\t\t\t? ((value as { Aliases?: unknown }).Aliases ?? [])\n\t\t\t\t\t: [];\n\t\t\treturn {\n\t\t\t\tname,\n\t\t\t\taliases: Array.isArray(aliases)\n\t\t\t\t\t? aliases.filter((alias): alias is string => typeof alias === 'string').sort()\n\t\t\t\t\t: [],\n\t\t\t};\n\t\t})\n\t\t.sort((a, b) => a.name.localeCompare(b.name));\n};\n\nconst readLifecycleState = (\n\tstate:\n\t\t| {\n\t\t\t\treadonly Running: boolean;\n\t\t\t\treadonly Paused: boolean;\n\t\t\t\treadonly ExitCode: number;\n\t\t }\n\t\t| undefined,\n): InspectLifecycleState => {\n\tif (state === undefined) return { kind: 'unknown' };\n\tif (state.Paused) return { kind: 'paused', exitCode: state.ExitCode };\n\tif (state.Running) return { kind: 'running', exitCode: state.ExitCode };\n\treturn { kind: 'stopped', exitCode: state.ExitCode };\n};\n\n// -----------------------------------------------------------------------------\n// Inspect — `docker container inspect <name>`\n// -----------------------------------------------------------------------------\n\nconst InspectSchema = Schema.Struct({\n\tId: Schema.String,\n\tImage: Schema.optional(Schema.String),\n\tMounts: Schema.optional(Schema.Unknown),\n\tHostConfig: Schema.optional(\n\t\tSchema.Struct({\n\t\t\tPortBindings: Schema.Unknown,\n\t\t}),\n\t),\n\tState: Schema.optional(\n\t\tSchema.Struct({\n\t\t\tRunning: Schema.Boolean,\n\t\t\tPaused: Schema.Boolean,\n\t\t\tExitCode: Schema.Number,\n\t\t}),\n\t),\n\tConfig: Schema.Struct({\n\t\tImage: Schema.String,\n\t\tCmd: Schema.optional(Schema.Unknown),\n\t\tLabels: Schema.optional(Schema.Unknown),\n\t}),\n\tNetworkSettings: Schema.Struct({\n\t\tNetworks: Schema.Unknown,\n\t\tPorts: Schema.optional(Schema.Unknown),\n\t}),\n});\n\nexport const inspectContainer = (\n\tname: string,\n): Effect.Effect<InspectFacts | null, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst decoded = yield* dockerInspectAndDecode({\n\t\t\tresourceKind: 'container',\n\t\t\tname,\n\t\t\top: 'docker.container.inspect',\n\t\t\tinspectCommand: dockerRunOk('container', ['inspect', name]).pipe(\n\t\t\t\tEffect.mapError(wrapGeneric('docker.container.inspect')),\n\t\t\t),\n\t\t\tschema: InspectSchema,\n\t\t\tisMissingStderr: isNoSuchContainerStderr,\n\t\t});\n\t\tif (decoded === null) return null;\n\t\tconst lifecycle = readLifecycleState(decoded.State);\n\t\tconst effectivePorts = readPublishedPorts(decoded.NetworkSettings.Ports);\n\t\tconst ports =\n\t\t\tdecoded.HostConfig === undefined\n\t\t\t\t? effectivePorts\n\t\t\t\t: readPublishedPorts(decoded.HostConfig.PortBindings);\n\t\tconst mounts = readMounts(decoded.Mounts);\n\t\tconst command = readStringArray(decoded.Config.Cmd);\n\t\tconst labels = readLabels(decoded.Config.Labels);\n\t\tconst networks = readNetworks(decoded.NetworkSettings.Networks);\n\t\tconst networkAttachments = readNetworkAttachments(decoded.NetworkSettings.Networks);\n\t\treturn {\n\t\t\tid: decoded.Id,\n\t\t\tlifecycle,\n\t\t\trunning: lifecycle.kind === 'running' || lifecycle.kind === 'paused',\n\t\t\tpaused: lifecycle.kind === 'paused',\n\t\t\texitCode: lifecycle.kind === 'unknown' ? null : lifecycle.exitCode,\n\t\t\t// The container's recorded image. Docker may omit the\n\t\t\t// top-level digest field, but lifecycle decisions need the\n\t\t\t// create-time ref from Config.Image.\n\t\t\timage: decoded.Config.Image,\n\t\t\t...(decoded.Image !== undefined ? { imageDigest: decoded.Image } : {}),\n\t\t\tmounts,\n\t\t\tportBindings: canonicalPortBindings(ports),\n\t\t\tports,\n\t\t\teffectivePortBindings: canonicalPortBindings(effectivePorts),\n\t\t\teffectivePorts,\n\t\t\tcommand,\n\t\t\tlabels,\n\t\t\tnetworks,\n\t\t\tnetworkAttachments,\n\t\t};\n\t}).pipe(Effect.withSpan('runtime.docker.container.inspect'));\n\n// -----------------------------------------------------------------------------\n// Argv construction\n// -----------------------------------------------------------------------------\n\nconst normalizeNetworkAttachment = (\n\tentry: string | NetworkAttachment,\n): { readonly name: string; readonly aliases?: ReadonlyArray<string> } =>\n\ttypeof entry === 'string'\n\t\t? { name: entry }\n\t\t: entry.aliases === undefined || entry.aliases.length === 0\n\t\t\t? { name: entry.name }\n\t\t\t: { name: entry.name, aliases: entry.aliases };\n\nconst createArgv = (\n\tspec: EnsureContainerSpec,\n\tcycle: number,\n\timageRef: string,\n): ReadonlyArray<string> => {\n\tconst configLabels: Readonly<Record<string, string>> | undefined =\n\t\tspec.configHash === undefined ? undefined : { [LabelKey.configHash]: spec.configHash };\n\tconst labels = renderContainerLabels(spec.labels, cycle, configLabels);\n\t// First attach is rendered into `--network` + `--network-alias`;\n\t// subsequent attaches happen post-start via `network connect` so we\n\t// can wait for IP readback.\n\tconst firstNetwork =\n\t\tspec.networkAttach && spec.networkAttach.length > 0\n\t\t\t? normalizeNetworkAttachment(spec.networkAttach[0]!)\n\t\t\t: undefined;\n\treturn renderCreateArgs({\n\t\tname: spec.name,\n\t\timage: imageRef,\n\t\tlabels,\n\t\tenv: spec.env,\n\t\tports: spec.ports,\n\t\tmounts: spec.mounts,\n\t\tnetwork: firstNetwork,\n\t\taddHosts: spec.extraHosts,\n\t\tentrypoint: spec.entrypoint,\n\t\tcommand: spec.command,\n\t});\n};\n\n// -----------------------------------------------------------------------------\n// Apply the state machine\n// -----------------------------------------------------------------------------\n\nconst handleOf = (\n\tid: string,\n\tname: string,\n\timageName: string,\n\tstatus: ContainerHandle['status'],\n\tips: ReadonlyArray<string>,\n\tports?: ReadonlyArray<ContainerPortPublish>,\n\tlabels?: EnsureContainerSpec['labels'],\n): ContainerHandle => ({\n\tid,\n\tname,\n\t...(labels !== undefined ? { labels } : {}),\n\timageName,\n\tstatus,\n\tips,\n\t...(ports !== undefined ? { ports } : {}),\n});\n\n/** Force-remove by name. Used by recreate. Idempotent on\n * \"no such container\". */\nconst forceRemove = (\n\tname: string,\n): Effect.Effect<void, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst res = yield* dockerRunOk('rm', ['-f', name]).pipe(\n\t\t\tEffect.mapError(wrapGeneric('docker.rm')),\n\t\t);\n\t\tif (res.exitCode !== 0 && !isNoSuchContainerStderr(res.stderr)) {\n\t\t\t// best-effort; we surface as a span event but do not fail\n\t\t\t// the rm step (the next create will collision-recover).\n\t\t\tyield* Effect.annotateCurrentSpan({ 'docker.rm.warning': res.stderr });\n\t\t}\n\t}).pipe(Effect.withSpan('runtime.docker.container.forceRemove'));\n\nconst ownershipFailure = (\n\tname: string,\n\texpected: Readonly<Record<string, string>>,\n\tactual: Readonly<Record<string, string>>,\n\tdetail: string,\n): ForeignDockerResource =>\n\tnew ForeignDockerResource({\n\t\tresource: 'container',\n\t\tname,\n\t\texpected,\n\t\tactual,\n\t\tdetail,\n\t});\n\nconst assertOwnedFacts = (\n\tname: string,\n\tfacts: InspectFacts,\n\tlabels: EnsureContainerSpec['labels'],\n): Effect.Effect<void, DockerRuntimeError> =>\n\tEffect.gen(function* () {\n\t\tconst expected = expectedContainerOwnershipLabels(labels);\n\t\tconst actual = facts.labels ?? {};\n\t\tconst mismatch = ownershipMismatchDetail(expected, actual);\n\t\tif (mismatch !== null) {\n\t\t\treturn yield* Effect.fail(ownershipFailure(name, expected, actual, mismatch));\n\t\t}\n\t});\n\nconst failUnknownCollisionLifecycle = (\n\tname: string,\n\tstage: 'before-start' | 'after-start',\n): Effect.Effect<never, DockerRuntimeError> =>\n\tEffect.fail(\n\t\tnew ContainerNameCollisionUnrecoverable({\n\t\t\tname,\n\t\t\tdetail: `name collision recovery refused unknown lifecycle state ${stage}`,\n\t\t}),\n\t);\n\nexport const assertContainerHandleOwned = (\n\thandle: ContainerHandle,\n): Effect.Effect<void, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tif (handle.labels === undefined) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\townershipFailure(handle.name, {}, {}, 'container handle has no ownership labels'),\n\t\t\t);\n\t\t}\n\t\tconst facts = yield* inspectContainer(handle.name);\n\t\tconst expected = expectedContainerOwnershipLabels(handle.labels);\n\t\tif (facts === null) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\townershipFailure(handle.name, expected, {}, 'container is missing'),\n\t\t\t);\n\t\t}\n\t\tif (facts.id !== handle.id) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\townershipFailure(handle.name, expected, facts.labels ?? {}, `id changed to ${facts.id}`),\n\t\t\t);\n\t\t}\n\t\tyield* assertOwnedFacts(handle.name, facts, handle.labels);\n\t}).pipe(Effect.withSpan('runtime.docker.container.assertOwned'));\n\nconst forceRemoveOwned = (\n\tname: string,\n\tid: string,\n\tlabels: EnsureContainerSpec['labels'],\n): Effect.Effect<void, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst current = yield* inspectContainer(name);\n\t\tif (current === null) return;\n\t\tif (current.id !== id) {\n\t\t\tconst expected = expectedContainerOwnershipLabels(labels);\n\t\t\treturn yield* Effect.fail(\n\t\t\t\townershipFailure(name, expected, current.labels ?? {}, `id changed to ${current.id}`),\n\t\t\t);\n\t\t}\n\t\tyield* assertOwnedFacts(name, current, labels);\n\t\tyield* forceRemove(name);\n\t});\n\n/** Single-shot start-and-adopt fallback after `docker create` exit-125\n * with name-collision. Architecture §1 / G10 — one attempt; second\n * collision is a typed failure. */\nconst startAndAdopt = (\n\tname: string,\n\tlabels: EnsureContainerSpec['labels'],\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst beforeStart = yield* inspectContainer(name);\n\t\tif (beforeStart === null) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew ContainerNameCollisionUnrecoverable({\n\t\t\t\t\tname,\n\t\t\t\t\tdetail: 'name collision but inspect found no container',\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tyield* assertOwnedFacts(name, beforeStart, labels);\n\t\tif (beforeStart.lifecycle.kind === 'unknown') {\n\t\t\treturn yield* failUnknownCollisionLifecycle(name, 'before-start');\n\t\t}\n\t\tconst res = yield* dockerRunOk('start', [name]).pipe(\n\t\t\tEffect.mapError(wrapGeneric('docker.start')),\n\t\t);\n\t\tconst cls = classifyExit(res);\n\t\tif (cls.ok) {\n\t\t\tconst facts = yield* inspectContainer(name);\n\t\t\tif (facts === null) {\n\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\tnew ContainerNameCollisionUnrecoverable({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdetail: 'peer collision + start succeeded + inspect missed',\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\tyield* assertOwnedFacts(name, facts, labels);\n\t\t\tif (facts.lifecycle.kind === 'unknown') {\n\t\t\t\treturn yield* failUnknownCollisionLifecycle(name, 'after-start');\n\t\t\t}\n\t\t\treturn facts.id;\n\t\t}\n\t\tif (isNoSuchContainerStderr(cls.stderr)) {\n\t\t\t// Peer rm'd between our collision and the start. The caller's\n\t\t\t// outer loop will see this as \"missing\" and promote to fresh.\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew ContainerNameCollisionUnrecoverable({\n\t\t\t\t\tname,\n\t\t\t\t\tdetail: 'TOCTOU: start after collision found no container',\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn yield* Effect.fail(\n\t\t\tnew ContainerNameCollisionUnrecoverable({\n\t\t\t\tname,\n\t\t\t\tdetail: `start-and-adopt failed: ${cls.stderr}`,\n\t\t\t}),\n\t\t);\n\t});\n\nconst freshCreate = (\n\tspec: EnsureContainerSpec,\n\tcycle: number,\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst args = createArgv(spec, cycle, spec.image.tag ?? spec.image.digest);\n\t\tconst created = yield* dockerRun('run', args).pipe(Effect.mapError(wrapCreateError(spec.name)));\n\t\treturn created.stdout.trim();\n\t});\n\nconst resumeStart = (\n\tname: string,\n): Effect.Effect<\n\t{ readonly ok: true } | { readonly ok: false; readonly stderr: string },\n\tDockerRuntimeError,\n\tDockerHost | DockerSpawner\n> =>\n\tEffect.gen(function* () {\n\t\tconst res = yield* dockerRunOk('start', [name]).pipe(\n\t\t\tEffect.mapError(wrapGeneric('docker.start')),\n\t\t);\n\t\tif (res.exitCode === 0) return { ok: true as const };\n\t\tif (isDaemonUnreachableStderr(res.stderr)) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew DaemonUnreachable({\n\t\t\t\t\top: 'docker.start',\n\t\t\t\t\tdetail: 'docker daemon unreachable',\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn { ok: false as const, stderr: res.stderr };\n\t});\n\nconst recreateAfterResumeFailure = (\n\tid: string,\n\tspec: EnsureContainerSpec,\n\tdeps: EnsureContainerDeps,\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst routed = routeRecreate({ kind: 'recreate', id, reason: 'resume-failed' }, spec.recreate);\n\t\tif (routed.kind === 'refuse') {\n\t\t\treturn yield* Effect.fail(new RecreateRefused({ name: spec.name, reason: routed.reason }));\n\t\t}\n\t\tyield* forceRemoveOwned(spec.name, id, spec.labels);\n\t\treturn yield* createWithCollisionRecovery(spec, deps);\n\t});\n\nconst effectivePortsCompatible = (facts: InspectFacts, spec: EnsureContainerSpec): boolean => {\n\tconst desired = canonicalPortBindings(spec.ports);\n\tif (desired.length === 0) return true;\n\tconst actual = facts.effectivePortBindings ?? [];\n\tif (sameBindings(actual, desired)) return true;\n\treturn (\n\t\t(spec.portBindingReconciliation ?? 'exact') === 'adopt-existing' &&\n\t\tsameBindingContainerPorts(actual, desired)\n\t);\n};\n\nconst ensureEffectivePublishedPorts = (\n\tid: string,\n\tspec: EnsureContainerSpec,\n\tdeps: EnsureContainerDeps,\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tif ((spec.ports ?? []).length === 0) return id;\n\t\tconst facts = yield* inspectContainer(spec.name);\n\t\tif (facts === null || facts.id !== id || facts.lifecycle.kind !== 'running') return id;\n\t\tyield* assertOwnedFacts(spec.name, facts, spec.labels);\n\t\tif (effectivePortsCompatible(facts, spec)) return id;\n\t\tconst repairedId = yield* recreateAfterResumeFailure(id, spec, deps);\n\t\tconst repairedFacts = yield* inspectContainer(spec.name);\n\t\tif (\n\t\t\trepairedFacts !== null &&\n\t\t\trepairedFacts.id === repairedId &&\n\t\t\trepairedFacts.lifecycle.kind === 'running' &&\n\t\t\teffectivePortsCompatible(repairedFacts, spec)\n\t\t) {\n\t\t\treturn repairedId;\n\t\t}\n\t\treturn yield* Effect.fail(\n\t\t\tnew ContainerCreateFailed({\n\t\t\t\tname: spec.name,\n\t\t\t\tstderr: `container is running but Docker did not publish requested ports: desired=${JSON.stringify(\n\t\t\t\t\tcanonicalPortBindings(spec.ports),\n\t\t\t\t)} actual=${JSON.stringify(repairedFacts?.effectivePortBindings ?? [])}`,\n\t\t\t\texitCode: 0,\n\t\t\t}),\n\t\t);\n\t});\n\nconst stopWithGrace = (\n\tname: string,\n\tgraceSeconds: number,\n\tsignal?: string,\n): Effect.Effect<void, never, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst args: Array<string> = [];\n\t\tif (signal !== undefined) args.push('--signal', signal);\n\t\targs.push('--time', String(Math.max(0, Math.floor(graceSeconds))));\n\t\targs.push(name);\n\t\tyield* dockerRunOk('stop', args).pipe(\n\t\t\tEffect.tapCause((cause) =>\n\t\t\t\tEffect.logDebug('docker stop failed; container may already be gone', { name, cause }),\n\t\t\t),\n\t\t\tEffect.catch(() => Effect.void),\n\t\t\tEffect.asVoid,\n\t\t);\n\t});\n\n// -----------------------------------------------------------------------------\n// Public surface\n// -----------------------------------------------------------------------------\n\n/** Per-name lock state. Map entry present = name is held; the value is\n * the FIFO queue of waiter deferreds. Empty queue = held with no\n * waiters. Map entry absent = free. */\nexport type PerNameLockState = ReadonlyMap<string, ReadonlyArray<Deferred.Deferred<void>>>;\n\nexport interface EnsureContainerDeps {\n\t/** Current engine cycle id; stamped as the `devstack.cycle` label. */\n\treadonly cycle: number;\n\t/** Process-local lock holder to serialize per-name actions within\n\t * one Node process. Cross-process safety is the docker daemon's\n\t * `--name` atomicity. */\n\treadonly perNameLock: Ref.Ref<PerNameLockState>;\n}\n\n/** Per-name lock acquire/release. The in-process serialization is the\n * inspect→action window's invariant: two concurrent ensureContainer\n * calls for the same name must not race between the read (inspect)\n * and the write (create / start / recreate). Cross-process safety is\n * separately the docker daemon's `--name` atomicity.\n *\n * Implementation: a `Ref<Map<name, Deferred[]>>`. Acquire atomically\n * claims the slot (free → enter with empty queue) or enqueues a fresh\n * Deferred at the tail and awaits it. Release pops the head of the\n * queue and completes that waiter — transferring ownership without a\n * free intermediate window. Empty-queue release deletes the entry.\n * No wall-clock polling: contention parks fibers on Deferred.await\n * rather than spinning, so tests can use `it.effect` (TestClock) and\n * contended-acquire ordering is FIFO by construction.\n *\n * Exported for direct testing. */\nexport const acquirePerNameLock = (\n\tlock: Ref.Ref<PerNameLockState>,\n\tname: string,\n): Effect.Effect<void> =>\n\tEffect.gen(function* () {\n\t\tconst waiter = yield* Deferred.make<void>();\n\t\tconst claimed = yield* Ref.modify(lock, (m) => {\n\t\t\tconst queue = m.get(name);\n\t\t\tconst next = new Map(m);\n\t\t\tif (queue === undefined) {\n\t\t\t\t// Free → claim with empty waiter queue.\n\t\t\t\tnext.set(name, []);\n\t\t\t\treturn [true, next as PerNameLockState] as const;\n\t\t\t}\n\t\t\t// Held → enqueue and await.\n\t\t\tnext.set(name, [...queue, waiter]);\n\t\t\treturn [false, next as PerNameLockState] as const;\n\t\t});\n\t\tif (claimed) return;\n\t\t// Park until the current holder releases and completes our\n\t\t// deferred. Interrupt-cleanup mirrors the lease-broker pattern\n\t\t// (`substrate/runtime/lease-broker/service.ts:194-216`):\n\t\t// 1. If we're still queued → drop our deferred so a future\n\t\t// release doesn't transfer ownership to a dead waiter.\n\t\t// 2. If we are NO LONGER queued → a `releasePerNameLock`\n\t\t// already popped us as head (the ONLY way a queued waiter\n\t\t// leaves the queue) and transferred ownership to us, so we\n\t\t// release on our behalf to hand off to the next waiter.\n\t\t//\n\t\t// We discriminate on queue membership ALONE, not on\n\t\t// `Deferred.isDoneUnsafe(waiter)`: release pops the head (step 1\n\t\t// of releasePerNameLock's two-step transfer) and only THEN signals\n\t\t// the deferred (step 2). Between those steps the popped waiter is\n\t\t// already absent from the queue but its deferred is still pending;\n\t\t// keying on the signal would (incorrectly) classify us as \"still\n\t\t// queued\" and skip the release, orphaning the slot permanently.\n\t\t// A waiter that reached this await is only ever removed by a\n\t\t// release popping it, so \"not queued ⇒ promoted\" is exact —\n\t\t// matching the lease-broker, which keys off its explicit `holder`\n\t\t// field set atomically with the pop rather than the signal.\n\t\tyield* Deferred.await(waiter).pipe(\n\t\t\tEffect.onInterrupt(() =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst promotedButInterrupted = yield* Ref.modify(lock, (m) => {\n\t\t\t\t\t\tconst queue = m.get(name);\n\t\t\t\t\t\tif (queue === undefined) {\n\t\t\t\t\t\t\t// Entry gone entirely → a release fully drained\n\t\t\t\t\t\t\t// the slot (empty-queue delete) after popping us.\n\t\t\t\t\t\t\t// We held it; nothing to hand off.\n\t\t\t\t\t\t\treturn [false, m] as const;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst filtered = queue.filter((d) => d !== waiter);\n\t\t\t\t\t\tif (filtered.length !== queue.length) {\n\t\t\t\t\t\t\t// Still queued → drop ourselves; the holder\n\t\t\t\t\t\t\t// will release normally and skip us.\n\t\t\t\t\t\t\tconst next = new Map(m);\n\t\t\t\t\t\t\tnext.set(name, filtered);\n\t\t\t\t\t\t\treturn [false, next as PerNameLockState] as const;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Not queued, entry still present. A release already\n\t\t\t\t\t\t// popped us as head and transferred ownership; the\n\t\t\t\t\t\t// rest of the queue is waiting on us. Release on our\n\t\t\t\t\t\t// behalf so the next waiter proceeds.\n\t\t\t\t\t\treturn [true, m] as const;\n\t\t\t\t\t});\n\t\t\t\t\tif (promotedButInterrupted) {\n\t\t\t\t\t\tyield* releasePerNameLock(lock, name);\n\t\t\t\t\t}\n\t\t\t\t}).pipe(Effect.uninterruptible),\n\t\t\t),\n\t\t);\n\t});\n\nexport const releasePerNameLock = (\n\tlock: Ref.Ref<PerNameLockState>,\n\tname: string,\n): Effect.Effect<void> =>\n\tEffect.gen(function* () {\n\t\tconst head = yield* Ref.modify(lock, (m) => {\n\t\t\tconst queue = m.get(name);\n\t\t\tif (queue === undefined) return [undefined, m] as const;\n\t\t\tconst next = new Map(m);\n\t\t\tif (queue.length === 0) {\n\t\t\t\tnext.delete(name);\n\t\t\t\treturn [undefined, next as PerNameLockState] as const;\n\t\t\t}\n\t\t\tconst [first, ...rest] = queue;\n\t\t\tnext.set(name, rest);\n\t\t\treturn [first, next as PerNameLockState] as const;\n\t\t});\n\t\tif (head !== undefined) {\n\t\t\tyield* Deferred.succeed(head, undefined);\n\t\t}\n\t});\n\n/** Run `body` while holding the per-name lock for `name`. Wraps the\n * `acquireUseRelease(acquire, use, release)` triple so every caller\n * cannot accidentally forget the release on interrupt. The body is\n * responsible for running uninterruptibly over the inspect→action\n * window AND arming any stop-on-scope-close finalizer before this\n * helper releases the lock. */\nexport const withSerializedContainerOp = <A, E, R>(\n\tname: string,\n\tlock: Ref.Ref<PerNameLockState>,\n\tbody: Effect.Effect<A, E, R>,\n): Effect.Effect<A, E, R> =>\n\tEffect.acquireUseRelease(\n\t\tacquirePerNameLock(lock, name),\n\t\t() => body,\n\t\t() => releasePerNameLock(lock, name),\n\t);\n\n/** Idempotent ensure: apply the state machine, register a scope\n * finalizer that stops the container + releases the cross-process\n * claim.\n *\n * Returns the running container handle (id + name + status + ips). */\nexport const ensureContainer = (\n\tspec: EnsureContainerSpec,\n\tdeps: EnsureContainerDeps,\n): Effect.Effect<\n\tContainerHandle,\n\tDockerRuntimeError,\n\tDockerHost | DockerSpawner | StackPathsService | Scope.Scope\n> =>\n\tEffect.gen(function* () {\n\t\t// Per-name lock holds the inspect → applyAction → finalizer-registration\n\t\t// window. The lock CANNOT be released before the stop-on-scope-close\n\t\t// finalizer is armed: an interrupt or `addClaim` failure in that gap\n\t\t// would strand a running container with no scope-bound cleanup until\n\t\t// label-driven sweep ran later (per-scope contract: one\n\t\t// `Effect.scoped` ⇒ one container managed).\n\t\t//\n\t\t// The uninterruptible window is NARROWED to the orphan-safety\n\t\t// prefix: inspect → applyAction → ensureEffectivePublishedPorts →\n\t\t// `registerStopFinalizer`. That prefix MUST be uninterruptible so an\n\t\t// interrupt cannot land between \"container started\" and \"finalizer\n\t\t// armed\" (which would strand a running container with no scope-bound\n\t\t// cleanup). Once the stop-on-scope-close finalizer is armed, the\n\t\t// remaining work (assertOwned → secondary network attach → IP\n\t\t// readback → refresh inspect → `addClaim`) runs INTERRUPTIBLY via\n\t\t// `restore(...)`: an interrupt there simply triggers the armed\n\t\t// finalizer (stop + idempotent removeClaim), which is the desired\n\t\t// cleanup — so keeping that ~8s tail uninterruptible would only defer\n\t\t// Ctrl-C/shutdown for a bounded window with no orphan-safety benefit.\n\t\t// The finalizer itself is uninterruptible (Architecture §13).\n\t\tconst desiredImageRef = spec.image.tag ?? spec.image.digest;\n\t\tconst paths = yield* StackPathsService;\n\t\t// Preserve the substrate-side error taxonomy by surfacing a\n\t\t// distinct `op` per known cause tag. Labeling every roster/lock\n\t\t// failure as \"docker daemon unreachable\" misleads operators —\n\t\t// `RosterIoError` is a state-dir IO problem, `StackLockTimeoutError`\n\t\t// is a peer-holding-the-lock problem, neither of which has\n\t\t// anything to do with the docker socket. We still emit a typed\n\t\t// `DaemonUnreachable` envelope (substrate→docker channel needs\n\t\t// ONE bridging shape per the DockerRuntimeError union) but the\n\t\t// `op` / `detail` fields keep the original tag visible. A truly\n\t\t// unknown cause falls through to the legacy generic mapping.\n\t\tconst mapSubstrateClaimError = <A, R>(\n\t\t\teff: Effect.Effect<A, RosterError | StackLockError, R>,\n\t\t): Effect.Effect<A, DockerRuntimeError, R> =>\n\t\t\teff.pipe(\n\t\t\t\tEffect.catchTags({\n\t\t\t\t\tRosterIoError: (cause) =>\n\t\t\t\t\t\tEffect.fail(\n\t\t\t\t\t\t\tnew DaemonUnreachable({\n\t\t\t\t\t\t\t\top: 'cross-process.claim.roster-io',\n\t\t\t\t\t\t\t\tdetail: `roster IO failed at ${cause.path}`,\n\t\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\tRosterCorruptError: (cause) =>\n\t\t\t\t\t\tEffect.fail(\n\t\t\t\t\t\t\tnew DaemonUnreachable({\n\t\t\t\t\t\t\t\top: 'cross-process.claim.roster-corrupt',\n\t\t\t\t\t\t\t\tdetail: `roster ledger corrupt at ${cause.path}`,\n\t\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\tStackLockTimeoutError: (cause) =>\n\t\t\t\t\t\tEffect.fail(\n\t\t\t\t\t\t\tnew DaemonUnreachable({\n\t\t\t\t\t\t\t\top: 'cross-process.claim.stack-lock-timeout',\n\t\t\t\t\t\t\t\tdetail: `stack-lock acquire timed out after ${cause.waitedMillis}ms at ${cause.path}`,\n\t\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\tStackLockIoError: (cause) =>\n\t\t\t\t\t\tEffect.fail(\n\t\t\t\t\t\t\tnew DaemonUnreachable({\n\t\t\t\t\t\t\t\top: 'cross-process.claim.stack-lock-io',\n\t\t\t\t\t\t\t\tdetail: `stack-lock IO failed at ${cause.path}`,\n\t\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t);\n\t\tconst registerStopFinalizer = (\n\t\t\tid: string,\n\t\t): Effect.Effect<void, never, Scope.Scope | DockerHost | DockerSpawner> =>\n\t\t\tEffect.addFinalizer(() =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t// Restore may deliberately remove a claimed container and\n\t\t\t\t\t// a later acquire may reuse the name before this scope\n\t\t\t\t\t// closes; the old finalizer must not stop that newer\n\t\t\t\t\t// container — hence the id check.\n\t\t\t\t\tconst current = yield* inspectContainer(spec.name).pipe(\n\t\t\t\t\t\tEffect.tapCause((cause) =>\n\t\t\t\t\t\t\tEffect.logDebug('container inspect during scope-close failed', {\n\t\t\t\t\t\t\t\tname: spec.name,\n\t\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tEffect.catch(() => Effect.succeed(null)),\n\t\t\t\t\t);\n\t\t\t\t\tif (current?.id === id) {\n\t\t\t\t\t\tyield* stopWithGrace(spec.name, spec.stopGraceSeconds ?? 10);\n\t\t\t\t\t}\n\t\t\t\t\tyield* removeClaim(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstackLockFile: paths.stackLockFile,\n\t\t\t\t\t\t\trosterFile: paths.rosterFile,\n\t\t\t\t\t\t\tcontainerClaimsFile: paths.containerClaimsFile,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tspec.name,\n\t\t\t\t\t).pipe(\n\t\t\t\t\t\tEffect.tapCause((cause) =>\n\t\t\t\t\t\t\tEffect.logDebug('removeClaim during scope-close failed', {\n\t\t\t\t\t\t\t\tname: spec.name,\n\t\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tEffect.catch(() => Effect.succeed({ lastClaimReleased: false })),\n\t\t\t\t\t);\n\t\t\t\t}).pipe(Effect.uninterruptible),\n\t\t\t);\n\t\tconst { id, ips, ports } = yield* withSerializedContainerOp(\n\t\t\tspec.name,\n\t\t\tdeps.perNameLock,\n\t\t\tEffect.uninterruptibleMask((restore) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t// --- Orphan-safety prefix (uninterruptible) ---\n\t\t\t\t\t// inspect → applyAction → publish-ports → finalizer-arm\n\t\t\t\t\t// must run atomically: a stranded running container with\n\t\t\t\t\t// no scope-bound cleanup is the failure this guards.\n\t\t\t\t\tconst facts = yield* inspectContainer(spec.name);\n\t\t\t\t\tif (facts !== null) {\n\t\t\t\t\t\tyield* assertOwnedFacts(spec.name, facts, spec.labels);\n\t\t\t\t\t}\n\t\t\t\t\tconst action = decideRunAction(\n\t\t\t\t\t\tfacts,\n\t\t\t\t\t\tdesiredImageRef,\n\t\t\t\t\t\tspec.recreate,\n\t\t\t\t\t\tcanonicalPortBindings(spec.ports),\n\t\t\t\t\t\tspec.portBindingReconciliation ?? 'exact',\n\t\t\t\t\t\tspec.configHash,\n\t\t\t\t\t\tspec.image.digest,\n\t\t\t\t\t\tspec.networkAttach,\n\t\t\t\t\t);\n\t\t\t\t\tconst initialId = yield* applyAction(action, spec, deps);\n\t\t\t\t\tconst id = yield* ensureEffectivePublishedPorts(initialId, spec, deps);\n\n\t\t\t\t\t// Arm the stop-on-scope-close finalizer BEFORE we\n\t\t\t\t\t// release the per-name lock and BEFORE we call\n\t\t\t\t\t// `addClaim`. If anything below this point fails OR is\n\t\t\t\t\t// interrupted (assert, network attach, addClaim) the\n\t\t\t\t\t// container will still be stopped at scope close.\n\t\t\t\t\tyield* registerStopFinalizer(id);\n\n\t\t\t\t\t// --- Interruptible tail (restore) ---\n\t\t\t\t\t// The finalizer is now armed, so an interrupt here is\n\t\t\t\t\t// safe: it triggers the scope finalizer (stop + idempotent\n\t\t\t\t\t// removeClaim). Running this ~8s tail interruptibly keeps\n\t\t\t\t\t// Ctrl-C/shutdown responsive during bring-up.\n\t\t\t\t\tconst tail = yield* restore(\n\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\tyield* assertContainerHandleOwned({\n\t\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\t\tname: spec.name,\n\t\t\t\t\t\t\t\tlabels: spec.labels,\n\t\t\t\t\t\t\t\timageName: spec.image.tag ?? spec.image.digest,\n\t\t\t\t\t\t\t\tstatus: 'running',\n\t\t\t\t\t\t\t\tips: [],\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t// Architecture §5 — secondary network attaches (any\n\t\t\t\t\t\t\t// beyond the first, which is wired in via `--network`\n\t\t\t\t\t\t\t// on create) must wait for IP allocation before we\n\t\t\t\t\t\t\t// declare ready.\n\t\t\t\t\t\t\tconst secondaries = (spec.networkAttach ?? [])\n\t\t\t\t\t\t\t\t.slice(1)\n\t\t\t\t\t\t\t\t.map(normalizeNetworkAttachment);\n\t\t\t\t\t\t\tfor (const net of secondaries) {\n\t\t\t\t\t\t\t\tyield* connect(spec.name, net.name, net.aliases);\n\t\t\t\t\t\t\t\tyield* waitForIp(spec.name, net.name);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst ips = yield* readIps(spec.name);\n\t\t\t\t\t\t\tconst refreshedFacts = yield* inspectContainer(spec.name);\n\t\t\t\t\t\t\tconst ports = refreshedFacts?.effectivePorts ?? refreshedFacts?.ports ?? spec.ports;\n\n\t\t\t\t\t\t\t// Record cross-process claim. The scope finalizer\n\t\t\t\t\t\t\t// (already registered) will release it on scope\n\t\t\t\t\t\t\t// close. If this fails, the container is still\n\t\t\t\t\t\t\t// cleaned up at scope close.\n\t\t\t\t\t\t\tyield* mapSubstrateClaimError(\n\t\t\t\t\t\t\t\taddClaim(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tstackLockFile: paths.stackLockFile,\n\t\t\t\t\t\t\t\t\t\trosterFile: paths.rosterFile,\n\t\t\t\t\t\t\t\t\t\tcontainerClaimsFile: paths.containerClaimsFile,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tspec.name,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\treturn { ips, ports };\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\n\t\t\t\t\treturn { id, ips: tail.ips, ports: tail.ports };\n\t\t\t\t}),\n\t\t\t),\n\t\t);\n\n\t\treturn handleOf(\n\t\t\tid,\n\t\t\tspec.name,\n\t\t\tspec.image.tag ?? spec.image.digest,\n\t\t\t'running',\n\t\t\tips,\n\t\t\tports,\n\t\t\tspec.labels,\n\t\t);\n\t}).pipe(Effect.withSpan('runtime.docker.container.ensure'));\n\n/** Apply the decided action. Recovers from name-collision via\n * one-shot start-and-adopt; second collision surfaces typed. */\nconst applyAction = (\n\taction: RunAction,\n\tspec: EnsureContainerSpec,\n\tdeps: EnsureContainerDeps,\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner | Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tswitch (action.kind) {\n\t\t\tcase 'adopt':\n\t\t\t\treturn action.id;\n\t\t\tcase 'unpause-adopt':\n\t\t\t\tyield* assertContainerHandleOwned({\n\t\t\t\t\tid: action.id,\n\t\t\t\t\tname: spec.name,\n\t\t\t\t\tlabels: spec.labels,\n\t\t\t\t\timageName: spec.image.tag ?? spec.image.digest,\n\t\t\t\t\tstatus: 'paused',\n\t\t\t\t\tips: [],\n\t\t\t\t});\n\t\t\t\tyield* unpause(spec.name);\n\t\t\t\treturn action.id;\n\t\t\tcase 'resume': {\n\t\t\t\tyield* assertContainerHandleOwned({\n\t\t\t\t\tid: action.id,\n\t\t\t\t\tname: spec.name,\n\t\t\t\t\tlabels: spec.labels,\n\t\t\t\t\timageName: spec.image.tag ?? spec.image.digest,\n\t\t\t\t\tstatus: 'exited',\n\t\t\t\t\tips: [],\n\t\t\t\t});\n\t\t\t\tconst started = yield* resumeStart(spec.name);\n\t\t\t\tif (!started.ok) {\n\t\t\t\t\treturn yield* recreateAfterResumeFailure(action.id, spec, deps);\n\t\t\t\t}\n\t\t\t\treturn action.id;\n\t\t\t}\n\t\t\tcase 'recreate': {\n\t\t\t\tyield* forceRemoveOwned(spec.name, action.id, spec.labels);\n\t\t\t\treturn yield* createWithCollisionRecovery(spec, deps);\n\t\t\t}\n\t\t\tcase 'fresh':\n\t\t\t\treturn yield* createWithCollisionRecovery(spec, deps);\n\t\t\tcase 'refuse':\n\t\t\t\treturn yield* Effect.fail(new RecreateRefused({ name: spec.name, reason: action.reason }));\n\t\t}\n\t});\n\n/** `docker run -d` with single-shot start-and-adopt fallback on\n * name-collision. */\nconst createWithCollisionRecovery = (\n\tspec: EnsureContainerSpec,\n\tdeps: EnsureContainerDeps,\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tfreshCreate(spec, deps.cycle).pipe(\n\t\tEffect.catchTag('ContainerNameCollisionUnrecoverable', () =>\n\t\t\tstartAndAdopt(spec.name, spec.labels),\n\t\t),\n\t\t// If the original create surfaced a typed `ContainerCreateFailed`\n\t\t// where stderr was name-collision (sometimes the create variant\n\t\t// surfaces with that), attempt the same start-and-adopt.\n\t\tEffect.catchTag('ContainerCreateFailed', (err) =>\n\t\t\tisNameCollisionStderr(err.stderr) ? startAndAdopt(spec.name, spec.labels) : Effect.fail(err),\n\t\t),\n\t);\n\n// -----------------------------------------------------------------------------\n// Stop / commit / pause — used by the snapshot orchestrator\n// -----------------------------------------------------------------------------\n\nexport const stop = (\n\tname: string,\n\tgraceSeconds: number,\n\tsignal?: string,\n): Effect.Effect<void, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tstopWithGrace(name, graceSeconds, signal).pipe(Effect.asVoid);\n\nexport const pause = (\n\tname: string,\n): Effect.Effect<void, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tyield* dockerRun('pause', [name]).pipe(Effect.mapError(wrapGeneric('docker.pause')));\n\t}).pipe(Effect.withSpan('runtime.docker.container.pause'));\n\nexport const unpause = (\n\tname: string,\n): Effect.Effect<void, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tyield* dockerRun('unpause', [name]).pipe(Effect.mapError(wrapGeneric('docker.unpause')));\n\t}).pipe(Effect.withSpan('runtime.docker.container.unpause'));\n\n/** Reserved `devstack.role` value stamped on every committed snapshot\n * byproduct image. Plugin BUILD images carry the source plugin's real\n * role (`db`, `validator`, …) or no role at all; committed snapshot\n * images carry THIS sentinel instead. Snapshot prune scopes its image\n * sweep to `{app, stack, role: SNAPSHOT_IMAGE_ROLE}` so it reaps the\n * byproducts WITHOUT ever matching the live stack's build images.\n *\n * This is a label-value protocol token shared with the snapshot prune\n * orchestrator (`orchestrators/snapshot/prune.ts`), which imports it. */\nexport const SNAPSHOT_IMAGE_ROLE = 'snapshot-image';\n\n/** Render `{managed, app, stack, role}` ownership labels into\n * `docker commit --change 'LABEL …'` argv. `docker commit` has no\n * `--label` flag, so labels must ride in as `--change` Dockerfile\n * instructions. Values are quoted so an app/stack carrying whitespace\n * cannot split the instruction. */\nconst snapshotImageChangeArgs = (\n\tapp: string | undefined,\n\tstack: string | undefined,\n): ReadonlyArray<string> => {\n\tconst labels: Array<[string, string]> = [[LabelKey.managed, 'true']];\n\tif (app !== undefined) labels.push([LabelKey.app, app]);\n\tif (stack !== undefined) labels.push([LabelKey.stack, stack]);\n\tlabels.push([LabelKey.role, SNAPSHOT_IMAGE_ROLE]);\n\treturn labels.flatMap(([key, value]) => ['--change', `LABEL \"${key}\"=\"${value}\"`]);\n};\n\n/** `docker commit <name> <tag>` — writable layer → image. Used by\n * snapshot capture.\n *\n * The committed image is stamped with `{managed:'true', app, stack,\n * role:SNAPSHOT_IMAGE_ROLE}` ownership labels so label-driven snapshot\n * prune can reap leaked byproducts (a hard-killed capture that never\n * reached its `removeImage` cleanup) while leaving the stack's build\n * images untouched. A bare `docker commit` produces an UNlabelled image\n * that no label-driven sweep can find — hence the explicit stamp.\n *\n * `app`/`stack` are recovered from the source container's own ownership\n * labels (`docker commit` does NOT copy container labels onto the image).\n * Capture only commits containers it owns, so those labels are present;\n * if the inspect misses they are simply omitted and prune's app/stack-\n * scoped filter will not match — a degenerate case capture cannot reach. */\nexport const commit = (\n\tname: string,\n\ttag: string,\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\t// Recover the source container's app/stack so the committed image\n\t\t// inherits the SAME ownership scope. Best-effort: a failed inspect\n\t\t// must not abort the commit (the image is the product; labels are\n\t\t// metadata), so degrade to the role-only stamp.\n\t\tconst facts = yield* inspectContainer(name).pipe(Effect.catch(() => Effect.succeed(null)));\n\t\tconst sourceLabels = facts?.labels ?? {};\n\t\tconst changeArgs = snapshotImageChangeArgs(\n\t\t\tsourceLabels[LabelKey.app],\n\t\t\tsourceLabels[LabelKey.stack],\n\t\t);\n\t\tconst res = yield* dockerRun('commit', [...changeArgs, name, tag]).pipe(\n\t\t\tEffect.mapError(wrapGeneric('docker.commit')),\n\t\t);\n\t\tconst digest = res.stdout.trim();\n\t\tif (digest.length === 0) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew ContainerCreateFailed({\n\t\t\t\t\tname,\n\t\t\t\t\tstderr: 'commit returned empty digest',\n\t\t\t\t\texitCode: 0,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn digest;\n\t}).pipe(Effect.withSpan('runtime.docker.container.commit'));\n"],"mappings":"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"}
|
|
@@ -19,7 +19,6 @@ var ContainerPortPublishConflict = class extends Data.TaggedError("ContainerPort
|
|
|
19
19
|
* start-and-adopt fallback ALSO failed. Architecture forbids the
|
|
20
20
|
* infinite-loop retry; one shot at adopt then surface this. */
|
|
21
21
|
var ContainerNameCollisionUnrecoverable = class extends Data.TaggedError("ContainerNameCollisionUnrecoverable") {};
|
|
22
|
-
Data.TaggedError("ContainerExited");
|
|
23
22
|
/** `docker rm -f` failed while deliberately replacing a managed
|
|
24
23
|
* container set. Unlike orphan sweep, restore cannot silently leave
|
|
25
24
|
* the old writable layer in place. */
|
|
@@ -104,11 +103,6 @@ const toContractError = (err) => {
|
|
|
104
103
|
reason: "publish-port-conflict",
|
|
105
104
|
detail: `${err.name}: ${err.stderr}`
|
|
106
105
|
};
|
|
107
|
-
case "ContainerExited": return {
|
|
108
|
-
_tag: "ContainerRuntimeError",
|
|
109
|
-
reason: "ready-probe-failed",
|
|
110
|
-
detail: `${err.name} exited ${err.exitCode}: ${err.logTail}`
|
|
111
|
-
};
|
|
112
106
|
case "ContainerRemoveFailed": return {
|
|
113
107
|
_tag: "ContainerRuntimeError",
|
|
114
108
|
reason: "container-replace-failed",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.mjs","names":[],"sources":["../../../src/runtime/docker/errors.ts"],"sourcesContent":["// Docker runtime — typed error envelopes.\n//\n// Architecture inverts the legacy \"stderr-pattern wording\" coupling:\n// the public surface speaks in typed errors (`ImageNotFound`,\n// `BuildFailed`, …); raw `CaptureError`s from the subprocess seam\n// are translated by `wrap.ts` into these envelopes.\n//\n// Every error is `Data.TaggedError` so callers can `Effect.catchTag`\n// the precise failure mode.\n\nimport { Data } from 'effect';\n\nimport type { ContainerRuntimeError } from '../../contracts/container-runtime.ts';\n\n/** Daemon connection failure. The CLI returned the \"Cannot connect to\n * the Docker daemon\" pattern, or the binary is missing. */\nexport class DaemonUnreachable extends Data.TaggedError('DaemonUnreachable')<{\n\treadonly op: string;\n\treadonly detail: string;\n\treadonly cause?: unknown;\n}> {}\n\n/** Image pull / inspect could not locate the requested image. */\nexport class ImageNotFound extends Data.TaggedError('ImageNotFound')<{\n\treadonly ref: string;\n\treadonly detail: string;\n}> {}\n\n/** `docker pull` non-zero exit (network / auth / unknown ref). */\nexport class ImagePullFailed extends Data.TaggedError('ImagePullFailed')<{\n\treadonly ref: string;\n\treadonly stderr: string;\n\treadonly exitCode: number | undefined;\n}> {}\n\n/** `docker build` non-zero exit. `parsedStep` is best-effort —\n * populated by `wrap.ts` when the build log surfaces a clear failing\n * step line. */\nexport class BuildFailed extends Data.TaggedError('BuildFailed')<{\n\treadonly contextPath: string;\n\treadonly dockerfile: string | undefined;\n\treadonly stderr: string;\n\treadonly parsedStep?: string;\n\treadonly exitCode: number | undefined;\n}> {}\n\n/** `docker create` / `docker run -d` rejected; not a name collision. */\nexport class ContainerCreateFailed extends Data.TaggedError('ContainerCreateFailed')<{\n\treadonly name: string;\n\treadonly stderr: string;\n\treadonly exitCode: number | undefined;\n}> {}\n\n/** `docker run -d -p ...` lost the probe-to-publish race. */\nexport class ContainerPortPublishConflict extends Data.TaggedError('ContainerPortPublishConflict')<{\n\treadonly name: string;\n\treadonly stderr: string;\n\treadonly exitCode: number | undefined;\n}> {}\n\n/** Name-collision recovery exhausted: peer beat us and the\n * start-and-adopt fallback ALSO failed. Architecture forbids the\n * infinite-loop retry; one shot at adopt then surface this. */\nexport class ContainerNameCollisionUnrecoverable extends Data.TaggedError(\n\t'ContainerNameCollisionUnrecoverable',\n)<{\n\treadonly name: string;\n\treadonly detail: string;\n}> {}\n\n/** Container exited (non-zero or unexpected) during the run. */\nexport class ContainerExited extends Data.TaggedError('ContainerExited')<{\n\treadonly name: string;\n\treadonly exitCode: number;\n\treadonly logTail: string;\n}> {}\n\n/** `docker rm -f` failed while deliberately replacing a managed\n * container set. Unlike orphan sweep, restore cannot silently leave\n * the old writable layer in place. */\nexport class ContainerRemoveFailed extends Data.TaggedError('ContainerRemoveFailed')<{\n\treadonly name: string;\n\treadonly stderr: string;\n\treadonly exitCode: number | undefined;\n}> {}\n\nexport type DockerResourceKind = 'container' | 'network' | 'volume';\n\n/** Docker inspect failed for a reason other than \"not found\". */\nexport class DockerInspectFailed extends Data.TaggedError('DockerInspectFailed')<{\n\treadonly resource: DockerResourceKind;\n\treadonly name: string;\n\treadonly stderr: string;\n\treadonly exitCode: number | undefined;\n}> {}\n\n/** Docker inspect returned malformed JSON or a shape outside the\n * runtime's expected schema. */\nexport class DockerInspectDecodeFailed extends Data.TaggedError('DockerInspectDecodeFailed')<{\n\treadonly resource: DockerResourceKind;\n\treadonly name: string;\n\treadonly detail: string;\n\treadonly cause?: unknown;\n}> {}\n\n/** A same-name Docker resource exists but is not owned by the expected\n * devstack label tuple, so mutating it would cross stack/plugin\n * boundaries. */\nexport class ForeignDockerResource extends Data.TaggedError('ForeignDockerResource')<{\n\treadonly resource: DockerResourceKind;\n\treadonly name: string;\n\treadonly expected: Readonly<Record<string, string>>;\n\treadonly actual: Readonly<Record<string, string>>;\n\treadonly detail: string;\n}> {}\n\n/** `docker network connect` / `network create` failure that isn't the\n * idempotent \"already exists in network\" case. */\nexport class NetworkOperationFailed extends Data.TaggedError('NetworkOperationFailed')<{\n\treadonly op: 'create' | 'connect' | 'disconnect' | 'inspect' | 'remove';\n\treadonly network: string;\n\treadonly stderr: string;\n}> {}\n\n/** `docker network create` exhausted Docker's default bridge IPAM\n * pools. This is not a daemon reachability failure; stale long-lived\n * networks or missing explicit subnet/gateway policy are the usual\n * causes. */\nexport class NetworkAddressPoolExhausted extends Data.TaggedError('NetworkAddressPoolExhausted')<{\n\treadonly network: string;\n\treadonly stderr: string;\n\treadonly hint: string;\n}> {}\n\n/** Container's IP on a secondary network was not allocated within the\n * bounded poll budget. Architecture § Async network-connect. */\nexport class NetworkIpReadbackTimeout extends Data.TaggedError('NetworkIpReadbackTimeout')<{\n\treadonly container: string;\n\treadonly network: string;\n\treadonly waitedMillis: number;\n}> {}\n\n/** Volume create / inspect failed. */\nexport class VolumeOperationFailed extends Data.TaggedError('VolumeOperationFailed')<{\n\treadonly op: 'create' | 'inspect' | 'remove';\n\treadonly volume: string;\n\treadonly stderr: string;\n}> {}\n\n/** Recreate was refused — the caller's `RecreatePolicy` was `never`\n * but the lifecycle state machine concluded recreate was required\n * (image/config mismatch, unclean exit, unknown state). Caller must explicitly opt\n * in to a recreate to proceed (architecture G1 — Move-build-\n * container's no-auto-recreate case). */\nexport class RecreateRefused extends Data.TaggedError('RecreateRefused')<{\n\treadonly name: string;\n\treadonly reason:\n\t\t| 'image-mismatch'\n\t\t| 'config-mismatch'\n\t\t| 'unclean-shutdown'\n\t\t| 'resume-failed'\n\t\t| 'unknown-state';\n}> {}\n\n/** Generic exec / one-shot failure when the caller asked us to\n * promote a non-zero exit. */\nexport class ExecFailed extends Data.TaggedError('ExecFailed')<{\n\treadonly name: string;\n\treadonly argv: ReadonlyArray<string>;\n\treadonly exitCode: number;\n\treadonly stderr: string;\n}> {}\n\n/** `docker save` failed — daemon error, missing image, or pipe failure\n * draining stdout. */\nexport class ImageSaveFailed extends Data.TaggedError('ImageSaveFailed')<{\n\treadonly ref: string;\n\treadonly detail: string;\n\treadonly cause?: unknown;\n}> {}\n\n/** `docker load` failed — corrupt tar, daemon error, or no `Loaded\n * image:` line parsed from stdout. */\nexport class ImageLoadFailed extends Data.TaggedError('ImageLoadFailed')<{\n\treadonly detail: string;\n\treadonly stderr?: string;\n\treadonly cause?: unknown;\n}> {}\n\n/** `docker tag` failed — source image missing or invalid tag string. */\nexport class ImageTagFailed extends Data.TaggedError('ImageTagFailed')<{\n\treadonly src: string;\n\treadonly dst: string;\n\treadonly stderr: string;\n}> {}\n\n/** `docker image rm` failed while removing managed snapshot/build\n * byproducts. */\nexport class ImageRemoveFailed extends Data.TaggedError('ImageRemoveFailed')<{\n\treadonly ref: string;\n\treadonly stderr: string;\n\treadonly exitCode: number | undefined;\n}> {}\n\n/** Union of every docker-runtime typed error. */\nexport type DockerRuntimeError =\n\t| DaemonUnreachable\n\t| ImageNotFound\n\t| ImagePullFailed\n\t| BuildFailed\n\t| ContainerCreateFailed\n\t| ContainerPortPublishConflict\n\t| ContainerNameCollisionUnrecoverable\n\t| ContainerExited\n\t| ContainerRemoveFailed\n\t| DockerInspectFailed\n\t| DockerInspectDecodeFailed\n\t| ForeignDockerResource\n\t| NetworkOperationFailed\n\t| NetworkAddressPoolExhausted\n\t| NetworkIpReadbackTimeout\n\t| VolumeOperationFailed\n\t| RecreateRefused\n\t| ExecFailed\n\t| ImageSaveFailed\n\t| ImageLoadFailed\n\t| ImageTagFailed\n\t| ImageRemoveFailed;\n\n/** Project a typed `DockerRuntimeError` into the contract-shaped\n * `ContainerRuntimeError`. The contract is intentionally narrow\n * (`reason` is a closed enum); plugins that want the precise tag\n * can `Effect.catchTag` against the typed errors BEFORE the contract\n * projection runs. */\nexport const toContractError = (err: DockerRuntimeError): ContainerRuntimeError => {\n\tswitch (err._tag) {\n\t\tcase 'DaemonUnreachable':\n\t\t\treturn { _tag: 'ContainerRuntimeError', reason: 'daemon-unreachable', detail: err.detail };\n\t\tcase 'ImageNotFound':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'image-build-failed',\n\t\t\t\tdetail: `${err.ref}: ${err.detail}`,\n\t\t\t};\n\t\tcase 'ImagePullFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'image-build-failed',\n\t\t\t\tdetail: `pull ${err.ref} failed: ${err.stderr}`,\n\t\t\t};\n\t\tcase 'BuildFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'image-build-failed',\n\t\t\t\tdetail: err.parsedStep ?? err.stderr,\n\t\t\t};\n\t\tcase 'ContainerCreateFailed':\n\t\tcase 'ContainerNameCollisionUnrecoverable':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'name-collision',\n\t\t\t\tdetail: 'detail' in err ? err.detail : err.stderr,\n\t\t\t};\n\t\tcase 'ContainerPortPublishConflict':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'publish-port-conflict',\n\t\t\t\tdetail: `${err.name}: ${err.stderr}`,\n\t\t\t};\n\t\tcase 'ContainerExited':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'ready-probe-failed',\n\t\t\t\tdetail: `${err.name} exited ${err.exitCode}: ${err.logTail}`,\n\t\t\t};\n\t\tcase 'ContainerRemoveFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'container-replace-failed',\n\t\t\t\tdetail: `${err.name}: ${err.stderr}`,\n\t\t\t};\n\t\tcase 'DockerInspectFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'docker-inspect-failed',\n\t\t\t\tdetail: `${err.resource} ${err.name}: ${err.stderr}`,\n\t\t\t};\n\t\tcase 'DockerInspectDecodeFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'docker-inspect-failed',\n\t\t\t\tdetail: `${err.resource} ${err.name}: ${err.detail}`,\n\t\t\t};\n\t\tcase 'ForeignDockerResource':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'foreign-resource',\n\t\t\t\tdetail: `${err.resource} ${err.name}: ${err.detail}`,\n\t\t\t};\n\t\tcase 'NetworkOperationFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'daemon-unreachable',\n\t\t\t\tdetail: `network ${err.op} ${err.network}: ${err.stderr}`,\n\t\t\t};\n\t\tcase 'NetworkAddressPoolExhausted':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'network-address-pool-exhausted',\n\t\t\t\tdetail: `network create ${err.network}: ${err.hint} stderr=${err.stderr}`,\n\t\t\t};\n\t\tcase 'NetworkIpReadbackTimeout':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'ip-readback-timeout',\n\t\t\t\tdetail: `${err.container} on ${err.network} after ${err.waitedMillis}ms`,\n\t\t\t};\n\t\tcase 'VolumeOperationFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'daemon-unreachable',\n\t\t\t\tdetail: `volume ${err.op} ${err.volume}: ${err.stderr}`,\n\t\t\t};\n\t\tcase 'RecreateRefused':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'recreate-refused',\n\t\t\t\tdetail: `${err.name}: ${err.reason}`,\n\t\t\t};\n\t\tcase 'ExecFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'ready-probe-failed',\n\t\t\t\tdetail: `exec ${err.name} exit ${err.exitCode}: ${err.stderr}`,\n\t\t\t};\n\t\tcase 'ImageSaveFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'image-save-failed',\n\t\t\t\tdetail: `${err.ref}: ${err.detail}`,\n\t\t\t};\n\t\tcase 'ImageLoadFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'image-load-failed',\n\t\t\t\tdetail: err.stderr !== undefined ? `${err.detail}: ${err.stderr}` : err.detail,\n\t\t\t};\n\t\tcase 'ImageTagFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'image-tag-failed',\n\t\t\t\tdetail: `${err.src} → ${err.dst}: ${err.stderr}`,\n\t\t\t};\n\t\tcase 'ImageRemoveFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'image-remove-failed',\n\t\t\t\tdetail: `${err.ref}: ${err.stderr}`,\n\t\t\t};\n\t}\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"errors.mjs","names":[],"sources":["../../../src/runtime/docker/errors.ts"],"sourcesContent":["// Docker runtime — typed error envelopes.\n//\n// Architecture inverts the legacy \"stderr-pattern wording\" coupling:\n// the public surface speaks in typed errors (`ImageNotFound`,\n// `BuildFailed`, …); raw `CaptureError`s from the subprocess seam\n// are translated by `wrap.ts` into these envelopes.\n//\n// Every error is `Data.TaggedError` so callers can `Effect.catchTag`\n// the precise failure mode.\n\nimport { Data } from 'effect';\n\nimport type { ContainerRuntimeError } from '../../contracts/container-runtime.ts';\n\n/** Daemon connection failure. The CLI returned the \"Cannot connect to\n * the Docker daemon\" pattern, or the binary is missing. */\nexport class DaemonUnreachable extends Data.TaggedError('DaemonUnreachable')<{\n\treadonly op: string;\n\treadonly detail: string;\n\treadonly cause?: unknown;\n}> {}\n\n/** Image pull / inspect could not locate the requested image. */\nexport class ImageNotFound extends Data.TaggedError('ImageNotFound')<{\n\treadonly ref: string;\n\treadonly detail: string;\n}> {}\n\n/** `docker pull` non-zero exit (network / auth / unknown ref). */\nexport class ImagePullFailed extends Data.TaggedError('ImagePullFailed')<{\n\treadonly ref: string;\n\treadonly stderr: string;\n\treadonly exitCode: number | undefined;\n}> {}\n\n/** `docker build` non-zero exit. `parsedStep` is best-effort —\n * populated by `wrap.ts` when the build log surfaces a clear failing\n * step line. */\nexport class BuildFailed extends Data.TaggedError('BuildFailed')<{\n\treadonly contextPath: string;\n\treadonly dockerfile: string | undefined;\n\treadonly stderr: string;\n\treadonly parsedStep?: string;\n\treadonly exitCode: number | undefined;\n}> {}\n\n/** `docker create` / `docker run -d` rejected; not a name collision. */\nexport class ContainerCreateFailed extends Data.TaggedError('ContainerCreateFailed')<{\n\treadonly name: string;\n\treadonly stderr: string;\n\treadonly exitCode: number | undefined;\n}> {}\n\n/** `docker run -d -p ...` lost the probe-to-publish race. */\nexport class ContainerPortPublishConflict extends Data.TaggedError('ContainerPortPublishConflict')<{\n\treadonly name: string;\n\treadonly stderr: string;\n\treadonly exitCode: number | undefined;\n}> {}\n\n/** Name-collision recovery exhausted: peer beat us and the\n * start-and-adopt fallback ALSO failed. Architecture forbids the\n * infinite-loop retry; one shot at adopt then surface this. */\nexport class ContainerNameCollisionUnrecoverable extends Data.TaggedError(\n\t'ContainerNameCollisionUnrecoverable',\n)<{\n\treadonly name: string;\n\treadonly detail: string;\n}> {}\n\n/** `docker rm -f` failed while deliberately replacing a managed\n * container set. Unlike orphan sweep, restore cannot silently leave\n * the old writable layer in place. */\nexport class ContainerRemoveFailed extends Data.TaggedError('ContainerRemoveFailed')<{\n\treadonly name: string;\n\treadonly stderr: string;\n\treadonly exitCode: number | undefined;\n}> {}\n\nexport type DockerResourceKind = 'container' | 'network' | 'volume';\n\n/** Docker inspect failed for a reason other than \"not found\". */\nexport class DockerInspectFailed extends Data.TaggedError('DockerInspectFailed')<{\n\treadonly resource: DockerResourceKind;\n\treadonly name: string;\n\treadonly stderr: string;\n\treadonly exitCode: number | undefined;\n}> {}\n\n/** Docker inspect returned malformed JSON or a shape outside the\n * runtime's expected schema. */\nexport class DockerInspectDecodeFailed extends Data.TaggedError('DockerInspectDecodeFailed')<{\n\treadonly resource: DockerResourceKind;\n\treadonly name: string;\n\treadonly detail: string;\n\treadonly cause?: unknown;\n}> {}\n\n/** A same-name Docker resource exists but is not owned by the expected\n * devstack label tuple, so mutating it would cross stack/plugin\n * boundaries. */\nexport class ForeignDockerResource extends Data.TaggedError('ForeignDockerResource')<{\n\treadonly resource: DockerResourceKind;\n\treadonly name: string;\n\treadonly expected: Readonly<Record<string, string>>;\n\treadonly actual: Readonly<Record<string, string>>;\n\treadonly detail: string;\n}> {}\n\n/** `docker network connect` / `network create` failure that isn't the\n * idempotent \"already exists in network\" case. */\nexport class NetworkOperationFailed extends Data.TaggedError('NetworkOperationFailed')<{\n\treadonly op: 'create' | 'connect' | 'disconnect' | 'inspect' | 'remove';\n\treadonly network: string;\n\treadonly stderr: string;\n}> {}\n\n/** `docker network create` exhausted Docker's default bridge IPAM\n * pools. This is not a daemon reachability failure; stale long-lived\n * networks or missing explicit subnet/gateway policy are the usual\n * causes. */\nexport class NetworkAddressPoolExhausted extends Data.TaggedError('NetworkAddressPoolExhausted')<{\n\treadonly network: string;\n\treadonly stderr: string;\n\treadonly hint: string;\n}> {}\n\n/** Container's IP on a secondary network was not allocated within the\n * bounded poll budget. Architecture § Async network-connect. */\nexport class NetworkIpReadbackTimeout extends Data.TaggedError('NetworkIpReadbackTimeout')<{\n\treadonly container: string;\n\treadonly network: string;\n\treadonly waitedMillis: number;\n}> {}\n\n/** Volume create / inspect failed. */\nexport class VolumeOperationFailed extends Data.TaggedError('VolumeOperationFailed')<{\n\treadonly op: 'create' | 'inspect' | 'remove';\n\treadonly volume: string;\n\treadonly stderr: string;\n}> {}\n\n/** Recreate was refused — the caller's `RecreatePolicy` was `never`\n * but the lifecycle state machine concluded recreate was required\n * (image/config mismatch, unclean exit, unknown state). Caller must explicitly opt\n * in to a recreate to proceed (architecture G1 — Move-build-\n * container's no-auto-recreate case). */\nexport class RecreateRefused extends Data.TaggedError('RecreateRefused')<{\n\treadonly name: string;\n\treadonly reason:\n\t\t| 'image-mismatch'\n\t\t| 'config-mismatch'\n\t\t| 'unclean-shutdown'\n\t\t| 'resume-failed'\n\t\t| 'unknown-state';\n}> {}\n\n/** Generic exec / one-shot failure when the caller asked us to\n * promote a non-zero exit. */\nexport class ExecFailed extends Data.TaggedError('ExecFailed')<{\n\treadonly name: string;\n\treadonly argv: ReadonlyArray<string>;\n\treadonly exitCode: number;\n\treadonly stderr: string;\n}> {}\n\n/** `docker save` failed — daemon error, missing image, or pipe failure\n * draining stdout. */\nexport class ImageSaveFailed extends Data.TaggedError('ImageSaveFailed')<{\n\treadonly ref: string;\n\treadonly detail: string;\n\treadonly cause?: unknown;\n}> {}\n\n/** `docker load` failed — corrupt tar, daemon error, or no `Loaded\n * image:` line parsed from stdout. */\nexport class ImageLoadFailed extends Data.TaggedError('ImageLoadFailed')<{\n\treadonly detail: string;\n\treadonly stderr?: string;\n\treadonly cause?: unknown;\n}> {}\n\n/** `docker tag` failed — source image missing or invalid tag string. */\nexport class ImageTagFailed extends Data.TaggedError('ImageTagFailed')<{\n\treadonly src: string;\n\treadonly dst: string;\n\treadonly stderr: string;\n}> {}\n\n/** `docker image rm` failed while removing managed snapshot/build\n * byproducts. */\nexport class ImageRemoveFailed extends Data.TaggedError('ImageRemoveFailed')<{\n\treadonly ref: string;\n\treadonly stderr: string;\n\treadonly exitCode: number | undefined;\n}> {}\n\n/** Union of every docker-runtime typed error. */\nexport type DockerRuntimeError =\n\t| DaemonUnreachable\n\t| ImageNotFound\n\t| ImagePullFailed\n\t| BuildFailed\n\t| ContainerCreateFailed\n\t| ContainerPortPublishConflict\n\t| ContainerNameCollisionUnrecoverable\n\t| ContainerRemoveFailed\n\t| DockerInspectFailed\n\t| DockerInspectDecodeFailed\n\t| ForeignDockerResource\n\t| NetworkOperationFailed\n\t| NetworkAddressPoolExhausted\n\t| NetworkIpReadbackTimeout\n\t| VolumeOperationFailed\n\t| RecreateRefused\n\t| ExecFailed\n\t| ImageSaveFailed\n\t| ImageLoadFailed\n\t| ImageTagFailed\n\t| ImageRemoveFailed;\n\n/** Project a typed `DockerRuntimeError` into the contract-shaped\n * `ContainerRuntimeError`. The contract is intentionally narrow\n * (`reason` is a closed enum); plugins that want the precise tag\n * can `Effect.catchTag` against the typed errors BEFORE the contract\n * projection runs. */\nexport const toContractError = (err: DockerRuntimeError): ContainerRuntimeError => {\n\tswitch (err._tag) {\n\t\tcase 'DaemonUnreachable':\n\t\t\treturn { _tag: 'ContainerRuntimeError', reason: 'daemon-unreachable', detail: err.detail };\n\t\tcase 'ImageNotFound':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'image-build-failed',\n\t\t\t\tdetail: `${err.ref}: ${err.detail}`,\n\t\t\t};\n\t\tcase 'ImagePullFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'image-build-failed',\n\t\t\t\tdetail: `pull ${err.ref} failed: ${err.stderr}`,\n\t\t\t};\n\t\tcase 'BuildFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'image-build-failed',\n\t\t\t\tdetail: err.parsedStep ?? err.stderr,\n\t\t\t};\n\t\tcase 'ContainerCreateFailed':\n\t\tcase 'ContainerNameCollisionUnrecoverable':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'name-collision',\n\t\t\t\tdetail: 'detail' in err ? err.detail : err.stderr,\n\t\t\t};\n\t\tcase 'ContainerPortPublishConflict':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'publish-port-conflict',\n\t\t\t\tdetail: `${err.name}: ${err.stderr}`,\n\t\t\t};\n\t\tcase 'ContainerRemoveFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'container-replace-failed',\n\t\t\t\tdetail: `${err.name}: ${err.stderr}`,\n\t\t\t};\n\t\tcase 'DockerInspectFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'docker-inspect-failed',\n\t\t\t\tdetail: `${err.resource} ${err.name}: ${err.stderr}`,\n\t\t\t};\n\t\tcase 'DockerInspectDecodeFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'docker-inspect-failed',\n\t\t\t\tdetail: `${err.resource} ${err.name}: ${err.detail}`,\n\t\t\t};\n\t\tcase 'ForeignDockerResource':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'foreign-resource',\n\t\t\t\tdetail: `${err.resource} ${err.name}: ${err.detail}`,\n\t\t\t};\n\t\tcase 'NetworkOperationFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'daemon-unreachable',\n\t\t\t\tdetail: `network ${err.op} ${err.network}: ${err.stderr}`,\n\t\t\t};\n\t\tcase 'NetworkAddressPoolExhausted':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'network-address-pool-exhausted',\n\t\t\t\tdetail: `network create ${err.network}: ${err.hint} stderr=${err.stderr}`,\n\t\t\t};\n\t\tcase 'NetworkIpReadbackTimeout':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'ip-readback-timeout',\n\t\t\t\tdetail: `${err.container} on ${err.network} after ${err.waitedMillis}ms`,\n\t\t\t};\n\t\tcase 'VolumeOperationFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'daemon-unreachable',\n\t\t\t\tdetail: `volume ${err.op} ${err.volume}: ${err.stderr}`,\n\t\t\t};\n\t\tcase 'RecreateRefused':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'recreate-refused',\n\t\t\t\tdetail: `${err.name}: ${err.reason}`,\n\t\t\t};\n\t\tcase 'ExecFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'ready-probe-failed',\n\t\t\t\tdetail: `exec ${err.name} exit ${err.exitCode}: ${err.stderr}`,\n\t\t\t};\n\t\tcase 'ImageSaveFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'image-save-failed',\n\t\t\t\tdetail: `${err.ref}: ${err.detail}`,\n\t\t\t};\n\t\tcase 'ImageLoadFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'image-load-failed',\n\t\t\t\tdetail: err.stderr !== undefined ? `${err.detail}: ${err.stderr}` : err.detail,\n\t\t\t};\n\t\tcase 'ImageTagFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'image-tag-failed',\n\t\t\t\tdetail: `${err.src} → ${err.dst}: ${err.stderr}`,\n\t\t\t};\n\t\tcase 'ImageRemoveFailed':\n\t\t\treturn {\n\t\t\t\t_tag: 'ContainerRuntimeError',\n\t\t\t\treason: 'image-remove-failed',\n\t\t\t\tdetail: `${err.ref}: ${err.stderr}`,\n\t\t\t};\n\t}\n};\n"],"mappings":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { mintRandomSuffix } from "../../substrate/runtime/random-suffix.mjs";
|
|
1
2
|
import { dockerRunOk } from "./client.mjs";
|
|
2
3
|
import { DaemonUnreachable, ExecFailed } from "./errors.mjs";
|
|
3
4
|
import { wrapGeneric } from "./wrap.mjs";
|
|
5
|
+
import { renderRunArgs } from "./render-run-args.mjs";
|
|
4
6
|
import { Effect } from "effect";
|
|
5
|
-
import { randomUUID } from "node:crypto";
|
|
6
7
|
//#region src/runtime/docker/exec.ts
|
|
7
8
|
/** `docker exec [-u user] [-w workdir] [-e k=v]... <name> <argv...>`. */
|
|
8
9
|
const dockerExec = (containerNameOrId, argv, opts = {}) => Effect.gen(function* () {
|
|
@@ -11,10 +12,14 @@ const dockerExec = (containerNameOrId, argv, opts = {}) => Effect.gen(function*
|
|
|
11
12
|
if (opts.workdir) args.push("--workdir", opts.workdir);
|
|
12
13
|
if (opts.env) for (const [k, v] of Object.entries(opts.env)) args.push("--env", `${k}=${v}`);
|
|
13
14
|
args.push(containerNameOrId, ...argv);
|
|
14
|
-
const
|
|
15
|
+
const baseInvocation = dockerRunOk("exec", args, {
|
|
15
16
|
onStdoutLine: opts.onStdoutLine,
|
|
16
17
|
onStderrLine: opts.onStderrLine
|
|
17
18
|
}).pipe(Effect.mapError(wrapGeneric("docker.exec")));
|
|
19
|
+
const res = yield* opts.timeoutMillis === void 0 ? baseInvocation : baseInvocation.pipe(Effect.timeout(`${opts.timeoutMillis} millis`), Effect.catchTag("TimeoutError", () => Effect.fail(new DaemonUnreachable({
|
|
20
|
+
op: "docker.exec",
|
|
21
|
+
detail: `exec into ${containerNameOrId} timed out after ${opts.timeoutMillis}ms`
|
|
22
|
+
}))));
|
|
18
23
|
if (opts.failOnNonZero && res.exitCode !== 0) return yield* Effect.fail(new ExecFailed({
|
|
19
24
|
name: containerNameOrId,
|
|
20
25
|
argv,
|
|
@@ -30,22 +35,20 @@ const dockerExec = (containerNameOrId, argv, opts = {}) => Effect.gen(function*
|
|
|
30
35
|
* `docker rm -f <name>` to catch containers that outlived the
|
|
31
36
|
* foreground subprocess on the timeout path. */
|
|
32
37
|
const dockerRunOneShot = (opts) => Effect.gen(function* () {
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
args.push(opts.image);
|
|
48
|
-
if (opts.argv) args.push(...opts.argv);
|
|
38
|
+
const name = opts.name ?? `devstack-oneshot-${Date.now()}-${mintRandomSuffix(8)}`;
|
|
39
|
+
const args = renderRunArgs({
|
|
40
|
+
keep: opts.keep,
|
|
41
|
+
name,
|
|
42
|
+
image: opts.image,
|
|
43
|
+
argv: opts.argv,
|
|
44
|
+
network: opts.network,
|
|
45
|
+
entrypoint: opts.entrypoint,
|
|
46
|
+
user: opts.user,
|
|
47
|
+
env: opts.env,
|
|
48
|
+
mounts: opts.mounts,
|
|
49
|
+
labels: opts.labels,
|
|
50
|
+
addHosts: opts.extraHosts
|
|
51
|
+
});
|
|
49
52
|
if (!opts.keep) yield* Effect.addFinalizer(() => dockerRunOk("rm", ["-f", name]).pipe(Effect.catch(() => Effect.void), Effect.asVoid));
|
|
50
53
|
const baseInvocation = dockerRunOk("run", args, {
|
|
51
54
|
onStdoutLine: opts.onStdoutLine,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec.mjs","names":[],"sources":["../../../src/runtime/docker/exec.ts"],"sourcesContent":["// One-shot `docker exec` and `docker run --rm`.\n//\n// Architecture:\n// - `dockerExec` invokes inside an already-running long-lived\n// container; captures stdout/stderr/exitCode.\n// - `dockerRunOneShot` is for `docker run --rm` style invocation —\n// a transient container that runs to completion.\n// - Wall-clock timeout with SIGTERM-then-SIGKILL escalation is\n// scoped at the L0 capture level via `Effect.timeout`; the\n// belt-and-suspenders `rm -f` is registered as a finalizer so a\n// timed-out container that outlived its foreground subprocess is\n// still reaped.\n\nimport { randomUUID } from 'node:crypto';\n\nimport { Effect, Scope } from 'effect';\n\nimport type {\n\tCaptureOptions,\n\tCaptureResult,\n} from '../../substrate/runtime/observability/subprocess-capture.ts';\nimport { DockerHost, DockerSpawner, dockerRunOk } from './client.ts';\nimport { DaemonUnreachable, type DockerRuntimeError, ExecFailed } from './errors.ts';\nimport { wrapGeneric } from './wrap.ts';\n\n// -----------------------------------------------------------------------------\n// Exec — into a running container\n// -----------------------------------------------------------------------------\n\nexport interface DockerExecOptions {\n\treadonly user?: string;\n\treadonly env?: Readonly<Record<string, string>>;\n\treadonly workdir?: string;\n\treadonly onStdoutLine?: (line: string) => Effect.Effect<void>;\n\treadonly onStderrLine?: (line: string) => Effect.Effect<void>;\n\t/** Promote non-zero exit to `ExecFailed`. Default false; the caller\n\t * gets the full result and decides. */\n\treadonly failOnNonZero?: boolean;\n}\n\nexport interface DockerExecResult {\n\treadonly exitCode: number;\n\treadonly stdout: string;\n\treadonly stderr: string;\n}\n\n/** `docker exec [-u user] [-w workdir] [-e k=v]... <name> <argv...>`. */\nexport const dockerExec = (\n\tcontainerNameOrId: string,\n\targv: ReadonlyArray<string>,\n\topts: DockerExecOptions = {},\n): Effect.Effect<DockerExecResult, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst args: Array<string> = [];\n\t\tif (opts.user) args.push('--user', opts.user);\n\t\tif (opts.workdir) args.push('--workdir', opts.workdir);\n\t\tif (opts.env) {\n\t\t\tfor (const [k, v] of Object.entries(opts.env)) {\n\t\t\t\targs.push('--env', `${k}=${v}`);\n\t\t\t}\n\t\t}\n\t\targs.push(containerNameOrId, ...argv);\n\t\tconst captureOpts: Omit<CaptureOptions, 'op' | 'nonZeroIsFailure'> = {\n\t\t\tonStdoutLine: opts.onStdoutLine,\n\t\t\tonStderrLine: opts.onStderrLine,\n\t\t};\n\t\tconst res = yield* dockerRunOk('exec', args, captureOpts).pipe(\n\t\t\tEffect.mapError(wrapGeneric('docker.exec')),\n\t\t);\n\t\tif (opts.failOnNonZero && res.exitCode !== 0) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew ExecFailed({\n\t\t\t\t\tname: containerNameOrId,\n\t\t\t\t\targv,\n\t\t\t\t\texitCode: res.exitCode,\n\t\t\t\t\tstderr: res.stderr,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn res;\n\t}).pipe(Effect.withSpan('runtime.docker.exec'));\n\n// -----------------------------------------------------------------------------\n// One-shot — `docker run --rm`\n// -----------------------------------------------------------------------------\n\nexport interface DockerOneShotOptions {\n\treadonly name?: string;\n\treadonly image: string;\n\treadonly argv?: ReadonlyArray<string>;\n\treadonly env?: Readonly<Record<string, string>>;\n\treadonly mounts?: ReadonlyArray<{\n\t\treadonly source: string;\n\t\treadonly target: string;\n\t\treadonly readonly?: boolean;\n\t}>;\n\treadonly network?: string;\n\treadonly entrypoint?: string;\n\treadonly user?: string;\n\treadonly labels?: ReadonlyArray<string>;\n\t/** `--add-host <host>:<ip>` entries. See contract docs. */\n\treadonly extraHosts?: Readonly<Record<string, string>>;\n\treadonly onStdoutLine?: (line: string) => Effect.Effect<void>;\n\treadonly onStderrLine?: (line: string) => Effect.Effect<void>;\n\t/** Wall-clock timeout. After this the subprocess is killed; the\n\t * outer `rm -f` belt-and-suspenders finalizer catches any\n\t * container that survived the kill. */\n\treadonly timeoutMillis?: number;\n\t/** Keep the container after exit (forensic retention escape hatch).\n\t * When true, drops `--rm` AND the finalizer rm. */\n\treadonly keep?: boolean;\n}\n\n/** `docker run --rm [-name <n>] [-e ...] [--mount ...] [--network n]\n * [--entrypoint e] [--label ...] <image> <argv...>`.\n *\n * Belt-and-suspenders: when `keep` is false, a Scope finalizer fires\n * `docker rm -f <name>` to catch containers that outlived the\n * foreground subprocess on the timeout path. */\nexport const dockerRunOneShot = (\n\topts: DockerOneShotOptions,\n): Effect.Effect<CaptureResult, DockerRuntimeError, DockerHost | DockerSpawner | Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst args: Array<string> = [];\n\t\tif (!opts.keep) args.push('--rm');\n\t\tconst name =\n\t\t\topts.name ?? `devstack-oneshot-${Date.now()}-${randomUUID().replace(/-/g, '').slice(0, 8)}`;\n\t\targs.push('--name', name);\n\t\tif (opts.network) args.push('--network', opts.network);\n\t\tif (opts.entrypoint) args.push('--entrypoint', opts.entrypoint);\n\t\tif (opts.user) args.push('--user', opts.user);\n\t\tif (opts.env) {\n\t\t\tfor (const [k, v] of Object.entries(opts.env)) {\n\t\t\t\targs.push('--env', `${k}=${v}`);\n\t\t\t}\n\t\t}\n\t\tif (opts.mounts) {\n\t\t\tfor (const m of opts.mounts) {\n\t\t\t\tconst ro = m.readonly ? ',readonly' : '';\n\t\t\t\targs.push('--mount', `type=bind,source=${m.source},target=${m.target}${ro}`);\n\t\t\t}\n\t\t}\n\t\tif (opts.labels) {\n\t\t\tfor (const l of opts.labels) args.push('--label', l);\n\t\t}\n\t\tif (opts.extraHosts) {\n\t\t\tfor (const [host, ip] of Object.entries(opts.extraHosts)) {\n\t\t\t\targs.push('--add-host', `${host}:${ip}`);\n\t\t\t}\n\t\t}\n\t\targs.push(opts.image);\n\t\tif (opts.argv) args.push(...opts.argv);\n\n\t\t// Register the belt-and-suspenders rm finalizer BEFORE we\n\t\t// invoke. Even if the spawner blows up mid-flight, the\n\t\t// finalizer fires on scope close.\n\t\tif (!opts.keep) {\n\t\t\tyield* Effect.addFinalizer(() =>\n\t\t\t\tdockerRunOk('rm', ['-f', name]).pipe(\n\t\t\t\t\tEffect.catch(() => Effect.void),\n\t\t\t\t\tEffect.asVoid,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tconst captureOpts: Omit<CaptureOptions, 'op' | 'nonZeroIsFailure'> = {\n\t\t\tonStdoutLine: opts.onStdoutLine,\n\t\t\tonStderrLine: opts.onStderrLine,\n\t\t};\n\t\tconst baseInvocation = dockerRunOk('run', args, captureOpts).pipe(\n\t\t\tEffect.mapError(wrapGeneric('docker.run-oneshot')),\n\t\t);\n\t\tif (opts.timeoutMillis !== undefined) {\n\t\t\t// Effect.timeout fails with a TimeoutError (Effect v4\n\t\t\t// renamed it from TimeoutException); collapse into our\n\t\t\t// daemon-unreachable envelope so the caller sees the same\n\t\t\t// shape they handle for any docker subprocess.\n\t\t\treturn yield* baseInvocation.pipe(\n\t\t\t\tEffect.timeout(`${opts.timeoutMillis} millis`),\n\t\t\t\tEffect.catchTag('TimeoutError', () =>\n\t\t\t\t\tEffect.fail(\n\t\t\t\t\t\tnew DaemonUnreachable({\n\t\t\t\t\t\t\top: 'docker.run-oneshot',\n\t\t\t\t\t\t\tdetail: `one-shot timed out after ${opts.timeoutMillis}ms`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\treturn yield* baseInvocation;\n\t}).pipe(Effect.withSpan('runtime.docker.oneShot'));\n"],"mappings":";;;;;;;AA+CA,MAAa,cACZ,mBACA,MACA,OAA0B,EAAE,KAE5B,OAAO,IAAI,aAAa;CACvB,MAAM,OAAsB,EAAE;AAC9B,KAAI,KAAK,KAAM,MAAK,KAAK,UAAU,KAAK,KAAK;AAC7C,KAAI,KAAK,QAAS,MAAK,KAAK,aAAa,KAAK,QAAQ;AACtD,KAAI,KAAK,IACR,MAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,KAAK,IAAI,CAC5C,MAAK,KAAK,SAAS,GAAG,EAAE,GAAG,IAAI;AAGjC,MAAK,KAAK,mBAAmB,GAAG,KAAK;CAKrC,MAAM,MAAM,OAAO,YAAY,QAAQ,MAAM;EAH5C,cAAc,KAAK;EACnB,cAAc,KAAK;EAEoC,CAAC,CAAC,KACzD,OAAO,SAAS,YAAY,cAAc,CAAC,CAC3C;AACD,KAAI,KAAK,iBAAiB,IAAI,aAAa,EAC1C,QAAO,OAAO,OAAO,KACpB,IAAI,WAAW;EACd,MAAM;EACN;EACA,UAAU,IAAI;EACd,QAAQ,IAAI;EACZ,CAAC,CACF;AAEF,QAAO;EACN,CAAC,KAAK,OAAO,SAAS,sBAAsB,CAAC;;;;;;;AAuChD,MAAa,oBACZ,SAEA,OAAO,IAAI,aAAa;CACvB,MAAM,OAAsB,EAAE;AAC9B,KAAI,CAAC,KAAK,KAAM,MAAK,KAAK,OAAO;CACjC,MAAM,OACL,KAAK,QAAQ,oBAAoB,KAAK,KAAK,CAAC,GAAG,YAAY,CAAC,QAAQ,MAAM,GAAG,CAAC,MAAM,GAAG,EAAE;AAC1F,MAAK,KAAK,UAAU,KAAK;AACzB,KAAI,KAAK,QAAS,MAAK,KAAK,aAAa,KAAK,QAAQ;AACtD,KAAI,KAAK,WAAY,MAAK,KAAK,gBAAgB,KAAK,WAAW;AAC/D,KAAI,KAAK,KAAM,MAAK,KAAK,UAAU,KAAK,KAAK;AAC7C,KAAI,KAAK,IACR,MAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,KAAK,IAAI,CAC5C,MAAK,KAAK,SAAS,GAAG,EAAE,GAAG,IAAI;AAGjC,KAAI,KAAK,OACR,MAAK,MAAM,KAAK,KAAK,QAAQ;EAC5B,MAAM,KAAK,EAAE,WAAW,cAAc;AACtC,OAAK,KAAK,WAAW,oBAAoB,EAAE,OAAO,UAAU,EAAE,SAAS,KAAK;;AAG9E,KAAI,KAAK,OACR,MAAK,MAAM,KAAK,KAAK,OAAQ,MAAK,KAAK,WAAW,EAAE;AAErD,KAAI,KAAK,WACR,MAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,KAAK,WAAW,CACvD,MAAK,KAAK,cAAc,GAAG,KAAK,GAAG,KAAK;AAG1C,MAAK,KAAK,KAAK,MAAM;AACrB,KAAI,KAAK,KAAM,MAAK,KAAK,GAAG,KAAK,KAAK;AAKtC,KAAI,CAAC,KAAK,KACT,QAAO,OAAO,mBACb,YAAY,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,KAC/B,OAAO,YAAY,OAAO,KAAK,EAC/B,OAAO,OACP,CACD;CAOF,MAAM,iBAAiB,YAAY,OAAO,MAAM;EAH/C,cAAc,KAAK;EACnB,cAAc,KAAK;EAEuC,CAAC,CAAC,KAC5D,OAAO,SAAS,YAAY,qBAAqB,CAAC,CAClD;AACD,KAAI,KAAK,kBAAkB,KAAA,EAK1B,QAAO,OAAO,eAAe,KAC5B,OAAO,QAAQ,GAAG,KAAK,cAAc,SAAS,EAC9C,OAAO,SAAS,sBACf,OAAO,KACN,IAAI,kBAAkB;EACrB,IAAI;EACJ,QAAQ,4BAA4B,KAAK,cAAc;EACvD,CAAC,CACF,CACD,CACD;AAEF,QAAO,OAAO;EACb,CAAC,KAAK,OAAO,SAAS,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"exec.mjs","names":[],"sources":["../../../src/runtime/docker/exec.ts"],"sourcesContent":["// One-shot `docker exec` and `docker run --rm`.\n//\n// Architecture:\n// - `dockerExec` invokes inside an already-running long-lived\n// container; captures stdout/stderr/exitCode.\n// - `dockerRunOneShot` is for `docker run --rm` style invocation —\n// a transient container that runs to completion.\n// - Both verbs take an OPTIONAL wall-clock `timeoutMillis`. When set,\n// `Effect.timeout` bounds the foreground subprocess and collapses a\n// timeout into the verb's typed error envelope. The actual\n// SIGTERM-then-SIGKILL escalation of the docker CLI child on the\n// resulting interrupt lives at the spawn seam (`client.ts`'s\n// `forceKillAfter`), not here. For `dockerRunOneShot` a\n// belt-and-suspenders `rm -f` finalizer additionally reaps any\n// container that outlived its foreground subprocess on timeout.\n// - Callers that drive `dockerExec` through `waitForProbe` should\n// still pass `timeoutMillis` (or the probe's `attemptTimeoutMs`): a\n// never-returning exec — wedged container `sh`, half-open daemon\n// socket — is otherwise never timed out, because `waitForProbe`\n// only checks its deadline BETWEEN attempts.\n\nimport { Effect, Scope } from 'effect';\n\nimport { mintRandomSuffix } from '../../substrate/runtime/random-suffix.ts';\n\nimport type {\n\tCaptureOptions,\n\tCaptureResult,\n} from '../../substrate/runtime/observability/subprocess-capture.ts';\nimport { DockerHost, DockerSpawner, dockerRunOk } from './client.ts';\nimport { DaemonUnreachable, type DockerRuntimeError, ExecFailed } from './errors.ts';\nimport { renderRunArgs } from './render-run-args.ts';\nimport { wrapGeneric } from './wrap.ts';\n\n// -----------------------------------------------------------------------------\n// Exec — into a running container\n// -----------------------------------------------------------------------------\n\nexport interface DockerExecOptions {\n\treadonly user?: string;\n\treadonly env?: Readonly<Record<string, string>>;\n\treadonly workdir?: string;\n\treadonly onStdoutLine?: (line: string) => Effect.Effect<void>;\n\treadonly onStderrLine?: (line: string) => Effect.Effect<void>;\n\t/** Promote non-zero exit to `ExecFailed`. Default false; the caller\n\t * gets the full result and decides. */\n\treadonly failOnNonZero?: boolean;\n\t/** Wall-clock timeout for the foreground `docker exec` subprocess.\n\t * Without it a wedged exec (hung container `sh`, half-open daemon\n\t * socket) hangs the fiber forever — and a caller's `waitForProbe`\n\t * wrapper without `attemptTimeoutMs` never times it out, because the\n\t * probe only checks its deadline between attempts. On timeout the\n\t * exec is interrupted (the spawn seam escalates SIGTERM→SIGKILL via\n\t * `forceKillAfter`) and collapses to a typed `DaemonUnreachable`. */\n\treadonly timeoutMillis?: number;\n}\n\nexport interface DockerExecResult {\n\treadonly exitCode: number;\n\treadonly stdout: string;\n\treadonly stderr: string;\n}\n\n/** `docker exec [-u user] [-w workdir] [-e k=v]... <name> <argv...>`. */\nexport const dockerExec = (\n\tcontainerNameOrId: string,\n\targv: ReadonlyArray<string>,\n\topts: DockerExecOptions = {},\n): Effect.Effect<DockerExecResult, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst args: Array<string> = [];\n\t\tif (opts.user) args.push('--user', opts.user);\n\t\tif (opts.workdir) args.push('--workdir', opts.workdir);\n\t\tif (opts.env) {\n\t\t\tfor (const [k, v] of Object.entries(opts.env)) {\n\t\t\t\targs.push('--env', `${k}=${v}`);\n\t\t\t}\n\t\t}\n\t\targs.push(containerNameOrId, ...argv);\n\t\tconst captureOpts: Omit<CaptureOptions, 'op' | 'nonZeroIsFailure'> = {\n\t\t\tonStdoutLine: opts.onStdoutLine,\n\t\t\tonStderrLine: opts.onStderrLine,\n\t\t};\n\t\tconst baseInvocation = dockerRunOk('exec', args, captureOpts).pipe(\n\t\t\tEffect.mapError(wrapGeneric('docker.exec')),\n\t\t);\n\t\t// Bound the foreground subprocess when asked. Mirrors\n\t\t// `dockerRunOneShot`: Effect.timeout fails with a TimeoutError\n\t\t// (Effect v4 renamed it from TimeoutException); collapse into the\n\t\t// daemon-unreachable envelope wrapGeneric already produces for\n\t\t// this surface, so the caller sees one shape. The interrupt\n\t\t// unwinds the capture's scope, whose spawn-seam finalizer\n\t\t// escalates SIGTERM→SIGKILL (client.ts `forceKillAfter`).\n\t\tconst invocation =\n\t\t\topts.timeoutMillis === undefined\n\t\t\t\t? baseInvocation\n\t\t\t\t: baseInvocation.pipe(\n\t\t\t\t\t\tEffect.timeout(`${opts.timeoutMillis} millis`),\n\t\t\t\t\t\tEffect.catchTag('TimeoutError', () =>\n\t\t\t\t\t\t\tEffect.fail(\n\t\t\t\t\t\t\t\tnew DaemonUnreachable({\n\t\t\t\t\t\t\t\t\top: 'docker.exec',\n\t\t\t\t\t\t\t\t\tdetail: `exec into ${containerNameOrId} timed out after ${opts.timeoutMillis}ms`,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\tconst res = yield* invocation;\n\t\tif (opts.failOnNonZero && res.exitCode !== 0) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew ExecFailed({\n\t\t\t\t\tname: containerNameOrId,\n\t\t\t\t\targv,\n\t\t\t\t\texitCode: res.exitCode,\n\t\t\t\t\tstderr: res.stderr,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn res;\n\t}).pipe(Effect.withSpan('runtime.docker.exec'));\n\n// -----------------------------------------------------------------------------\n// One-shot — `docker run --rm`\n// -----------------------------------------------------------------------------\n\nexport interface DockerOneShotOptions {\n\treadonly name?: string;\n\treadonly image: string;\n\treadonly argv?: ReadonlyArray<string>;\n\treadonly env?: Readonly<Record<string, string>>;\n\treadonly mounts?: ReadonlyArray<{\n\t\treadonly source: string;\n\t\treadonly target: string;\n\t\treadonly readonly?: boolean;\n\t}>;\n\treadonly network?: string;\n\treadonly entrypoint?: string;\n\treadonly user?: string;\n\treadonly labels?: ReadonlyArray<string>;\n\t/** `--add-host <host>:<ip>` entries. See contract docs. */\n\treadonly extraHosts?: Readonly<Record<string, string>>;\n\treadonly onStdoutLine?: (line: string) => Effect.Effect<void>;\n\treadonly onStderrLine?: (line: string) => Effect.Effect<void>;\n\t/** Wall-clock timeout. After this the subprocess is killed; the\n\t * outer `rm -f` belt-and-suspenders finalizer catches any\n\t * container that survived the kill. */\n\treadonly timeoutMillis?: number;\n\t/** Keep the container after exit (forensic retention escape hatch).\n\t * When true, drops `--rm` AND the finalizer rm. */\n\treadonly keep?: boolean;\n}\n\n/** `docker run --rm [-name <n>] [-e ...] [--mount ...] [--network n]\n * [--entrypoint e] [--label ...] <image> <argv...>`.\n *\n * Belt-and-suspenders: when `keep` is false, a Scope finalizer fires\n * `docker rm -f <name>` to catch containers that outlived the\n * foreground subprocess on the timeout path. */\nexport const dockerRunOneShot = (\n\topts: DockerOneShotOptions,\n): Effect.Effect<CaptureResult, DockerRuntimeError, DockerHost | DockerSpawner | Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst name = opts.name ?? `devstack-oneshot-${Date.now()}-${mintRandomSuffix(8)}`;\n\t\tconst args = renderRunArgs({\n\t\t\tkeep: opts.keep,\n\t\t\tname,\n\t\t\timage: opts.image,\n\t\t\targv: opts.argv,\n\t\t\tnetwork: opts.network,\n\t\t\tentrypoint: opts.entrypoint,\n\t\t\tuser: opts.user,\n\t\t\tenv: opts.env,\n\t\t\tmounts: opts.mounts,\n\t\t\tlabels: opts.labels,\n\t\t\taddHosts: opts.extraHosts,\n\t\t});\n\n\t\t// Register the belt-and-suspenders rm finalizer BEFORE we\n\t\t// invoke. Even if the spawner blows up mid-flight, the\n\t\t// finalizer fires on scope close.\n\t\tif (!opts.keep) {\n\t\t\tyield* Effect.addFinalizer(() =>\n\t\t\t\tdockerRunOk('rm', ['-f', name]).pipe(\n\t\t\t\t\tEffect.catch(() => Effect.void),\n\t\t\t\t\tEffect.asVoid,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tconst captureOpts: Omit<CaptureOptions, 'op' | 'nonZeroIsFailure'> = {\n\t\t\tonStdoutLine: opts.onStdoutLine,\n\t\t\tonStderrLine: opts.onStderrLine,\n\t\t};\n\t\tconst baseInvocation = dockerRunOk('run', args, captureOpts).pipe(\n\t\t\tEffect.mapError(wrapGeneric('docker.run-oneshot')),\n\t\t);\n\t\tif (opts.timeoutMillis !== undefined) {\n\t\t\t// Effect.timeout fails with a TimeoutError (Effect v4\n\t\t\t// renamed it from TimeoutException); collapse into our\n\t\t\t// daemon-unreachable envelope so the caller sees the same\n\t\t\t// shape they handle for any docker subprocess.\n\t\t\treturn yield* baseInvocation.pipe(\n\t\t\t\tEffect.timeout(`${opts.timeoutMillis} millis`),\n\t\t\t\tEffect.catchTag('TimeoutError', () =>\n\t\t\t\t\tEffect.fail(\n\t\t\t\t\t\tnew DaemonUnreachable({\n\t\t\t\t\t\t\top: 'docker.run-oneshot',\n\t\t\t\t\t\t\tdetail: `one-shot timed out after ${opts.timeoutMillis}ms`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\treturn yield* baseInvocation;\n\t}).pipe(Effect.withSpan('runtime.docker.oneShot'));\n"],"mappings":";;;;;;;;AAgEA,MAAa,cACZ,mBACA,MACA,OAA0B,EAAE,KAE5B,OAAO,IAAI,aAAa;CACvB,MAAM,OAAsB,EAAE;AAC9B,KAAI,KAAK,KAAM,MAAK,KAAK,UAAU,KAAK,KAAK;AAC7C,KAAI,KAAK,QAAS,MAAK,KAAK,aAAa,KAAK,QAAQ;AACtD,KAAI,KAAK,IACR,MAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,KAAK,IAAI,CAC5C,MAAK,KAAK,SAAS,GAAG,EAAE,GAAG,IAAI;AAGjC,MAAK,KAAK,mBAAmB,GAAG,KAAK;CAKrC,MAAM,iBAAiB,YAAY,QAAQ,MAAM;EAHhD,cAAc,KAAK;EACnB,cAAc,KAAK;EAEwC,CAAC,CAAC,KAC7D,OAAO,SAAS,YAAY,cAAc,CAAC,CAC3C;CAsBD,MAAM,MAAM,OAbX,KAAK,kBAAkB,KAAA,IACpB,iBACA,eAAe,KACf,OAAO,QAAQ,GAAG,KAAK,cAAc,SAAS,EAC9C,OAAO,SAAS,sBACf,OAAO,KACN,IAAI,kBAAkB;EACrB,IAAI;EACJ,QAAQ,aAAa,kBAAkB,mBAAmB,KAAK,cAAc;EAC7E,CAAC,CACF,CACD,CACD;AAEJ,KAAI,KAAK,iBAAiB,IAAI,aAAa,EAC1C,QAAO,OAAO,OAAO,KACpB,IAAI,WAAW;EACd,MAAM;EACN;EACA,UAAU,IAAI;EACd,QAAQ,IAAI;EACZ,CAAC,CACF;AAEF,QAAO;EACN,CAAC,KAAK,OAAO,SAAS,sBAAsB,CAAC;;;;;;;AAuChD,MAAa,oBACZ,SAEA,OAAO,IAAI,aAAa;CACvB,MAAM,OAAO,KAAK,QAAQ,oBAAoB,KAAK,KAAK,CAAC,GAAG,iBAAiB,EAAE;CAC/E,MAAM,OAAO,cAAc;EAC1B,MAAM,KAAK;EACX;EACA,OAAO,KAAK;EACZ,MAAM,KAAK;EACX,SAAS,KAAK;EACd,YAAY,KAAK;EACjB,MAAM,KAAK;EACX,KAAK,KAAK;EACV,QAAQ,KAAK;EACb,QAAQ,KAAK;EACb,UAAU,KAAK;EACf,CAAC;AAKF,KAAI,CAAC,KAAK,KACT,QAAO,OAAO,mBACb,YAAY,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,KAC/B,OAAO,YAAY,OAAO,KAAK,EAC/B,OAAO,OACP,CACD;CAOF,MAAM,iBAAiB,YAAY,OAAO,MAAM;EAH/C,cAAc,KAAK;EACnB,cAAc,KAAK;EAEuC,CAAC,CAAC,KAC5D,OAAO,SAAS,YAAY,qBAAqB,CAAC,CAClD;AACD,KAAI,KAAK,kBAAkB,KAAA,EAK1B,QAAO,OAAO,eAAe,KAC5B,OAAO,QAAQ,GAAG,KAAK,cAAc,SAAS,EAC9C,OAAO,SAAS,sBACf,OAAO,KACN,IAAI,kBAAkB;EACrB,IAAI;EACJ,QAAQ,4BAA4B,KAAK,cAAc;EACvD,CAAC,CACF,CACD,CACD;AAEF,QAAO,OAAO;EACb,CAAC,KAAK,OAAO,SAAS,yBAAyB,CAAC"}
|