@mysten-incubation/devstack 0.1.1 → 0.3.0
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 +6 -3
- package/dashboard-ui/assets/grpc-Clz0oOtc.js +3 -0
- package/dashboard-ui/assets/index-B82Bh84P.css +1 -0
- package/dashboard-ui/assets/index-Cmqv9kiU.js +1283 -0
- package/dashboard-ui/index.html +2 -2
- package/dist/api/define-capabilities.d.mts +1 -20
- package/dist/api/define-capabilities.mjs +15 -22
- package/dist/api/define-capabilities.mjs.map +1 -1
- package/dist/api/define-devstack-with.d.mts +7 -1
- package/dist/api/define-devstack-with.mjs.map +1 -1
- package/dist/api/define-devstack.mjs.map +1 -1
- package/dist/api/define-plugin.d.mts +2 -1
- package/dist/api/inference-network.d.mts +31 -17
- package/dist/api/inference-network.mjs +40 -43
- package/dist/api/inference-network.mjs.map +1 -1
- package/dist/api/load-config.mjs +88 -0
- package/dist/api/load-config.mjs.map +1 -0
- package/dist/api/mode-narrowed-factory.d.mts +1 -1
- package/dist/api/mode-narrowed-factory.mjs.map +1 -1
- package/dist/api/run-stack-internal.mjs +203 -0
- package/dist/api/run-stack-internal.mjs.map +1 -0
- package/dist/api/run-stack.d.mts +82 -31
- package/dist/api/run-stack.mjs +22 -141
- package/dist/api/run-stack.mjs.map +1 -1
- package/dist/build-integrations/dapp-kit/index.d.mts +61 -0
- package/dist/build-integrations/dapp-kit/index.mjs +58 -0
- package/dist/build-integrations/dapp-kit/index.mjs.map +1 -0
- package/dist/build-integrations/playwright/config.d.mts +3 -31
- package/dist/build-integrations/playwright/config.mjs +2 -28
- package/dist/build-integrations/playwright/config.mjs.map +1 -1
- package/dist/build-integrations/playwright/errors.d.mts +4 -7
- package/dist/build-integrations/playwright/errors.mjs.map +1 -1
- package/dist/build-integrations/playwright/global-setup.d.mts +42 -71
- package/dist/build-integrations/playwright/global-setup.mjs +142 -218
- package/dist/build-integrations/playwright/global-setup.mjs.map +1 -1
- package/dist/build-integrations/playwright/index.d.mts +2 -2
- package/dist/build-integrations/playwright/index.mjs +2 -2
- package/dist/build-integrations/playwright/stack-context.d.mts +3 -1
- package/dist/build-integrations/playwright/stack-context.mjs +4 -2
- package/dist/build-integrations/playwright/stack-context.mjs.map +1 -1
- package/dist/build-integrations/playwright/wallet-context.mjs +44 -19
- package/dist/build-integrations/playwright/wallet-context.mjs.map +1 -1
- package/dist/build-integrations/runtime/cold-start-url.mjs.map +1 -1
- package/dist/build-integrations/runtime/conventional-routes.mjs.map +1 -1
- package/dist/build-integrations/runtime/dapp-kit-slot.mjs.map +1 -1
- package/dist/build-integrations/runtime/discover.d.mts +6 -4
- package/dist/build-integrations/runtime/discover.mjs +15 -4
- package/dist/build-integrations/runtime/discover.mjs.map +1 -1
- package/dist/build-integrations/runtime/endpoint-registry.mjs.map +1 -1
- package/dist/build-integrations/runtime/errors.mjs.map +1 -1
- package/dist/build-integrations/runtime/read-stack-context.mjs +3 -3
- package/dist/build-integrations/runtime/read-stack-context.mjs.map +1 -1
- package/dist/build-integrations/runtime/resolve-discovery-env.d.mts +23 -7
- package/dist/build-integrations/runtime/resolve-discovery-env.mjs +25 -12
- package/dist/build-integrations/runtime/resolve-discovery-env.mjs.map +1 -1
- package/dist/build-integrations/runtime/stack-context.d.mts +2 -2
- package/dist/build-integrations/vite/index.d.mts +114 -19
- package/dist/build-integrations/vite/index.mjs +239 -28
- package/dist/build-integrations/vite/index.mjs.map +1 -1
- package/dist/build-integrations/vitest/config.d.mts +20 -2
- package/dist/build-integrations/vitest/config.mjs +15 -4
- package/dist/build-integrations/vitest/config.mjs.map +1 -1
- package/dist/build-integrations/vitest/env.d.mts +18 -10
- package/dist/build-integrations/vitest/env.mjs +11 -10
- package/dist/build-integrations/vitest/env.mjs.map +1 -1
- package/dist/build-integrations/vitest/errors.d.mts +7 -11
- package/dist/build-integrations/vitest/errors.mjs +3 -4
- package/dist/build-integrations/vitest/errors.mjs.map +1 -1
- package/dist/build-integrations/vitest/global-setup.d.mts +35 -0
- package/dist/build-integrations/vitest/global-setup.mjs +156 -0
- package/dist/build-integrations/vitest/global-setup.mjs.map +1 -0
- package/dist/build-integrations/vitest/index.d.mts +3 -2
- package/dist/build-integrations/vitest/index.mjs +3 -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 +5 -3
- package/dist/build-integrations/vitest/stack-context.mjs +3 -2
- package/dist/build-integrations/vitest/stack-context.mjs.map +1 -1
- package/dist/cli/bail.mjs.map +1 -1
- package/dist/cli/doctor-probes.mjs +8 -5
- package/dist/cli/doctor-probes.mjs.map +1 -1
- package/dist/cli/main.d.mts +23 -1
- package/dist/cli/main.mjs +63 -8
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/prune-direct.mjs.map +1 -1
- package/dist/cli/snapshot-reader.mjs.map +1 -1
- package/dist/cli/up-lifecycle.mjs.map +1 -1
- package/dist/cli/wirings/apply.mjs +28 -21
- package/dist/cli/wirings/apply.mjs.map +1 -1
- package/dist/cli/wirings/codegen.mjs +108 -0
- package/dist/cli/wirings/codegen.mjs.map +1 -0
- package/dist/cli/wirings/config-loader.mjs +12 -62
- package/dist/cli/wirings/config-loader.mjs.map +1 -1
- package/dist/cli/wirings/dump-ids.mjs +86 -0
- package/dist/cli/wirings/dump-ids.mjs.map +1 -0
- package/dist/cli/wirings/engine-command.mjs +1 -1
- package/dist/cli/wirings/engine-command.mjs.map +1 -1
- package/dist/cli/wirings/identity.mjs +2 -2
- package/dist/cli/wirings/identity.mjs.map +1 -1
- package/dist/cli/wirings/provide-file-system.mjs.map +1 -1
- package/dist/cli/wirings/read-devstack-version.mjs +17 -0
- package/dist/cli/wirings/read-devstack-version.mjs.map +1 -0
- package/dist/cli/wirings/snapshot.mjs +27 -34
- package/dist/cli/wirings/snapshot.mjs.map +1 -1
- package/dist/cli/wirings/up-ipc.mjs +147 -0
- package/dist/cli/wirings/up-ipc.mjs.map +1 -0
- package/dist/cli/wirings/up.mjs +225 -198
- package/dist/cli/wirings/up.mjs.map +1 -1
- package/dist/cli/wirings/wipe.mjs +1 -1
- package/dist/cli/wirings/wipe.mjs.map +1 -1
- package/dist/contracts/chain-probe.d.mts +1 -1
- package/dist/contracts/chain-probe.mjs +1 -1
- package/dist/contracts/chain-probe.mjs.map +1 -1
- package/dist/contracts/codegenable.d.mts +60 -6
- package/dist/contracts/codegenable.mjs +28 -0
- package/dist/contracts/codegenable.mjs.map +1 -0
- package/dist/contracts/config-bindings.mjs +162 -0
- package/dist/contracts/config-bindings.mjs.map +1 -0
- package/dist/contracts/container-runtime.d.mts +23 -17
- package/dist/contracts/plugin-expander.mjs.map +1 -1
- package/dist/contracts/snapshotable.d.mts +5 -7
- package/dist/contracts/wallet-protocol.d.mts +2 -5
- package/dist/contracts/wallet-protocol.mjs +2 -5
- package/dist/contracts/wallet-protocol.mjs.map +1 -1
- package/dist/index.d.mts +21 -26
- package/dist/index.mjs +8 -9
- package/dist/orchestrators/boot.d.mts +28 -0
- package/dist/orchestrators/boot.mjs +450 -0
- package/dist/orchestrators/boot.mjs.map +1 -0
- package/dist/orchestrators/codegen/bindings.d.mts +13 -1
- package/dist/orchestrators/codegen/bindings.mjs +23 -9
- package/dist/orchestrators/codegen/bindings.mjs.map +1 -1
- package/dist/orchestrators/codegen/config-runtime.mjs +208 -0
- package/dist/orchestrators/codegen/config-runtime.mjs.map +1 -0
- package/dist/orchestrators/codegen/emit.mjs +1 -1
- package/dist/orchestrators/codegen/emit.mjs.map +1 -1
- package/dist/orchestrators/codegen/errors.mjs +21 -1
- package/dist/orchestrators/codegen/errors.mjs.map +1 -1
- package/dist/orchestrators/codegen/format.mjs +2 -0
- package/dist/orchestrators/codegen/format.mjs.map +1 -1
- package/dist/orchestrators/codegen/gitignore.mjs +30 -11
- package/dist/orchestrators/codegen/gitignore.mjs.map +1 -1
- package/dist/orchestrators/codegen/id-config.mjs +107 -0
- package/dist/orchestrators/codegen/id-config.mjs.map +1 -0
- package/dist/orchestrators/codegen/output-location.mjs +23 -32
- package/dist/orchestrators/codegen/output-location.mjs.map +1 -1
- package/dist/orchestrators/codegen/paths.mjs +8 -1
- package/dist/orchestrators/codegen/paths.mjs.map +1 -1
- package/dist/orchestrators/codegen/permissions.mjs.map +1 -1
- package/dist/orchestrators/codegen/service.mjs +303 -60
- package/dist/orchestrators/codegen/service.mjs.map +1 -1
- package/dist/orchestrators/layers.mjs +31 -0
- package/dist/orchestrators/layers.mjs.map +1 -0
- package/dist/orchestrators/lifecycle-prune/errors.mjs.map +1 -1
- package/dist/orchestrators/lifecycle-prune/index.mjs +8 -10
- package/dist/orchestrators/lifecycle-prune/index.mjs.map +1 -1
- package/dist/orchestrators/network-options.d.mts +52 -0
- package/dist/orchestrators/network-options.mjs +43 -0
- package/dist/orchestrators/network-options.mjs.map +1 -0
- package/dist/orchestrators/router/cleanup.mjs.map +1 -1
- package/dist/orchestrators/router/cors.mjs.map +1 -1
- package/dist/orchestrators/router/entrypoints.mjs.map +1 -1
- package/dist/orchestrators/router/errors.mjs.map +1 -1
- package/dist/orchestrators/router/file-provider.mjs.map +1 -1
- package/dist/orchestrators/router/hostname.mjs.map +1 -1
- package/dist/orchestrators/router/profile.mjs +1 -1
- package/dist/orchestrators/router/profile.mjs.map +1 -1
- package/dist/orchestrators/router/service.d.mts +2 -2
- package/dist/orchestrators/router/service.mjs +12 -27
- package/dist/orchestrators/router/service.mjs.map +1 -1
- package/dist/orchestrators/router/traefik-container.mjs +1 -1
- package/dist/orchestrators/router/traefik-container.mjs.map +1 -1
- package/dist/orchestrators/snapshot/capture.mjs +171 -195
- package/dist/orchestrators/snapshot/capture.mjs.map +1 -1
- package/dist/orchestrators/snapshot/descriptor.d.mts +1 -1
- package/dist/orchestrators/snapshot/descriptor.mjs +53 -11
- package/dist/orchestrators/snapshot/descriptor.mjs.map +1 -1
- package/dist/orchestrators/snapshot/identity-guard.mjs +3 -5
- package/dist/orchestrators/snapshot/identity-guard.mjs.map +1 -1
- package/dist/orchestrators/snapshot/image-bundle-tags.mjs +32 -101
- package/dist/orchestrators/snapshot/image-bundle-tags.mjs.map +1 -1
- package/dist/orchestrators/snapshot/index.mjs +1 -4
- package/dist/orchestrators/snapshot/integrity.mjs.map +1 -1
- package/dist/orchestrators/snapshot/interrupted-restore.mjs +116 -0
- package/dist/orchestrators/snapshot/interrupted-restore.mjs.map +1 -0
- package/dist/orchestrators/snapshot/phase-error.mjs.map +1 -1
- package/dist/orchestrators/snapshot/prune.mjs +40 -31
- package/dist/orchestrators/snapshot/prune.mjs.map +1 -1
- package/dist/orchestrators/snapshot/restore.mjs +221 -196
- package/dist/orchestrators/snapshot/restore.mjs.map +1 -1
- package/dist/orchestrators/snapshot/service.mjs +72 -62
- package/dist/orchestrators/snapshot/service.mjs.map +1 -1
- package/dist/orchestrators/snapshot/wipe.mjs +67 -56
- package/dist/orchestrators/snapshot/wipe.mjs.map +1 -1
- package/dist/plugins/account/codegen.mjs +3 -0
- package/dist/plugins/account/codegen.mjs.map +1 -1
- package/dist/plugins/account/errors.d.mts +2 -2
- package/dist/plugins/account/errors.mjs +1 -4
- package/dist/plugins/account/errors.mjs.map +1 -1
- package/dist/plugins/account/funding.mjs +3 -27
- package/dist/plugins/account/funding.mjs.map +1 -1
- package/dist/plugins/account/index.d.mts +3 -8
- package/dist/plugins/account/index.mjs +71 -35
- package/dist/plugins/account/index.mjs.map +1 -1
- package/dist/plugins/account/keypair.d.mts +8 -7
- package/dist/plugins/account/keypair.mjs +5 -18
- package/dist/plugins/account/keypair.mjs.map +1 -1
- package/dist/plugins/account/lease.mjs.map +1 -1
- package/dist/plugins/account/registry.d.mts +1 -46
- package/dist/plugins/account/registry.mjs.map +1 -1
- package/dist/plugins/account/service.d.mts +43 -34
- package/dist/plugins/account/service.mjs +9 -54
- package/dist/plugins/account/service.mjs.map +1 -1
- package/dist/plugins/account/snapshot.mjs.map +1 -1
- package/dist/plugins/account/variants/ephemeral.mjs.map +1 -1
- package/dist/plugins/account/variants/impersonate.mjs.map +1 -1
- package/dist/plugins/account/variants/signer.mjs.map +1 -1
- package/dist/plugins/action/discriminator.mjs.map +1 -1
- package/dist/plugins/action/errors.mjs +1 -4
- package/dist/plugins/action/errors.mjs.map +1 -1
- package/dist/plugins/action/execute.mjs +3 -4
- package/dist/plugins/action/execute.mjs.map +1 -1
- package/dist/plugins/action/index.d.mts +2 -2
- package/dist/plugins/action/index.mjs +7 -11
- package/dist/plugins/action/index.mjs.map +1 -1
- package/dist/plugins/action/service.d.mts +5 -7
- package/dist/plugins/action/service.mjs +2 -16
- package/dist/plugins/action/service.mjs.map +1 -1
- package/dist/plugins/coin/address-resolution.mjs.map +1 -1
- package/dist/plugins/coin/codegen.mjs +97 -16
- package/dist/plugins/coin/codegen.mjs.map +1 -1
- package/dist/plugins/coin/discovery.mjs.map +1 -1
- package/dist/plugins/coin/errors.mjs +1 -4
- package/dist/plugins/coin/errors.mjs.map +1 -1
- package/dist/plugins/coin/index.d.mts +4 -34
- package/dist/plugins/coin/index.mjs +47 -28
- package/dist/plugins/coin/index.mjs.map +1 -1
- package/dist/plugins/coin/metadata.d.mts +1 -0
- package/dist/plugins/coin/metadata.mjs +8 -9
- package/dist/plugins/coin/metadata.mjs.map +1 -1
- package/dist/plugins/coin/mint.mjs +7 -21
- package/dist/plugins/coin/mint.mjs.map +1 -1
- package/dist/plugins/coin/registry.mjs +33 -20
- package/dist/plugins/coin/registry.mjs.map +1 -1
- package/dist/plugins/coin/service.d.mts +1 -1
- package/dist/plugins/coin/service.mjs +1 -8
- package/dist/plugins/coin/service.mjs.map +1 -1
- package/dist/plugins/coin/snapshot.mjs.map +1 -1
- package/dist/plugins/coin/type-strings.mjs.map +1 -1
- package/dist/plugins/dashboard/domain.mjs +124 -168
- package/dist/plugins/dashboard/domain.mjs.map +1 -1
- package/dist/plugins/dashboard/index.mjs +13 -13
- package/dist/plugins/dashboard/index.mjs.map +1 -1
- package/dist/plugins/dashboard/origin-policy.mjs +3 -3
- package/dist/plugins/dashboard/origin-policy.mjs.map +1 -1
- package/dist/plugins/dashboard/routable.mjs.map +1 -1
- package/dist/plugins/dashboard/schema/builder.mjs.map +1 -1
- package/dist/plugins/dashboard/schema/enums.mjs.map +1 -1
- package/dist/plugins/dashboard/schema/root.mjs +25 -46
- package/dist/plugins/dashboard/schema/root.mjs.map +1 -1
- package/dist/plugins/dashboard/schema/types.mjs +52 -93
- package/dist/plugins/dashboard/schema/types.mjs.map +1 -1
- package/dist/plugins/dashboard/schema.mjs.map +1 -1
- package/dist/plugins/dashboard/server.mjs.map +1 -1
- package/dist/plugins/deepbook/codegen.d.mts +12 -11
- package/dist/plugins/deepbook/codegen.mjs +108 -11
- package/dist/plugins/deepbook/codegen.mjs.map +1 -1
- package/dist/plugins/deepbook/deploy.mjs +7 -14
- package/dist/plugins/deepbook/deploy.mjs.map +1 -1
- package/dist/plugins/deepbook/errors.mjs +4 -2
- package/dist/plugins/deepbook/errors.mjs.map +1 -1
- package/dist/plugins/deepbook/faucet-strategy.mjs +4 -10
- package/dist/plugins/deepbook/faucet-strategy.mjs.map +1 -1
- package/dist/plugins/deepbook/hash.mjs.map +1 -1
- package/dist/plugins/deepbook/index.d.mts +45 -37
- package/dist/plugins/deepbook/index.mjs +136 -67
- package/dist/plugins/deepbook/index.mjs.map +1 -1
- package/dist/plugins/deepbook/plugin-key.mjs.map +1 -1
- package/dist/plugins/deepbook/pyth/index.mjs +4 -8
- package/dist/plugins/deepbook/pyth/index.mjs.map +1 -1
- package/dist/plugins/deepbook/snapshot.mjs +0 -1
- package/dist/plugins/deepbook/snapshot.mjs.map +1 -1
- package/dist/plugins/deepbook/type-strings.mjs.map +1 -1
- package/dist/plugins/deepbook/types.d.mts +2 -1
- package/dist/plugins/deepbook/types.mjs.map +1 -1
- package/dist/plugins/faucet/dispatcher.d.mts +3 -3
- package/dist/plugins/faucet/dispatcher.mjs.map +1 -1
- package/dist/plugins/faucet/errors.mjs.map +1 -1
- package/dist/plugins/faucet/http.mjs +2 -10
- package/dist/plugins/faucet/http.mjs.map +1 -1
- package/dist/plugins/faucet/index.mjs +0 -1
- package/dist/plugins/faucet/index.mjs.map +1 -1
- package/dist/plugins/host-service/errors.d.mts +1 -3
- package/dist/plugins/host-service/errors.mjs +1 -2
- package/dist/plugins/host-service/errors.mjs.map +1 -1
- package/dist/plugins/host-service/index.d.mts +1 -2
- package/dist/plugins/host-service/index.mjs +11 -11
- package/dist/plugins/host-service/index.mjs.map +1 -1
- package/dist/plugins/host-service/routable.mjs.map +1 -1
- package/dist/plugins/host-service/service.mjs +13 -13
- package/dist/plugins/host-service/service.mjs.map +1 -1
- package/dist/plugins/internal/acquire-on-chain-artifact.mjs.map +1 -1
- package/dist/plugins/internal/codegen-helpers.mjs +2 -0
- package/dist/plugins/internal/codegen-helpers.mjs.map +1 -1
- package/dist/plugins/internal/funding-failure-error.mjs.map +1 -1
- package/dist/plugins/{postgres → internal/postgres-sidecar}/connection.mjs +1 -1
- package/dist/plugins/internal/postgres-sidecar/connection.mjs.map +1 -0
- package/dist/plugins/{postgres → internal/postgres-sidecar}/db-ensure.mjs +30 -16
- package/dist/plugins/internal/postgres-sidecar/db-ensure.mjs.map +1 -0
- package/dist/plugins/internal/postgres-sidecar/errors.mjs +21 -0
- package/dist/plugins/internal/postgres-sidecar/errors.mjs.map +1 -0
- package/dist/{substrate/runtime/scoped-multimap → plugins/internal/postgres-sidecar}/index.mjs +1 -0
- package/dist/plugins/internal/postgres-sidecar/service.mjs +121 -0
- package/dist/plugins/internal/postgres-sidecar/service.mjs.map +1 -0
- package/dist/plugins/package/build.mjs +2 -2
- package/dist/plugins/package/build.mjs.map +1 -1
- package/dist/plugins/package/codegen.d.mts +7 -14
- package/dist/plugins/package/codegen.mjs +187 -59
- package/dist/plugins/package/codegen.mjs.map +1 -1
- package/dist/plugins/package/dep-resolution.mjs +51 -3
- package/dist/plugins/package/dep-resolution.mjs.map +1 -1
- package/dist/plugins/package/errors.mjs +1 -4
- package/dist/plugins/package/errors.mjs.map +1 -1
- package/dist/plugins/package/git-source.d.mts +18 -0
- package/dist/plugins/package/git-source.mjs +119 -0
- package/dist/plugins/package/git-source.mjs.map +1 -0
- package/dist/plugins/package/index.d.mts +28 -19
- package/dist/plugins/package/index.mjs +107 -32
- package/dist/plugins/package/index.mjs.map +1 -1
- package/dist/plugins/package/mode-known.mjs +2 -2
- package/dist/plugins/package/mode-known.mjs.map +1 -1
- package/dist/plugins/package/mode-local.mjs +18 -35
- package/dist/plugins/package/mode-local.mjs.map +1 -1
- package/dist/plugins/package/publish-executor.mjs +13 -8
- package/dist/plugins/package/publish-executor.mjs.map +1 -1
- package/dist/plugins/package/publish-output.d.mts +1 -11
- package/dist/plugins/package/publish-output.mjs +1 -9
- package/dist/plugins/package/publish-output.mjs.map +1 -1
- package/dist/plugins/package/registry.d.mts +1 -1
- package/dist/plugins/package/registry.mjs +26 -14
- package/dist/plugins/package/registry.mjs.map +1 -1
- package/dist/plugins/package/service.mjs.map +1 -1
- package/dist/plugins/package/snapshot.mjs.map +1 -1
- package/dist/plugins/router-entrypoints.mjs +1 -3
- package/dist/plugins/router-entrypoints.mjs.map +1 -1
- package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs +1 -2
- package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs.map +1 -1
- package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs +1 -6
- package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs.map +1 -1
- package/dist/plugins/seal/codegen.d.mts +1 -5
- package/dist/plugins/seal/codegen.mjs +83 -12
- package/dist/plugins/seal/codegen.mjs.map +1 -1
- package/dist/plugins/seal/config-render.mjs +2 -6
- package/dist/plugins/seal/config-render.mjs.map +1 -1
- package/dist/plugins/seal/deploy.mjs +18 -29
- package/dist/plugins/seal/deploy.mjs.map +1 -1
- package/dist/plugins/seal/errors.d.mts +4 -5
- package/dist/plugins/seal/errors.mjs +1 -8
- package/dist/plugins/seal/errors.mjs.map +1 -1
- package/dist/plugins/seal/index.d.mts +7 -28
- package/dist/plugins/seal/index.mjs +69 -47
- package/dist/plugins/seal/index.mjs.map +1 -1
- package/dist/plugins/seal/key-manager.mjs.map +1 -1
- package/dist/plugins/seal/key-server.mjs +1 -6
- package/dist/plugins/seal/key-server.mjs.map +1 -1
- package/dist/plugins/seal/keygen.mjs +2 -3
- package/dist/plugins/seal/keygen.mjs.map +1 -1
- package/dist/plugins/seal/mode/fork-known.mjs.map +1 -1
- package/dist/plugins/seal/mode/live.mjs +1 -1
- package/dist/plugins/seal/mode/live.mjs.map +1 -1
- package/dist/plugins/seal/mode/local-keygen.mjs +4 -10
- package/dist/plugins/seal/mode/local-keygen.mjs.map +1 -1
- package/dist/plugins/seal/plugin-key.mjs.map +1 -1
- 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/snapshot.mjs +1 -2
- package/dist/plugins/seal/snapshot.mjs.map +1 -1
- package/dist/plugins/sui/auto-tick.mjs +5 -5
- package/dist/plugins/sui/auto-tick.mjs.map +1 -1
- package/dist/plugins/sui/chain-build-container.mjs +2 -2
- package/dist/plugins/sui/chain-build-container.mjs.map +1 -1
- package/dist/plugins/sui/chain-probe.mjs +4 -4
- package/dist/plugins/sui/chain-probe.mjs.map +1 -1
- package/dist/plugins/sui/codegen.d.mts +9 -7
- package/dist/plugins/sui/codegen.mjs +49 -46
- package/dist/plugins/sui/codegen.mjs.map +1 -1
- package/dist/plugins/sui/errors.d.mts +1 -1
- package/dist/plugins/sui/errors.mjs +1 -9
- package/dist/plugins/sui/errors.mjs.map +1 -1
- package/dist/{substrate/runtime/sui-execute → plugins/sui/exec}/index.d.mts +1 -1
- package/dist/{substrate/runtime/sui-execute → plugins/sui/exec}/index.mjs +3 -7
- package/dist/plugins/sui/exec/index.mjs.map +1 -0
- package/dist/{substrate/runtime/sui-execute → plugins/sui/exec}/sign-and-dispatch.mjs +1 -1
- package/dist/plugins/sui/exec/sign-and-dispatch.mjs.map +1 -0
- package/dist/plugins/sui/fork-faucet-strategy.mjs +2 -6
- package/dist/plugins/sui/fork-faucet-strategy.mjs.map +1 -1
- package/dist/plugins/sui/fork-orchestration.mjs +13 -23
- package/dist/plugins/sui/fork-orchestration.mjs.map +1 -1
- package/dist/plugins/sui/fork-transaction.mjs.map +1 -1
- package/dist/plugins/sui/index.d.mts +44 -93
- package/dist/plugins/sui/index.mjs +200 -68
- package/dist/plugins/sui/index.mjs.map +1 -1
- package/dist/{substrate/runtime/sui-ledger → plugins/sui/ledger}/object-ref.mjs +1 -1
- package/dist/plugins/sui/ledger/object-ref.mjs.map +1 -0
- package/dist/plugins/sui/local-faucet-strategy.mjs +1 -5
- package/dist/plugins/sui/local-faucet-strategy.mjs.map +1 -1
- package/dist/plugins/sui/log-attrs.mjs +11 -0
- package/dist/plugins/sui/log-attrs.mjs.map +1 -0
- package/dist/plugins/sui/mode/external.mjs +4 -12
- package/dist/plugins/sui/mode/external.mjs.map +1 -1
- package/dist/plugins/sui/mode/fork.mjs +19 -16
- package/dist/plugins/sui/mode/fork.mjs.map +1 -1
- package/dist/plugins/sui/mode/live.mjs +4 -17
- package/dist/plugins/sui/mode/live.mjs.map +1 -1
- package/dist/plugins/sui/mode/local.d.mts +1 -0
- package/dist/plugins/sui/mode/local.mjs +203 -61
- package/dist/plugins/sui/mode/local.mjs.map +1 -1
- package/dist/plugins/sui/mode/shared-boot.mjs +18 -23
- package/dist/plugins/sui/mode/shared-boot.mjs.map +1 -1
- package/dist/plugins/sui/mode/shared.d.mts +6 -7
- package/dist/plugins/sui/mode/shared.mjs.map +1 -1
- package/dist/plugins/sui/mode/spec.d.mts +23 -6
- package/dist/{substrate/runtime/sui-move-build → plugins/sui/move}/index.mjs +28 -30
- package/dist/plugins/sui/move/index.mjs.map +1 -0
- package/dist/plugins/sui/move-summary-runner.mjs +37 -6
- package/dist/plugins/sui/move-summary-runner.mjs.map +1 -1
- package/dist/{substrate/network.d.mts → plugins/sui/network-config.d.mts} +11 -10
- package/dist/plugins/sui/network-resolver.d.mts +6 -6
- package/dist/plugins/sui/routable.mjs.map +1 -1
- package/dist/plugins/sui/service.mjs +10 -6
- package/dist/plugins/sui/service.mjs.map +1 -1
- package/dist/plugins/sui/snapshot.mjs +10 -5
- package/dist/plugins/sui/snapshot.mjs.map +1 -1
- package/dist/plugins/wallet/codegen.d.mts +8 -6
- package/dist/plugins/wallet/codegen.mjs +4 -10
- package/dist/plugins/wallet/codegen.mjs.map +1 -1
- package/dist/plugins/wallet/errors.mjs +1 -4
- package/dist/plugins/wallet/errors.mjs.map +1 -1
- package/dist/plugins/wallet/index.d.mts +3 -6
- package/dist/plugins/wallet/index.mjs +16 -21
- package/dist/plugins/wallet/index.mjs.map +1 -1
- package/dist/plugins/wallet/origin-policy.mjs +3 -3
- package/dist/plugins/wallet/origin-policy.mjs.map +1 -1
- package/dist/plugins/wallet/pairing.mjs +6 -24
- package/dist/plugins/wallet/pairing.mjs.map +1 -1
- package/dist/plugins/wallet/protocol.mjs.map +1 -1
- package/dist/plugins/wallet/routable.mjs.map +1 -1
- package/dist/plugins/wallet/server.mjs +17 -24
- package/dist/plugins/wallet/server.mjs.map +1 -1
- package/dist/plugins/wallet/service.d.mts +2 -2
- package/dist/plugins/wallet/service.mjs +4 -15
- package/dist/plugins/wallet/service.mjs.map +1 -1
- package/dist/plugins/wallet/snapshot.mjs.map +1 -1
- package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs +1 -5
- package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs.map +1 -1
- package/dist/plugins/walrus/codegen.d.mts +2 -13
- package/dist/plugins/walrus/codegen.mjs +93 -28
- package/dist/plugins/walrus/codegen.mjs.map +1 -1
- package/dist/plugins/walrus/deploy-paths.mjs +2 -3
- package/dist/plugins/walrus/deploy-paths.mjs.map +1 -1
- package/dist/plugins/walrus/deploy.mjs +26 -19
- package/dist/plugins/walrus/deploy.mjs.map +1 -1
- package/dist/plugins/walrus/errors.mjs +1 -8
- package/dist/plugins/walrus/errors.mjs.map +1 -1
- package/dist/plugins/walrus/faucet-strategy.mjs +15 -1
- package/dist/plugins/walrus/faucet-strategy.mjs.map +1 -1
- package/dist/plugins/walrus/index.d.mts +13 -44
- package/dist/plugins/walrus/index.mjs +119 -122
- package/dist/plugins/walrus/index.mjs.map +1 -1
- package/dist/plugins/walrus/mode/known-deploy.mjs +6 -6
- package/dist/plugins/walrus/mode/known-deploy.mjs.map +1 -1
- package/dist/plugins/walrus/mode/local-cluster.d.mts +2 -2
- package/dist/plugins/walrus/mode/local-cluster.mjs +2 -10
- package/dist/plugins/walrus/mode/local-cluster.mjs.map +1 -1
- package/dist/plugins/walrus/plugin-key.mjs.map +1 -1
- package/dist/plugins/walrus/registry-publish.mjs.map +1 -1
- package/dist/plugins/walrus/routable.mjs.map +1 -1
- package/dist/plugins/walrus/service.mjs.map +1 -1
- package/dist/plugins/walrus/snapshot.mjs +3 -3
- package/dist/plugins/walrus/snapshot.mjs.map +1 -1
- package/dist/plugins/walrus/storage-nodes.mjs +53 -14
- package/dist/plugins/walrus/storage-nodes.mjs.map +1 -1
- package/dist/plugins/walrus/wal-swap.mjs +4 -8
- package/dist/plugins/walrus/wal-swap.mjs.map +1 -1
- package/dist/primitives/artifact-publisher.mjs.map +1 -1
- package/dist/primitives/cache.d.mts +1 -1
- package/dist/runtime/docker/client.mjs +47 -3
- package/dist/runtime/docker/client.mjs.map +1 -1
- package/dist/runtime/docker/container.mjs +37 -57
- package/dist/runtime/docker/container.mjs.map +1 -1
- package/dist/runtime/docker/errors.mjs.map +1 -1
- package/dist/runtime/docker/exec.mjs +2 -2
- package/dist/runtime/docker/exec.mjs.map +1 -1
- package/dist/runtime/docker/image.mjs +10 -11
- package/dist/runtime/docker/image.mjs.map +1 -1
- package/dist/runtime/docker/index.mjs +0 -1
- package/dist/runtime/docker/inspect-and-decode.mjs.map +1 -1
- package/dist/runtime/docker/inventory.mjs +9 -9
- package/dist/runtime/docker/inventory.mjs.map +1 -1
- package/dist/runtime/docker/labels.mjs +12 -1
- package/dist/runtime/docker/labels.mjs.map +1 -1
- package/dist/runtime/docker/network.mjs +6 -6
- package/dist/runtime/docker/network.mjs.map +1 -1
- package/dist/runtime/docker/render-run-args.mjs.map +1 -1
- package/dist/runtime/docker/service.mjs +31 -45
- package/dist/runtime/docker/service.mjs.map +1 -1
- package/dist/runtime/docker/sweep.mjs +14 -64
- package/dist/runtime/docker/sweep.mjs.map +1 -1
- package/dist/runtime/docker/volume.mjs +1 -1
- package/dist/runtime/docker/volume.mjs.map +1 -1
- package/dist/runtime/docker/wrap.mjs +14 -2
- package/dist/runtime/docker/wrap.mjs.map +1 -1
- package/dist/substrate/brand.d.mts +2 -5
- package/dist/substrate/brand.mjs +3 -2
- package/dist/substrate/brand.mjs.map +1 -1
- package/dist/substrate/cross-process.mjs +2 -16
- package/dist/substrate/cross-process.mjs.map +1 -1
- package/dist/substrate/event-time.mjs +0 -2
- package/dist/substrate/event-time.mjs.map +1 -1
- package/dist/substrate/events.d.mts +46 -16
- package/dist/substrate/identity.d.mts +11 -5
- package/dist/substrate/manifest.d.mts +33 -26
- package/dist/substrate/manifest.mjs +8 -3
- package/dist/substrate/manifest.mjs.map +1 -1
- package/dist/substrate/options.d.mts +33 -4
- package/dist/substrate/plugin-ctx.d.mts +70 -0
- package/dist/substrate/plugin-ctx.mjs +66 -0
- package/dist/substrate/plugin-ctx.mjs.map +1 -0
- package/dist/substrate/plugin.d.mts +46 -38
- package/dist/substrate/plugin.mjs +13 -9
- package/dist/substrate/plugin.mjs.map +1 -1
- package/dist/substrate/projection.d.mts +1 -1
- package/dist/substrate/runtime/atomic-write.mjs +3 -4
- package/dist/substrate/runtime/atomic-write.mjs.map +1 -1
- package/dist/substrate/runtime/cache/schema.mjs.map +1 -1
- package/dist/substrate/runtime/cache/service.mjs +50 -20
- package/dist/substrate/runtime/cache/service.mjs.map +1 -1
- package/dist/substrate/runtime/config-validation.mjs.map +1 -1
- package/dist/substrate/runtime/control-plane/domain.mjs +34 -12
- package/dist/substrate/runtime/control-plane/domain.mjs.map +1 -1
- package/dist/substrate/runtime/control-plane/service.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/command-channel/channel.mjs +14 -17
- package/dist/substrate/runtime/cross-process/command-channel/channel.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs.map +1 -1
- 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.map +1 -1
- package/dist/substrate/runtime/cross-process/index.mjs +0 -2
- package/dist/substrate/runtime/cross-process/live-clock.mjs +1 -1
- package/dist/substrate/runtime/cross-process/live-clock.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/liveness.mjs +11 -18
- package/dist/substrate/runtime/cross-process/liveness.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs +2 -2
- package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/roster.mjs +17 -127
- package/dist/substrate/runtime/cross-process/roster.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/self-pid.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/stack-lock.mjs +29 -28
- package/dist/substrate/runtime/cross-process/stack-lock.mjs.map +1 -1
- package/dist/substrate/runtime/current-plugin.mjs.map +1 -1
- package/dist/substrate/runtime/errors.mjs +1 -13
- package/dist/substrate/runtime/errors.mjs.map +1 -1
- package/dist/substrate/runtime/format-unknown-error.mjs.map +1 -1
- package/dist/substrate/runtime/host-bind-mount-owner.mjs.map +1 -1
- package/dist/substrate/runtime/host-gateway.mjs.map +1 -1
- package/dist/substrate/runtime/host-tree-tar/index.mjs +15 -163
- package/dist/substrate/runtime/host-tree-tar/index.mjs.map +1 -1
- package/dist/substrate/runtime/http-probe.d.mts +1 -3
- package/dist/substrate/runtime/http-probe.mjs.map +1 -1
- package/dist/substrate/runtime/index.mjs +2 -6
- package/dist/substrate/runtime/lease-broker/service.mjs +5 -23
- package/dist/substrate/runtime/lease-broker/service.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/dep-graph.mjs +3 -3
- package/dist/substrate/runtime/lifecycle/dep-graph.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/file-watcher.mjs +54 -0
- package/dist/substrate/runtime/lifecycle/file-watcher.mjs.map +1 -0
- package/dist/substrate/runtime/lifecycle/graph-input-id.d.mts +1 -0
- package/dist/substrate/runtime/lifecycle/graph-input-id.mjs +133 -0
- package/dist/substrate/runtime/lifecycle/graph-input-id.mjs.map +1 -0
- package/dist/substrate/runtime/lifecycle/index.mjs +3 -2
- package/dist/substrate/runtime/lifecycle/plugin-registry.d.mts +1 -1
- package/dist/substrate/runtime/lifecycle/plugin-registry.mjs +22 -1
- package/dist/substrate/runtime/lifecycle/plugin-registry.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/ready-gate.mjs +2 -15
- package/dist/substrate/runtime/lifecycle/ready-gate.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/selective-restart.mjs +29 -25
- package/dist/substrate/runtime/lifecycle/selective-restart.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/signals.mjs +1 -1
- package/dist/substrate/runtime/lifecycle/signals.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/state-machine.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/watch-attribution.d.mts +1 -1
- package/dist/substrate/runtime/lifecycle/watch-attribution.mjs +76 -7
- package/dist/substrate/runtime/lifecycle/watch-attribution.mjs.map +1 -1
- package/dist/substrate/runtime/managed-container.d.mts +5 -1
- package/dist/substrate/runtime/managed-container.mjs +8 -10
- package/dist/substrate/runtime/managed-container.mjs.map +1 -1
- package/dist/substrate/runtime/manifest/manifest.mjs +8 -30
- package/dist/substrate/runtime/manifest/manifest.mjs.map +1 -1
- package/dist/substrate/runtime/mode-errors.d.mts +1 -2
- package/dist/substrate/runtime/mode-errors.mjs.map +1 -1
- package/dist/substrate/runtime/observability/cascade-formatter.mjs +1 -11
- package/dist/substrate/runtime/observability/cascade-formatter.mjs.map +1 -1
- package/dist/substrate/runtime/observability/ignore-with-log.mjs.map +1 -1
- package/dist/substrate/runtime/observability/index.d.mts +1 -1
- package/dist/substrate/runtime/observability/index.mjs +4 -6
- package/dist/substrate/runtime/observability/log-attrs.mjs +46 -0
- package/dist/substrate/runtime/observability/log-attrs.mjs.map +1 -0
- package/dist/substrate/runtime/observability/log-store.mjs.map +1 -1
- package/dist/substrate/runtime/observability/logger.mjs +3 -3
- package/dist/substrate/runtime/observability/logger.mjs.map +1 -1
- package/dist/substrate/runtime/observability/output-truncate.mjs.map +1 -1
- package/dist/substrate/runtime/observability/pretty-error.mjs.map +1 -1
- package/dist/substrate/runtime/observability/process-lines.mjs.map +1 -1
- package/dist/substrate/runtime/observability/redaction.mjs.map +1 -1
- package/dist/substrate/runtime/observability/subprocess-capture.mjs +2 -2
- package/dist/substrate/runtime/observability/subprocess-capture.mjs.map +1 -1
- package/dist/substrate/runtime/passthrough-or-wrap.mjs.map +1 -1
- package/dist/substrate/runtime/paths.mjs +27 -9
- package/dist/substrate/runtime/paths.mjs.map +1 -1
- package/dist/substrate/runtime/phase-preserving-produce.mjs.map +1 -1
- package/dist/substrate/runtime/port-broker/service.mjs +10 -27
- package/dist/substrate/runtime/port-broker/service.mjs.map +1 -1
- package/dist/substrate/runtime/post-acquire-tasks.mjs.map +1 -1
- package/dist/substrate/runtime/probes.d.mts +2 -3
- package/dist/substrate/runtime/probes.mjs.map +1 -1
- package/dist/substrate/runtime/process-supervisor.mjs.map +1 -1
- package/dist/substrate/runtime/projection/operational-endpoints.mjs.map +1 -1
- package/dist/substrate/runtime/projection/state-ref.mjs.map +1 -1
- package/dist/substrate/runtime/projection/update.mjs +87 -11
- package/dist/substrate/runtime/projection/update.mjs.map +1 -1
- package/dist/substrate/runtime/random-suffix.mjs.map +1 -1
- package/dist/substrate/runtime/reconcile/fs-plan.mjs +146 -0
- package/dist/substrate/runtime/reconcile/fs-plan.mjs.map +1 -0
- package/dist/substrate/runtime/reconcile/graph.mjs +19 -0
- package/dist/substrate/runtime/reconcile/graph.mjs.map +1 -0
- package/dist/substrate/runtime/reconcile/index.mjs +5 -0
- package/dist/substrate/runtime/reconcile/label.mjs +41 -0
- package/dist/substrate/runtime/reconcile/label.mjs.map +1 -0
- package/dist/substrate/runtime/reconcile/spec.mjs +15 -0
- package/dist/substrate/runtime/reconcile/spec.mjs.map +1 -0
- package/dist/substrate/runtime/retry-policy.d.mts +2 -3
- package/dist/substrate/runtime/retry-policy.mjs.map +1 -1
- package/dist/substrate/runtime/routed-url.mjs.map +1 -1
- package/dist/substrate/runtime/runtime-decode.mjs.map +1 -1
- package/dist/substrate/runtime/scoped-http-server.mjs.map +1 -1
- package/dist/substrate/runtime/stage-and-swap/index.mjs +49 -12
- package/dist/substrate/runtime/stage-and-swap/index.mjs.map +1 -1
- package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.mjs.map +1 -1
- package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs.map +1 -1
- package/dist/substrate/runtime/strategy-registry/service.mjs +29 -17
- package/dist/substrate/runtime/strategy-registry/service.mjs.map +1 -1
- package/dist/substrate/runtime/subnet-broker.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/acquire-node.mjs +188 -56
- package/dist/substrate/runtime/supervisor/acquire-node.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/background-tasks.mjs +79 -65
- package/dist/substrate/runtime/supervisor/background-tasks.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/command-loop.mjs +82 -23
- package/dist/substrate/runtime/supervisor/command-loop.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/contribution-dispatcher.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/contribution-dispatcher.mjs +16 -0
- package/dist/substrate/runtime/supervisor/contribution-dispatcher.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/errors.mjs +11 -2
- package/dist/substrate/runtime/supervisor/errors.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/index.mjs +2 -0
- package/dist/substrate/runtime/supervisor/shutdown.mjs +6 -6
- package/dist/substrate/runtime/supervisor/shutdown.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/start-supervisor.mjs +61 -75
- package/dist/substrate/runtime/supervisor/start-supervisor.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/state.d.mts +1 -1
- package/dist/substrate/runtime/supervisor/state.mjs +1 -1
- package/dist/substrate/runtime/supervisor/state.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/teardown.mjs +10 -9
- package/dist/substrate/runtime/supervisor/teardown.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/wiring.mjs +6 -20
- package/dist/substrate/runtime/supervisor/wiring.mjs.map +1 -1
- package/dist/substrate/runtime/tar/reader.mjs +216 -0
- package/dist/substrate/runtime/tar/reader.mjs.map +1 -0
- package/dist/substrate/runtime/typed-env.mjs.map +1 -1
- package/dist/substrate/versioned-doc-schema.mjs.map +1 -1
- package/dist/substrate/versioned-doc-sync.mjs +5 -5
- package/dist/substrate/versioned-doc-sync.mjs.map +1 -1
- package/dist/surfaces/cli/command-tree.mjs +49 -7
- package/dist/surfaces/cli/command-tree.mjs.map +1 -1
- package/dist/surfaces/cli/commands/config.mjs +1 -1
- package/dist/surfaces/cli/commands/config.mjs.map +1 -1
- package/dist/surfaces/cli/commands/confirm-node.mjs.map +1 -1
- package/dist/surfaces/cli/commands/confirm.mjs.map +1 -1
- package/dist/surfaces/cli/commands/doctor.mjs +1 -1
- package/dist/surfaces/cli/commands/doctor.mjs.map +1 -1
- package/dist/surfaces/cli/commands/prune-picker-entry.mjs.map +1 -1
- package/dist/surfaces/cli/commands/prune-picker.mjs.map +1 -1
- package/dist/surfaces/cli/commands/prune.mjs +1 -1
- package/dist/surfaces/cli/commands/prune.mjs.map +1 -1
- package/dist/surfaces/cli/commands/snapshot.mjs +1 -1
- package/dist/surfaces/cli/commands/snapshot.mjs.map +1 -1
- package/dist/surfaces/cli/commands/status.mjs +1 -1
- package/dist/surfaces/cli/commands/status.mjs.map +1 -1
- package/dist/surfaces/cli/commands/supervisor-presence.mjs.map +1 -1
- package/dist/surfaces/cli/commands/wipe.mjs +3 -4
- package/dist/surfaces/cli/commands/wipe.mjs.map +1 -1
- package/dist/surfaces/cli/envelope.mjs.map +1 -1
- package/dist/surfaces/cli/errors.mjs.map +1 -1
- package/dist/surfaces/cli/flags.mjs.map +1 -1
- package/dist/surfaces/cli/index.mjs +45 -14
- package/dist/surfaces/cli/index.mjs.map +1 -1
- package/dist/surfaces/cli/output.mjs.map +1 -1
- package/dist/surfaces/cli/sysexits.mjs.map +1 -1
- package/dist/surfaces/tui/app.mjs +0 -21
- package/dist/surfaces/tui/app.mjs.map +1 -1
- package/dist/surfaces/tui/dashboard.mjs +0 -48
- package/dist/surfaces/tui/dashboard.mjs.map +1 -1
- package/dist/surfaces/tui/display-derivation.mjs +80 -16
- package/dist/surfaces/tui/display-derivation.mjs.map +1 -1
- package/dist/surfaces/tui/errors.mjs.map +1 -1
- package/dist/surfaces/tui/event-log.mjs +0 -9
- package/dist/surfaces/tui/event-log.mjs.map +1 -1
- package/dist/surfaces/tui/heartbeat.mjs.map +1 -1
- package/dist/surfaces/tui/index.mjs +2 -2
- package/dist/surfaces/tui/index.mjs.map +1 -1
- package/dist/surfaces/tui/input.mjs.map +1 -1
- package/dist/surfaces/tui/mode-detect.mjs.map +1 -1
- package/dist/surfaces/tui/mount-ink.mjs.map +1 -1
- package/dist/surfaces/tui/plain-renderer.mjs +26 -19
- package/dist/surfaces/tui/plain-renderer.mjs.map +1 -1
- package/dist/surfaces/tui/resource-table.mjs +8 -10
- package/dist/surfaces/tui/resource-table.mjs.map +1 -1
- package/images/postgres/Dockerfile +0 -1
- package/images/sui/Dockerfile +27 -54
- package/images/sui/entrypoint.sh +17 -179
- package/package.json +23 -15
- package/dashboard-ui/assets/index-Bmi1UtAg.js +0 -1356
- package/dashboard-ui/assets/index-D5EShVt4.js +0 -3
- package/dashboard-ui/assets/index-Deml9drg.css +0 -1
- package/dist/api/plugin-errors.d.mts +0 -7
- package/dist/api/plugin-errors.mjs +0 -10
- package/dist/api/plugin-errors.mjs.map +0 -1
- package/dist/cli/wirings/build-verb-layers.mjs +0 -42
- package/dist/cli/wirings/build-verb-layers.mjs.map +0 -1
- package/dist/contracts/capability-decl.d.mts +0 -40
- package/dist/orchestrators/built-in-plugin-layers.mjs +0 -54
- package/dist/orchestrators/built-in-plugin-layers.mjs.map +0 -1
- package/dist/orchestrators/run.mjs +0 -91
- package/dist/orchestrators/run.mjs.map +0 -1
- package/dist/orchestrators/runtime-composition.d.mts +0 -10
- package/dist/orchestrators/runtime-composition.mjs +0 -252
- package/dist/orchestrators/runtime-composition.mjs.map +0 -1
- package/dist/orchestrators/snapshot/capture-command.d.mts +0 -1
- package/dist/orchestrators/snapshot/capture-command.mjs +0 -25
- package/dist/orchestrators/snapshot/capture-command.mjs.map +0 -1
- package/dist/orchestrators/snapshot/pending-marker.mjs +0 -99
- package/dist/orchestrators/snapshot/pending-marker.mjs.map +0 -1
- package/dist/orchestrators/snapshot/recover-pending.mjs +0 -223
- package/dist/orchestrators/snapshot/recover-pending.mjs.map +0 -1
- package/dist/orchestrators/snapshot/state-document.d.mts +0 -1
- package/dist/orchestrators/snapshot/state-document.mjs +0 -58
- package/dist/orchestrators/snapshot/state-document.mjs.map +0 -1
- package/dist/plugins/account/spans.mjs +0 -16
- package/dist/plugins/account/spans.mjs.map +0 -1
- package/dist/plugins/account/variants/env.mjs +0 -24
- package/dist/plugins/account/variants/env.mjs.map +0 -1
- package/dist/plugins/account/variants/inline.mjs +0 -13
- package/dist/plugins/account/variants/inline.mjs.map +0 -1
- package/dist/plugins/account/variants/keystore.mjs +0 -91
- package/dist/plugins/account/variants/keystore.mjs.map +0 -1
- package/dist/plugins/action/spans.mjs +0 -11
- package/dist/plugins/action/spans.mjs.map +0 -1
- package/dist/plugins/coin/spans.mjs +0 -20
- package/dist/plugins/coin/spans.mjs.map +0 -1
- package/dist/plugins/deepbook/spans.mjs +0 -18
- package/dist/plugins/deepbook/spans.mjs.map +0 -1
- package/dist/plugins/faucet/spans.mjs +0 -12
- package/dist/plugins/faucet/spans.mjs.map +0 -1
- package/dist/plugins/package/spans.mjs +0 -14
- package/dist/plugins/package/spans.mjs.map +0 -1
- package/dist/plugins/postgres/codegen.mjs +0 -42
- package/dist/plugins/postgres/codegen.mjs.map +0 -1
- package/dist/plugins/postgres/connection.d.mts +0 -33
- package/dist/plugins/postgres/connection.mjs.map +0 -1
- package/dist/plugins/postgres/db-ensure.mjs.map +0 -1
- package/dist/plugins/postgres/errors.d.mts +0 -60
- package/dist/plugins/postgres/errors.mjs +0 -29
- package/dist/plugins/postgres/errors.mjs.map +0 -1
- package/dist/plugins/postgres/index.d.mts +0 -37
- package/dist/plugins/postgres/index.mjs +0 -68
- package/dist/plugins/postgres/index.mjs.map +0 -1
- package/dist/plugins/postgres/routable.mjs +0 -33
- package/dist/plugins/postgres/routable.mjs.map +0 -1
- package/dist/plugins/postgres/service.d.mts +0 -50
- package/dist/plugins/postgres/service.mjs +0 -179
- package/dist/plugins/postgres/service.mjs.map +0 -1
- package/dist/plugins/postgres/snapshot.mjs +0 -32
- package/dist/plugins/postgres/snapshot.mjs.map +0 -1
- package/dist/plugins/postgres/spans.mjs +0 -11
- package/dist/plugins/postgres/spans.mjs.map +0 -1
- package/dist/plugins/seal/spans.mjs +0 -18
- package/dist/plugins/seal/spans.mjs.map +0 -1
- package/dist/plugins/sui/spans.mjs +0 -17
- package/dist/plugins/sui/spans.mjs.map +0 -1
- package/dist/plugins/wallet/spans.mjs +0 -22
- package/dist/plugins/wallet/spans.mjs.map +0 -1
- package/dist/plugins/walrus/registry-publish.d.mts +0 -24
- package/dist/plugins/walrus/spans.mjs +0 -18
- package/dist/plugins/walrus/spans.mjs.map +0 -1
- package/dist/runtime/docker/logs.d.mts +0 -1
- package/dist/runtime/docker/logs.mjs +0 -34
- package/dist/runtime/docker/logs.mjs.map +0 -1
- package/dist/substrate/runtime/artifact-publisher/index.mjs +0 -86
- package/dist/substrate/runtime/artifact-publisher/index.mjs.map +0 -1
- package/dist/substrate/runtime/capability-sinks/index.d.mts +0 -1
- package/dist/substrate/runtime/capability-sinks/index.mjs +0 -3
- package/dist/substrate/runtime/capability-sinks/layer.d.mts +0 -1
- package/dist/substrate/runtime/capability-sinks/layer.mjs +0 -31
- package/dist/substrate/runtime/capability-sinks/layer.mjs.map +0 -1
- package/dist/substrate/runtime/capability-sinks/service.d.mts +0 -95
- package/dist/substrate/runtime/capability-sinks/service.mjs +0 -69
- package/dist/substrate/runtime/capability-sinks/service.mjs.map +0 -1
- package/dist/substrate/runtime/cross-process/lock.d.mts +0 -1
- package/dist/substrate/runtime/cross-process/lock.mjs +0 -23
- package/dist/substrate/runtime/cross-process/lock.mjs.map +0 -1
- package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs +0 -113
- package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs.map +0 -1
- package/dist/substrate/runtime/lifecycle/lifecycle-fact.mjs +0 -31
- package/dist/substrate/runtime/lifecycle/lifecycle-fact.mjs.map +0 -1
- package/dist/substrate/runtime/observability/formatter-registry.d.mts +0 -1
- package/dist/substrate/runtime/observability/formatter-registry.mjs +0 -48
- package/dist/substrate/runtime/observability/formatter-registry.mjs.map +0 -1
- package/dist/substrate/runtime/observability/span-store.d.mts +0 -1
- package/dist/substrate/runtime/observability/span-store.mjs +0 -110
- package/dist/substrate/runtime/observability/span-store.mjs.map +0 -1
- package/dist/substrate/runtime/observability/spans.d.mts +0 -1
- package/dist/substrate/runtime/observability/spans.mjs +0 -87
- package/dist/substrate/runtime/observability/spans.mjs.map +0 -1
- package/dist/substrate/runtime/projection/index.mjs +0 -4
- package/dist/substrate/runtime/projection/persisted.mjs +0 -213
- package/dist/substrate/runtime/projection/persisted.mjs.map +0 -1
- package/dist/substrate/runtime/scoped-multimap/service.mjs +0 -52
- package/dist/substrate/runtime/scoped-multimap/service.mjs.map +0 -1
- package/dist/substrate/runtime/scoped-ref-map/index.mjs +0 -2
- package/dist/substrate/runtime/scoped-ref-map/service.mjs +0 -83
- package/dist/substrate/runtime/scoped-ref-map/service.mjs.map +0 -1
- package/dist/substrate/runtime/state-store/index.mjs +0 -3
- package/dist/substrate/runtime/state-store/schema.d.mts +0 -1
- package/dist/substrate/runtime/state-store/schema.mjs +0 -41
- package/dist/substrate/runtime/state-store/schema.mjs.map +0 -1
- package/dist/substrate/runtime/state-store/service.d.mts +0 -1
- package/dist/substrate/runtime/state-store/service.mjs +0 -145
- package/dist/substrate/runtime/state-store/service.mjs.map +0 -1
- package/dist/substrate/runtime/sui-execute/index.mjs.map +0 -1
- package/dist/substrate/runtime/sui-execute/sign-and-dispatch.mjs.map +0 -1
- package/dist/substrate/runtime/sui-ledger/object-ref.mjs.map +0 -1
- package/dist/substrate/runtime/sui-move-build/index.mjs.map +0 -1
- package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs +0 -151
- package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs.map +0 -1
- package/dist/substrate/state-store.d.mts +0 -1
- /package/dist/orchestrators/{snapshot/pending-marker.d.mts → codegen/id-config.d.mts} +0 -0
- /package/dist/orchestrators/snapshot/{recover-pending.d.mts → interrupted-restore.d.mts} +0 -0
- /package/dist/{substrate/runtime/sui-execute → plugins/sui/exec}/sign-and-dispatch.d.mts +0 -0
- /package/dist/plugins/{postgres/snapshot.d.mts → sui/ledger/object-ref.d.mts} +0 -0
- /package/dist/{substrate/runtime/sui-move-build → plugins/sui/move}/index.d.mts +0 -0
- /package/dist/substrate/runtime/{cross-process/snapshot-reservation.d.mts → lifecycle/file-watcher.d.mts} +0 -0
- /package/dist/substrate/runtime/{state-store/index.d.mts → reconcile/graph.d.mts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dep-graph.mjs","names":["makePluginKey"],"sources":["../../../../src/substrate/runtime/lifecycle/dep-graph.ts"],"sourcesContent":["// Dep-graph resolution — turn a `Stack` member tuple into a topo-sorted\n// acquire schedule.\n//\n// Architecture § Plugin lifecycle within a stack:\n// \"Resolution. Upstream keys (concrete or capability-typed) resolve\n// once. Bootstrap asset dedup-by-key fires before the scheduler\n// starts node fibers. Scheduling. Plugin enters `pending`. When all\n// upstream keys are `ready`, the node begins `acquiring`. Per-key\n// serialization: only one acquire at a time per key.\"\n//\n// This module is the pure dep-graph math: members in, levels out.\n\nimport { Data, Effect } from 'effect';\n\nimport type { PluginKey } from '../../brand.ts';\nimport { pluginKey as makePluginKey } from '../../brand.ts';\nimport { uniqueResourceRefs, type AnyPlugin, type AnyResourceRef } from '../../plugin.ts';\n\n// -----------------------------------------------------------------------------\n// Errors\n// -----------------------------------------------------------------------------\n\n/** Cycle detected in the dep graph. Carries the offending key path so\n * the user sees the loop. Compile-time `defineDevstack` doesn't catch\n * every cycle (capability-typed consumes resolve at runtime), so this\n * surfaces a typed error at boot. */\nexport class DepGraphCycleError extends Data.TaggedError('DepGraphCycleError')<{\n\treadonly cycle: ReadonlyArray<PluginKey>;\n}> {}\n\n/** A dependency resource matched no provider. This is normally caught by\n * the compile-time `MissingProviders` check, but runtime-built stacks can\n * hit it. */\nexport class UnresolvedDependencyError extends Data.TaggedError('UnresolvedDependencyError')<{\n\treadonly pluginKey: PluginKey;\n\treadonly missingResourceId: string;\n}> {}\n\n/** Two members declared the same `resource id`. The compile-time\n * `MissingProviders` check only catches collisions on the user-typed\n * dependency path, NOT two members declared in the same stack with the\n * same `definePlugin({ id })`. Without this guard the dep-graph would\n * last-writer-wins the provider index and silently bind every dependent\n * to the second declaration. Phase 22e/E3 added a complementary\n * package-plugin-level guard (`plugins/package/mode-local.ts`) for the\n * registry path; this surfaces the same class of mistake for ALL plugins\n * at the substrate dep-graph layer. */\nexport class DuplicateResourceIdError extends Data.TaggedError('DuplicateResourceIdError')<{\n\treadonly resourceId: string;\n\treadonly firstPluginKey: PluginKey;\n\treadonly secondPluginKey: PluginKey;\n}> {}\n\nexport type DepGraphError =\n\t| DepGraphCycleError\n\t| UnresolvedDependencyError\n\t| DuplicateResourceIdError;\n\n// -----------------------------------------------------------------------------\n// Node shape\n// -----------------------------------------------------------------------------\n\n/** A resolved node in the dep graph. Wraps the original plugin with a\n * substrate-assigned `PluginKey`. */\nexport interface DepNode {\n\treadonly key: PluginKey;\n\treadonly member: AnyPlugin;\n\t/** Unique dependency refs and their resolved upstream keys. The two\n\t * arrays are positional peers. */\n\treadonly upstreamResources: ReadonlyArray<AnyResourceRef>;\n\treadonly upstreamKeys: ReadonlyArray<PluginKey>;\n}\n\n/** The result of resolving a member tuple. Levels are batches the\n * scheduler can acquire in parallel; each level's nodes only depend\n * on prior levels. */\nexport interface ResolvedGraph {\n\treadonly nodes: ReadonlyMap<PluginKey, DepNode>;\n\treadonly levels: ReadonlyArray<ReadonlyArray<PluginKey>>;\n\t/** Reverse-dep index: each key → keys that depend on it. The\n\t * supervisor uses this for selective-restart cascade. */\n\treadonly downstream: ReadonlyMap<PluginKey, ReadonlySet<PluginKey>>;\n}\n\n// -----------------------------------------------------------------------------\n// Plugin key minting\n// -----------------------------------------------------------------------------\n\ninterface NamedMember {\n\treadonly key: PluginKey;\n\treadonly member: AnyPlugin;\n}\n\n/** Mint a stable PluginKey for a plugin. Plugins may declare a stable\n * key; otherwise keys derive from resource id + ordinal so duplicates\n * do not collide. */\nconst mintKey = (member: AnyPlugin, ordinal: number): PluginKey => {\n\tif (member.pluginKey !== undefined) {\n\t\treturn makePluginKey(String(member.pluginKey));\n\t}\n\treturn makePluginKey(`${member.id}#${ordinal}`);\n};\n\n/** Walk the member tuple and emit one named-member entry per node. */\nconst expand = (members: ReadonlyArray<AnyPlugin>): ReadonlyArray<NamedMember> => {\n\tconst out: NamedMember[] = [];\n\tlet ordinal = 0;\n\tfor (const member of members) {\n\t\tconst key = mintKey(member, ordinal++);\n\t\tout.push({ key, member });\n\t}\n\treturn out;\n};\n\n// -----------------------------------------------------------------------------\n// Topological sort (Kahn's algorithm)\n// -----------------------------------------------------------------------------\n\n/**\n * Resolve a flat member tuple into a topo-sorted level batch.\n *\n * Steps:\n * 1. Mint a plugin key for every member.\n * 2. Build the resource-id -> key index (providers). Two members with\n * the same `id` fail with `DuplicateResourceIdError`.\n * 3. For each node, resolve its dependency refs to upstream keys.\n * 4. Kahn's algorithm: peel zero-indegree nodes into level 0, decrement\n * downstream indegrees, repeat.\n * 5. If any node remains, return `DepGraphCycleError`.\n *\n * Span-instrumented so trace exports show the resolution alongside the\n * supervisor's acquire spans.\n */\nexport const resolveGraph = (\n\tmembers: ReadonlyArray<AnyPlugin>,\n): Effect.Effect<ResolvedGraph, DepGraphError> =>\n\tEffect.gen(function* () {\n\t\tyield* Effect.annotateCurrentSpan({ 'devstack.dep-graph.memberCount': members.length });\n\t\tconst named = expand(members);\n\n\t\t// Provider index: resource-id → key. The compile-time\n\t\t// `MissingProviders` check ensures uniqueness on the user-typed\n\t\t// dependency path, but a runtime-built stack (or a typo'd\n\t\t// `definePlugin({ id })`) can still ship two members with the\n\t\t// same `resource id`. Without an explicit guard the index would\n\t\t// last-writer-wins and every dependent would silently bind to\n\t\t// the second declaration; we fail early with a typed error\n\t\t// instead so a developer sees the conflicting plugin keys at\n\t\t// boot rather than chasing a \"wrong provider\" mystery downstream.\n\t\t// Phase 22e/E3's package-plugin-level guard in\n\t\t// `plugins/package/mode-local.ts` is complementary — it fires on\n\t\t// the registry path before this resolver runs.\n\t\tconst providerByResourceId = new Map<string, PluginKey>();\n\t\tfor (const { key, member } of named) {\n\t\t\tconst existing = providerByResourceId.get(member.id);\n\t\t\tif (existing !== undefined) {\n\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\tnew DuplicateResourceIdError({\n\t\t\t\t\t\tresourceId: member.id,\n\t\t\t\t\t\tfirstPluginKey: existing,\n\t\t\t\t\t\tsecondPluginKey: key,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\tproviderByResourceId.set(member.id, key);\n\t\t}\n\n\t\tconst nodes = new Map<PluginKey, DepNode>();\n\t\tconst indegree = new Map<PluginKey, number>();\n\t\tconst downstream = new Map<PluginKey, Set<PluginKey>>();\n\t\tfor (const { key } of named) {\n\t\t\tindegree.set(key, 0);\n\t\t\tdownstream.set(key, new Set());\n\t\t}\n\n\t\tfor (const { key, member } of named) {\n\t\t\tconst upstreamKeys: PluginKey[] = [];\n\t\t\tconst upstreamResources = uniqueResourceRefs(member.dependsOn);\n\t\t\tfor (const resource of upstreamResources) {\n\t\t\t\tconst providerKey = providerByResourceId.get(resource.id);\n\t\t\t\tif (providerKey === undefined) {\n\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\tnew UnresolvedDependencyError({ pluginKey: key, missingResourceId: resource.id }),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tupstreamKeys.push(providerKey);\n\t\t\t\tdownstream.get(providerKey)?.add(key);\n\t\t\t\tindegree.set(key, (indegree.get(key) ?? 0) + 1);\n\t\t\t}\n\t\t\tnodes.set(key, {\n\t\t\t\tkey,\n\t\t\t\tmember,\n\t\t\t\tupstreamResources,\n\t\t\t\tupstreamKeys,\n\t\t\t});\n\t\t}\n\n\t\t// Kahn's algorithm — peel zero-indegree nodes level by level.\n\t\tconst levels: PluginKey[][] = [];\n\t\tconst settled = new Set<PluginKey>();\n\t\twhile (settled.size < nodes.size) {\n\t\t\tconst layer: PluginKey[] = [];\n\t\t\tfor (const [key, deg] of indegree) {\n\t\t\t\tif (settled.has(key)) continue;\n\t\t\t\tif (deg === 0) layer.push(key);\n\t\t\t}\n\t\t\tif (layer.length === 0) {\n\t\t\t\t// Cycle: collect every unsettled node as the cycle's witness.\n\t\t\t\t// More precise cycle extraction (Tarjan SCC) is overkill for\n\t\t\t\t// the user-facing message; we surface the trapped keys.\n\t\t\t\tconst trapped: PluginKey[] = [];\n\t\t\t\tfor (const key of nodes.keys()) {\n\t\t\t\t\tif (!settled.has(key)) trapped.push(key);\n\t\t\t\t}\n\t\t\t\treturn yield* Effect.fail(new DepGraphCycleError({ cycle: trapped }));\n\t\t\t}\n\t\t\tlevels.push(layer);\n\t\t\tfor (const key of layer) {\n\t\t\t\tsettled.add(key);\n\t\t\t\tfor (const child of downstream.get(key) ?? []) {\n\t\t\t\t\tindegree.set(child, (indegree.get(child) ?? 1) - 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Freeze downstream sets to ReadonlySet shape.\n\t\tconst downstreamFrozen = new Map<PluginKey, ReadonlySet<PluginKey>>();\n\t\tfor (const [k, v] of downstream) downstreamFrozen.set(k, v);\n\n\t\treturn {\n\t\t\tnodes,\n\t\t\tlevels,\n\t\t\tdownstream: downstreamFrozen,\n\t\t} satisfies ResolvedGraph;\n\t}).pipe(Effect.withSpan('lifecycle.dep-graph.resolve'));\n\n// -----------------------------------------------------------------------------\n// Selective-restart helpers\n// -----------------------------------------------------------------------------\n\n/**\n * Compute the closure of nodes downstream of `root` (inclusive).\n * Used by the supervisor to tear down a subgraph in reverse-dep order\n * and re-acquire in forward order.\n *\n * Architecture § Watch-triggered invalidation:\n * Invalidating a producer invalidates downstream consumers along\n * dep-graph edges (cascade semantics).\n */\nexport const downstreamClosure = (\n\tgraph: ResolvedGraph,\n\troot: PluginKey,\n): ReadonlySet<PluginKey> => {\n\tconst closure = new Set<PluginKey>([root]);\n\tconst queue: PluginKey[] = [root];\n\twhile (queue.length > 0) {\n\t\tconst next = queue.shift()!;\n\t\tfor (const child of graph.downstream.get(next) ?? []) {\n\t\t\tif (!closure.has(child)) {\n\t\t\t\tclosure.add(child);\n\t\t\t\tqueue.push(child);\n\t\t\t}\n\t\t}\n\t}\n\treturn closure;\n};\n\n/** Order a set of keys by their dep-graph level — forward (low-to-high)\n * for acquire, reverse (high-to-low) for teardown. */\nexport const orderByLevel = (\n\tgraph: ResolvedGraph,\n\tkeys: ReadonlySet<PluginKey>,\n\tdirection: 'forward' | 'reverse',\n): ReadonlyArray<PluginKey> => {\n\tconst out: PluginKey[] = [];\n\tfor (const level of graph.levels) {\n\t\tfor (const key of level) if (keys.has(key)) out.push(key);\n\t}\n\treturn direction === 'reverse' ? out.slice().reverse() : out;\n};\n"],"mappings":";;;;;;;;AA0BA,IAAa,qBAAb,cAAwC,KAAK,YAAY,qBAAqB,CAE3E;;;;AAKH,IAAa,4BAAb,cAA+C,KAAK,YAAY,4BAA4B,CAGzF;;;;;;;;;;AAWH,IAAa,2BAAb,cAA8C,KAAK,YAAY,2BAA2B,CAIvF;;;;AA6CH,MAAM,WAAW,QAAmB,YAA+B;AAClE,KAAI,OAAO,cAAc,KAAA,EACxB,QAAOA,UAAc,OAAO,OAAO,UAAU,CAAC;AAE/C,QAAOA,UAAc,GAAG,OAAO,GAAG,GAAG,UAAU;;;AAIhD,MAAM,UAAU,YAAkE;CACjF,MAAM,MAAqB,EAAE;CAC7B,IAAI,UAAU;AACd,MAAK,MAAM,UAAU,SAAS;EAC7B,MAAM,MAAM,QAAQ,QAAQ,UAAU;AACtC,MAAI,KAAK;GAAE;GAAK;GAAQ,CAAC;;AAE1B,QAAO;;;;;;;;;;;;;;;;;AAsBR,MAAa,gBACZ,YAEA,OAAO,IAAI,aAAa;AACvB,QAAO,OAAO,oBAAoB,EAAE,kCAAkC,QAAQ,QAAQ,CAAC;CACvF,MAAM,QAAQ,OAAO,QAAQ;CAc7B,MAAM,uCAAuB,IAAI,KAAwB;AACzD,MAAK,MAAM,EAAE,KAAK,YAAY,OAAO;EACpC,MAAM,WAAW,qBAAqB,IAAI,OAAO,GAAG;AACpD,MAAI,aAAa,KAAA,EAChB,QAAO,OAAO,OAAO,KACpB,IAAI,yBAAyB;GAC5B,YAAY,OAAO;GACnB,gBAAgB;GAChB,iBAAiB;GACjB,CAAC,CACF;AAEF,uBAAqB,IAAI,OAAO,IAAI,IAAI;;CAGzC,MAAM,wBAAQ,IAAI,KAAyB;CAC3C,MAAM,2BAAW,IAAI,KAAwB;CAC7C,MAAM,6BAAa,IAAI,KAAgC;AACvD,MAAK,MAAM,EAAE,SAAS,OAAO;AAC5B,WAAS,IAAI,KAAK,EAAE;AACpB,aAAW,IAAI,qBAAK,IAAI,KAAK,CAAC;;AAG/B,MAAK,MAAM,EAAE,KAAK,YAAY,OAAO;EACpC,MAAM,eAA4B,EAAE;EACpC,MAAM,oBAAoB,mBAAmB,OAAO,UAAU;AAC9D,OAAK,MAAM,YAAY,mBAAmB;GACzC,MAAM,cAAc,qBAAqB,IAAI,SAAS,GAAG;AACzD,OAAI,gBAAgB,KAAA,EACnB,QAAO,OAAO,OAAO,KACpB,IAAI,0BAA0B;IAAE,WAAW;IAAK,mBAAmB,SAAS;IAAI,CAAC,CACjF;AAEF,gBAAa,KAAK,YAAY;AAC9B,cAAW,IAAI,YAAY,EAAE,IAAI,IAAI;AACrC,YAAS,IAAI,MAAM,SAAS,IAAI,IAAI,IAAI,KAAK,EAAE;;AAEhD,QAAM,IAAI,KAAK;GACd;GACA;GACA;GACA;GACA,CAAC;;CAIH,MAAM,SAAwB,EAAE;CAChC,MAAM,0BAAU,IAAI,KAAgB;AACpC,QAAO,QAAQ,OAAO,MAAM,MAAM;EACjC,MAAM,QAAqB,EAAE;AAC7B,OAAK,MAAM,CAAC,KAAK,QAAQ,UAAU;AAClC,OAAI,QAAQ,IAAI,IAAI,CAAE;AACtB,OAAI,QAAQ,EAAG,OAAM,KAAK,IAAI;;AAE/B,MAAI,MAAM,WAAW,GAAG;GAIvB,MAAM,UAAuB,EAAE;AAC/B,QAAK,MAAM,OAAO,MAAM,MAAM,CAC7B,KAAI,CAAC,QAAQ,IAAI,IAAI,CAAE,SAAQ,KAAK,IAAI;AAEzC,UAAO,OAAO,OAAO,KAAK,IAAI,mBAAmB,EAAE,OAAO,SAAS,CAAC,CAAC;;AAEtE,SAAO,KAAK,MAAM;AAClB,OAAK,MAAM,OAAO,OAAO;AACxB,WAAQ,IAAI,IAAI;AAChB,QAAK,MAAM,SAAS,WAAW,IAAI,IAAI,IAAI,EAAE,CAC5C,UAAS,IAAI,QAAQ,SAAS,IAAI,MAAM,IAAI,KAAK,EAAE;;;CAMtD,MAAM,mCAAmB,IAAI,KAAwC;AACrE,MAAK,MAAM,CAAC,GAAG,MAAM,WAAY,kBAAiB,IAAI,GAAG,EAAE;AAE3D,QAAO;EACN;EACA;EACA,YAAY;EACZ;EACA,CAAC,KAAK,OAAO,SAAS,8BAA8B,CAAC;;;;;;;;;;AAexD,MAAa,qBACZ,OACA,SAC4B;CAC5B,MAAM,UAAU,IAAI,IAAe,CAAC,KAAK,CAAC;CAC1C,MAAM,QAAqB,CAAC,KAAK;AACjC,QAAO,MAAM,SAAS,GAAG;EACxB,MAAM,OAAO,MAAM,OAAO;AAC1B,OAAK,MAAM,SAAS,MAAM,WAAW,IAAI,KAAK,IAAI,EAAE,CACnD,KAAI,CAAC,QAAQ,IAAI,MAAM,EAAE;AACxB,WAAQ,IAAI,MAAM;AAClB,SAAM,KAAK,MAAM;;;AAIpB,QAAO;;;;AAKR,MAAa,gBACZ,OACA,MACA,cAC8B;CAC9B,MAAM,MAAmB,EAAE;AAC3B,MAAK,MAAM,SAAS,MAAM,OACzB,MAAK,MAAM,OAAO,MAAO,KAAI,KAAK,IAAI,IAAI,CAAE,KAAI,KAAK,IAAI;AAE1D,QAAO,cAAc,YAAY,IAAI,OAAO,CAAC,SAAS,GAAG"}
|
|
1
|
+
{"version":3,"file":"dep-graph.mjs","names":["makePluginKey"],"sources":["../../../../src/substrate/runtime/lifecycle/dep-graph.ts"],"sourcesContent":["// Dep-graph resolution — turn a `Stack` member tuple into a topo-sorted\n// acquire schedule.\n//\n// Architecture § Plugin lifecycle within a stack:\n// \"Resolution. Upstream keys (concrete or capability-typed) resolve\n// once. Bootstrap asset dedup-by-key fires before the scheduler\n// starts node fibers. Scheduling. Plugin enters `pending`. When all\n// upstream keys are `ready`, the node begins `acquiring`. Per-key\n// serialization: only one acquire at a time per key.\"\n//\n// This module is the pure dep-graph math: members in, levels out.\n\nimport { Data, Effect } from 'effect';\n\nimport type { PluginKey } from '../../brand.ts';\nimport { pluginKey as makePluginKey } from '../../brand.ts';\nimport { uniqueResourceRefs, type AnyPlugin, type AnyResourceRef } from '../../plugin.ts';\n\n// -----------------------------------------------------------------------------\n// Errors\n// -----------------------------------------------------------------------------\n\n/** Cycle detected in the dep graph. Carries the offending key path so\n * the user sees the loop. Compile-time `defineDevstack` doesn't catch\n * every cycle (capability-typed consumes resolve at runtime), so this\n * surfaces a typed error at boot. */\nexport class DepGraphCycleError extends Data.TaggedError('DepGraphCycleError')<{\n\treadonly cycle: ReadonlyArray<PluginKey>;\n}> {}\n\n/** A dependency resource matched no provider. This is normally caught by\n * the compile-time `MissingProviders` check, but runtime-built stacks can\n * hit it. */\nexport class UnresolvedDependencyError extends Data.TaggedError('UnresolvedDependencyError')<{\n\treadonly pluginKey: PluginKey;\n\treadonly missingResourceId: string;\n}> {}\n\n/** Two members declared the same `resource id`. The compile-time\n * `MissingProviders` check only catches collisions on the user-typed\n * dependency path, NOT two members declared in the same stack with the\n * same `definePlugin({ id })`. Without this guard the dep-graph would\n * last-writer-wins the provider index and silently bind every dependent\n * to the second declaration. Phase 22e/E3 added a complementary\n * package-plugin-level guard (`plugins/package/mode-local.ts`) for the\n * registry path; this surfaces the same class of mistake for ALL plugins\n * at the substrate dep-graph layer. */\nexport class DuplicateResourceIdError extends Data.TaggedError('DuplicateResourceIdError')<{\n\treadonly resourceId: string;\n\treadonly firstPluginKey: PluginKey;\n\treadonly secondPluginKey: PluginKey;\n}> {}\n\nexport type DepGraphError =\n\t| DepGraphCycleError\n\t| UnresolvedDependencyError\n\t| DuplicateResourceIdError;\n\n// -----------------------------------------------------------------------------\n// Node shape\n// -----------------------------------------------------------------------------\n\n/** A resolved node in the dep graph. Wraps the original plugin with a\n * substrate-assigned `PluginKey`. */\nexport interface DepNode {\n\treadonly key: PluginKey;\n\treadonly member: AnyPlugin;\n\t/** Unique dependency refs and their resolved upstream keys. The two\n\t * arrays are positional peers. */\n\treadonly upstreamResources: ReadonlyArray<AnyResourceRef>;\n\treadonly upstreamKeys: ReadonlyArray<PluginKey>;\n\t/** Plugin-declared flag: a live restore re-acquire leaves this node\n\t * running instead of draining it. Substrate filters on this with no\n\t * knowledge of which plugin set it (see plugin decl\n\t * `keepAliveOnRestore`). */\n\treadonly keepAliveOnRestore: boolean;\n}\n\n/** The result of resolving a member tuple. Levels are batches the\n * scheduler can acquire in parallel; each level's nodes only depend\n * on prior levels. */\nexport interface ResolvedGraph {\n\treadonly nodes: ReadonlyMap<PluginKey, DepNode>;\n\treadonly levels: ReadonlyArray<ReadonlyArray<PluginKey>>;\n\t/** Reverse-dep index: each key → keys that depend on it. The\n\t * supervisor uses this for selective-restart cascade. */\n\treadonly downstream: ReadonlyMap<PluginKey, ReadonlySet<PluginKey>>;\n}\n\n// -----------------------------------------------------------------------------\n// Plugin key minting\n// -----------------------------------------------------------------------------\n\ninterface NamedMember {\n\treadonly key: PluginKey;\n\treadonly member: AnyPlugin;\n}\n\n/** Mint a stable PluginKey for a plugin. Plugins may declare a stable\n * key; otherwise keys derive from resource id + ordinal so duplicates\n * do not collide. */\nconst mintKey = (member: AnyPlugin, ordinal: number): PluginKey => {\n\tif (member.pluginKey !== undefined) {\n\t\treturn makePluginKey(String(member.pluginKey));\n\t}\n\treturn makePluginKey(`${member.id}#${ordinal}`);\n};\n\n/** Walk the member tuple and emit one named-member entry per node. */\nconst expand = (members: ReadonlyArray<AnyPlugin>): ReadonlyArray<NamedMember> => {\n\tconst out: NamedMember[] = [];\n\tlet ordinal = 0;\n\tfor (const member of members) {\n\t\tconst key = mintKey(member, ordinal++);\n\t\tout.push({ key, member });\n\t}\n\treturn out;\n};\n\n// -----------------------------------------------------------------------------\n// Topological sort (Kahn's algorithm)\n// -----------------------------------------------------------------------------\n\n/**\n * Resolve a flat member tuple into a topo-sorted level batch.\n *\n * Steps:\n * 1. Mint a plugin key for every member.\n * 2. Build the resource-id -> key index (providers). Two members with\n * the same `id` fail with `DuplicateResourceIdError`.\n * 3. For each node, resolve its dependency refs to upstream keys.\n * 4. Kahn's algorithm: peel zero-indegree nodes into level 0, decrement\n * downstream indegrees, repeat.\n * 5. If any node remains, return `DepGraphCycleError`.\n *\n * Span-instrumented so trace exports show the resolution alongside the\n * supervisor's acquire spans.\n */\nexport const resolveGraph = (\n\tmembers: ReadonlyArray<AnyPlugin>,\n): Effect.Effect<ResolvedGraph, DepGraphError> =>\n\tEffect.gen(function* () {\n\t\tconst named = expand(members);\n\n\t\t// Provider index: resource-id → key. The compile-time\n\t\t// `MissingProviders` check ensures uniqueness on the user-typed\n\t\t// dependency path, but a runtime-built stack (or a typo'd\n\t\t// `definePlugin({ id })`) can still ship two members with the\n\t\t// same `resource id`. Without an explicit guard the index would\n\t\t// last-writer-wins and every dependent would silently bind to\n\t\t// the second declaration; we fail early with a typed error\n\t\t// instead so a developer sees the conflicting plugin keys at\n\t\t// boot rather than chasing a \"wrong provider\" mystery downstream.\n\t\t// Phase 22e/E3's package-plugin-level guard in\n\t\t// `plugins/package/mode-local.ts` is complementary — it fires on\n\t\t// the registry path before this resolver runs.\n\t\tconst providerByResourceId = new Map<string, PluginKey>();\n\t\tfor (const { key, member } of named) {\n\t\t\tconst existing = providerByResourceId.get(member.id);\n\t\t\tif (existing !== undefined) {\n\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\tnew DuplicateResourceIdError({\n\t\t\t\t\t\tresourceId: member.id,\n\t\t\t\t\t\tfirstPluginKey: existing,\n\t\t\t\t\t\tsecondPluginKey: key,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\tproviderByResourceId.set(member.id, key);\n\t\t}\n\n\t\tconst nodes = new Map<PluginKey, DepNode>();\n\t\tconst indegree = new Map<PluginKey, number>();\n\t\tconst downstream = new Map<PluginKey, Set<PluginKey>>();\n\t\tfor (const { key } of named) {\n\t\t\tindegree.set(key, 0);\n\t\t\tdownstream.set(key, new Set());\n\t\t}\n\n\t\tfor (const { key, member } of named) {\n\t\t\tconst upstreamKeys: PluginKey[] = [];\n\t\t\tconst upstreamResources = uniqueResourceRefs(member.dependsOn);\n\t\t\tfor (const resource of upstreamResources) {\n\t\t\t\tconst providerKey = providerByResourceId.get(resource.id);\n\t\t\t\tif (providerKey === undefined) {\n\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\tnew UnresolvedDependencyError({ pluginKey: key, missingResourceId: resource.id }),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tupstreamKeys.push(providerKey);\n\t\t\t\tdownstream.get(providerKey)?.add(key);\n\t\t\t\tindegree.set(key, (indegree.get(key) ?? 0) + 1);\n\t\t\t}\n\t\t\tnodes.set(key, {\n\t\t\t\tkey,\n\t\t\t\tmember,\n\t\t\t\tupstreamResources,\n\t\t\t\tupstreamKeys,\n\t\t\t\tkeepAliveOnRestore: member.keepAliveOnRestore === true,\n\t\t\t});\n\t\t}\n\n\t\t// Kahn's algorithm — peel zero-indegree nodes level by level.\n\t\tconst levels: PluginKey[][] = [];\n\t\tconst settled = new Set<PluginKey>();\n\t\twhile (settled.size < nodes.size) {\n\t\t\tconst layer: PluginKey[] = [];\n\t\t\tfor (const [key, deg] of indegree) {\n\t\t\t\tif (settled.has(key)) continue;\n\t\t\t\tif (deg === 0) layer.push(key);\n\t\t\t}\n\t\t\tif (layer.length === 0) {\n\t\t\t\t// Cycle: collect every unsettled node as the cycle's witness.\n\t\t\t\t// More precise cycle extraction (Tarjan SCC) is overkill for\n\t\t\t\t// the user-facing message; we surface the trapped keys.\n\t\t\t\tconst trapped: PluginKey[] = [];\n\t\t\t\tfor (const key of nodes.keys()) {\n\t\t\t\t\tif (!settled.has(key)) trapped.push(key);\n\t\t\t\t}\n\t\t\t\treturn yield* Effect.fail(new DepGraphCycleError({ cycle: trapped }));\n\t\t\t}\n\t\t\tlevels.push(layer);\n\t\t\tfor (const key of layer) {\n\t\t\t\tsettled.add(key);\n\t\t\t\tfor (const child of downstream.get(key) ?? []) {\n\t\t\t\t\tindegree.set(child, (indegree.get(child) ?? 1) - 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Freeze downstream sets to ReadonlySet shape.\n\t\tconst downstreamFrozen = new Map<PluginKey, ReadonlySet<PluginKey>>();\n\t\tfor (const [k, v] of downstream) downstreamFrozen.set(k, v);\n\n\t\treturn {\n\t\t\tnodes,\n\t\t\tlevels,\n\t\t\tdownstream: downstreamFrozen,\n\t\t} satisfies ResolvedGraph;\n\t});\n\n// -----------------------------------------------------------------------------\n// Selective-restart helpers\n// -----------------------------------------------------------------------------\n\n/**\n * Compute the closure of nodes downstream of `root` (inclusive).\n * Used by the supervisor to tear down a subgraph in reverse-dep order\n * and re-acquire in forward order.\n *\n * Architecture § Watch-triggered invalidation:\n * Invalidating a producer invalidates downstream consumers along\n * dep-graph edges (cascade semantics).\n */\nexport const downstreamClosure = (\n\tgraph: ResolvedGraph,\n\troot: PluginKey,\n): ReadonlySet<PluginKey> => {\n\tconst closure = new Set<PluginKey>([root]);\n\tconst queue: PluginKey[] = [root];\n\twhile (queue.length > 0) {\n\t\tconst next = queue.shift()!;\n\t\tfor (const child of graph.downstream.get(next) ?? []) {\n\t\t\tif (!closure.has(child)) {\n\t\t\t\tclosure.add(child);\n\t\t\t\tqueue.push(child);\n\t\t\t}\n\t\t}\n\t}\n\treturn closure;\n};\n\n/** Order a set of keys by their dep-graph level — forward (low-to-high)\n * for acquire, reverse (high-to-low) for teardown. */\nexport const orderByLevel = (\n\tgraph: ResolvedGraph,\n\tkeys: ReadonlySet<PluginKey>,\n\tdirection: 'forward' | 'reverse',\n): ReadonlyArray<PluginKey> => {\n\tconst out: PluginKey[] = [];\n\tfor (const level of graph.levels) {\n\t\tfor (const key of level) if (keys.has(key)) out.push(key);\n\t}\n\treturn direction === 'reverse' ? out.slice().reverse() : out;\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { deriveWatchRoots } from "./watch-attribution.mjs";
|
|
2
|
+
import { Effect, Queue } from "effect";
|
|
3
|
+
import { watch } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
//#region src/substrate/runtime/lifecycle/file-watcher.ts
|
|
6
|
+
/** Coalescing window for a burst of fs events. Editors save by
|
|
7
|
+
* rename-replace (temp write + rename), so a single save surfaces as
|
|
8
|
+
* several events within a few ms — one settle window collapses them
|
|
9
|
+
* into one restart per plugin. */
|
|
10
|
+
const DEFAULT_DEBOUNCE_MILLIS = 150;
|
|
11
|
+
/**
|
|
12
|
+
* Start the L0 file watcher. Acquires one recursive `fs.watch` per
|
|
13
|
+
* distinct root (released on scope close) and forks a debouncing drain
|
|
14
|
+
* loop that fires `notifyWatchFire` for each distinct changed path.
|
|
15
|
+
* Returns once the watchers + loop are installed; it lives for the
|
|
16
|
+
* lifetime of the surrounding scope, so callers `Effect.forkScoped` it
|
|
17
|
+
* (or just `yield*` it inside a scoped region).
|
|
18
|
+
*
|
|
19
|
+
* Watcher setup never fails the boot: a root that cannot be watched
|
|
20
|
+
* (e.g. a not-yet-created directory) is logged and skipped.
|
|
21
|
+
*/
|
|
22
|
+
const startFileWatcher = (params) => Effect.gen(function* () {
|
|
23
|
+
const roots = deriveWatchRoots(params.watchIndex);
|
|
24
|
+
if (roots.length === 0) return;
|
|
25
|
+
const debounceMillis = params.debounceMillis ?? DEFAULT_DEBOUNCE_MILLIS;
|
|
26
|
+
const events = yield* Queue.dropping(1024);
|
|
27
|
+
const supervisorContext = yield* Effect.context();
|
|
28
|
+
const runForkInherited = Effect.runForkWith(supervisorContext);
|
|
29
|
+
for (const root of roots) if ((yield* Effect.acquireRelease(Effect.sync(() => {
|
|
30
|
+
try {
|
|
31
|
+
const fsWatcher = watch(root, { recursive: true }, (_eventType, filename) => {
|
|
32
|
+
if (filename === null) return;
|
|
33
|
+
const abs = join(root, filename.toString());
|
|
34
|
+
runForkInherited(Queue.offer(events, abs));
|
|
35
|
+
});
|
|
36
|
+
fsWatcher.on("error", () => {});
|
|
37
|
+
return fsWatcher;
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}), (watcher) => Effect.sync(() => watcher?.close()))) === null) yield* Effect.logWarning(`file-watcher: could not watch ${root}`);
|
|
42
|
+
const drain = Effect.gen(function* () {
|
|
43
|
+
const first = yield* Queue.take(events);
|
|
44
|
+
yield* Effect.sleep(`${debounceMillis} millis`);
|
|
45
|
+
const rest = yield* Queue.takeAll(events);
|
|
46
|
+
const paths = new Set([first, ...rest]);
|
|
47
|
+
for (const path of paths) yield* params.notifyWatchFire(path);
|
|
48
|
+
}).pipe(Effect.forever);
|
|
49
|
+
yield* Effect.forkScoped(drain);
|
|
50
|
+
});
|
|
51
|
+
//#endregion
|
|
52
|
+
export { startFileWatcher };
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=file-watcher.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-watcher.mjs","names":["fsWatch"],"sources":["../../../../src/substrate/runtime/lifecycle/file-watcher.ts"],"sourcesContent":["// L0 file watcher — the \"thick watcher\" the lifecycle architecture\n// describes (§ L3 Watch dispatcher: \"receives watcher events from L0\n// which already debounced + dedup'd\").\n//\n// Generic: it watches the literal roots derived from the supervisor's\n// watch index — the union of every plugin's declared `watch` paths,\n// whatever they are — and feeds each changed path to `notifyWatchFire`,\n// which attributes it to the owning plugin(s) and issues a selective\n// restart (→ re-acquire → re-cache-key → cache-miss → re-produce). The\n// package plugin's Move sources are today's only declarer, but nothing\n// here is Move-specific. Without this, the watch index +\n// `notifyWatchFire` are built but never driven, so a `watch`-declaring\n// plugin never restarts on a source edit.\n//\n// Dev-only: wired from the `up` verb (see `cli/wirings/up.ts`). `apply`\n// and the snapshot verbs boot once and exit, so they never start it.\n//\n// Dependency-free by design — devstack pulls in no glob/watch library\n// (cf. the hand-rolled `collectHashedSources`). Node's recursive\n// `fs.watch` is supported on macOS and Windows, and on Linux from\n// Node 20; one watcher is placed per distinct root.\n\nimport { type FSWatcher, watch as fsWatch } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { Effect, Queue, Scope } from 'effect';\n\nimport { deriveWatchRoots, type WatchEntry } from './watch-attribution.ts';\n\n/** Coalescing window for a burst of fs events. Editors save by\n * rename-replace (temp write + rename), so a single save surfaces as\n * several events within a few ms — one settle window collapses them\n * into one restart per plugin. */\nconst DEFAULT_DEBOUNCE_MILLIS = 150;\n\nexport interface FileWatcherParams {\n\treadonly watchIndex: ReadonlyArray<WatchEntry>;\n\treadonly notifyWatchFire: (path: string) => Effect.Effect<void>;\n\treadonly debounceMillis?: number;\n}\n\n/**\n * Start the L0 file watcher. Acquires one recursive `fs.watch` per\n * distinct root (released on scope close) and forks a debouncing drain\n * loop that fires `notifyWatchFire` for each distinct changed path.\n * Returns once the watchers + loop are installed; it lives for the\n * lifetime of the surrounding scope, so callers `Effect.forkScoped` it\n * (or just `yield*` it inside a scoped region).\n *\n * Watcher setup never fails the boot: a root that cannot be watched\n * (e.g. a not-yet-created directory) is logged and skipped.\n */\nexport const startFileWatcher = (\n\tparams: FileWatcherParams,\n): Effect.Effect<void, never, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst roots = deriveWatchRoots(params.watchIndex);\n\t\tif (roots.length === 0) return;\n\n\t\tconst debounceMillis = params.debounceMillis ?? DEFAULT_DEBOUNCE_MILLIS;\n\t\t// Bounded so a pathological event storm (e.g. a `git checkout` touching\n\t\t// thousands of files) can't grow the queue unboundedly; offers into a\n\t\t// dropping queue never suspend, so the fs.watch callback stays cheap.\n\t\t// 1024 comfortably covers a normal multi-file save burst, whose\n\t\t// duplicates the drain loop collapses within the settle window into one\n\t\t// restart per plugin. If a burst ever exceeds the bound the overflow is\n\t\t// dropped — at worst a reload is missed until the next edit re-fires the\n\t\t// path (and dev reload stays manually recoverable).\n\t\tconst events = yield* Queue.dropping<string>(1024);\n\t\t// Capture the supervisor Context so the offer fork inherits its\n\t\t// logger Layer / fiber-refs (mirrors `installSignalHandler`); a bare\n\t\t// `Effect.runFork` would evaluate against an empty context.\n\t\tconst supervisorContext = yield* Effect.context<never>();\n\t\tconst runForkInherited = Effect.runForkWith(supervisorContext);\n\n\t\tfor (const root of roots) {\n\t\t\tconst watcher = yield* Effect.acquireRelease(\n\t\t\t\tEffect.sync((): FSWatcher | null => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst fsWatcher = fsWatch(root, { recursive: true }, (_eventType, filename) => {\n\t\t\t\t\t\t\tif (filename === null) return;\n\t\t\t\t\t\t\tconst abs = join(root, filename.toString());\n\t\t\t\t\t\t\t// Bridge the Node callback into the queue via the captured\n\t\t\t\t\t\t\t// Context. Dropping queue ⇒ offer never suspends.\n\t\t\t\t\t\t\trunForkInherited(Queue.offer(events, abs));\n\t\t\t\t\t\t});\n\t\t\t\t\t\t// A watcher-level error (e.g. the root was removed) must not\n\t\t\t\t\t\t// crash the supervisor; swallow it. Scope close still calls\n\t\t\t\t\t\t// `close()` on the finalizer below.\n\t\t\t\t\t\tfsWatcher.on('error', () => {});\n\t\t\t\t\t\treturn fsWatcher;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t\t(watcher) => Effect.sync(() => watcher?.close()),\n\t\t\t);\n\t\t\tif (watcher === null) {\n\t\t\t\tyield* Effect.logWarning(`file-watcher: could not watch ${root}`);\n\t\t\t}\n\t\t}\n\n\t\t// Drain loop: block for one change, settle, then drain + dedup the\n\t\t// burst and fire each distinct path once. `notifyWatchFire` itself\n\t\t// dedups owning plugins, so editing several files in one save yields\n\t\t// one restart per affected plugin.\n\t\tconst drain = Effect.gen(function* () {\n\t\t\tconst first = yield* Queue.take(events);\n\t\t\tyield* Effect.sleep(`${debounceMillis} millis`);\n\t\t\tconst rest = yield* Queue.takeAll(events);\n\t\t\tconst paths = new Set<string>([first, ...rest]);\n\t\t\tfor (const path of paths) {\n\t\t\t\tyield* params.notifyWatchFire(path);\n\t\t\t}\n\t\t}).pipe(Effect.forever);\n\n\t\tyield* Effect.forkScoped(drain);\n\t});\n"],"mappings":";;;;;;;;;AAiCA,MAAM,0BAA0B;;;;;;;;;;;;AAmBhC,MAAa,oBACZ,WAEA,OAAO,IAAI,aAAa;CACvB,MAAM,QAAQ,iBAAiB,OAAO,UAAU;CAChD,IAAI,MAAM,WAAW,GAAG;CAExB,MAAM,iBAAiB,OAAO,kBAAkB;CAShD,MAAM,SAAS,OAAO,MAAM,SAAiB,IAAI;CAIjD,MAAM,oBAAoB,OAAO,OAAO,QAAe;CACvD,MAAM,mBAAmB,OAAO,YAAY,iBAAiB;CAE7D,KAAK,MAAM,QAAQ,OAsBlB,KAAI,OArBmB,OAAO,eAC7B,OAAO,WAA6B;EACnC,IAAI;GACH,MAAM,YAAYA,MAAQ,MAAM,EAAE,WAAW,KAAK,IAAI,YAAY,aAAa;IAC9E,IAAI,aAAa,MAAM;IACvB,MAAM,MAAM,KAAK,MAAM,SAAS,SAAS,CAAC;IAG1C,iBAAiB,MAAM,MAAM,QAAQ,GAAG,CAAC;GAC1C,CAAC;GAID,UAAU,GAAG,eAAe,CAAC,CAAC;GAC9B,OAAO;EACR,QAAQ;GACP,OAAO;EACR;CACD,CAAC,IACA,YAAY,OAAO,WAAW,SAAS,MAAM,CAAC,CAChD,OACgB,MACf,OAAO,OAAO,WAAW,iCAAiC,MAAM;CAQlE,MAAM,QAAQ,OAAO,IAAI,aAAa;EACrC,MAAM,QAAQ,OAAO,MAAM,KAAK,MAAM;EACtC,OAAO,OAAO,MAAM,GAAG,eAAe,QAAQ;EAC9C,MAAM,OAAO,OAAO,MAAM,QAAQ,MAAM;EACxC,MAAM,QAAQ,IAAI,IAAY,CAAC,OAAO,GAAG,IAAI,CAAC;EAC9C,KAAK,MAAM,QAAQ,OAClB,OAAO,OAAO,gBAAgB,IAAI;CAEpC,CAAC,CAAC,CAAC,KAAK,OAAO,OAAO;CAEtB,OAAO,OAAO,WAAW,KAAK;AAC/B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { graphInputId, nodeInputId } from "../../brand.mjs";
|
|
2
|
+
import { resolveGraph } from "./dep-graph.mjs";
|
|
3
|
+
import { Effect, Exit, Schema } from "effect";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
//#region src/substrate/runtime/lifecycle/graph-input-id.ts
|
|
6
|
+
const GRAPH_INPUT_ID_VERSION = 1;
|
|
7
|
+
var GraphInputIdentityError = class extends Schema.TaggedErrorClass()("GraphInputIdentityError", {
|
|
8
|
+
pluginKey: Schema.String,
|
|
9
|
+
detail: Schema.String,
|
|
10
|
+
cause: Schema.optional(Schema.Defect)
|
|
11
|
+
}) {};
|
|
12
|
+
const canonicalize = (value) => {
|
|
13
|
+
if (typeof value === "bigint") return {
|
|
14
|
+
type: "bigint",
|
|
15
|
+
value: value.toString()
|
|
16
|
+
};
|
|
17
|
+
if (Array.isArray(value)) return value.map((entry) => canonicalize(entry));
|
|
18
|
+
if (value !== null && typeof value === "object") {
|
|
19
|
+
const source = value;
|
|
20
|
+
const out = {};
|
|
21
|
+
for (const key of Object.keys(source).sort((a, b) => a.localeCompare(b))) {
|
|
22
|
+
const entry = source[key];
|
|
23
|
+
if (entry === void 0) continue;
|
|
24
|
+
out[key] = canonicalize(entry);
|
|
25
|
+
}
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
};
|
|
30
|
+
const canonicalStringify = (value) => {
|
|
31
|
+
const encoded = JSON.stringify(canonicalize(value));
|
|
32
|
+
return encoded === void 0 ? String(encoded) : encoded;
|
|
33
|
+
};
|
|
34
|
+
const sha256Hex = (data) => createHash("sha256").update(data).digest("hex");
|
|
35
|
+
const sortStrings = (values) => [...values].sort((a, b) => a.localeCompare(b));
|
|
36
|
+
const graphRelevantOptions = (options) => {
|
|
37
|
+
const { renderer: _renderer, extras: _extras, codegen: _codegen, stackName: _stackName, stateDir: _stateDir, ...rest } = options;
|
|
38
|
+
return rest;
|
|
39
|
+
};
|
|
40
|
+
const nodeBaseDocument = (node, inputIdentity) => ({
|
|
41
|
+
resourceId: node.member.id,
|
|
42
|
+
role: node.member.role,
|
|
43
|
+
section: node.member.section,
|
|
44
|
+
...node.member.endpointSection === void 0 ? {} : { endpointSection: node.member.endpointSection },
|
|
45
|
+
keepAliveOnRestore: node.keepAliveOnRestore,
|
|
46
|
+
upstreamResources: sortStrings(node.upstreamResources.map((resource) => resource.id)),
|
|
47
|
+
...node.member.watch === void 0 ? {} : { watch: {
|
|
48
|
+
paths: sortStrings(node.member.watch.paths),
|
|
49
|
+
cascade: node.member.watch.cascade ?? true
|
|
50
|
+
} },
|
|
51
|
+
...inputIdentity === void 0 ? {} : { inputIdentity }
|
|
52
|
+
});
|
|
53
|
+
const resolveNodeInputIdentity = (node) => {
|
|
54
|
+
const contribution = node.member.inputIdentity;
|
|
55
|
+
if (contribution === void 0) return Effect.succeed(void 0);
|
|
56
|
+
if (contribution.kind === "static") return Effect.succeed(contribution.value);
|
|
57
|
+
const pluginKey = String(node.key);
|
|
58
|
+
return Effect.try({
|
|
59
|
+
try: () => contribution.compute(),
|
|
60
|
+
catch: (cause) => new GraphInputIdentityError({
|
|
61
|
+
pluginKey,
|
|
62
|
+
detail: "node input identity computation could not be created",
|
|
63
|
+
cause
|
|
64
|
+
})
|
|
65
|
+
}).pipe(Effect.flatMap((effect) => Effect.exit(effect)), Effect.flatMap((exit) => Exit.isSuccess(exit) ? Effect.succeed(exit.value) : Effect.fail(new GraphInputIdentityError({
|
|
66
|
+
pluginKey,
|
|
67
|
+
detail: "node input identity computation failed",
|
|
68
|
+
cause: exit.cause
|
|
69
|
+
}))));
|
|
70
|
+
};
|
|
71
|
+
const computeGraphInputIdentity = (args) => Effect.gen(function* () {
|
|
72
|
+
const inputIdByKey = /* @__PURE__ */ new Map();
|
|
73
|
+
const nodeIdentityByKey = /* @__PURE__ */ new Map();
|
|
74
|
+
for (const level of args.graph.levels) for (const key of level) {
|
|
75
|
+
const node = args.graph.nodes.get(key);
|
|
76
|
+
if (node === void 0) continue;
|
|
77
|
+
const upstreamInputIds = [];
|
|
78
|
+
for (const upstreamKey of node.upstreamKeys) {
|
|
79
|
+
const upstreamKeyString = String(upstreamKey);
|
|
80
|
+
const inputId = inputIdByKey.get(upstreamKeyString);
|
|
81
|
+
if (inputId === void 0) return yield* Effect.fail(new GraphInputIdentityError({
|
|
82
|
+
pluginKey: String(key),
|
|
83
|
+
detail: `upstream node input id missing for ${upstreamKeyString}`
|
|
84
|
+
}));
|
|
85
|
+
upstreamInputIds.push({
|
|
86
|
+
key: upstreamKeyString,
|
|
87
|
+
inputId
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
upstreamInputIds.sort((a, b) => a.key.localeCompare(b.key));
|
|
91
|
+
const inputId = nodeInputId(sha256Hex(canonicalStringify({
|
|
92
|
+
v: GRAPH_INPUT_ID_VERSION,
|
|
93
|
+
node: nodeBaseDocument(node, yield* resolveNodeInputIdentity(node)),
|
|
94
|
+
upstreamInputIds
|
|
95
|
+
})));
|
|
96
|
+
inputIdByKey.set(String(key), inputId);
|
|
97
|
+
nodeIdentityByKey.set(String(key), {
|
|
98
|
+
key: String(key),
|
|
99
|
+
inputId,
|
|
100
|
+
upstreamInputIds
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
const nodes = [...nodeIdentityByKey.values()].sort((a, b) => a.key.localeCompare(b.key));
|
|
104
|
+
const downstream = [...args.graph.downstream.entries()].map(([key, children]) => ({
|
|
105
|
+
key: String(key),
|
|
106
|
+
children: sortStrings([...children].map(String))
|
|
107
|
+
})).sort((a, b) => a.key.localeCompare(b.key));
|
|
108
|
+
return {
|
|
109
|
+
graphInputId: graphInputId(sha256Hex(canonicalStringify({
|
|
110
|
+
v: GRAPH_INPUT_ID_VERSION,
|
|
111
|
+
devstackVersion: args.devstackVersion,
|
|
112
|
+
options: graphRelevantOptions(args.options),
|
|
113
|
+
levels: args.graph.levels.map((level) => sortStrings(level.map(String))),
|
|
114
|
+
nodes: nodes.map((node) => ({
|
|
115
|
+
key: node.key,
|
|
116
|
+
inputId: node.inputId
|
|
117
|
+
})),
|
|
118
|
+
downstream
|
|
119
|
+
}))),
|
|
120
|
+
nodes
|
|
121
|
+
};
|
|
122
|
+
});
|
|
123
|
+
const computeStackGraphInputIdentity = (args) => Effect.gen(function* () {
|
|
124
|
+
return yield* computeGraphInputIdentity({
|
|
125
|
+
graph: yield* resolveGraph(args.stack.members),
|
|
126
|
+
options: args.stack.options,
|
|
127
|
+
devstackVersion: args.devstackVersion
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
//#endregion
|
|
131
|
+
export { GraphInputIdentityError, computeGraphInputIdentity, computeStackGraphInputIdentity, graphRelevantOptions };
|
|
132
|
+
|
|
133
|
+
//# sourceMappingURL=graph-input-id.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-input-id.mjs","names":[],"sources":["../../../../src/substrate/runtime/lifecycle/graph-input-id.ts"],"sourcesContent":["// Graph input identity.\n//\n// This is the substrate-level desired-state identity primitive for a resolved\n// graph. Each node gets a deterministic input id from its declared static\n// inputs plus upstream node input ids; the graph gets an aggregate id from\n// node ids, graph shape, graph-relevant options, and the devstack version.\n// Snapshot policy can compare these ids to warn or refuse restores.\n\nimport { createHash } from 'node:crypto';\n\nimport { Effect, Exit, Schema } from 'effect';\n\nimport type { GraphInputId, NodeInputId } from '../../brand.ts';\nimport { graphInputId, nodeInputId } from '../../brand.ts';\nimport type { DevstackOptions } from '../../options.ts';\nimport { resolveGraph, type DepGraphError, type DepNode, type ResolvedGraph } from './dep-graph.ts';\n\nconst GRAPH_INPUT_ID_VERSION = 1 as const;\n\nexport interface NodeInputIdentity {\n\treadonly key: string;\n\treadonly inputId: NodeInputId;\n\treadonly upstreamInputIds: ReadonlyArray<{\n\t\treadonly key: string;\n\t\treadonly inputId: NodeInputId;\n\t}>;\n}\n\nexport interface GraphInputIdentity {\n\treadonly graphInputId: GraphInputId;\n\treadonly nodes: ReadonlyArray<NodeInputIdentity>;\n}\n\nexport interface StackGraphInputSource {\n\treadonly members: ReadonlyArray<DepNode['member']>;\n\treadonly options: DevstackOptions;\n}\n\nexport class GraphInputIdentityError extends Schema.TaggedErrorClass<GraphInputIdentityError>()(\n\t'GraphInputIdentityError',\n\t{\n\t\tpluginKey: Schema.String,\n\t\tdetail: Schema.String,\n\t\tcause: Schema.optional(Schema.Defect),\n\t},\n) {}\n\nexport type StackGraphInputIdentityError = DepGraphError | GraphInputIdentityError;\n\nconst canonicalize = (value: unknown): unknown => {\n\tif (typeof value === 'bigint') {\n\t\treturn { type: 'bigint', value: value.toString() };\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn value.map((entry) => canonicalize(entry));\n\t}\n\tif (value !== null && typeof value === 'object') {\n\t\tconst source = value as Record<string, unknown>;\n\t\tconst out: Record<string, unknown> = {};\n\t\tfor (const key of Object.keys(source).sort((a, b) => a.localeCompare(b))) {\n\t\t\tconst entry = source[key];\n\t\t\tif (entry === undefined) continue;\n\t\t\tout[key] = canonicalize(entry);\n\t\t}\n\t\treturn out;\n\t}\n\treturn value;\n};\n\nconst canonicalStringify = (value: unknown): string => {\n\tconst encoded = JSON.stringify(canonicalize(value));\n\treturn encoded === undefined ? String(encoded) : encoded;\n};\n\nconst sha256Hex = (data: string | Uint8Array): string =>\n\tcreateHash('sha256').update(data).digest('hex');\n\nconst sortStrings = (values: ReadonlyArray<string>): ReadonlyArray<string> =>\n\t[...values].sort((a, b) => a.localeCompare(b));\n\nexport const graphRelevantOptions = (options: DevstackOptions): unknown => {\n\tconst {\n\t\trenderer: _renderer,\n\t\textras: _extras,\n\t\tcodegen: _codegen,\n\t\tstackName: _stackName,\n\t\tstateDir: _stateDir,\n\t\t...rest\n\t} = options;\n\treturn rest;\n};\n\nconst nodeBaseDocument = (node: DepNode, inputIdentity: unknown): unknown => ({\n\tresourceId: node.member.id,\n\trole: node.member.role,\n\tsection: node.member.section,\n\t...(node.member.endpointSection === undefined\n\t\t? {}\n\t\t: { endpointSection: node.member.endpointSection }),\n\tkeepAliveOnRestore: node.keepAliveOnRestore,\n\tupstreamResources: sortStrings(node.upstreamResources.map((resource) => resource.id)),\n\t...(node.member.watch === undefined\n\t\t? {}\n\t\t: {\n\t\t\t\twatch: {\n\t\t\t\t\tpaths: sortStrings(node.member.watch.paths),\n\t\t\t\t\tcascade: node.member.watch.cascade ?? true,\n\t\t\t\t},\n\t\t\t}),\n\t...(inputIdentity === undefined ? {} : { inputIdentity }),\n});\n\nconst resolveNodeInputIdentity = (\n\tnode: DepNode,\n): Effect.Effect<unknown, GraphInputIdentityError> => {\n\tconst contribution = node.member.inputIdentity;\n\tif (contribution === undefined) return Effect.succeed(undefined);\n\tif (contribution.kind === 'static') return Effect.succeed(contribution.value);\n\n\tconst pluginKey = String(node.key);\n\treturn Effect.try({\n\t\ttry: () => contribution.compute(),\n\t\tcatch: (cause) =>\n\t\t\tnew GraphInputIdentityError({\n\t\t\t\tpluginKey,\n\t\t\t\tdetail: 'node input identity computation could not be created',\n\t\t\t\tcause,\n\t\t\t}),\n\t}).pipe(\n\t\tEffect.flatMap((effect) => Effect.exit(effect)),\n\t\tEffect.flatMap((exit) =>\n\t\t\tExit.isSuccess(exit)\n\t\t\t\t? Effect.succeed(exit.value)\n\t\t\t\t: Effect.fail(\n\t\t\t\t\t\tnew GraphInputIdentityError({\n\t\t\t\t\t\t\tpluginKey,\n\t\t\t\t\t\t\tdetail: 'node input identity computation failed',\n\t\t\t\t\t\t\tcause: exit.cause,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t),\n\t);\n};\n\nexport const computeGraphInputIdentity = (args: {\n\treadonly graph: ResolvedGraph;\n\treadonly options: DevstackOptions;\n\treadonly devstackVersion: string;\n}): Effect.Effect<GraphInputIdentity, GraphInputIdentityError> =>\n\tEffect.gen(function* () {\n\t\tconst inputIdByKey = new Map<string, NodeInputId>();\n\t\tconst nodeIdentityByKey = new Map<string, NodeInputIdentity>();\n\n\t\tfor (const level of args.graph.levels) {\n\t\t\tfor (const key of level) {\n\t\t\t\tconst node = args.graph.nodes.get(key);\n\t\t\t\tif (node === undefined) continue;\n\t\t\t\tconst upstreamInputIds: Array<{ key: string; inputId: NodeInputId }> = [];\n\t\t\t\tfor (const upstreamKey of node.upstreamKeys) {\n\t\t\t\t\tconst upstreamKeyString = String(upstreamKey);\n\t\t\t\t\tconst inputId = inputIdByKey.get(upstreamKeyString);\n\t\t\t\t\tif (inputId === undefined) {\n\t\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\t\tnew GraphInputIdentityError({\n\t\t\t\t\t\t\t\tpluginKey: String(key),\n\t\t\t\t\t\t\t\tdetail: `upstream node input id missing for ${upstreamKeyString}`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tupstreamInputIds.push({ key: upstreamKeyString, inputId });\n\t\t\t\t}\n\t\t\t\tupstreamInputIds.sort((a, b) => a.key.localeCompare(b.key));\n\t\t\t\tconst inputIdentity = yield* resolveNodeInputIdentity(node);\n\t\t\t\tconst inputId = nodeInputId(\n\t\t\t\t\tsha256Hex(\n\t\t\t\t\t\tcanonicalStringify({\n\t\t\t\t\t\t\tv: GRAPH_INPUT_ID_VERSION,\n\t\t\t\t\t\t\tnode: nodeBaseDocument(node, inputIdentity),\n\t\t\t\t\t\t\tupstreamInputIds,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tinputIdByKey.set(String(key), inputId);\n\t\t\t\tnodeIdentityByKey.set(String(key), {\n\t\t\t\t\tkey: String(key),\n\t\t\t\t\tinputId,\n\t\t\t\t\tupstreamInputIds,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconst nodes = [...nodeIdentityByKey.values()].sort((a, b) => a.key.localeCompare(b.key));\n\t\tconst downstream = [...args.graph.downstream.entries()]\n\t\t\t.map(([key, children]) => ({\n\t\t\t\tkey: String(key),\n\t\t\t\tchildren: sortStrings([...children].map(String)),\n\t\t\t}))\n\t\t\t.sort((a, b) => a.key.localeCompare(b.key));\n\n\t\tconst graphDoc = {\n\t\t\tv: GRAPH_INPUT_ID_VERSION,\n\t\t\tdevstackVersion: args.devstackVersion,\n\t\t\toptions: graphRelevantOptions(args.options),\n\t\t\tlevels: args.graph.levels.map((level) => sortStrings(level.map(String))),\n\t\t\tnodes: nodes.map((node) => ({ key: node.key, inputId: node.inputId })),\n\t\t\tdownstream,\n\t\t};\n\n\t\treturn {\n\t\t\tgraphInputId: graphInputId(sha256Hex(canonicalStringify(graphDoc))),\n\t\t\tnodes,\n\t\t};\n\t});\n\nexport const computeStackGraphInputIdentity = (args: {\n\treadonly stack: StackGraphInputSource;\n\treadonly devstackVersion: string;\n}): Effect.Effect<GraphInputIdentity, StackGraphInputIdentityError> =>\n\tEffect.gen(function* () {\n\t\tconst graph = yield* resolveGraph(args.stack.members);\n\t\treturn yield* computeGraphInputIdentity({\n\t\t\tgraph,\n\t\t\toptions: args.stack.options,\n\t\t\tdevstackVersion: args.devstackVersion,\n\t\t});\n\t});\n"],"mappings":"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"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import "./state-machine.mjs";
|
|
2
|
-
import "./plugin-registry.mjs";
|
|
3
|
-
import "./lifecycle-fact.mjs";
|
|
4
2
|
import "./dep-graph.mjs";
|
|
3
|
+
import "./graph-input-id.mjs";
|
|
4
|
+
import "./plugin-registry.mjs";
|
|
5
5
|
import "./ready-gate.mjs";
|
|
6
6
|
import "./watch-attribution.mjs";
|
|
7
|
+
import "./file-watcher.mjs";
|
|
7
8
|
import "./selective-restart.mjs";
|
|
8
9
|
import "./signals.mjs";
|
|
9
10
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import { Deferred, Effect, Ref, Scope } from "effect";
|
|
1
|
+
import { Deferred, Effect, Fiber, Ref, Scope } from "effect";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { assertTransition } from "./state-machine.mjs";
|
|
2
|
-
import { Data, Deferred, Effect, Ref, Scope } from "effect";
|
|
2
|
+
import { Data, Deferred, Effect, Fiber, Ref, Scope } from "effect";
|
|
3
3
|
//#region src/substrate/runtime/lifecycle/plugin-registry.ts
|
|
4
4
|
/** Tagged failure: a plugin's `start` rejected. Carries the cause and
|
|
5
5
|
* the failing plugin's key so the cause walker / cascade formatter can
|
|
@@ -17,6 +17,7 @@ const makeEntry = (node, parentScope) => Effect.gen(function* () {
|
|
|
17
17
|
return {
|
|
18
18
|
node,
|
|
19
19
|
statusRef: yield* Ref.make("pending"),
|
|
20
|
+
acquireFiberRef: yield* Ref.make(null),
|
|
20
21
|
readyGate: yield* Deferred.make(),
|
|
21
22
|
scope: yield* Scope.fork(parentScope)
|
|
22
23
|
};
|
|
@@ -85,8 +86,11 @@ const makeRegistry = (entries, onTransition) => {
|
|
|
85
86
|
}),
|
|
86
87
|
resetForRestart: (key, parentScope) => Effect.gen(function* () {
|
|
87
88
|
const entry = yield* getEntry(key);
|
|
89
|
+
const acquireFiber = yield* Ref.getAndSet(entry.acquireFiberRef, null);
|
|
90
|
+
if (acquireFiber !== null) yield* Fiber.interrupt(acquireFiber);
|
|
88
91
|
resolved.delete(key);
|
|
89
92
|
const readyGate = yield* Deferred.make();
|
|
93
|
+
const acquireFiberRef = yield* Ref.make(null);
|
|
90
94
|
const scope = yield* Scope.fork(parentScope);
|
|
91
95
|
const from = yield* Ref.get(entry.statusRef);
|
|
92
96
|
yield* Ref.set(entry.statusRef, "pending");
|
|
@@ -94,10 +98,27 @@ const makeRegistry = (entries, onTransition) => {
|
|
|
94
98
|
mutableEntries.set(key, {
|
|
95
99
|
node: entry.node,
|
|
96
100
|
statusRef: entry.statusRef,
|
|
101
|
+
acquireFiberRef,
|
|
97
102
|
readyGate,
|
|
98
103
|
scope
|
|
99
104
|
});
|
|
100
105
|
}),
|
|
106
|
+
setAcquireFiberIfEntry: (key, expectedEntry, fiber) => Effect.gen(function* () {
|
|
107
|
+
const entry = yield* getEntry(key);
|
|
108
|
+
if (entry !== expectedEntry) return false;
|
|
109
|
+
yield* Ref.set(entry.acquireFiberRef, fiber);
|
|
110
|
+
return true;
|
|
111
|
+
}),
|
|
112
|
+
clearAcquireFiberIfEntry: (key, expectedEntry, fiberId) => Effect.gen(function* () {
|
|
113
|
+
const entry = yield* getEntry(key);
|
|
114
|
+
if (entry !== expectedEntry) return;
|
|
115
|
+
yield* Ref.update(entry.acquireFiberRef, (current) => current !== null && current.id === fiberId ? null : current);
|
|
116
|
+
}),
|
|
117
|
+
interruptAcquire: (key) => Effect.gen(function* () {
|
|
118
|
+
const entry = yield* getEntry(key);
|
|
119
|
+
const acquireFiber = yield* Ref.getAndSet(entry.acquireFiberRef, null);
|
|
120
|
+
if (acquireFiber !== null) yield* Fiber.interrupt(acquireFiber);
|
|
121
|
+
}),
|
|
101
122
|
awaitReady: (key) => Effect.gen(function* () {
|
|
102
123
|
const entry = yield* getEntry(key);
|
|
103
124
|
return yield* Deferred.await(entry.readyGate);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-registry.mjs","names":[],"sources":["../../../../src/substrate/runtime/lifecycle/plugin-registry.ts"],"sourcesContent":["// Per-plugin lifecycle bookkeeping.\n//\n// One `PluginEntry` per node in the resolved dep-graph. The entry\n// holds:\n// - the live `LifecycleStatus` (Ref, single-fiber linearizable),\n// - the resolved value (set when status transitions to `ready`),\n// - the scope owning the plugin's `start` finalizers,\n// - a `Deferred` that downstream consumers await for the ready gate.\n//\n// The registry tracks per-key lifecycle only; projection concerns stay\n// in the supervisor and reducer.\n\nimport { Data, Deferred, Effect, Ref, Scope } from 'effect';\n\nimport type { PluginKey } from '../../brand.ts';\nimport type { LifecycleStatus } from '../../lifecycle.ts';\nimport type { DepNode } from './dep-graph.ts';\nimport { assertTransition } from './state-machine.ts';\n\n/** Per-registry side channel: synchronously-readable resolved values.\n * Keyed by plugin key. Populated by `markReady`; consulted by the\n * synchronous dependency reader. We can't put the value on the\n * `Deferred` itself in a publicly-supported way, and plugin start\n * receives dependency values synchronously; this is the safe escape hatch.\n *\n * Module-private; only `makeRegistry` writes into the map it\n * allocates. */\ntype ResolvedMap = Map<PluginKey, ResolvedValue>;\n\n// -----------------------------------------------------------------------------\n// Resolved-value shape\n// -----------------------------------------------------------------------------\n\n/** Erased resolved value held in the registry. The supervisor casts\n * back to the concrete type at the boundary where it threads the\n * value into a downstream plugin's resolved dependency object. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type ResolvedValue = any;\n\n// -----------------------------------------------------------------------------\n// Per-plugin entry\n// -----------------------------------------------------------------------------\n\n/** Mutable lifecycle state for one plugin instance. */\nexport interface PluginEntry {\n\treadonly node: DepNode;\n\treadonly statusRef: Ref.Ref<LifecycleStatus>;\n\t/** Resolved when the plugin reaches `ready`. Downstream consumers\n\t * await this in the ready-gate. Failure is propagated by interruption\n\t * via `Deferred.fail` to keep the error chain in the cause walker. */\n\treadonly readyGate: Deferred.Deferred<ResolvedValue, PluginAcquireFailed>;\n\t/** Per-plugin Scope. Closing it runs the `start` finalizers. */\n\treadonly scope: Scope.Closeable;\n}\n\n/** Tagged failure: a plugin's `start` rejected. Carries the cause and\n * the failing plugin's key so the cause walker / cascade formatter can\n * attribute it. */\nexport class PluginAcquireFailed extends Data.TaggedError('PluginAcquireFailed')<{\n\treadonly pluginKey: PluginKey;\n\treadonly cause: unknown;\n}> {}\n\n/** Tagged failure: a downstream plugin tried to read a resolved value\n * whose entry isn't registered or hasn't reached `ready`. Programmer-\n * level error class — the dep-graph guarantees this can't happen on\n * the supervisor's own scheduling path. Surfaced when a plugin author\n * reaches outside their declared dependencies. */\nexport class UnknownDependency extends Data.TaggedError('UnknownDependency')<{\n\treadonly pluginKey: PluginKey;\n\treadonly requestedResourceId: string;\n}> {}\n\n// -----------------------------------------------------------------------------\n// Registry\n// -----------------------------------------------------------------------------\n\n/** Build a fresh entry for `node`. Caller still owns the entry — the\n * registry below holds a `ReadonlyMap` of these. */\nexport const makeEntry = (\n\tnode: DepNode,\n\tparentScope: Scope.Scope,\n): Effect.Effect<PluginEntry, never, never> =>\n\tEffect.gen(function* () {\n\t\tconst statusRef = yield* Ref.make<LifecycleStatus>('pending');\n\t\tconst readyGate = yield* Deferred.make<ResolvedValue, PluginAcquireFailed>();\n\t\tconst scope = yield* Scope.fork(parentScope);\n\t\treturn { node, statusRef, readyGate, scope } satisfies PluginEntry;\n\t});\n\n/** The lifecycle registry. Holds one entry per dep-graph node. */\nexport interface PluginRegistry {\n\treadonly entries: ReadonlyMap<PluginKey, PluginEntry>;\n\t/** Read a plugin's current status. */\n\treadonly getStatus: (key: PluginKey) => Effect.Effect<LifecycleStatus, UnknownDependency>;\n\t/** Transition a plugin to a new status. Validates against the\n\t * transition table; emits via `onTransition`. */\n\treadonly transition: (\n\t\tkey: PluginKey,\n\t\tto: LifecycleStatus,\n\t) => Effect.Effect<\n\t\t{ readonly from: LifecycleStatus; readonly to: LifecycleStatus },\n\t\tUnknownDependency\n\t>;\n\t/** Mark a plugin ready with its resolved value. */\n\treadonly markReady: (\n\t\tkey: PluginKey,\n\t\tvalue: ResolvedValue,\n\t) => Effect.Effect<void, UnknownDependency>;\n\t/** Mark a plugin failed. */\n\treadonly markFailed: (key: PluginKey, cause: unknown) => Effect.Effect<void, UnknownDependency>;\n\t/** Prepare a previously torn-down entry for hot restart. Plugin\n\t * scopes and ready gates are single-use: once a scope has been closed,\n\t * any finalizer registered during a later acquire would run\n\t * immediately, and an already-resolved ready gate would leak the old\n\t * value to downstream consumers. */\n\treadonly resetForRestart: (\n\t\tkey: PluginKey,\n\t\tparentScope: Scope.Scope,\n\t) => Effect.Effect<void, UnknownDependency>;\n\t/** Await `ready` for `key`. Suspends until the plugin's `readyGate`\n\t * resolves. The deferred's failure channel propagates a\n\t * `PluginAcquireFailed` so the supervisor's outer error path picks\n\t * it up. */\n\treadonly awaitReady: (\n\t\tkey: PluginKey,\n\t) => Effect.Effect<ResolvedValue, PluginAcquireFailed | UnknownDependency>;\n}\n\n/** Build a registry from a map of entries. The `onTransition` callback\n * is the supervisor's published event sink — every status change\n * flows through here. */\nexport const makeRegistry = (\n\tentries: ReadonlyMap<PluginKey, PluginEntry>,\n\tonTransition: (key: PluginKey, from: LifecycleStatus, to: LifecycleStatus) => Effect.Effect<void>,\n): PluginRegistry => {\n\tconst mutableEntries = new Map(entries);\n\tconst resolved: ResolvedMap = new Map();\n\n\tconst getEntry = (key: PluginKey): Effect.Effect<PluginEntry, UnknownDependency> => {\n\t\tconst entry = mutableEntries.get(key);\n\t\tif (entry === undefined) {\n\t\t\treturn Effect.fail(new UnknownDependency({ pluginKey: key, requestedResourceId: '' }));\n\t\t}\n\t\treturn Effect.succeed(entry);\n\t};\n\n\tconst reg: PluginRegistry & { __resolved: ResolvedMap } = {\n\t\tentries: mutableEntries,\n\t\t__resolved: resolved,\n\t\tgetStatus: (key) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst entry = yield* getEntry(key);\n\t\t\t\treturn yield* Ref.get(entry.statusRef);\n\t\t\t}),\n\t\ttransition: (key, to) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst entry = yield* getEntry(key);\n\t\t\t\tconst from = yield* Ref.get(entry.statusRef);\n\t\t\t\tyield* assertTransition(from, to);\n\t\t\t\tyield* Ref.set(entry.statusRef, to);\n\t\t\t\tyield* onTransition(key, from, to);\n\t\t\t\treturn { from, to };\n\t\t\t}),\n\t\tmarkReady: (key, value) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst entry = yield* getEntry(key);\n\t\t\t\tconst from = yield* Ref.get(entry.statusRef);\n\t\t\t\tresolved.set(key, value);\n\t\t\t\tif (from !== 'ready') {\n\t\t\t\t\t// `pending → ready` is off-table — the state machine\n\t\t\t\t\t// requires the intermediate `acquiring` hop. Bridge it\n\t\t\t\t\t// here so callers reaching `markReady` from a `pending`\n\t\t\t\t\t// entry (test fixtures, callers that mark a synthetic\n\t\t\t\t\t// already-resolved value) don't have to pre-walk the\n\t\t\t\t\t// machine. Both transitions still emit through\n\t\t\t\t\t// `onTransition` so subscribers see the full path.\n\t\t\t\t\tif (from === 'pending') {\n\t\t\t\t\t\tyield* assertTransition(from, 'acquiring');\n\t\t\t\t\t\tyield* Ref.set(entry.statusRef, 'acquiring');\n\t\t\t\t\t\tyield* onTransition(key, from, 'acquiring');\n\t\t\t\t\t\tyield* assertTransition('acquiring', 'ready');\n\t\t\t\t\t\tyield* Ref.set(entry.statusRef, 'ready');\n\t\t\t\t\t\tyield* onTransition(key, 'acquiring', 'ready');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tyield* assertTransition(from, 'ready');\n\t\t\t\t\t\tyield* Ref.set(entry.statusRef, 'ready');\n\t\t\t\t\t\tyield* onTransition(key, from, 'ready');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tyield* Deferred.succeed(entry.readyGate, value);\n\t\t\t}),\n\t\tmarkFailed: (key, cause) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst entry = yield* getEntry(key);\n\t\t\t\tconst from = yield* Ref.get(entry.statusRef);\n\t\t\t\tresolved.delete(key);\n\t\t\t\tyield* assertTransition(from, 'failed');\n\t\t\t\tyield* Ref.set(entry.statusRef, 'failed');\n\t\t\t\tyield* onTransition(key, from, 'failed');\n\t\t\t\tyield* Deferred.fail(entry.readyGate, new PluginAcquireFailed({ pluginKey: key, cause }));\n\t\t\t}),\n\t\tresetForRestart: (key, parentScope) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst entry = yield* getEntry(key);\n\t\t\t\tresolved.delete(key);\n\t\t\t\tconst readyGate = yield* Deferred.make<ResolvedValue, PluginAcquireFailed>();\n\t\t\t\tconst scope = yield* Scope.fork(parentScope);\n\t\t\t\t// Authoritatively reset the status to `pending`. The\n\t\t\t\t// transition table only admits `→ pending` from terminal\n\t\t\t\t// states (`failed` / `stopped` / `done`), but a selective\n\t\t\t\t// restart can reset a node that is still `acquiring` or\n\t\t\t\t// `pending` (its scope close interrupted an in-flight\n\t\t\t\t// acquire). Routing that through `transition` would die on\n\t\t\t\t// the off-table move — a defect the supervisor's command\n\t\t\t\t// loop can't catch — so we set the Ref directly and emit\n\t\t\t\t// the `statusChanged` event ourselves to keep the\n\t\t\t\t// projection's restart blip and the \"every status change\n\t\t\t\t// flows through `onTransition`\" contract intact. `acquire`\n\t\t\t\t// then performs a clean `pending → acquiring` for every\n\t\t\t\t// prior node state.\n\t\t\t\tconst from = yield* Ref.get(entry.statusRef);\n\t\t\t\tyield* Ref.set(entry.statusRef, 'pending');\n\t\t\t\tif (from !== 'pending') yield* onTransition(key, from, 'pending');\n\t\t\t\tmutableEntries.set(key, {\n\t\t\t\t\tnode: entry.node,\n\t\t\t\t\tstatusRef: entry.statusRef,\n\t\t\t\t\treadyGate,\n\t\t\t\t\tscope,\n\t\t\t\t});\n\t\t\t}),\n\t\tawaitReady: (key) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst entry = yield* getEntry(key);\n\t\t\t\treturn yield* Deferred.await(entry.readyGate);\n\t\t\t}),\n\t};\n\treturn reg;\n};\n\n/** Synchronous accessor: snapshot the resolved value for `key`.\n * Returns `undefined` if the plugin isn't ready yet OR isn't\n * registered. The supervisor guarantees readiness before any\n * consumer calls this; it's the ONLY synchronous path. */\nexport const readResolvedSync = (\n\tregistry: PluginRegistry,\n\tkey: PluginKey,\n): ResolvedValue | undefined => {\n\tconst resolved = (registry as PluginRegistry & { __resolved?: ResolvedMap }).__resolved;\n\treturn resolved?.get(key);\n};\n\n// -----------------------------------------------------------------------------\n// Dependency reader over the registry\n// -----------------------------------------------------------------------------\n\n/**\n * Build a synchronous dependency reader over the registry for one\n * plugin. The upstream key must already be `ready`; the supervisor\n * ensures this by awaiting upstream ready-gates before invoking start.\n */\nexport const buildDependencyReaderFor = (\n\tregistry: PluginRegistry,\n\tnode: DepNode,\n): ((resource: { readonly id: string }) => unknown) => {\n\t// Pre-build a resource-id → upstream-key index for this node so the\n\t// lookups are O(1) instead of scanning dependencies.\n\tconst resourceIdToKey = new Map<string, PluginKey>();\n\tnode.upstreamResources.forEach((resource, i) => {\n\t\tconst upstream = node.upstreamKeys[i];\n\t\tif (upstream !== undefined) resourceIdToKey.set(resource.id, upstream);\n\t});\n\treturn (resource): unknown => {\n\t\tconst key = resourceIdToKey.get(resource.id);\n\t\tif (key === undefined) {\n\t\t\t// Programmer error: the plugin reached outside its declared\n\t\t\t// dependencies. The type system normally rules this out — defending\n\t\t\t// here keeps the runtime honest in the face of cast escapes.\n\t\t\tthrow new DependencyReaderViolation({\n\t\t\t\tkind: 'undeclared-dependency',\n\t\t\t\ttarget: resource.id,\n\t\t\t});\n\t\t}\n\t\tconst value = readResolvedSync(registry, key);\n\t\tif (value === undefined) {\n\t\t\tthrow new DependencyReaderViolation({\n\t\t\t\tkind: 'unresolved-upstream',\n\t\t\t\ttarget: key,\n\t\t\t});\n\t\t}\n\t\treturn value;\n\t};\n};\n\n/** Tagged defect surfaced when a plugin's `start` callback reads a\n * dependency outside its declared `dependsOn` set, or an upstream\n * that hasn't been marked ready yet. Throws synchronously inside the\n * dependency-reader closure; the Effect runtime captures it as a\n * defect the cascade-formatter projects via `_tag`. The `kind`\n * discriminator and `target` carry the offending name; consumers\n * read both. */\nexport class DependencyReaderViolation extends Data.TaggedError('DependencyReaderViolation')<{\n\treadonly kind: 'undeclared-dependency' | 'unresolved-upstream';\n\treadonly target: string;\n}> {}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin-registry.mjs","names":[],"sources":["../../../../src/substrate/runtime/lifecycle/plugin-registry.ts"],"sourcesContent":["// Per-plugin lifecycle bookkeeping.\n//\n// One `PluginEntry` per node in the resolved dep-graph. The entry\n// holds:\n// - the live `LifecycleStatus` (Ref, single-fiber linearizable),\n// - the resolved value (set when status transitions to `ready`),\n// - the in-flight acquire fiber, when one is running,\n// - the scope owning the plugin's `start` finalizers,\n// - a `Deferred` that downstream consumers await for the ready gate.\n//\n// The registry tracks per-key lifecycle only; projection concerns stay\n// in the supervisor and reducer.\n\nimport { Data, Deferred, Effect, Fiber, Ref, Scope } from 'effect';\n\nimport type { PluginKey } from '../../brand.ts';\nimport type { LifecycleStatus } from '../../lifecycle.ts';\nimport type { DepNode } from './dep-graph.ts';\nimport { assertTransition } from './state-machine.ts';\n\n/** Per-registry side channel: synchronously-readable resolved values.\n * Keyed by plugin key. Populated by `markReady`; consulted by the\n * synchronous dependency reader. We can't put the value on the\n * `Deferred` itself in a publicly-supported way, and plugin start\n * receives dependency values synchronously; this is the safe escape hatch.\n *\n * Module-private; only `makeRegistry` writes into the map it\n * allocates. */\ntype ResolvedMap = Map<PluginKey, ResolvedValue>;\n\n// -----------------------------------------------------------------------------\n// Resolved-value shape\n// -----------------------------------------------------------------------------\n\n/** Erased resolved value held in the registry. The supervisor casts\n * back to the concrete type at the boundary where it threads the\n * value into a downstream plugin's resolved dependency object. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type ResolvedValue = any;\n\n// -----------------------------------------------------------------------------\n// Per-plugin entry\n// -----------------------------------------------------------------------------\n\n/** Mutable lifecycle state for one plugin instance. */\nexport interface PluginEntry {\n\treadonly node: DepNode;\n\treadonly statusRef: Ref.Ref<LifecycleStatus>;\n\treadonly acquireFiberRef: Ref.Ref<Fiber.Fiber<void, never> | null>;\n\t/** Resolved when the plugin reaches `ready`. Downstream consumers\n\t * await this in the ready-gate. Failure is propagated by interruption\n\t * via `Deferred.fail` to keep the error chain in the cause walker. */\n\treadonly readyGate: Deferred.Deferred<ResolvedValue, PluginAcquireFailed>;\n\t/** Per-plugin Scope. Closing it runs the `start` finalizers. */\n\treadonly scope: Scope.Closeable;\n}\n\n/** Tagged failure: a plugin's `start` rejected. Carries the cause and\n * the failing plugin's key so the cause walker / cascade formatter can\n * attribute it. */\nexport class PluginAcquireFailed extends Data.TaggedError('PluginAcquireFailed')<{\n\treadonly pluginKey: PluginKey;\n\treadonly cause: unknown;\n}> {}\n\n/** Tagged failure: a downstream plugin tried to read a resolved value\n * whose entry isn't registered or hasn't reached `ready`. Programmer-\n * level error class — the dep-graph guarantees this can't happen on\n * the supervisor's own scheduling path. Surfaced when a plugin author\n * reaches outside their declared dependencies. */\nexport class UnknownDependency extends Data.TaggedError('UnknownDependency')<{\n\treadonly pluginKey: PluginKey;\n\treadonly requestedResourceId: string;\n}> {}\n\n// -----------------------------------------------------------------------------\n// Registry\n// -----------------------------------------------------------------------------\n\n/** Build a fresh entry for `node`. Caller still owns the entry — the\n * registry below holds a `ReadonlyMap` of these. */\nexport const makeEntry = (\n\tnode: DepNode,\n\tparentScope: Scope.Scope,\n): Effect.Effect<PluginEntry, never, never> =>\n\tEffect.gen(function* () {\n\t\tconst statusRef = yield* Ref.make<LifecycleStatus>('pending');\n\t\tconst acquireFiberRef = yield* Ref.make<Fiber.Fiber<void, never> | null>(null);\n\t\tconst readyGate = yield* Deferred.make<ResolvedValue, PluginAcquireFailed>();\n\t\tconst scope = yield* Scope.fork(parentScope);\n\t\treturn { node, statusRef, acquireFiberRef, readyGate, scope } satisfies PluginEntry;\n\t});\n\n/** The lifecycle registry. Holds one entry per dep-graph node. */\nexport interface PluginRegistry {\n\treadonly entries: ReadonlyMap<PluginKey, PluginEntry>;\n\t/** Read a plugin's current status. */\n\treadonly getStatus: (key: PluginKey) => Effect.Effect<LifecycleStatus, UnknownDependency>;\n\t/** Transition a plugin to a new status. Validates against the\n\t * transition table; emits via `onTransition`. */\n\treadonly transition: (\n\t\tkey: PluginKey,\n\t\tto: LifecycleStatus,\n\t) => Effect.Effect<\n\t\t{ readonly from: LifecycleStatus; readonly to: LifecycleStatus },\n\t\tUnknownDependency\n\t>;\n\t/** Mark a plugin ready with its resolved value. */\n\treadonly markReady: (\n\t\tkey: PluginKey,\n\t\tvalue: ResolvedValue,\n\t) => Effect.Effect<void, UnknownDependency>;\n\t/** Mark a plugin failed. */\n\treadonly markFailed: (key: PluginKey, cause: unknown) => Effect.Effect<void, UnknownDependency>;\n\t/** Prepare a previously torn-down entry for hot restart. Plugin\n\t * scopes and ready gates are single-use: once a scope has been closed,\n\t * any finalizer registered during a later acquire would run\n\t * immediately, and an already-resolved ready gate would leak the old\n\t * value to downstream consumers. */\n\treadonly resetForRestart: (\n\t\tkey: PluginKey,\n\t\tparentScope: Scope.Scope,\n\t) => Effect.Effect<void, UnknownDependency>;\n\t/** Record the acquire fiber currently running for this key, but only if\n\t * the caller still owns the same registry entry generation it read before\n\t * forking. Selective restart swaps entries; stale acquire parents must not\n\t * write their old fiber into the new generation. */\n\treadonly setAcquireFiberIfEntry: (\n\t\tkey: PluginKey,\n\t\texpectedEntry: PluginEntry,\n\t\tfiber: Fiber.Fiber<void, never>,\n\t) => Effect.Effect<boolean, UnknownDependency>;\n\t/** Clear the slot only when it still belongs to the same entry generation\n\t * and settling acquire fiber. */\n\treadonly clearAcquireFiberIfEntry: (\n\t\tkey: PluginKey,\n\t\texpectedEntry: PluginEntry,\n\t\tfiberId: number,\n\t) => Effect.Effect<void, UnknownDependency>;\n\t/** Interrupt any acquire fiber still running for this key. */\n\treadonly interruptAcquire: (key: PluginKey) => Effect.Effect<void, UnknownDependency>;\n\t/** Await `ready` for `key`. Suspends until the plugin's `readyGate`\n\t * resolves. The deferred's failure channel propagates a\n\t * `PluginAcquireFailed` so the supervisor's outer error path picks\n\t * it up. */\n\treadonly awaitReady: (\n\t\tkey: PluginKey,\n\t) => Effect.Effect<ResolvedValue, PluginAcquireFailed | UnknownDependency>;\n}\n\n/** Build a registry from a map of entries. The `onTransition` callback\n * is the supervisor's published event sink — every status change\n * flows through here. */\nexport const makeRegistry = (\n\tentries: ReadonlyMap<PluginKey, PluginEntry>,\n\tonTransition: (key: PluginKey, from: LifecycleStatus, to: LifecycleStatus) => Effect.Effect<void>,\n): PluginRegistry => {\n\tconst mutableEntries = new Map(entries);\n\tconst resolved: ResolvedMap = new Map();\n\n\tconst getEntry = (key: PluginKey): Effect.Effect<PluginEntry, UnknownDependency> => {\n\t\tconst entry = mutableEntries.get(key);\n\t\tif (entry === undefined) {\n\t\t\treturn Effect.fail(new UnknownDependency({ pluginKey: key, requestedResourceId: '' }));\n\t\t}\n\t\treturn Effect.succeed(entry);\n\t};\n\n\tconst reg: PluginRegistry & { __resolved: ResolvedMap } = {\n\t\tentries: mutableEntries,\n\t\t__resolved: resolved,\n\t\tgetStatus: (key) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst entry = yield* getEntry(key);\n\t\t\t\treturn yield* Ref.get(entry.statusRef);\n\t\t\t}),\n\t\ttransition: (key, to) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst entry = yield* getEntry(key);\n\t\t\t\tconst from = yield* Ref.get(entry.statusRef);\n\t\t\t\tyield* assertTransition(from, to);\n\t\t\t\tyield* Ref.set(entry.statusRef, to);\n\t\t\t\tyield* onTransition(key, from, to);\n\t\t\t\treturn { from, to };\n\t\t\t}),\n\t\tmarkReady: (key, value) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst entry = yield* getEntry(key);\n\t\t\t\tconst from = yield* Ref.get(entry.statusRef);\n\t\t\t\tresolved.set(key, value);\n\t\t\t\tif (from !== 'ready') {\n\t\t\t\t\t// `pending → ready` is off-table — the state machine\n\t\t\t\t\t// requires the intermediate `acquiring` hop. Bridge it\n\t\t\t\t\t// here so callers reaching `markReady` from a `pending`\n\t\t\t\t\t// entry (test fixtures, callers that mark a synthetic\n\t\t\t\t\t// already-resolved value) don't have to pre-walk the\n\t\t\t\t\t// machine. Both transitions still emit through\n\t\t\t\t\t// `onTransition` so subscribers see the full path.\n\t\t\t\t\tif (from === 'pending') {\n\t\t\t\t\t\tyield* assertTransition(from, 'acquiring');\n\t\t\t\t\t\tyield* Ref.set(entry.statusRef, 'acquiring');\n\t\t\t\t\t\tyield* onTransition(key, from, 'acquiring');\n\t\t\t\t\t\tyield* assertTransition('acquiring', 'ready');\n\t\t\t\t\t\tyield* Ref.set(entry.statusRef, 'ready');\n\t\t\t\t\t\tyield* onTransition(key, 'acquiring', 'ready');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tyield* assertTransition(from, 'ready');\n\t\t\t\t\t\tyield* Ref.set(entry.statusRef, 'ready');\n\t\t\t\t\t\tyield* onTransition(key, from, 'ready');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tyield* Deferred.succeed(entry.readyGate, value);\n\t\t\t}),\n\t\tmarkFailed: (key, cause) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst entry = yield* getEntry(key);\n\t\t\t\tconst from = yield* Ref.get(entry.statusRef);\n\t\t\t\tresolved.delete(key);\n\t\t\t\tyield* assertTransition(from, 'failed');\n\t\t\t\tyield* Ref.set(entry.statusRef, 'failed');\n\t\t\t\tyield* onTransition(key, from, 'failed');\n\t\t\t\tyield* Deferred.fail(entry.readyGate, new PluginAcquireFailed({ pluginKey: key, cause }));\n\t\t\t}),\n\t\tresetForRestart: (key, parentScope) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst entry = yield* getEntry(key);\n\t\t\t\tconst acquireFiber = yield* Ref.getAndSet(entry.acquireFiberRef, null);\n\t\t\t\tif (acquireFiber !== null) {\n\t\t\t\t\tyield* Fiber.interrupt(acquireFiber);\n\t\t\t\t}\n\t\t\t\tresolved.delete(key);\n\t\t\t\tconst readyGate = yield* Deferred.make<ResolvedValue, PluginAcquireFailed>();\n\t\t\t\tconst acquireFiberRef = yield* Ref.make<Fiber.Fiber<void, never> | null>(null);\n\t\t\t\tconst scope = yield* Scope.fork(parentScope);\n\t\t\t\t// Authoritatively reset the status to `pending`. The\n\t\t\t\t// transition table only admits `→ pending` from terminal\n\t\t\t\t// states (`failed` / `stopped` / `done`), but a selective\n\t\t\t\t// restart can reset a node that is still `acquiring` or\n\t\t\t\t// `pending` (its scope close interrupted an in-flight\n\t\t\t\t// acquire). Routing that through `transition` would die on\n\t\t\t\t// the off-table move — a defect the supervisor's command\n\t\t\t\t// loop can't catch — so we set the Ref directly and emit\n\t\t\t\t// the `statusChanged` event ourselves to keep the\n\t\t\t\t// projection's restart blip and the \"every status change\n\t\t\t\t// flows through `onTransition`\" contract intact. `acquire`\n\t\t\t\t// then performs a clean `pending → acquiring` for every\n\t\t\t\t// prior node state.\n\t\t\t\tconst from = yield* Ref.get(entry.statusRef);\n\t\t\t\tyield* Ref.set(entry.statusRef, 'pending');\n\t\t\t\tif (from !== 'pending') yield* onTransition(key, from, 'pending');\n\t\t\t\tmutableEntries.set(key, {\n\t\t\t\t\tnode: entry.node,\n\t\t\t\t\tstatusRef: entry.statusRef,\n\t\t\t\t\tacquireFiberRef,\n\t\t\t\t\treadyGate,\n\t\t\t\t\tscope,\n\t\t\t\t});\n\t\t\t}),\n\t\tsetAcquireFiberIfEntry: (key, expectedEntry, fiber) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst entry = yield* getEntry(key);\n\t\t\t\tif (entry !== expectedEntry) return false;\n\t\t\t\tyield* Ref.set(entry.acquireFiberRef, fiber);\n\t\t\t\treturn true;\n\t\t\t}),\n\t\tclearAcquireFiberIfEntry: (key, expectedEntry, fiberId) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst entry = yield* getEntry(key);\n\t\t\t\tif (entry !== expectedEntry) return;\n\t\t\t\tyield* Ref.update(entry.acquireFiberRef, (current) =>\n\t\t\t\t\tcurrent !== null && current.id === fiberId ? null : current,\n\t\t\t\t);\n\t\t\t}),\n\t\tinterruptAcquire: (key) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst entry = yield* getEntry(key);\n\t\t\t\tconst acquireFiber = yield* Ref.getAndSet(entry.acquireFiberRef, null);\n\t\t\t\tif (acquireFiber !== null) {\n\t\t\t\t\tyield* Fiber.interrupt(acquireFiber);\n\t\t\t\t}\n\t\t\t}),\n\t\tawaitReady: (key) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst entry = yield* getEntry(key);\n\t\t\t\treturn yield* Deferred.await(entry.readyGate);\n\t\t\t}),\n\t};\n\treturn reg;\n};\n\n/** Synchronous accessor: snapshot the resolved value for `key`.\n * Returns `undefined` if the plugin isn't ready yet OR isn't\n * registered. The supervisor guarantees readiness before any\n * consumer calls this; it's the ONLY synchronous path. */\nexport const readResolvedSync = (\n\tregistry: PluginRegistry,\n\tkey: PluginKey,\n): ResolvedValue | undefined => {\n\tconst resolved = (registry as PluginRegistry & { __resolved?: ResolvedMap }).__resolved;\n\treturn resolved?.get(key);\n};\n\n// -----------------------------------------------------------------------------\n// Dependency reader over the registry\n// -----------------------------------------------------------------------------\n\n/**\n * Build a synchronous dependency reader over the registry for one\n * plugin. The upstream key must already be `ready`; the supervisor\n * ensures this by awaiting upstream ready-gates before invoking start.\n */\nexport const buildDependencyReaderFor = (\n\tregistry: PluginRegistry,\n\tnode: DepNode,\n): ((resource: { readonly id: string }) => unknown) => {\n\t// Pre-build a resource-id → upstream-key index for this node so the\n\t// lookups are O(1) instead of scanning dependencies.\n\tconst resourceIdToKey = new Map<string, PluginKey>();\n\tnode.upstreamResources.forEach((resource, i) => {\n\t\tconst upstream = node.upstreamKeys[i];\n\t\tif (upstream !== undefined) resourceIdToKey.set(resource.id, upstream);\n\t});\n\treturn (resource): unknown => {\n\t\tconst key = resourceIdToKey.get(resource.id);\n\t\tif (key === undefined) {\n\t\t\t// Programmer error: the plugin reached outside its declared\n\t\t\t// dependencies. The type system normally rules this out — defending\n\t\t\t// here keeps the runtime honest in the face of cast escapes.\n\t\t\tthrow new DependencyReaderViolation({\n\t\t\t\tkind: 'undeclared-dependency',\n\t\t\t\ttarget: resource.id,\n\t\t\t});\n\t\t}\n\t\tconst value = readResolvedSync(registry, key);\n\t\tif (value === undefined) {\n\t\t\tthrow new DependencyReaderViolation({\n\t\t\t\tkind: 'unresolved-upstream',\n\t\t\t\ttarget: key,\n\t\t\t});\n\t\t}\n\t\treturn value;\n\t};\n};\n\n/** Tagged defect surfaced when a plugin's `start` callback reads a\n * dependency outside its declared `dependsOn` set, or an upstream\n * that hasn't been marked ready yet. Throws synchronously inside the\n * dependency-reader closure; the Effect runtime captures it as a\n * defect the cascade-formatter projects via `_tag`. The `kind`\n * discriminator and `target` carry the offending name; consumers\n * read both. */\nexport class DependencyReaderViolation extends Data.TaggedError('DependencyReaderViolation')<{\n\treadonly kind: 'undeclared-dependency' | 'unresolved-upstream';\n\treadonly target: string;\n}> {}\n"],"mappings":"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"}
|
|
@@ -9,26 +9,13 @@ import { Effect } from "effect";
|
|
|
9
9
|
* the node begins `acquiring`."
|
|
10
10
|
*/
|
|
11
11
|
const awaitUpstreams = (registry, node) => Effect.gen(function* () {
|
|
12
|
-
yield* Effect.annotateCurrentSpan({
|
|
13
|
-
"devstack.plugin.key": node.key,
|
|
14
|
-
"devstack.plugin.upstreamCount": node.upstreamKeys.length
|
|
15
|
-
});
|
|
16
12
|
if (node.upstreamKeys.length === 0) return;
|
|
17
13
|
yield* Effect.all(node.upstreamKeys.map((key) => registry.awaitReady(key)), {
|
|
18
14
|
concurrency: "unbounded",
|
|
19
15
|
discard: true
|
|
20
16
|
});
|
|
21
|
-
})
|
|
22
|
-
/**
|
|
23
|
-
* Wait for every plugin in `keys` to reach `ready`. Used by the
|
|
24
|
-
* supervisor's "stack is ready" gate after the level-batched parallel
|
|
25
|
-
* acquire completes.
|
|
26
|
-
*/
|
|
27
|
-
const awaitAll = (registry, keys) => Effect.all(keys.map((key) => registry.awaitReady(key)), {
|
|
28
|
-
concurrency: "unbounded",
|
|
29
|
-
discard: true
|
|
30
|
-
}).pipe(Effect.withSpan("lifecycle.ready-gate.awaitAll"));
|
|
17
|
+
});
|
|
31
18
|
//#endregion
|
|
32
|
-
export {
|
|
19
|
+
export { awaitUpstreams };
|
|
33
20
|
|
|
34
21
|
//# sourceMappingURL=ready-gate.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ready-gate.mjs","names":[],"sources":["../../../../src/substrate/runtime/lifecycle/ready-gate.ts"],"sourcesContent":["// Ready-gate composition over `PluginRegistry`.\n//\n// Architecture § Plugin lifecycle within a stack § Ready gate:\n// \"Plugin's acquire procedure returns the resolved value + capability\n// decls. Substrate writes them to the typed registries. Plugin\n// transitions to `ready`. Downstream consumers are unblocked.\"\n//\n// This module provides the small `
|
|
1
|
+
{"version":3,"file":"ready-gate.mjs","names":[],"sources":["../../../../src/substrate/runtime/lifecycle/ready-gate.ts"],"sourcesContent":["// Ready-gate composition over `PluginRegistry`.\n//\n// Architecture § Plugin lifecycle within a stack § Ready gate:\n// \"Plugin's acquire procedure returns the resolved value + capability\n// decls. Substrate writes them to the typed registries. Plugin\n// transitions to `ready`. Downstream consumers are unblocked.\"\n//\n// This module provides the small `awaitUpstreams` helper the\n// supervisor's acquire loop calls. The actual `Deferred` machinery\n// lives on `PluginRegistry`; here we just compose it and short-circuit\n// on the first upstream failure. (The stack-wide \"all ready\" gate is\n// the supervisor's own `allReadyOrTerminal` status signal, which is\n// `done`-tolerant — see supervisor/state.ts — not a per-node\n// ready-gate fan-out.)\n\nimport { Effect } from 'effect';\n\nimport type { DepNode } from './dep-graph.ts';\nimport type { PluginAcquireFailed, PluginRegistry, UnknownDependency } from './plugin-registry.ts';\n\n/**\n * Wait for every upstream of `node` to reach `ready`. Returns when\n * they all have; short-circuits on the first upstream failure (the\n * failed deferred propagates `PluginAcquireFailed`).\n *\n * Architecture § Scheduling: \"When all upstream keys are `ready`,\n * the node begins `acquiring`.\"\n */\nexport const awaitUpstreams = (\n\tregistry: PluginRegistry,\n\tnode: DepNode,\n): Effect.Effect<void, PluginAcquireFailed | UnknownDependency> =>\n\tEffect.gen(function* () {\n\t\tif (node.upstreamKeys.length === 0) return;\n\t\t// Parallelize the awaits — every upstream's ready-gate resolves\n\t\t// once (or fails once); racing them is the right shape.\n\t\tyield* Effect.all(\n\t\t\tnode.upstreamKeys.map((key) => registry.awaitReady(key)),\n\t\t\t{ concurrency: 'unbounded', discard: true },\n\t\t);\n\t});\n"],"mappings":";;;;;;;;;;AA4BA,MAAa,kBACZ,UACA,SAEA,OAAO,IAAI,aAAa;CACvB,IAAI,KAAK,aAAa,WAAW,GAAG;CAGpC,OAAO,OAAO,IACb,KAAK,aAAa,KAAK,QAAQ,SAAS,WAAW,GAAG,CAAC,GACvD;EAAE,aAAa;EAAa,SAAS;CAAK,CAC3C;AACD,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { downstreamClosure
|
|
1
|
+
import { downstreamClosure } from "./dep-graph.mjs";
|
|
2
|
+
import { plan } from "../reconcile/graph.mjs";
|
|
2
3
|
import { Data, Effect } from "effect";
|
|
3
4
|
//#region src/substrate/runtime/lifecycle/selective-restart.ts
|
|
4
5
|
/** Tagged error: a restart was requested for a key that isn't in the
|
|
@@ -7,37 +8,40 @@ import { Data, Effect } from "effect";
|
|
|
7
8
|
var RestartTargetMissing = class extends Data.TaggedError("RestartTargetMissing") {};
|
|
8
9
|
/**
|
|
9
10
|
* Build a restart plan from a set of root invalidation targets. Each
|
|
10
|
-
* root contributes its full downstream closure to the slice.
|
|
11
|
+
* root contributes its full downstream closure to the slice. The
|
|
12
|
+
* downstream-closure slice computation + the root-membership validation
|
|
13
|
+
* are this planner's unique work; the dep-ordering itself delegates to
|
|
14
|
+
* the shared reconcile `plan` body, which returns a `GraphPlan`.
|
|
11
15
|
*/
|
|
12
16
|
const planRestart = (graph, roots) => Effect.gen(function* () {
|
|
13
|
-
yield* Effect.annotateCurrentSpan({ "devstack.restart.rootCount": roots.size });
|
|
14
17
|
for (const root of roots) if (!graph.nodes.has(root)) return yield* Effect.fail(new RestartTargetMissing({ pluginKey: root }));
|
|
15
18
|
const slice = /* @__PURE__ */ new Set();
|
|
16
19
|
for (const root of roots) for (const key of downstreamClosure(graph, root)) slice.add(key);
|
|
17
|
-
return {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
*
|
|
25
|
-
* dep-graph order, reverse. Architecture § Stack lifecycle:
|
|
26
|
-
* "shutdown.requested → parallel teardown (max grace, not sum grace)"
|
|
20
|
+
return plan(graph, {
|
|
21
|
+
kind: "graph-keys",
|
|
22
|
+
keys: [...slice]
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
/** Plan a drain + re-acquire of the whole graph MINUS the nodes matched by
|
|
26
|
+
* `exclude`. The excluded nodes stay live while every other plugin is
|
|
27
|
+
* drained + re-acquired.
|
|
27
28
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
* The live `snapshot.restore` re-acquire passes a predicate over the
|
|
30
|
+
* plugin-declared keep-alive flag so a plugin whose transport is
|
|
31
|
+
* answering the restore isn't torn down mid-flight (which would surface
|
|
32
|
+
* to its caller as a 502 even though the restore succeeded). This module
|
|
33
|
+
* filters purely on the node flag — it has no knowledge of which plugins
|
|
34
|
+
* set it. `stack.restart` / CLI full-restart drains everything by passing
|
|
35
|
+
* the full key set straight to `plan`. */
|
|
36
|
+
const planExcluding = (graph, exclude) => {
|
|
37
|
+
const slice = /* @__PURE__ */ new Set();
|
|
38
|
+
for (const [key, node] of graph.nodes) if (!exclude(node)) slice.add(key);
|
|
39
|
+
return plan(graph, {
|
|
40
|
+
kind: "graph-keys",
|
|
41
|
+
keys: [...slice]
|
|
42
|
+
});
|
|
39
43
|
};
|
|
40
44
|
//#endregion
|
|
41
|
-
export { RestartTargetMissing,
|
|
45
|
+
export { RestartTargetMissing, planExcluding, planRestart };
|
|
42
46
|
|
|
43
47
|
//# sourceMappingURL=selective-restart.mjs.map
|