@mysten-incubation/devstack 0.1.1 → 0.2.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-a4usE3Nk.js +3 -0
- package/dashboard-ui/assets/index-B82Bh84P.css +1 -0
- package/dashboard-ui/assets/index-CRYJ4pru.js +1277 -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 +202 -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 +1 -30
- package/dist/build-integrations/playwright/config.mjs +1 -27
- 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 +84 -19
- package/dist/build-integrations/vite/index.mjs +203 -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 +16 -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 +1 -3
- 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 +218 -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 +440 -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 +286 -58
- 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 +106 -167
- 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 +23 -44
- package/dist/plugins/dashboard/schema/root.mjs.map +1 -1
- package/dist/plugins/dashboard/schema/types.mjs +37 -91
- 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 +38 -34
- package/dist/plugins/deepbook/index.mjs +133 -64
- 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 +34 -83
- 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 +8 -4
- 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 +1 -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/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 +2 -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 +0 -1
- 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.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 +60 -70
- 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/{state-store/index.d.mts → reconcile/graph.d.mts} +0 -0
- /package/dist/substrate/runtime/{cross-process/snapshot-reservation.d.mts → supervisor/contribution-dispatcher.d.mts} +0 -0
|
@@ -12,16 +12,10 @@ import { runSnapshot } from "./commands/snapshot.mjs";
|
|
|
12
12
|
import { runStatus } from "./commands/status.mjs";
|
|
13
13
|
import { runWipe } from "./commands/wipe.mjs";
|
|
14
14
|
import "./commands/index.mjs";
|
|
15
|
+
import { readDevstackVersion } from "../../cli/wirings/read-devstack-version.mjs";
|
|
15
16
|
import { Effect } from "effect";
|
|
16
|
-
import { readFileSync } from "node:fs";
|
|
17
17
|
import { buildApplication, buildChoiceParser, buildCommand, buildRouteMap, run, text_en } from "@stricli/core";
|
|
18
18
|
//#region src/surfaces/cli/index.ts
|
|
19
|
-
const readPackageVersion = () => {
|
|
20
|
-
const raw = readFileSync(new URL("../../../package.json", import.meta.url), "utf8");
|
|
21
|
-
const pkg = JSON.parse(raw);
|
|
22
|
-
if (typeof pkg.version !== "string") throw new Error("devstack package.json is missing a string version");
|
|
23
|
-
return pkg.version;
|
|
24
|
-
};
|
|
25
19
|
const makeBufferedProcess = (env) => {
|
|
26
20
|
const stdoutBuffer = [];
|
|
27
21
|
const stderrBuffer = [];
|
|
@@ -113,6 +107,11 @@ const rendererParser = buildChoiceParser([
|
|
|
113
107
|
"plain",
|
|
114
108
|
"silent"
|
|
115
109
|
]);
|
|
110
|
+
const snapshotStaleParser = buildChoiceParser([
|
|
111
|
+
"warn",
|
|
112
|
+
"block",
|
|
113
|
+
"clean-start"
|
|
114
|
+
]);
|
|
116
115
|
const outputModeFrom = (flags, env) => flags.json === true || env[ENV_VARS.JSON] === "1" ? "json" : "human";
|
|
117
116
|
const pruneResourcesFromFlags = (flags) => ({
|
|
118
117
|
containers: flags.noContainers !== true,
|
|
@@ -140,6 +139,9 @@ const makeGlobalFlags = (ctx, flags, rest) => {
|
|
|
140
139
|
configPath: optionalEnv(flags.config, ctx.env, ENV_VARS.CONFIG_PATH),
|
|
141
140
|
network,
|
|
142
141
|
renderer: flags.renderer,
|
|
142
|
+
fromSnapshot: flags.fromSnapshot,
|
|
143
|
+
snapshotCache: flags.snapshotCache,
|
|
144
|
+
snapshotStalePolicy: flags.snapshotStale,
|
|
143
145
|
dryRun: flags.dryRun === true,
|
|
144
146
|
confirm: {
|
|
145
147
|
assumeYes: flags.yes === true,
|
|
@@ -239,6 +241,15 @@ const app = buildApplication(buildRouteMap({
|
|
|
239
241
|
optional: true,
|
|
240
242
|
placeholder: "tui|plain|silent",
|
|
241
243
|
brief: "Select the attached renderer"
|
|
244
|
+
},
|
|
245
|
+
fromSnapshot: stringFlag("Start by restoring a named snapshot before acquire", "name-or-id"),
|
|
246
|
+
snapshotCache: stringFlag("Use a named snapshot as a startup cache and refresh it when stale", "name"),
|
|
247
|
+
snapshotStale: {
|
|
248
|
+
kind: "parsed",
|
|
249
|
+
parse: snapshotStaleParser,
|
|
250
|
+
optional: true,
|
|
251
|
+
placeholder: "warn|block|clean-start",
|
|
252
|
+
brief: "Policy when --from-snapshot inputs differ from the current stack"
|
|
242
253
|
}
|
|
243
254
|
} },
|
|
244
255
|
docs: { brief: "Boot a stack and stay attached until interrupted" },
|
|
@@ -253,9 +264,31 @@ const app = buildApplication(buildRouteMap({
|
|
|
253
264
|
return runWithFlags(this, "apply", flags, [], (global) => this.deps.apply.run(global));
|
|
254
265
|
}
|
|
255
266
|
}),
|
|
267
|
+
codegen: buildCommand({
|
|
268
|
+
parameters: { flags: configFlagParams },
|
|
269
|
+
docs: { brief: "Regenerate committed bindings from Move source (no stack boot)" },
|
|
270
|
+
func: function(flags) {
|
|
271
|
+
return runWithFlags(this, "codegen", flags, [], (global) => this.deps.codegen.run({ configPath: global.configPath }));
|
|
272
|
+
}
|
|
273
|
+
}),
|
|
274
|
+
dumpIds: buildCommand({
|
|
275
|
+
parameters: { flags: {
|
|
276
|
+
...configFlagParams,
|
|
277
|
+
out: stringFlag("Write the id-config JSON to this file instead of stdout", "path")
|
|
278
|
+
} },
|
|
279
|
+
docs: { brief: "Emit the stack id-config (devstack-ids.json) for a real-network deploy" },
|
|
280
|
+
func: function(flags) {
|
|
281
|
+
return runWithFlags(this, "dump-ids", flags, [], (global) => this.deps.dumpIds.run({
|
|
282
|
+
configPath: global.configPath,
|
|
283
|
+
out: flags.out,
|
|
284
|
+
io: this.io,
|
|
285
|
+
outputMode: global.outputMode
|
|
286
|
+
}));
|
|
287
|
+
}
|
|
288
|
+
}),
|
|
256
289
|
status: buildCommand({
|
|
257
290
|
parameters: { flags: identityFlagParams },
|
|
258
|
-
docs: { brief: "Show the
|
|
291
|
+
docs: { brief: "Show the current stack projection (offline: from the manifest)" },
|
|
259
292
|
func: function(flags) {
|
|
260
293
|
return runWithFlags(this, "status", flags, [], (global) => runStatus(this.deps.status, {
|
|
261
294
|
flags: global,
|
|
@@ -399,7 +432,7 @@ const app = buildApplication(buildRouteMap({
|
|
|
399
432
|
docs: { brief: "Sui development stack CLI" }
|
|
400
433
|
}), {
|
|
401
434
|
name: "devstack",
|
|
402
|
-
versionInfo: { currentVersion:
|
|
435
|
+
versionInfo: { currentVersion: readDevstackVersion() },
|
|
403
436
|
scanner: { caseStyle: "allow-kebab-for-camel" },
|
|
404
437
|
documentation: {
|
|
405
438
|
caseStyle: "convert-camel-to-kebab",
|
|
@@ -423,11 +456,9 @@ const jsonRequested = (argv, env) => env[ENV_VARS.JSON] === "1" || argv.includes
|
|
|
423
456
|
* `io.touched()` and short-circuits this projection in `dispatch`
|
|
424
457
|
* before `flushBufferedProcess` is reached.
|
|
425
458
|
*
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
* `USAGE` mapping holds by construction. Kept as a named function
|
|
430
|
-
* so the invariant is documented at the call site.
|
|
459
|
+
* A non-zero value here means Stricli rejected argv before any verb
|
|
460
|
+
* ran, so mapping to `USAGE` holds by construction. Kept as a named
|
|
461
|
+
* function so the invariant is documented at the call site.
|
|
431
462
|
*/
|
|
432
463
|
const normalizeStricliExitCode = (code) => {
|
|
433
464
|
if (typeof code === "number" && code !== 0) return ExitCode.USAGE;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["runStricli"],"sources":["../../../src/surfaces/cli/index.ts"],"sourcesContent":["// CLI surface — top-level entry point.\n//\n// The public CLI is intentionally small: `up` is the attached operator\n// surface, `apply` is live-aware reconcile (publish to `up` when it is\n// running, one-shot otherwise), and every other command is offline/direct.\n\nimport {\n\tbuildApplication,\n\tbuildChoiceParser,\n\tbuildCommand,\n\tbuildRouteMap,\n\trun as runStricli,\n\ttext_en,\n\ttype CommandContext as StricliCommandContext,\n\ttype StricliProcess,\n} from '@stricli/core';\nimport { Effect, type Scope } from 'effect';\nimport { readFileSync } from 'node:fs';\n\nimport { commandSchema } from './command-tree.ts';\nimport { type CliError, CliInternalError, CliUsageError, exitCodeFor } from './errors.ts';\nimport { type CliRendererMode, ENV_VARS, type GlobalFlags, type OutputMode } from './flags.ts';\nimport { ExitCode } from './sysexits.ts';\nimport { parseDevstackNetworkName } from '../../api/inference-network.ts';\nimport { type CliIO, emitFailure, emitSuccess, nodeProcessIO } from './output.ts';\nimport {\n\ttype CommandResult,\n\ttype ConfigDeps,\n\ttype DoctorDeps,\n\ttype PruneDeps,\n\ttype PruneResourceScope,\n\ttype SnapshotDeps,\n\ttype StatusDeps,\n\ttype WipeDeps,\n\trunConfig,\n\trunDoctor,\n\trunPrune,\n\trunSnapshot,\n\trunStatus,\n\trunWipe,\n} from './commands/index.ts';\n\nconst readPackageVersion = (): string => {\n\tconst raw = readFileSync(new URL('../../../package.json', import.meta.url), 'utf8');\n\tconst pkg = JSON.parse(raw) as { readonly version?: unknown };\n\tif (typeof pkg.version !== 'string') {\n\t\tthrow new Error('devstack package.json is missing a string version');\n\t}\n\treturn pkg.version;\n};\n\n// -----------------------------------------------------------------------------\n// Deps bundle\n// -----------------------------------------------------------------------------\n\nexport interface LifecycleCommandDeps {\n\treadonly run: (flags: GlobalFlags) => Effect.Effect<CommandResult, CliError>;\n}\n\nexport interface CliDeps {\n\treadonly up: LifecycleCommandDeps;\n\treadonly apply: LifecycleCommandDeps;\n\treadonly status: StatusDeps;\n\treadonly snapshot: SnapshotDeps;\n\treadonly prune: PruneDeps;\n\treadonly doctor: DoctorDeps;\n\treadonly config: ConfigDeps;\n\treadonly wipe: WipeDeps;\n}\n\nexport interface DispatchEnv {\n\treadonly argv: ReadonlyArray<string>;\n\treadonly env: Readonly<Record<string, string | undefined>>;\n\treadonly stdinIsTty: boolean;\n\treadonly io?: CliIO;\n}\n\n// -----------------------------------------------------------------------------\n// Stricli context + buffered process\n// -----------------------------------------------------------------------------\n\ninterface BufferedProcess extends StricliProcess {\n\treadonly stdoutBuffer: Array<string>;\n\treadonly stderrBuffer: Array<string>;\n\texitCode?: number | string | null;\n}\n\ninterface TrackedIO extends CliIO {\n\treadonly touched: () => boolean;\n\treadonly lastExitCode: () => number | null;\n}\n\ninterface DevstackCliContext extends StricliCommandContext {\n\treadonly deps: CliDeps;\n\treadonly env: Readonly<Record<string, string | undefined>>;\n\treadonly stdinIsTty: boolean;\n\treadonly io: TrackedIO;\n\treadonly process: BufferedProcess;\n}\n\nconst makeBufferedProcess = (\n\tenv: Readonly<Record<string, string | undefined>>,\n): BufferedProcess => {\n\tconst stdoutBuffer: Array<string> = [];\n\tconst stderrBuffer: Array<string> = [];\n\treturn {\n\t\tstdoutBuffer,\n\t\tstderrBuffer,\n\t\tenv,\n\t\tstdout: {\n\t\t\twrite: (str) => {\n\t\t\t\tstdoutBuffer.push(str);\n\t\t\t},\n\t\t},\n\t\tstderr: {\n\t\t\twrite: (str) => {\n\t\t\t\tstderrBuffer.push(str);\n\t\t\t},\n\t\t},\n\t};\n};\n\nconst trackIO = (io: CliIO): TrackedIO => {\n\tlet touched = false;\n\tlet lastExitCode: number | null = null;\n\treturn {\n\t\ttouched: () => touched,\n\t\tlastExitCode: () => lastExitCode,\n\t\twriteStdout: (line) =>\n\t\t\tio.writeStdout(line).pipe(\n\t\t\t\tEffect.tap(() =>\n\t\t\t\t\tEffect.sync(() => {\n\t\t\t\t\t\ttouched = true;\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t\twriteStderr: (line) =>\n\t\t\tio.writeStderr(line).pipe(\n\t\t\t\tEffect.tap(() =>\n\t\t\t\t\tEffect.sync(() => {\n\t\t\t\t\t\ttouched = true;\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t\tsetExitCode: (code) =>\n\t\t\tio.setExitCode(code).pipe(\n\t\t\t\tEffect.tap(() =>\n\t\t\t\t\tEffect.sync(() => {\n\t\t\t\t\t\ttouched = true;\n\t\t\t\t\t\tlastExitCode = code;\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t};\n};\n\n// -----------------------------------------------------------------------------\n// Flag models\n// -----------------------------------------------------------------------------\n\ninterface IdentityFlags {\n\treadonly json?: boolean;\n\treadonly app?: string;\n\treadonly stack?: string;\n\treadonly stateDir?: string;\n\treadonly verbose?: boolean;\n}\n\ninterface ConfigFlags extends IdentityFlags {\n\treadonly config?: string;\n\treadonly network?: string;\n}\n\ninterface UpFlags extends ConfigFlags {\n\treadonly renderer?: CliRendererMode;\n}\n\ninterface DestructiveFlags extends IdentityFlags {\n\treadonly dryRun?: boolean;\n\treadonly yes?: boolean;\n\treadonly noInput?: boolean;\n}\n\ninterface ConfirmFlags extends IdentityFlags {\n\treadonly yes?: boolean;\n\treadonly noInput?: boolean;\n}\n\ninterface PruneFlags {\n\treadonly json?: boolean;\n\treadonly stateDir?: string;\n\treadonly verbose?: boolean;\n\treadonly dryRun?: boolean;\n\treadonly yes?: boolean;\n\treadonly noInput?: boolean;\n\treadonly list?: boolean;\n\treadonly all?: boolean;\n\treadonly noContainers?: boolean;\n\treadonly noNetworks?: boolean;\n\treadonly noVolumes?: boolean;\n\treadonly includeImages?: boolean;\n}\n\ninterface SnapshotSaveFlags extends ConfigFlags {\n\treadonly name?: string;\n}\n\nconst textParser = (input: string): string => input;\n\nconst stringFlag = (brief: string, placeholder: string) =>\n\t({\n\t\tkind: 'parsed',\n\t\tparse: textParser,\n\t\toptional: true,\n\t\tplaceholder,\n\t\tbrief,\n\t}) as const;\n\nconst boolFlag = (brief: string) =>\n\t({\n\t\tkind: 'boolean',\n\t\toptional: true,\n\t\tbrief,\n\t}) as const;\n\nconst identityFlagParams = {\n\tjson: boolFlag('Emit JSON envelope output'),\n\tapp: stringFlag('Override app name', 'name'),\n\tstack: stringFlag('Override stack name', 'name'),\n\tstateDir: stringFlag('Override state directory', 'path'),\n\tverbose: boolFlag('Enable more verbose logging'),\n} as const;\n\nconst configFlagParams = {\n\t...identityFlagParams,\n\tconfig: stringFlag('Override devstack.config.ts path', 'path'),\n\tnetwork: stringFlag('Override network before config import', 'name'),\n} as const;\n\nconst destructiveFlagParams = {\n\t...identityFlagParams,\n\tdryRun: boolFlag('Skip mutating effects'),\n\tyes: boolFlag('Assume yes on prompts'),\n\tnoInput: boolFlag('Forbid prompts'),\n} as const;\n\nconst globalMaintenanceFlagParams = {\n\tjson: identityFlagParams.json,\n\tstateDir: identityFlagParams.stateDir,\n\tverbose: identityFlagParams.verbose,\n} as const;\n\nconst confirmFlagParams = {\n\t...identityFlagParams,\n\tyes: boolFlag('Assume yes on prompts'),\n\tnoInput: boolFlag('Forbid prompts'),\n} as const;\n\nconst pruneFlagParams = {\n\t...globalMaintenanceFlagParams,\n\tdryRun: destructiveFlagParams.dryRun,\n\tyes: destructiveFlagParams.yes,\n\tnoInput: destructiveFlagParams.noInput,\n\tlist: boolFlag('List devstack-labelled Docker resources without pruning'),\n\tall: boolFlag('Prune every idle non-shared resource group'),\n\tnoContainers: boolFlag('Do not remove containers'),\n\tnoNetworks: boolFlag('Do not remove networks'),\n\tnoVolumes: boolFlag('Do not remove volumes'),\n\tincludeImages: boolFlag('Also remove devstack-labelled images for selected groups'),\n} as const;\n\nconst rendererParser = buildChoiceParser(['tui', 'plain', 'silent'] as const);\n\nconst outputModeFrom = (\n\tflags: Pick<IdentityFlags, 'json'>,\n\tenv: Readonly<Record<string, string | undefined>>,\n): OutputMode => (flags.json === true || env[ENV_VARS.JSON] === '1' ? 'json' : 'human');\n\nconst pruneResourcesFromFlags = (flags: PruneFlags): PruneResourceScope => ({\n\tcontainers: flags.noContainers !== true,\n\tnetworks: flags.noNetworks !== true,\n\tvolumes: flags.noVolumes !== true,\n\timages: flags.includeImages === true,\n});\n\nconst optionalEnv = (\n\tvalue: string | undefined,\n\tenv: Readonly<Record<string, string | undefined>>,\n\tkey: string,\n): string | undefined => value ?? env[key];\n\nconst makeGlobalFlags = (\n\tctx: DevstackCliContext,\n\tflags: IdentityFlags & Partial<ConfigFlags & UpFlags & DestructiveFlags>,\n\trest: ReadonlyArray<string>,\n): GlobalFlags => {\n\tconst networkRaw = optionalEnv(flags.network, ctx.env, ENV_VARS.NETWORK);\n\tlet network: string | undefined;\n\tif (networkRaw !== undefined) {\n\t\ttry {\n\t\t\tnetwork = parseDevstackNetworkName(\n\t\t\t\tnetworkRaw,\n\t\t\t\tflags.network === undefined ? ENV_VARS.NETWORK : '--network',\n\t\t\t);\n\t\t} catch (cause) {\n\t\t\tthrow cause instanceof Error\n\t\t\t\t? new CliUsageError({ message: cause.message })\n\t\t\t\t: new CliInternalError({ message: 'failed to parse network flag', cause });\n\t\t}\n\t}\n\treturn {\n\t\toutputMode: outputModeFrom(flags, ctx.env),\n\t\tapp: optionalEnv(flags.app, ctx.env, ENV_VARS.APP),\n\t\tstack: optionalEnv(flags.stack, ctx.env, ENV_VARS.STACK),\n\t\tstateDir: optionalEnv(flags.stateDir, ctx.env, ENV_VARS.STATE_DIR),\n\t\tconfigPath: optionalEnv(flags.config, ctx.env, ENV_VARS.CONFIG_PATH),\n\t\tnetwork,\n\t\trenderer: flags.renderer,\n\t\tdryRun: flags.dryRun === true,\n\t\tconfirm: {\n\t\t\tassumeYes: flags.yes === true,\n\t\t\tforbidPrompt: flags.noInput === true || ctx.env[ENV_VARS.NO_INPUT] === '1',\n\t\t\tstdinIsTty: ctx.stdinIsTty,\n\t\t},\n\t\tverbose: flags.verbose === true,\n\t\trest,\n\t};\n};\n\n/**\n * Bridge the CLI `--network` flag through `process.env` so config-load-time\n * factory reads pick it up. This indirection is deliberate, not a leak.\n *\n * Why the mutation exists:\n * The `deepbook()` factory (`plugins/deepbook/index.ts`) defaults its mode\n * by reading `process.env.DEVSTACK_NETWORK` at config import time — before\n * any flag value has reached the orchestrator. To make `--network` affect\n * the same default, we must mutate the env BEFORE the user's\n * `devstack.config.ts` is loaded. The chain is:\n * `--network=<net>` flag → setNetworkEnv → `process.env.DEVSTACK_NETWORK`\n * → `deepbook()` factory's env read at import.\n *\n * Why save/restore (and a scoped finalizer) matters:\n * The CLI is also invoked from tests and embedded harnesses inside a single\n * process. An unscoped mutation leaks across invocations: a test that runs\n * `dispatch(['up','--network=testnet'])` followed by `dispatch(['up'])`\n * would see the second call inherit `testnet` from the first. The\n * finalizer restores the prior value (or deletes the key if it was unset)\n * on success, failure, AND interrupt — `Effect.addFinalizer` guarantees\n * the cleanup runs regardless of how the scope closes.\n */\nconst setNetworkEnv = (flags: GlobalFlags): Effect.Effect<void, never, Scope.Scope> => {\n\tif (flags.network === undefined) return Effect.void;\n\tconst next = flags.network;\n\treturn Effect.gen(function* () {\n\t\tconst prior = process.env[ENV_VARS.NETWORK];\n\t\tprocess.env[ENV_VARS.NETWORK] = next;\n\t\tyield* Effect.addFinalizer(() =>\n\t\t\tEffect.sync(() => {\n\t\t\t\tif (prior === undefined) {\n\t\t\t\t\tdelete process.env[ENV_VARS.NETWORK];\n\t\t\t\t} else {\n\t\t\t\t\tprocess.env[ENV_VARS.NETWORK] = prior;\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t});\n};\n\n// -----------------------------------------------------------------------------\n// Command execution helpers\n// -----------------------------------------------------------------------------\n\nconst runCommandEffect = async (\n\tctx: DevstackCliContext,\n\tcommand: string,\n\tflags: GlobalFlags,\n\teffect: Effect.Effect<CommandResult, CliError>,\n): Promise<void> => {\n\t// `setNetworkEnv` registers a `process.env[ENV_VARS.NETWORK]` restore as a\n\t// scope finalizer; the outer `Effect.scoped` closes that scope after the\n\t// command completes (success, failure, or interrupt), preventing env leaks\n\t// between concurrent CLI invocations in the same process.\n\tconst program = Effect.scoped(\n\t\tsetNetworkEnv(flags).pipe(\n\t\t\tEffect.andThen(effect),\n\t\t\tEffect.catch((error: CliError) =>\n\t\t\t\temitFailure(ctx.io, flags.outputMode, {\n\t\t\t\t\tcommand,\n\t\t\t\t\telapsedMs: 0,\n\t\t\t\t\terror,\n\t\t\t\t}).pipe(Effect.as({ exitCode: exitCodeFor(error) })),\n\t\t\t),\n\t\t\tEffect.catchCause((cause) =>\n\t\t\t\temitFailure(ctx.io, flags.outputMode, {\n\t\t\t\t\tcommand,\n\t\t\t\t\telapsedMs: 0,\n\t\t\t\t\terror: new CliInternalError({ message: 'unexpected internal failure' }),\n\t\t\t\t\tcause,\n\t\t\t\t}).pipe(Effect.as({ exitCode: ExitCode.SOFTWARE })),\n\t\t\t),\n\t\t),\n\t);\n\tconst result = await Effect.runPromise(program);\n\tif (ctx.io.lastExitCode() === null) {\n\t\tawait Effect.runPromise(ctx.io.setExitCode(result.exitCode));\n\t}\n};\n\nconst runWithFlags = async (\n\tctx: DevstackCliContext,\n\tcommand: string,\n\trawFlags: IdentityFlags & Partial<ConfigFlags & UpFlags & DestructiveFlags>,\n\trest: ReadonlyArray<string>,\n\teffect: (flags: GlobalFlags) => Effect.Effect<CommandResult, CliError>,\n): Promise<void> => {\n\tlet flags: GlobalFlags;\n\ttry {\n\t\tflags = makeGlobalFlags(ctx, rawFlags, rest);\n\t} catch (cause) {\n\t\tconst error =\n\t\t\tcause instanceof CliUsageError\n\t\t\t\t? cause\n\t\t\t\t: new CliInternalError({ message: 'failed to resolve CLI flags', cause });\n\t\tconst mode = outputModeFrom(rawFlags, ctx.env);\n\t\tawait Effect.runPromise(\n\t\t\temitFailure(ctx.io, mode, {\n\t\t\t\tcommand,\n\t\t\t\telapsedMs: 0,\n\t\t\t\terror,\n\t\t\t}),\n\t\t);\n\t\treturn;\n\t}\n\tawait runCommandEffect(ctx, command, flags, effect(flags));\n};\n\nconst requiredPositional = (placeholder: string, brief: string) =>\n\t({\n\t\tparse: textParser,\n\t\tplaceholder,\n\t\tbrief,\n\t}) as const;\n\nconst optionalPositional = (placeholder: string, brief: string) =>\n\t({\n\t\tparse: textParser,\n\t\tplaceholder,\n\t\tbrief,\n\t\toptional: true as const,\n\t}) as const;\n\n// -----------------------------------------------------------------------------\n// Commands\n// -----------------------------------------------------------------------------\n\nconst upCommand = buildCommand<UpFlags, [], DevstackCliContext>({\n\tparameters: {\n\t\tflags: {\n\t\t\t...configFlagParams,\n\t\t\trenderer: {\n\t\t\t\tkind: 'parsed',\n\t\t\t\tparse: rendererParser,\n\t\t\t\toptional: true,\n\t\t\t\tplaceholder: 'tui|plain|silent',\n\t\t\t\tbrief: 'Select the attached renderer',\n\t\t\t},\n\t\t},\n\t},\n\tdocs: {\n\t\tbrief: 'Boot a stack and stay attached until interrupted',\n\t},\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'up', flags, [], (global) => this.deps.up.run(global));\n\t},\n});\n\nconst applyCommand = buildCommand<ConfigFlags, [], DevstackCliContext>({\n\tparameters: { flags: configFlagParams },\n\tdocs: {\n\t\tbrief: 'Reconcile a live stack or run one-shot setup',\n\t},\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'apply', flags, [], (global) => this.deps.apply.run(global));\n\t},\n});\n\nconst statusCommand = buildCommand<IdentityFlags, [], DevstackCliContext>({\n\tparameters: { flags: identityFlagParams },\n\tdocs: { brief: 'Show the persisted stack projection' },\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'status', flags, [], (global) =>\n\t\t\trunStatus(this.deps.status, { flags: global, io: this.io }),\n\t\t);\n\t},\n});\n\nconst doctorCommand = buildCommand<IdentityFlags, [], DevstackCliContext>({\n\tparameters: { flags: identityFlagParams },\n\tdocs: { brief: 'Run host and stack preflight checks' },\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'doctor', flags, [], (global) =>\n\t\t\trunDoctor(this.deps.doctor, { flags: global, io: this.io }),\n\t\t);\n\t},\n});\n\nconst configCommand = buildCommand<ConfigFlags, [], DevstackCliContext>({\n\tparameters: { flags: configFlagParams },\n\tdocs: { brief: 'Print resolved config inputs' },\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'config', flags, [], (global) =>\n\t\t\trunConfig(this.deps.config, { flags: global, io: this.io }),\n\t\t);\n\t},\n});\n\nconst schemaCommand = buildCommand<Pick<IdentityFlags, 'json'>, [], DevstackCliContext>({\n\tparameters: { flags: { json: identityFlagParams.json } },\n\tdocs: { brief: 'Emit the CLI schema' },\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'schema', flags, [], (global) => {\n\t\t\tconst data = { ...commandSchema(), outputMode: global.outputMode };\n\t\t\treturn emitSuccess(this.io, global.outputMode, {\n\t\t\t\tcommand: 'schema',\n\t\t\t\telapsedMs: 0,\n\t\t\t\tdata,\n\t\t\t\thumanLines: [JSON.stringify(data, null, 2)],\n\t\t\t}).pipe(Effect.as({ exitCode: 0 }));\n\t\t});\n\t},\n});\n\nconst snapshotSaveCommand = buildCommand<\n\tSnapshotSaveFlags,\n\t[string | undefined],\n\tDevstackCliContext\n>({\n\tparameters: {\n\t\tflags: {\n\t\t\t...configFlagParams,\n\t\t\tname: stringFlag('Human-readable snapshot name', 'name'),\n\t\t},\n\t\tpositional: { kind: 'tuple', parameters: [optionalPositional('name', 'snapshot name')] },\n\t},\n\tdocs: { brief: 'Capture a snapshot' },\n\tfunc: function (flags, snapshotName) {\n\t\tconst rest = [\n\t\t\t'save',\n\t\t\t...(snapshotName === undefined ? [] : [snapshotName]),\n\t\t\t...(flags.name === undefined ? [] : ['--name', flags.name]),\n\t\t];\n\t\treturn runWithFlags(this, 'snapshot save', flags, rest, (global) =>\n\t\t\trunSnapshot(this.deps.snapshot, { flags: global, io: this.io }),\n\t\t);\n\t},\n});\n\nconst snapshotRestoreCommand = buildCommand<ConfirmFlags, [string], DevstackCliContext>({\n\tparameters: {\n\t\tflags: confirmFlagParams,\n\t\tpositional: {\n\t\t\tkind: 'tuple',\n\t\t\tparameters: [requiredPositional('name-or-id', 'snapshot name or id')],\n\t\t},\n\t},\n\tdocs: { brief: 'Restore a snapshot' },\n\tfunc: function (flags, snapshotRef) {\n\t\treturn runWithFlags(this, 'snapshot restore', flags, ['restore', snapshotRef], (global) =>\n\t\t\trunSnapshot(this.deps.snapshot, { flags: global, io: this.io }),\n\t\t);\n\t},\n});\n\nconst snapshotListCommand = buildCommand<IdentityFlags, [], DevstackCliContext>({\n\tparameters: { flags: identityFlagParams },\n\tdocs: { brief: 'List snapshots' },\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'snapshot list', flags, ['list'], (global) =>\n\t\t\trunSnapshot(this.deps.snapshot, { flags: global, io: this.io }),\n\t\t);\n\t},\n});\n\nconst snapshotDeleteCommand = buildCommand<ConfirmFlags, [string], DevstackCliContext>({\n\tparameters: {\n\t\tflags: confirmFlagParams,\n\t\tpositional: {\n\t\t\tkind: 'tuple',\n\t\t\tparameters: [requiredPositional('name-or-id', 'snapshot name or id')],\n\t\t},\n\t},\n\tdocs: { brief: 'Delete a snapshot' },\n\tfunc: function (flags, snapshotRef) {\n\t\treturn runWithFlags(this, 'snapshot delete', flags, ['delete', snapshotRef], (global) =>\n\t\t\trunSnapshot(this.deps.snapshot, { flags: global, io: this.io }),\n\t\t);\n\t},\n});\n\nconst snapshotCommands = buildRouteMap({\n\troutes: {\n\t\tsave: snapshotSaveCommand,\n\t\trestore: snapshotRestoreCommand,\n\t\tlist: snapshotListCommand,\n\t\tdelete: snapshotDeleteCommand,\n\t},\n\tdocs: { brief: 'Capture, restore, list, or delete stack snapshots' },\n});\n\nconst pruneCommand = buildCommand<PruneFlags, [], DevstackCliContext>({\n\tparameters: { flags: pruneFlagParams },\n\tdocs: { brief: 'Inventory and prune devstack-labelled Docker resources' },\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'prune', flags, [], (global) =>\n\t\t\trunPrune(\n\t\t\t\tthis.deps.prune,\n\t\t\t\t{ flags: global, io: this.io },\n\t\t\t\t{\n\t\t\t\t\tmode: flags.list === true ? 'list' : flags.all === true ? 'all' : 'auto',\n\t\t\t\t\tresources: pruneResourcesFromFlags(flags),\n\t\t\t\t},\n\t\t\t),\n\t\t);\n\t},\n});\n\nconst wipeCommand = buildCommand<DestructiveFlags, [], DevstackCliContext>({\n\tparameters: { flags: destructiveFlagParams },\n\tdocs: { brief: 'Destroy all state for the selected stack' },\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'wipe', flags, [], (global) =>\n\t\t\trunWipe(this.deps.wipe, { flags: global, io: this.io }),\n\t\t);\n\t},\n});\n\nconst root = buildRouteMap({\n\troutes: {\n\t\tup: upCommand,\n\t\tapply: applyCommand,\n\t\tstatus: statusCommand,\n\t\tdoctor: doctorCommand,\n\t\tconfig: configCommand,\n\t\tschema: schemaCommand,\n\t\tsnapshot: snapshotCommands,\n\t\tprune: pruneCommand,\n\t\twipe: wipeCommand,\n\t},\n\tdocs: {\n\t\tbrief: 'Sui development stack CLI',\n\t},\n});\n\nconst app = buildApplication(root, {\n\tname: 'devstack',\n\tversionInfo: { currentVersion: readPackageVersion() },\n\tscanner: { caseStyle: 'allow-kebab-for-camel' },\n\tdocumentation: {\n\t\tcaseStyle: 'convert-camel-to-kebab',\n\t\tdisableAnsiColor: true,\n\t\tonlyRequiredInUsageLine: true,\n\t},\n\tlocalization: {\n\t\tloadText: () => ({\n\t\t\t...text_en,\n\t\t\texceptionWhileParsingArguments: (error) =>\n\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t}),\n\t},\n});\n\nconst jsonRequested = (\n\targv: ReadonlyArray<string>,\n\tenv: Readonly<Record<string, string | undefined>>,\n): boolean => env[ENV_VARS.JSON] === '1' || argv.includes('--json');\n\n/**\n * Project a `BufferedProcess.exitCode` to a sysexit code AT THE\n * STRICLI-PARSE BOUNDARY ONLY.\n *\n * Contract: `BufferedProcess.exitCode` is mutated ONLY by Stricli's\n * argv-parser when an argv parse step fails (unknown subcommand,\n * malformed flag value, missing required positional). Verbs route\n * their own outcomes through `ctx.io.setExitCode`, which marks\n * `io.touched()` and short-circuits this projection in `dispatch`\n * before `flushBufferedProcess` is reached.\n *\n * The historic implementation collapsed ANY non-zero `code` to\n * `USAGE` (64), but that was wrong: it could only ever observe a\n * Stricli parse failure (the only writer to this field), so the\n * `USAGE` mapping holds by construction. Kept as a named function\n * so the invariant is documented at the call site.\n */\nconst normalizeStricliExitCode = (code: number | string | null | undefined): number => {\n\tif (typeof code === 'number' && code !== 0) return ExitCode.USAGE;\n\treturn ExitCode.OK;\n};\n\n/**\n * Bridge Stricli's synchronous `StricliProcess.{stdout,stderr}.write`\n * shape to our async (Effect-based) `CliIO` surface.\n *\n * The indirection is load-bearing for the JSON-envelope contract:\n * Stricli writes argv-parse errors to stderr the moment the parser\n * trips, but `--json` mode demands the failure be EMITTED as a\n * structured envelope on stdout (not raw text on stderr) with exit\n * code `EX_USAGE`. We can't wire Stricli's `stderr.write` directly to\n * `nodeProcessIO.writeStderr` because:\n *\n * 1. The stderr bytes are the raw parser error text; in `--json`\n * mode we need to transform them into a failure envelope.\n * 2. We don't know whether the verb handler \"touched\" the IO\n * (rendered its own envelope) until after Stricli returns.\n *\n * Buffering lets us delay the decision until both signals are\n * available. Tests substitute a `BufferedProcess` whose buffers are\n * later inspected, mirroring the prod flush behavior.\n */\nconst flushBufferedProcess = (\n\tprocess: BufferedProcess,\n\tio: CliIO,\n\targv: ReadonlyArray<string>,\n\tenv: Readonly<Record<string, string | undefined>>,\n): Effect.Effect<void> =>\n\tEffect.gen(function* () {\n\t\tconst exitCode = normalizeStricliExitCode(process.exitCode);\n\t\tconst stdout = process.stdoutBuffer.join('');\n\t\tconst stderr = process.stderrBuffer.join('').trim();\n\t\tif (exitCode !== 0 && jsonRequested(argv, env)) {\n\t\t\tyield* emitFailure(io, 'json', {\n\t\t\t\tcommand: '(parse)',\n\t\t\t\telapsedMs: 0,\n\t\t\t\terror: new CliUsageError({\n\t\t\t\t\tmessage: stderr.length > 0 ? stderr : 'invalid command line',\n\t\t\t\t}),\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (stdout.length > 0)\n\t\t\tyield* io.writeStdout(stdout.endsWith('\\n') ? stdout.slice(0, -1) : stdout);\n\t\tif (stderr.length > 0) yield* io.writeStderr(stderr);\n\t\tyield* io.setExitCode(exitCode);\n\t});\n\nexport const dispatch = (deps: CliDeps, dispatchEnv: DispatchEnv): Effect.Effect<void> =>\n\tEffect.gen(function* () {\n\t\tconst io = trackIO(dispatchEnv.io ?? nodeProcessIO);\n\t\tconst process = makeBufferedProcess(dispatchEnv.env);\n\t\tconst ctx: DevstackCliContext = {\n\t\t\tprocess,\n\t\t\tdeps,\n\t\t\tenv: dispatchEnv.env,\n\t\t\tstdinIsTty: dispatchEnv.stdinIsTty,\n\t\t\tio,\n\t\t};\n\t\tyield* Effect.tryPromise({\n\t\t\ttry: () => runStricli(app, dispatchEnv.argv, ctx),\n\t\t\tcatch: (cause) => new CliInternalError({ message: 'CLI dispatcher failed', cause }),\n\t\t}).pipe(\n\t\t\tEffect.catch((error: CliError) =>\n\t\t\t\temitFailure(io, jsonRequested(dispatchEnv.argv, dispatchEnv.env) ? 'json' : 'human', {\n\t\t\t\t\tcommand: '(dispatch)',\n\t\t\t\t\telapsedMs: 0,\n\t\t\t\t\terror,\n\t\t\t\t}),\n\t\t\t),\n\t\t);\n\t\tif (!io.touched()) {\n\t\t\tyield* flushBufferedProcess(process, io, dispatchEnv.argv, dispatchEnv.env);\n\t\t}\n\t});\n\n// -----------------------------------------------------------------------------\n// Re-exports\n// -----------------------------------------------------------------------------\n\nexport type { CliIO } from './output.ts';\nexport type { GlobalFlags } from './flags.ts';\nexport { COMMAND_TREE, commandSchema, VERBS, type Verb } from './command-tree.ts';\nexport type { Envelope, EnvelopeError } from './envelope.ts';\nexport {\n\tENVELOPE_SCHEMA_VERSION,\n\tfailureEnvelope,\n\tstreamingEvent,\n\tsuccessEnvelope,\n\ttype StreamingEvent,\n} from './envelope.ts';\nexport { ExitCode, exitCodeName } from './sysexits.ts';\nexport {\n\ttype CliError,\n\tCliAlreadyReportedError,\n\tCliConfigInvalidError,\n\tCliConfigNotFoundError,\n\tCliConfirmDeclinedError,\n\tCliConfirmRequiredError,\n\tCliInternalError,\n\tCliSnapshotNotFoundError,\n\tCliSupervisorLiveError,\n\tCliUnavailableError,\n\tCliUsageError,\n} from './errors.ts';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["runStricli"],"sources":["../../../src/surfaces/cli/index.ts"],"sourcesContent":["// CLI surface — top-level entry point.\n//\n// The public CLI is intentionally small: `up` is the attached operator\n// surface, `apply` is live-aware reconcile (publish to `up` when it is\n// running, one-shot otherwise), and every other command is offline/direct.\n\nimport {\n\tbuildApplication,\n\tbuildChoiceParser,\n\tbuildCommand,\n\tbuildRouteMap,\n\trun as runStricli,\n\ttext_en,\n\ttype CommandContext as StricliCommandContext,\n\ttype StricliProcess,\n} from '@stricli/core';\nimport { Effect, type Scope } from 'effect';\n\nimport { commandSchema } from './command-tree.ts';\nimport { type CliError, CliInternalError, CliUsageError, exitCodeFor } from './errors.ts';\nimport {\n\ttype CliRendererMode,\n\tENV_VARS,\n\ttype GlobalFlags,\n\ttype OutputMode,\n\ttype SnapshotStalePolicy,\n} from './flags.ts';\nimport { ExitCode } from './sysexits.ts';\nimport { parseDevstackNetworkName } from '../../api/inference-network.ts';\nimport { type CliIO, emitFailure, emitSuccess, nodeProcessIO } from './output.ts';\nimport {\n\ttype CommandResult,\n\ttype ConfigDeps,\n\ttype DoctorDeps,\n\ttype PruneDeps,\n\ttype PruneResourceScope,\n\ttype SnapshotDeps,\n\ttype StatusDeps,\n\ttype WipeDeps,\n\trunConfig,\n\trunDoctor,\n\trunPrune,\n\trunSnapshot,\n\trunStatus,\n\trunWipe,\n} from './commands/index.ts';\nimport { readDevstackVersion } from '../../cli/wirings/read-devstack-version.ts';\n\n// -----------------------------------------------------------------------------\n// Deps bundle\n// -----------------------------------------------------------------------------\n\nexport interface LifecycleCommandDeps {\n\treadonly run: (flags: GlobalFlags) => Effect.Effect<CommandResult, CliError>;\n}\n\n/** The stack-free `codegen` verb takes only a config path — it boots no\n * stack, so it needs no renderer/snapshot/identity flags. */\nexport interface CodegenCommandDeps {\n\treadonly run: (flags: {\n\t\treadonly configPath: string | undefined;\n\t}) => Effect.Effect<CommandResult, CliError>;\n}\n\n/** `dump-ids` emits the stack's `devstack-ids.json` id-config. It owns\n * its own output (file via `--out`, else stdout), so it receives `io`\n * and the resolved `outputMode` alongside the config path + destination. */\nexport interface DumpIdsCommandDeps {\n\treadonly run: (flags: {\n\t\treadonly configPath: string | undefined;\n\t\treadonly out: string | undefined;\n\t\treadonly io: CliIO;\n\t\treadonly outputMode: OutputMode;\n\t}) => Effect.Effect<CommandResult, CliError>;\n}\n\nexport interface CliDeps {\n\treadonly up: LifecycleCommandDeps;\n\treadonly apply: LifecycleCommandDeps;\n\treadonly codegen: CodegenCommandDeps;\n\treadonly dumpIds: DumpIdsCommandDeps;\n\treadonly status: StatusDeps;\n\treadonly snapshot: SnapshotDeps;\n\treadonly prune: PruneDeps;\n\treadonly doctor: DoctorDeps;\n\treadonly config: ConfigDeps;\n\treadonly wipe: WipeDeps;\n}\n\nexport interface DispatchEnv {\n\treadonly argv: ReadonlyArray<string>;\n\treadonly env: Readonly<Record<string, string | undefined>>;\n\treadonly stdinIsTty: boolean;\n\treadonly io?: CliIO;\n}\n\n// -----------------------------------------------------------------------------\n// Stricli context + buffered process\n// -----------------------------------------------------------------------------\n\ninterface BufferedProcess extends StricliProcess {\n\treadonly stdoutBuffer: Array<string>;\n\treadonly stderrBuffer: Array<string>;\n\texitCode?: number | string | null;\n}\n\ninterface TrackedIO extends CliIO {\n\treadonly touched: () => boolean;\n\treadonly lastExitCode: () => number | null;\n}\n\ninterface DevstackCliContext extends StricliCommandContext {\n\treadonly deps: CliDeps;\n\treadonly env: Readonly<Record<string, string | undefined>>;\n\treadonly stdinIsTty: boolean;\n\treadonly io: TrackedIO;\n\treadonly process: BufferedProcess;\n}\n\nconst makeBufferedProcess = (\n\tenv: Readonly<Record<string, string | undefined>>,\n): BufferedProcess => {\n\tconst stdoutBuffer: Array<string> = [];\n\tconst stderrBuffer: Array<string> = [];\n\treturn {\n\t\tstdoutBuffer,\n\t\tstderrBuffer,\n\t\tenv,\n\t\tstdout: {\n\t\t\twrite: (str) => {\n\t\t\t\tstdoutBuffer.push(str);\n\t\t\t},\n\t\t},\n\t\tstderr: {\n\t\t\twrite: (str) => {\n\t\t\t\tstderrBuffer.push(str);\n\t\t\t},\n\t\t},\n\t};\n};\n\nconst trackIO = (io: CliIO): TrackedIO => {\n\tlet touched = false;\n\tlet lastExitCode: number | null = null;\n\treturn {\n\t\ttouched: () => touched,\n\t\tlastExitCode: () => lastExitCode,\n\t\twriteStdout: (line) =>\n\t\t\tio.writeStdout(line).pipe(\n\t\t\t\tEffect.tap(() =>\n\t\t\t\t\tEffect.sync(() => {\n\t\t\t\t\t\ttouched = true;\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t\twriteStderr: (line) =>\n\t\t\tio.writeStderr(line).pipe(\n\t\t\t\tEffect.tap(() =>\n\t\t\t\t\tEffect.sync(() => {\n\t\t\t\t\t\ttouched = true;\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t\tsetExitCode: (code) =>\n\t\t\tio.setExitCode(code).pipe(\n\t\t\t\tEffect.tap(() =>\n\t\t\t\t\tEffect.sync(() => {\n\t\t\t\t\t\ttouched = true;\n\t\t\t\t\t\tlastExitCode = code;\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t};\n};\n\n// -----------------------------------------------------------------------------\n// Flag models\n// -----------------------------------------------------------------------------\n\ninterface IdentityFlags {\n\treadonly json?: boolean;\n\treadonly app?: string;\n\treadonly stack?: string;\n\treadonly stateDir?: string;\n\treadonly verbose?: boolean;\n}\n\ninterface ConfigFlags extends IdentityFlags {\n\treadonly config?: string;\n\treadonly network?: string;\n}\n\ninterface UpFlags extends ConfigFlags {\n\treadonly renderer?: CliRendererMode;\n\treadonly fromSnapshot?: string;\n\treadonly snapshotCache?: string;\n\treadonly snapshotStale?: SnapshotStalePolicy;\n}\n\ninterface DumpIdsFlags extends ConfigFlags {\n\treadonly out?: string;\n}\n\ninterface DestructiveFlags extends IdentityFlags {\n\treadonly dryRun?: boolean;\n\treadonly yes?: boolean;\n\treadonly noInput?: boolean;\n}\n\ninterface ConfirmFlags extends IdentityFlags {\n\treadonly yes?: boolean;\n\treadonly noInput?: boolean;\n}\n\ninterface PruneFlags {\n\treadonly json?: boolean;\n\treadonly stateDir?: string;\n\treadonly verbose?: boolean;\n\treadonly dryRun?: boolean;\n\treadonly yes?: boolean;\n\treadonly noInput?: boolean;\n\treadonly list?: boolean;\n\treadonly all?: boolean;\n\treadonly noContainers?: boolean;\n\treadonly noNetworks?: boolean;\n\treadonly noVolumes?: boolean;\n\treadonly includeImages?: boolean;\n}\n\ninterface SnapshotSaveFlags extends ConfigFlags {\n\treadonly name?: string;\n}\n\nconst textParser = (input: string): string => input;\n\nconst stringFlag = (brief: string, placeholder: string) =>\n\t({\n\t\tkind: 'parsed',\n\t\tparse: textParser,\n\t\toptional: true,\n\t\tplaceholder,\n\t\tbrief,\n\t}) as const;\n\nconst boolFlag = (brief: string) =>\n\t({\n\t\tkind: 'boolean',\n\t\toptional: true,\n\t\tbrief,\n\t}) as const;\n\nconst identityFlagParams = {\n\tjson: boolFlag('Emit JSON envelope output'),\n\tapp: stringFlag('Override app name', 'name'),\n\tstack: stringFlag('Override stack name', 'name'),\n\tstateDir: stringFlag('Override state directory', 'path'),\n\tverbose: boolFlag('Enable more verbose logging'),\n} as const;\n\nconst configFlagParams = {\n\t...identityFlagParams,\n\tconfig: stringFlag('Override devstack.config.ts path', 'path'),\n\tnetwork: stringFlag('Override network before config import', 'name'),\n} as const;\n\nconst destructiveFlagParams = {\n\t...identityFlagParams,\n\tdryRun: boolFlag('Skip mutating effects'),\n\tyes: boolFlag('Assume yes on prompts'),\n\tnoInput: boolFlag('Forbid prompts'),\n} as const;\n\nconst globalMaintenanceFlagParams = {\n\tjson: identityFlagParams.json,\n\tstateDir: identityFlagParams.stateDir,\n\tverbose: identityFlagParams.verbose,\n} as const;\n\nconst confirmFlagParams = {\n\t...identityFlagParams,\n\tyes: boolFlag('Assume yes on prompts'),\n\tnoInput: boolFlag('Forbid prompts'),\n} as const;\n\nconst pruneFlagParams = {\n\t...globalMaintenanceFlagParams,\n\tdryRun: destructiveFlagParams.dryRun,\n\tyes: destructiveFlagParams.yes,\n\tnoInput: destructiveFlagParams.noInput,\n\tlist: boolFlag('List devstack-labelled Docker resources without pruning'),\n\tall: boolFlag('Prune every idle non-shared resource group'),\n\tnoContainers: boolFlag('Do not remove containers'),\n\tnoNetworks: boolFlag('Do not remove networks'),\n\tnoVolumes: boolFlag('Do not remove volumes'),\n\tincludeImages: boolFlag('Also remove devstack-labelled images for selected groups'),\n} as const;\n\nconst rendererParser = buildChoiceParser(['tui', 'plain', 'silent'] as const);\nconst snapshotStaleParser = buildChoiceParser(['warn', 'block', 'clean-start'] as const);\n\nconst outputModeFrom = (\n\tflags: Pick<IdentityFlags, 'json'>,\n\tenv: Readonly<Record<string, string | undefined>>,\n): OutputMode => (flags.json === true || env[ENV_VARS.JSON] === '1' ? 'json' : 'human');\n\nconst pruneResourcesFromFlags = (flags: PruneFlags): PruneResourceScope => ({\n\tcontainers: flags.noContainers !== true,\n\tnetworks: flags.noNetworks !== true,\n\tvolumes: flags.noVolumes !== true,\n\timages: flags.includeImages === true,\n});\n\nconst optionalEnv = (\n\tvalue: string | undefined,\n\tenv: Readonly<Record<string, string | undefined>>,\n\tkey: string,\n): string | undefined => value ?? env[key];\n\nconst makeGlobalFlags = (\n\tctx: DevstackCliContext,\n\tflags: IdentityFlags & Partial<ConfigFlags & UpFlags & DestructiveFlags>,\n\trest: ReadonlyArray<string>,\n): GlobalFlags => {\n\tconst networkRaw = optionalEnv(flags.network, ctx.env, ENV_VARS.NETWORK);\n\tlet network: string | undefined;\n\tif (networkRaw !== undefined) {\n\t\ttry {\n\t\t\tnetwork = parseDevstackNetworkName(\n\t\t\t\tnetworkRaw,\n\t\t\t\tflags.network === undefined ? ENV_VARS.NETWORK : '--network',\n\t\t\t);\n\t\t} catch (cause) {\n\t\t\tthrow cause instanceof Error\n\t\t\t\t? new CliUsageError({ message: cause.message })\n\t\t\t\t: new CliInternalError({ message: 'failed to parse network flag', cause });\n\t\t}\n\t}\n\treturn {\n\t\toutputMode: outputModeFrom(flags, ctx.env),\n\t\tapp: optionalEnv(flags.app, ctx.env, ENV_VARS.APP),\n\t\tstack: optionalEnv(flags.stack, ctx.env, ENV_VARS.STACK),\n\t\tstateDir: optionalEnv(flags.stateDir, ctx.env, ENV_VARS.STATE_DIR),\n\t\tconfigPath: optionalEnv(flags.config, ctx.env, ENV_VARS.CONFIG_PATH),\n\t\tnetwork,\n\t\trenderer: flags.renderer,\n\t\tfromSnapshot: flags.fromSnapshot,\n\t\tsnapshotCache: flags.snapshotCache,\n\t\tsnapshotStalePolicy: flags.snapshotStale,\n\t\tdryRun: flags.dryRun === true,\n\t\tconfirm: {\n\t\t\tassumeYes: flags.yes === true,\n\t\t\tforbidPrompt: flags.noInput === true || ctx.env[ENV_VARS.NO_INPUT] === '1',\n\t\t\tstdinIsTty: ctx.stdinIsTty,\n\t\t},\n\t\tverbose: flags.verbose === true,\n\t\trest,\n\t};\n};\n\n/**\n * Bridge the CLI `--network` flag through `process.env` so config-load-time\n * factory reads pick it up. This indirection is deliberate, not a leak.\n *\n * Why the mutation exists:\n * The `deepbook()` factory (`plugins/deepbook/index.ts`) defaults its mode\n * by reading `process.env.DEVSTACK_NETWORK` at config import time — before\n * any flag value has reached the orchestrator. To make `--network` affect\n * the same default, we must mutate the env BEFORE the user's\n * `devstack.config.ts` is loaded. The chain is:\n * `--network=<net>` flag → setNetworkEnv → `process.env.DEVSTACK_NETWORK`\n * → `deepbook()` factory's env read at import.\n *\n * Why save/restore (and a scoped finalizer) matters:\n * The CLI is also invoked from tests and embedded harnesses inside a single\n * process. An unscoped mutation leaks across invocations: a test that runs\n * `dispatch(['up','--network=testnet'])` followed by `dispatch(['up'])`\n * would see the second call inherit `testnet` from the first. The\n * finalizer restores the prior value (or deletes the key if it was unset)\n * on success, failure, AND interrupt — `Effect.addFinalizer` guarantees\n * the cleanup runs regardless of how the scope closes.\n */\nconst setNetworkEnv = (flags: GlobalFlags): Effect.Effect<void, never, Scope.Scope> => {\n\tif (flags.network === undefined) return Effect.void;\n\tconst next = flags.network;\n\treturn Effect.gen(function* () {\n\t\tconst prior = process.env[ENV_VARS.NETWORK];\n\t\tprocess.env[ENV_VARS.NETWORK] = next;\n\t\tyield* Effect.addFinalizer(() =>\n\t\t\tEffect.sync(() => {\n\t\t\t\tif (prior === undefined) {\n\t\t\t\t\tdelete process.env[ENV_VARS.NETWORK];\n\t\t\t\t} else {\n\t\t\t\t\tprocess.env[ENV_VARS.NETWORK] = prior;\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t});\n};\n\n// -----------------------------------------------------------------------------\n// Command execution helpers\n// -----------------------------------------------------------------------------\n\nconst runCommandEffect = async (\n\tctx: DevstackCliContext,\n\tcommand: string,\n\tflags: GlobalFlags,\n\teffect: Effect.Effect<CommandResult, CliError>,\n): Promise<void> => {\n\t// `setNetworkEnv` registers a `process.env[ENV_VARS.NETWORK]` restore as a\n\t// scope finalizer; the outer `Effect.scoped` closes that scope after the\n\t// command completes (success, failure, or interrupt), preventing env leaks\n\t// between concurrent CLI invocations in the same process.\n\tconst program = Effect.scoped(\n\t\tsetNetworkEnv(flags).pipe(\n\t\t\tEffect.andThen(effect),\n\t\t\tEffect.catch((error: CliError) =>\n\t\t\t\temitFailure(ctx.io, flags.outputMode, {\n\t\t\t\t\tcommand,\n\t\t\t\t\telapsedMs: 0,\n\t\t\t\t\terror,\n\t\t\t\t}).pipe(Effect.as({ exitCode: exitCodeFor(error) })),\n\t\t\t),\n\t\t\tEffect.catchCause((cause) =>\n\t\t\t\temitFailure(ctx.io, flags.outputMode, {\n\t\t\t\t\tcommand,\n\t\t\t\t\telapsedMs: 0,\n\t\t\t\t\terror: new CliInternalError({ message: 'unexpected internal failure' }),\n\t\t\t\t\tcause,\n\t\t\t\t}).pipe(Effect.as({ exitCode: ExitCode.SOFTWARE })),\n\t\t\t),\n\t\t),\n\t);\n\tconst result = await Effect.runPromise(program);\n\tif (ctx.io.lastExitCode() === null) {\n\t\tawait Effect.runPromise(ctx.io.setExitCode(result.exitCode));\n\t}\n};\n\nconst runWithFlags = async (\n\tctx: DevstackCliContext,\n\tcommand: string,\n\trawFlags: IdentityFlags & Partial<ConfigFlags & UpFlags & DestructiveFlags>,\n\trest: ReadonlyArray<string>,\n\teffect: (flags: GlobalFlags) => Effect.Effect<CommandResult, CliError>,\n): Promise<void> => {\n\tlet flags: GlobalFlags;\n\ttry {\n\t\tflags = makeGlobalFlags(ctx, rawFlags, rest);\n\t} catch (cause) {\n\t\tconst error =\n\t\t\tcause instanceof CliUsageError\n\t\t\t\t? cause\n\t\t\t\t: new CliInternalError({ message: 'failed to resolve CLI flags', cause });\n\t\tconst mode = outputModeFrom(rawFlags, ctx.env);\n\t\tawait Effect.runPromise(\n\t\t\temitFailure(ctx.io, mode, {\n\t\t\t\tcommand,\n\t\t\t\telapsedMs: 0,\n\t\t\t\terror,\n\t\t\t}),\n\t\t);\n\t\treturn;\n\t}\n\tawait runCommandEffect(ctx, command, flags, effect(flags));\n};\n\nconst requiredPositional = (placeholder: string, brief: string) =>\n\t({\n\t\tparse: textParser,\n\t\tplaceholder,\n\t\tbrief,\n\t}) as const;\n\nconst optionalPositional = (placeholder: string, brief: string) =>\n\t({\n\t\tparse: textParser,\n\t\tplaceholder,\n\t\tbrief,\n\t\toptional: true as const,\n\t}) as const;\n\n// -----------------------------------------------------------------------------\n// Commands\n// -----------------------------------------------------------------------------\n\nconst upCommand = buildCommand<UpFlags, [], DevstackCliContext>({\n\tparameters: {\n\t\tflags: {\n\t\t\t...configFlagParams,\n\t\t\trenderer: {\n\t\t\t\tkind: 'parsed',\n\t\t\t\tparse: rendererParser,\n\t\t\t\toptional: true,\n\t\t\t\tplaceholder: 'tui|plain|silent',\n\t\t\t\tbrief: 'Select the attached renderer',\n\t\t\t},\n\t\t\tfromSnapshot: stringFlag('Start by restoring a named snapshot before acquire', 'name-or-id'),\n\t\t\tsnapshotCache: stringFlag(\n\t\t\t\t'Use a named snapshot as a startup cache and refresh it when stale',\n\t\t\t\t'name',\n\t\t\t),\n\t\t\tsnapshotStale: {\n\t\t\t\tkind: 'parsed',\n\t\t\t\tparse: snapshotStaleParser,\n\t\t\t\toptional: true,\n\t\t\t\tplaceholder: 'warn|block|clean-start',\n\t\t\t\tbrief: 'Policy when --from-snapshot inputs differ from the current stack',\n\t\t\t},\n\t\t},\n\t},\n\tdocs: {\n\t\tbrief: 'Boot a stack and stay attached until interrupted',\n\t},\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'up', flags, [], (global) => this.deps.up.run(global));\n\t},\n});\n\nconst applyCommand = buildCommand<ConfigFlags, [], DevstackCliContext>({\n\tparameters: { flags: configFlagParams },\n\tdocs: {\n\t\tbrief: 'Reconcile a live stack or run one-shot setup',\n\t},\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'apply', flags, [], (global) => this.deps.apply.run(global));\n\t},\n});\n\nconst codegenCommand = buildCommand<ConfigFlags, [], DevstackCliContext>({\n\tparameters: { flags: configFlagParams },\n\tdocs: {\n\t\tbrief: 'Regenerate committed bindings from Move source (no stack boot)',\n\t},\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'codegen', flags, [], (global) =>\n\t\t\tthis.deps.codegen.run({ configPath: global.configPath }),\n\t\t);\n\t},\n});\n\nconst dumpIdsCommand = buildCommand<DumpIdsFlags, [], DevstackCliContext>({\n\tparameters: {\n\t\tflags: {\n\t\t\t...configFlagParams,\n\t\t\tout: stringFlag('Write the id-config JSON to this file instead of stdout', 'path'),\n\t\t},\n\t},\n\tdocs: {\n\t\tbrief: 'Emit the stack id-config (devstack-ids.json) for a real-network deploy',\n\t},\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'dump-ids', flags, [], (global) =>\n\t\t\tthis.deps.dumpIds.run({\n\t\t\t\tconfigPath: global.configPath,\n\t\t\t\tout: flags.out,\n\t\t\t\tio: this.io,\n\t\t\t\toutputMode: global.outputMode,\n\t\t\t}),\n\t\t);\n\t},\n});\n\nconst statusCommand = buildCommand<IdentityFlags, [], DevstackCliContext>({\n\tparameters: { flags: identityFlagParams },\n\tdocs: { brief: 'Show the current stack projection (offline: from the manifest)' },\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'status', flags, [], (global) =>\n\t\t\trunStatus(this.deps.status, { flags: global, io: this.io }),\n\t\t);\n\t},\n});\n\nconst doctorCommand = buildCommand<IdentityFlags, [], DevstackCliContext>({\n\tparameters: { flags: identityFlagParams },\n\tdocs: { brief: 'Run host and stack preflight checks' },\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'doctor', flags, [], (global) =>\n\t\t\trunDoctor(this.deps.doctor, { flags: global, io: this.io }),\n\t\t);\n\t},\n});\n\nconst configCommand = buildCommand<ConfigFlags, [], DevstackCliContext>({\n\tparameters: { flags: configFlagParams },\n\tdocs: { brief: 'Print resolved config inputs' },\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'config', flags, [], (global) =>\n\t\t\trunConfig(this.deps.config, { flags: global, io: this.io }),\n\t\t);\n\t},\n});\n\nconst schemaCommand = buildCommand<Pick<IdentityFlags, 'json'>, [], DevstackCliContext>({\n\tparameters: { flags: { json: identityFlagParams.json } },\n\tdocs: { brief: 'Emit the CLI schema' },\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'schema', flags, [], (global) => {\n\t\t\tconst data = { ...commandSchema(), outputMode: global.outputMode };\n\t\t\treturn emitSuccess(this.io, global.outputMode, {\n\t\t\t\tcommand: 'schema',\n\t\t\t\telapsedMs: 0,\n\t\t\t\tdata,\n\t\t\t\thumanLines: [JSON.stringify(data, null, 2)],\n\t\t\t}).pipe(Effect.as({ exitCode: 0 }));\n\t\t});\n\t},\n});\n\nconst snapshotSaveCommand = buildCommand<\n\tSnapshotSaveFlags,\n\t[string | undefined],\n\tDevstackCliContext\n>({\n\tparameters: {\n\t\tflags: {\n\t\t\t...configFlagParams,\n\t\t\tname: stringFlag('Human-readable snapshot name', 'name'),\n\t\t},\n\t\tpositional: { kind: 'tuple', parameters: [optionalPositional('name', 'snapshot name')] },\n\t},\n\tdocs: { brief: 'Capture a snapshot' },\n\tfunc: function (flags, snapshotName) {\n\t\tconst rest = [\n\t\t\t'save',\n\t\t\t...(snapshotName === undefined ? [] : [snapshotName]),\n\t\t\t...(flags.name === undefined ? [] : ['--name', flags.name]),\n\t\t];\n\t\treturn runWithFlags(this, 'snapshot save', flags, rest, (global) =>\n\t\t\trunSnapshot(this.deps.snapshot, { flags: global, io: this.io }),\n\t\t);\n\t},\n});\n\nconst snapshotRestoreCommand = buildCommand<ConfirmFlags, [string], DevstackCliContext>({\n\tparameters: {\n\t\tflags: confirmFlagParams,\n\t\tpositional: {\n\t\t\tkind: 'tuple',\n\t\t\tparameters: [requiredPositional('name-or-id', 'snapshot name or id')],\n\t\t},\n\t},\n\tdocs: { brief: 'Restore a snapshot' },\n\tfunc: function (flags, snapshotRef) {\n\t\treturn runWithFlags(this, 'snapshot restore', flags, ['restore', snapshotRef], (global) =>\n\t\t\trunSnapshot(this.deps.snapshot, { flags: global, io: this.io }),\n\t\t);\n\t},\n});\n\nconst snapshotListCommand = buildCommand<IdentityFlags, [], DevstackCliContext>({\n\tparameters: { flags: identityFlagParams },\n\tdocs: { brief: 'List snapshots' },\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'snapshot list', flags, ['list'], (global) =>\n\t\t\trunSnapshot(this.deps.snapshot, { flags: global, io: this.io }),\n\t\t);\n\t},\n});\n\nconst snapshotDeleteCommand = buildCommand<ConfirmFlags, [string], DevstackCliContext>({\n\tparameters: {\n\t\tflags: confirmFlagParams,\n\t\tpositional: {\n\t\t\tkind: 'tuple',\n\t\t\tparameters: [requiredPositional('name-or-id', 'snapshot name or id')],\n\t\t},\n\t},\n\tdocs: { brief: 'Delete a snapshot' },\n\tfunc: function (flags, snapshotRef) {\n\t\treturn runWithFlags(this, 'snapshot delete', flags, ['delete', snapshotRef], (global) =>\n\t\t\trunSnapshot(this.deps.snapshot, { flags: global, io: this.io }),\n\t\t);\n\t},\n});\n\nconst snapshotCommands = buildRouteMap({\n\troutes: {\n\t\tsave: snapshotSaveCommand,\n\t\trestore: snapshotRestoreCommand,\n\t\tlist: snapshotListCommand,\n\t\tdelete: snapshotDeleteCommand,\n\t},\n\tdocs: { brief: 'Capture, restore, list, or delete stack snapshots' },\n});\n\nconst pruneCommand = buildCommand<PruneFlags, [], DevstackCliContext>({\n\tparameters: { flags: pruneFlagParams },\n\tdocs: { brief: 'Inventory and prune devstack-labelled Docker resources' },\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'prune', flags, [], (global) =>\n\t\t\trunPrune(\n\t\t\t\tthis.deps.prune,\n\t\t\t\t{ flags: global, io: this.io },\n\t\t\t\t{\n\t\t\t\t\tmode: flags.list === true ? 'list' : flags.all === true ? 'all' : 'auto',\n\t\t\t\t\tresources: pruneResourcesFromFlags(flags),\n\t\t\t\t},\n\t\t\t),\n\t\t);\n\t},\n});\n\nconst wipeCommand = buildCommand<DestructiveFlags, [], DevstackCliContext>({\n\tparameters: { flags: destructiveFlagParams },\n\tdocs: { brief: 'Destroy all state for the selected stack' },\n\tfunc: function (flags) {\n\t\treturn runWithFlags(this, 'wipe', flags, [], (global) =>\n\t\t\trunWipe(this.deps.wipe, { flags: global, io: this.io }),\n\t\t);\n\t},\n});\n\nconst root = buildRouteMap({\n\troutes: {\n\t\tup: upCommand,\n\t\tapply: applyCommand,\n\t\tcodegen: codegenCommand,\n\t\tdumpIds: dumpIdsCommand,\n\t\tstatus: statusCommand,\n\t\tdoctor: doctorCommand,\n\t\tconfig: configCommand,\n\t\tschema: schemaCommand,\n\t\tsnapshot: snapshotCommands,\n\t\tprune: pruneCommand,\n\t\twipe: wipeCommand,\n\t},\n\tdocs: {\n\t\tbrief: 'Sui development stack CLI',\n\t},\n});\n\nconst app = buildApplication(root, {\n\tname: 'devstack',\n\tversionInfo: { currentVersion: readDevstackVersion() },\n\tscanner: { caseStyle: 'allow-kebab-for-camel' },\n\tdocumentation: {\n\t\tcaseStyle: 'convert-camel-to-kebab',\n\t\tdisableAnsiColor: true,\n\t\tonlyRequiredInUsageLine: true,\n\t},\n\tlocalization: {\n\t\tloadText: () => ({\n\t\t\t...text_en,\n\t\t\texceptionWhileParsingArguments: (error) =>\n\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t}),\n\t},\n});\n\nconst jsonRequested = (\n\targv: ReadonlyArray<string>,\n\tenv: Readonly<Record<string, string | undefined>>,\n): boolean => env[ENV_VARS.JSON] === '1' || argv.includes('--json');\n\n/**\n * Project a `BufferedProcess.exitCode` to a sysexit code AT THE\n * STRICLI-PARSE BOUNDARY ONLY.\n *\n * Contract: `BufferedProcess.exitCode` is mutated ONLY by Stricli's\n * argv-parser when an argv parse step fails (unknown subcommand,\n * malformed flag value, missing required positional). Verbs route\n * their own outcomes through `ctx.io.setExitCode`, which marks\n * `io.touched()` and short-circuits this projection in `dispatch`\n * before `flushBufferedProcess` is reached.\n *\n * A non-zero value here means Stricli rejected argv before any verb\n * ran, so mapping to `USAGE` holds by construction. Kept as a named\n * function so the invariant is documented at the call site.\n */\nconst normalizeStricliExitCode = (code: number | string | null | undefined): number => {\n\tif (typeof code === 'number' && code !== 0) return ExitCode.USAGE;\n\treturn ExitCode.OK;\n};\n\n/**\n * Bridge Stricli's synchronous `StricliProcess.{stdout,stderr}.write`\n * shape to our async (Effect-based) `CliIO` surface.\n *\n * The indirection is load-bearing for the JSON-envelope contract:\n * Stricli writes argv-parse errors to stderr the moment the parser\n * trips, but `--json` mode demands the failure be EMITTED as a\n * structured envelope on stdout (not raw text on stderr) with exit\n * code `EX_USAGE`. We can't wire Stricli's `stderr.write` directly to\n * `nodeProcessIO.writeStderr` because:\n *\n * 1. The stderr bytes are the raw parser error text; in `--json`\n * mode we need to transform them into a failure envelope.\n * 2. We don't know whether the verb handler \"touched\" the IO\n * (rendered its own envelope) until after Stricli returns.\n *\n * Buffering lets us delay the decision until both signals are\n * available. Tests substitute a `BufferedProcess` whose buffers are\n * later inspected, mirroring the prod flush behavior.\n */\nconst flushBufferedProcess = (\n\tprocess: BufferedProcess,\n\tio: CliIO,\n\targv: ReadonlyArray<string>,\n\tenv: Readonly<Record<string, string | undefined>>,\n): Effect.Effect<void> =>\n\tEffect.gen(function* () {\n\t\tconst exitCode = normalizeStricliExitCode(process.exitCode);\n\t\tconst stdout = process.stdoutBuffer.join('');\n\t\tconst stderr = process.stderrBuffer.join('').trim();\n\t\tif (exitCode !== 0 && jsonRequested(argv, env)) {\n\t\t\tyield* emitFailure(io, 'json', {\n\t\t\t\tcommand: '(parse)',\n\t\t\t\telapsedMs: 0,\n\t\t\t\terror: new CliUsageError({\n\t\t\t\t\tmessage: stderr.length > 0 ? stderr : 'invalid command line',\n\t\t\t\t}),\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (stdout.length > 0)\n\t\t\tyield* io.writeStdout(stdout.endsWith('\\n') ? stdout.slice(0, -1) : stdout);\n\t\tif (stderr.length > 0) yield* io.writeStderr(stderr);\n\t\tyield* io.setExitCode(exitCode);\n\t});\n\nexport const dispatch = (deps: CliDeps, dispatchEnv: DispatchEnv): Effect.Effect<void> =>\n\tEffect.gen(function* () {\n\t\tconst io = trackIO(dispatchEnv.io ?? nodeProcessIO);\n\t\tconst process = makeBufferedProcess(dispatchEnv.env);\n\t\tconst ctx: DevstackCliContext = {\n\t\t\tprocess,\n\t\t\tdeps,\n\t\t\tenv: dispatchEnv.env,\n\t\t\tstdinIsTty: dispatchEnv.stdinIsTty,\n\t\t\tio,\n\t\t};\n\t\tyield* Effect.tryPromise({\n\t\t\ttry: () => runStricli(app, dispatchEnv.argv, ctx),\n\t\t\tcatch: (cause) => new CliInternalError({ message: 'CLI dispatcher failed', cause }),\n\t\t}).pipe(\n\t\t\tEffect.catch((error: CliError) =>\n\t\t\t\temitFailure(io, jsonRequested(dispatchEnv.argv, dispatchEnv.env) ? 'json' : 'human', {\n\t\t\t\t\tcommand: '(dispatch)',\n\t\t\t\t\telapsedMs: 0,\n\t\t\t\t\terror,\n\t\t\t\t}),\n\t\t\t),\n\t\t);\n\t\tif (!io.touched()) {\n\t\t\tyield* flushBufferedProcess(process, io, dispatchEnv.argv, dispatchEnv.env);\n\t\t}\n\t});\n\n// -----------------------------------------------------------------------------\n// Re-exports\n// -----------------------------------------------------------------------------\n\nexport type { CliIO } from './output.ts';\nexport type { GlobalFlags } from './flags.ts';\nexport { COMMAND_TREE, commandSchema, VERBS, type Verb } from './command-tree.ts';\nexport type { Envelope, EnvelopeError } from './envelope.ts';\nexport {\n\tENVELOPE_SCHEMA_VERSION,\n\tfailureEnvelope,\n\tstreamingEvent,\n\tsuccessEnvelope,\n\ttype StreamingEvent,\n} from './envelope.ts';\nexport { ExitCode, exitCodeName } from './sysexits.ts';\nexport {\n\ttype CliError,\n\tCliAlreadyReportedError,\n\tCliConfigInvalidError,\n\tCliConfigNotFoundError,\n\tCliConfirmDeclinedError,\n\tCliConfirmRequiredError,\n\tCliInternalError,\n\tCliSnapshotNotFoundError,\n\tCliSupervisorLiveError,\n\tCliUnavailableError,\n\tCliUsageError,\n} from './errors.ts';\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.mjs","names":[],"sources":["../../../src/surfaces/cli/output.ts"],"sourcesContent":["// CLI surface — output rendering (human / JSON envelope / structured\n// pretty error).\n//\n// Architecture (distilled/20-cli.md § Output formats):\n// - JSON envelope on stdout EXACTLY ONCE per command in `--json`\n// mode; stderr never receives the envelope.\n// - Human text on stdout otherwise.\n// - Pretty error tree on stderr only on failure — and only if the\n// subcommand hasn't already rendered (the `CliAlreadyReportedError`\n// sentinel suppresses).\n//\n// This module owns all stdout/stderr writes for the CLI. Subcommands\n// build envelope params; this module serializes and emits.\n\nimport { Effect } from 'effect';\nimport type { Cause } from 'effect';\n\nimport {\n\tformatCause,\n\tformatValue,\n} from '../../substrate/runtime/observability/cascade-formatter.ts';\nimport {\n\ttype Envelope,\n\tfailureEnvelope,\n\ttype FailureParams,\n\ttype StreamingEvent,\n\tsuccessEnvelope,\n\ttype SuccessParams,\n} from './envelope.ts';\nimport {\n\ttype CliError,\n\tCliAlreadyReportedError,\n\texitCodeFor,\n\thintFor,\n\tsummaryFor,\n} from './errors.ts';\nimport type { OutputMode } from './flags.ts';\nimport { type ExitCode } from './sysexits.ts';\n\n// -----------------------------------------------------------------------------\n// I/O service abstraction\n// -----------------------------------------------------------------------------\n\n/** Surface-level IO. Tests substitute a buffered impl. */\nexport interface CliIO {\n\treadonly writeStdout: (line: string) => Effect.Effect<void>;\n\treadonly writeStderr: (line: string) => Effect.Effect<void>;\n\treadonly setExitCode: (code: number) => Effect.Effect<void>;\n}\n\n/** Default IO bound to the Node process. */\nexport const nodeProcessIO: CliIO = {\n\twriteStdout: (line) =>\n\t\tEffect.sync(() => {\n\t\t\tprocess.stdout.write(line.endsWith('\\n') ? line : `${line}\\n`);\n\t\t}),\n\twriteStderr: (line) =>\n\t\tEffect.sync(() => {\n\t\t\tprocess.stderr.write(line.endsWith('\\n') ? line : `${line}\\n`);\n\t\t}),\n\tsetExitCode: (code) =>\n\t\tEffect.sync(() => {\n\t\t\tprocess.exitCode = code;\n\t\t}),\n};\n\n// -----------------------------------------------------------------------------\n// Stable JSON serialization\n// -----------------------------------------------------------------------------\n\n/**\n * `JSON.stringify` strips `undefined` from objects but NOT from\n * arrays (replaces with `null`). The envelope builders already omit\n * absent keys, but we add a guard so a future builder bug doesn't\n * leak `undefined` into automation output.\n *\n * Architecture: \"Absent fields are OMITTED from serialized output (no\n * `undefined`).\" This function enforces that promise.\n */\nexport const serializeEnvelope = (env: Envelope<unknown> | StreamingEvent<unknown>): string => {\n\tconst cleaned = stripUndefined(env);\n\treturn JSON.stringify(cleaned);\n};\n\nconst stripUndefined = (value: unknown): unknown => {\n\tif (value === undefined) return undefined;\n\tif (value === null) return null;\n\tif (Array.isArray(value)) return value.map(stripUndefined);\n\tif (typeof value !== 'object') return value;\n\tconst out: Record<string, unknown> = {};\n\tfor (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n\t\tif (v === undefined) continue;\n\t\tout[k] = stripUndefined(v);\n\t}\n\treturn out;\n};\n\n// -----------------------------------------------------------------------------\n// Success path\n// -----------------------------------------------------------------------------\n\n/**\n * Emit a success envelope OR a human-mode line block. Sets exit code\n * 0 unless a streaming success path supplies its own process code.\n *\n * In JSON mode: one envelope on stdout, nothing on stderr.\n * In human mode: each `humanLines` entry on stdout; hints rendered\n * after; no envelope.\n */\nexport const emitSuccess = <Data>(\n\tio: CliIO,\n\tmode: OutputMode,\n\tparams: SuccessParams<Data> & {\n\t\treadonly humanLines?: ReadonlyArray<string>;\n\t\t/** Override the OS exit code for commands whose transport\n\t\t * succeeded but whose payload carries a process-style status. */\n\t\treadonly exitCode?: number;\n\t},\n): Effect.Effect<void> =>\n\tEffect.gen(function* () {\n\t\tif (mode === 'json') {\n\t\t\tconst env = successEnvelope({\n\t\t\t\tcommand: params.command,\n\t\t\t\telapsedMs: params.elapsedMs,\n\t\t\t\tdata: params.data,\n\t\t\t\thints: params.hints,\n\t\t\t\tdryRun: params.dryRun,\n\t\t\t});\n\t\t\tyield* io.writeStdout(serializeEnvelope(env));\n\t\t} else {\n\t\t\tfor (const line of params.humanLines ?? []) {\n\t\t\t\tyield* io.writeStdout(line);\n\t\t\t}\n\t\t\tfor (const hint of params.hints ?? []) {\n\t\t\t\tyield* io.writeStdout(`hint: ${hint}`);\n\t\t\t}\n\t\t}\n\t\tyield* io.setExitCode(params.exitCode ?? 0);\n\t});\n\n// -----------------------------------------------------------------------------\n// Failure path\n// -----------------------------------------------------------------------------\n\n/**\n * Emit a failure for a `CliError`. Threads the sysexit code through\n * to `process.exitCode`. Honors the already-reported sentinel.\n *\n * Architecture invariant: \"Top-level error rendering must not\n * double-print when a subcommand already rendered.\" — we still set the\n * exit code but skip the envelope/stderr write.\n */\nexport const emitFailure = (\n\tio: CliIO,\n\tmode: OutputMode,\n\tparams: {\n\t\treadonly command: string;\n\t\treadonly elapsedMs: number;\n\t\treadonly error: CliError;\n\t\treadonly cause?: Cause.Cause<unknown>;\n\t\treadonly dryRun?: boolean;\n\t},\n): Effect.Effect<void> =>\n\tEffect.gen(function* () {\n\t\tconst exitCode = exitCodeFor(params.error);\n\t\tif (params.error._tag === 'CliAlreadyReportedError') {\n\t\t\tyield* io.setExitCode(exitCode);\n\t\t\treturn;\n\t\t}\n\t\tyield* renderFailure(io, mode, {\n\t\t\tcommand: params.command,\n\t\t\telapsedMs: params.elapsedMs,\n\t\t\texitCode,\n\t\t\tsummary: summaryFor(params.error),\n\t\t\thint: hintFor(params.error),\n\t\t\tcause: params.cause,\n\t\t\terrorCause:\n\t\t\t\t'cause' in params.error ? (params.error as { readonly cause?: unknown }).cause : undefined,\n\t\t\tdryRun: params.dryRun,\n\t\t});\n\t\tyield* io.setExitCode(exitCode);\n\t});\n\ninterface RenderFailureParams {\n\treadonly command: string;\n\treadonly elapsedMs: number;\n\treadonly exitCode: ExitCode;\n\treadonly summary: string;\n\treadonly hint?: string;\n\treadonly cause?: Cause.Cause<unknown>;\n\treadonly errorCause?: unknown;\n\treadonly dryRun?: boolean;\n}\n\nconst renderFailure = (io: CliIO, mode: OutputMode, p: RenderFailureParams): Effect.Effect<void> =>\n\tEffect.gen(function* () {\n\t\tconst rawChain =\n\t\t\tp.cause !== undefined\n\t\t\t\t? formatCause(p.cause)\n\t\t\t\t: p.errorCause !== undefined\n\t\t\t\t\t? formatValue(p.errorCause)\n\t\t\t\t\t: undefined;\n\t\tconst chain = rawChain?.split('\\n').filter((l) => l.length > 0);\n\n\t\tif (mode === 'json') {\n\t\t\tconst fp: FailureParams = {\n\t\t\t\tcommand: p.command,\n\t\t\t\telapsedMs: p.elapsedMs,\n\t\t\t\texitCode: p.exitCode,\n\t\t\t\tsummary: p.summary,\n\t\t\t\thint: p.hint,\n\t\t\t\tchain,\n\t\t\t\tdryRun: p.dryRun,\n\t\t\t};\n\t\t\tyield* io.writeStdout(serializeEnvelope(failureEnvelope(fp)));\n\t\t\treturn;\n\t\t}\n\n\t\t// Human mode: one-line summary on stderr, then optional hint and\n\t\t// the cascade chain (if present), all on stderr.\n\t\tyield* io.writeStderr(`error: ${p.summary}`);\n\t\tif (p.hint !== undefined) {\n\t\t\tyield* io.writeStderr(`hint: ${p.hint}`);\n\t\t}\n\t\tif (chain !== undefined && chain.length > 0) {\n\t\t\tfor (const line of chain) {\n\t\t\t\tyield* io.writeStderr(` ${line}`);\n\t\t\t}\n\t\t}\n\t});\n\n// -----------------------------------------------------------------------------\n// Already-reported helper\n// -----------------------------------------------------------------------------\n\n/** A subcommand that pretty-renders its own failure (e.g. an\n * interactive picker that already drew an error panel) returns this\n * sentinel so the top-level renderer skips re-rendering but still\n * propagates the right exit code. */\nexport const alreadyReported = (exitCode: ExitCode): CliAlreadyReportedError =>\n\tnew CliAlreadyReportedError({ exitCode });\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"output.mjs","names":[],"sources":["../../../src/surfaces/cli/output.ts"],"sourcesContent":["// CLI surface — output rendering (human / JSON envelope / structured\n// pretty error).\n//\n// Architecture (distilled/20-cli.md § Output formats):\n// - JSON envelope on stdout EXACTLY ONCE per command in `--json`\n// mode; stderr never receives the envelope.\n// - Human text on stdout otherwise.\n// - Pretty error tree on stderr only on failure — and only if the\n// subcommand hasn't already rendered (the `CliAlreadyReportedError`\n// sentinel suppresses).\n//\n// This module owns all stdout/stderr writes for the CLI. Subcommands\n// build envelope params; this module serializes and emits.\n\nimport { Effect } from 'effect';\nimport type { Cause } from 'effect';\n\nimport {\n\tformatCause,\n\tformatValue,\n} from '../../substrate/runtime/observability/cascade-formatter.ts';\nimport {\n\ttype Envelope,\n\tfailureEnvelope,\n\ttype FailureParams,\n\ttype StreamingEvent,\n\tsuccessEnvelope,\n\ttype SuccessParams,\n} from './envelope.ts';\nimport { type CliError, exitCodeFor, hintFor, summaryFor } from './errors.ts';\nimport type { OutputMode } from './flags.ts';\nimport { type ExitCode } from './sysexits.ts';\n\n// -----------------------------------------------------------------------------\n// I/O service abstraction\n// -----------------------------------------------------------------------------\n\n/** Surface-level IO. Tests substitute a buffered impl. */\nexport interface CliIO {\n\treadonly writeStdout: (line: string) => Effect.Effect<void>;\n\treadonly writeStderr: (line: string) => Effect.Effect<void>;\n\treadonly setExitCode: (code: number) => Effect.Effect<void>;\n}\n\n/** Default IO bound to the Node process. */\nexport const nodeProcessIO: CliIO = {\n\twriteStdout: (line) =>\n\t\tEffect.sync(() => {\n\t\t\tprocess.stdout.write(line.endsWith('\\n') ? line : `${line}\\n`);\n\t\t}),\n\twriteStderr: (line) =>\n\t\tEffect.sync(() => {\n\t\t\tprocess.stderr.write(line.endsWith('\\n') ? line : `${line}\\n`);\n\t\t}),\n\tsetExitCode: (code) =>\n\t\tEffect.sync(() => {\n\t\t\tprocess.exitCode = code;\n\t\t}),\n};\n\n// -----------------------------------------------------------------------------\n// Stable JSON serialization\n// -----------------------------------------------------------------------------\n\n/**\n * `JSON.stringify` strips `undefined` from objects but NOT from\n * arrays (replaces with `null`). The envelope builders already omit\n * absent keys, but we add a guard so a future builder bug doesn't\n * leak `undefined` into automation output.\n *\n * Architecture: \"Absent fields are OMITTED from serialized output (no\n * `undefined`).\" This function enforces that promise.\n */\nexport const serializeEnvelope = (env: Envelope<unknown> | StreamingEvent<unknown>): string => {\n\tconst cleaned = stripUndefined(env);\n\treturn JSON.stringify(cleaned);\n};\n\nconst stripUndefined = (value: unknown): unknown => {\n\tif (value === undefined) return undefined;\n\tif (value === null) return null;\n\tif (Array.isArray(value)) return value.map(stripUndefined);\n\tif (typeof value !== 'object') return value;\n\tconst out: Record<string, unknown> = {};\n\tfor (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n\t\tif (v === undefined) continue;\n\t\tout[k] = stripUndefined(v);\n\t}\n\treturn out;\n};\n\n// -----------------------------------------------------------------------------\n// Success path\n// -----------------------------------------------------------------------------\n\n/**\n * Emit a success envelope OR a human-mode line block. Sets exit code\n * 0 unless a streaming success path supplies its own process code.\n *\n * In JSON mode: one envelope on stdout, nothing on stderr.\n * In human mode: each `humanLines` entry on stdout; hints rendered\n * after; no envelope.\n */\nexport const emitSuccess = <Data>(\n\tio: CliIO,\n\tmode: OutputMode,\n\tparams: SuccessParams<Data> & {\n\t\treadonly humanLines?: ReadonlyArray<string>;\n\t\t/** Override the OS exit code for commands whose transport\n\t\t * succeeded but whose payload carries a process-style status. */\n\t\treadonly exitCode?: number;\n\t},\n): Effect.Effect<void> =>\n\tEffect.gen(function* () {\n\t\tif (mode === 'json') {\n\t\t\tconst env = successEnvelope({\n\t\t\t\tcommand: params.command,\n\t\t\t\telapsedMs: params.elapsedMs,\n\t\t\t\tdata: params.data,\n\t\t\t\thints: params.hints,\n\t\t\t\tdryRun: params.dryRun,\n\t\t\t});\n\t\t\tyield* io.writeStdout(serializeEnvelope(env));\n\t\t} else {\n\t\t\tfor (const line of params.humanLines ?? []) {\n\t\t\t\tyield* io.writeStdout(line);\n\t\t\t}\n\t\t\tfor (const hint of params.hints ?? []) {\n\t\t\t\tyield* io.writeStdout(`hint: ${hint}`);\n\t\t\t}\n\t\t}\n\t\tyield* io.setExitCode(params.exitCode ?? 0);\n\t});\n\n// -----------------------------------------------------------------------------\n// Failure path\n// -----------------------------------------------------------------------------\n\n/**\n * Emit a failure for a `CliError`. Threads the sysexit code through\n * to `process.exitCode`. Honors the already-reported sentinel.\n *\n * Architecture invariant: \"Top-level error rendering must not\n * double-print when a subcommand already rendered.\" — we still set the\n * exit code but skip the envelope/stderr write.\n */\nexport const emitFailure = (\n\tio: CliIO,\n\tmode: OutputMode,\n\tparams: {\n\t\treadonly command: string;\n\t\treadonly elapsedMs: number;\n\t\treadonly error: CliError;\n\t\treadonly cause?: Cause.Cause<unknown>;\n\t\treadonly dryRun?: boolean;\n\t},\n): Effect.Effect<void> =>\n\tEffect.gen(function* () {\n\t\tconst exitCode = exitCodeFor(params.error);\n\t\tif (params.error._tag === 'CliAlreadyReportedError') {\n\t\t\tyield* io.setExitCode(exitCode);\n\t\t\treturn;\n\t\t}\n\t\tyield* renderFailure(io, mode, {\n\t\t\tcommand: params.command,\n\t\t\telapsedMs: params.elapsedMs,\n\t\t\texitCode,\n\t\t\tsummary: summaryFor(params.error),\n\t\t\thint: hintFor(params.error),\n\t\t\tcause: params.cause,\n\t\t\terrorCause:\n\t\t\t\t'cause' in params.error ? (params.error as { readonly cause?: unknown }).cause : undefined,\n\t\t\tdryRun: params.dryRun,\n\t\t});\n\t\tyield* io.setExitCode(exitCode);\n\t});\n\ninterface RenderFailureParams {\n\treadonly command: string;\n\treadonly elapsedMs: number;\n\treadonly exitCode: ExitCode;\n\treadonly summary: string;\n\treadonly hint?: string;\n\treadonly cause?: Cause.Cause<unknown>;\n\treadonly errorCause?: unknown;\n\treadonly dryRun?: boolean;\n}\n\nconst renderFailure = (io: CliIO, mode: OutputMode, p: RenderFailureParams): Effect.Effect<void> =>\n\tEffect.gen(function* () {\n\t\tconst rawChain =\n\t\t\tp.cause !== undefined\n\t\t\t\t? formatCause(p.cause)\n\t\t\t\t: p.errorCause !== undefined\n\t\t\t\t\t? formatValue(p.errorCause)\n\t\t\t\t\t: undefined;\n\t\tconst chain = rawChain?.split('\\n').filter((l) => l.length > 0);\n\n\t\tif (mode === 'json') {\n\t\t\tconst fp: FailureParams = {\n\t\t\t\tcommand: p.command,\n\t\t\t\telapsedMs: p.elapsedMs,\n\t\t\t\texitCode: p.exitCode,\n\t\t\t\tsummary: p.summary,\n\t\t\t\thint: p.hint,\n\t\t\t\tchain,\n\t\t\t\tdryRun: p.dryRun,\n\t\t\t};\n\t\t\tyield* io.writeStdout(serializeEnvelope(failureEnvelope(fp)));\n\t\t\treturn;\n\t\t}\n\n\t\t// Human mode: one-line summary on stderr, then optional hint and\n\t\t// the cascade chain (if present), all on stderr.\n\t\tyield* io.writeStderr(`error: ${p.summary}`);\n\t\tif (p.hint !== undefined) {\n\t\t\tyield* io.writeStderr(`hint: ${p.hint}`);\n\t\t}\n\t\tif (chain !== undefined && chain.length > 0) {\n\t\t\tfor (const line of chain) {\n\t\t\t\tyield* io.writeStderr(` ${line}`);\n\t\t\t}\n\t\t}\n\t});\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sysexits.mjs","names":["_exhaustive"],"sources":["../../../src/surfaces/cli/sysexits.ts"],"sourcesContent":["// CLI surface — sysexits.h exit codes.\n//\n// Architecture (distilled/20-cli.md § Invariants) requires a single\n// centralized table. Numbers are pinned, names are stable, new\n// devstack-domain codes are added at the END of the domain block (so\n// downstream scripts keying off numerics never shift).\n//\n// Reference: /usr/include/sysexits.h (BSD-derived). We use only the\n// subset that maps to CLI failure shapes; everything else collapses to\n// `EX_SOFTWARE` (70). The devstack-domain block (40-43) is a private\n// extension carved out below the standard 64-78 range so it cannot\n// collide with the OS table.\n//\n// Surface invariant: every CLI failure carries one of these codes in\n// the JSON envelope's `error.exitCode` AND drives `process.exitCode`.\n// \"1 for everything\" is explicitly disallowed by the architecture.\n\n/** Sysexits-named exit codes (numeric values are stable; do NOT reuse). */\nexport const ExitCode = {\n\t/** Successful termination. */\n\tOK: 0,\n\t/** Generic catch-all failure. Use only when no specific code applies. */\n\tGENERIC: 1,\n\t/** Devstack-domain: supervisor for the target stack is already live\n\t * in another process. Destructive verbs refuse with this code. */\n\tSUPERVISOR_LIVE: 40,\n\t/** Devstack-domain: requested snapshot name / id not found. */\n\tSNAPSHOT_NOT_FOUND: 41,\n\t/** Devstack-domain: seed manifest mismatch between current chain\n\t * identity and the snapshot/seed being restored. */\n\tSEED_MISMATCH: 42,\n\t/** Devstack-domain: destructive verb requires explicit confirm but\n\t * `--no-input` / non-TTY / no `--yes` is in effect, or the\n\t * interactive prompt was declined. */\n\tCONFIRM_REQUIRED: 43,\n\t/** Bad usage (unknown flag, malformed args, mutually-exclusive\n\t * flag pair, ambiguous reference). */\n\tUSAGE: 64,\n\t/** Input data malformed (config schema invalid, JSON parse error\n\t * inside a snapshot manifest, etc.). */\n\tDATA_ERR: 65,\n\t/** Cannot open input (config not found, snapshot file missing). */\n\tNO_INPUT: 66,\n\t/** Internal software error / unhandled defect. Default for\n\t * defects that escape Effect.catch. */\n\tSOFTWARE: 70,\n\t/** Service required by the CLI is unavailable (Docker daemon\n\t * unreachable, network down). */\n\tUNAVAILABLE: 69,\n\t/** Output file/directory cannot be created (permissions, disk\n\t * full). */\n\tCANT_CREATE: 73,\n\t/** Temporary failure; retry might succeed (lock contention,\n\t * transient daemon hiccup). */\n\tTEMP_FAIL: 75,\n\t/** Configuration error — the user's devstack.config.ts is wrong\n\t * in a way that prevents *any* verb from running. */\n\tCONFIG: 78,\n} as const;\n\nexport type ExitCode = (typeof ExitCode)[keyof typeof ExitCode];\n\n/** Human-readable identifier for an exit code. Used by the\n * `schema --json` command and by the envelope `error.code` field. */\nexport const exitCodeName = (code: ExitCode): string => {\n\tswitch (code) {\n\t\tcase ExitCode.OK:\n\t\t\treturn 'OK';\n\t\tcase ExitCode.GENERIC:\n\t\t\treturn 'GENERIC';\n\t\tcase ExitCode.SUPERVISOR_LIVE:\n\t\t\treturn 'SUPERVISOR_LIVE';\n\t\tcase ExitCode.SNAPSHOT_NOT_FOUND:\n\t\t\treturn 'SNAPSHOT_NOT_FOUND';\n\t\tcase ExitCode.SEED_MISMATCH:\n\t\t\treturn 'SEED_MISMATCH';\n\t\tcase ExitCode.CONFIRM_REQUIRED:\n\t\t\treturn 'CONFIRM_REQUIRED';\n\t\tcase ExitCode.USAGE:\n\t\t\treturn 'USAGE';\n\t\tcase ExitCode.DATA_ERR:\n\t\t\treturn 'DATA_ERR';\n\t\tcase ExitCode.NO_INPUT:\n\t\t\treturn 'NO_INPUT';\n\t\tcase ExitCode.SOFTWARE:\n\t\t\treturn 'SOFTWARE';\n\t\tcase ExitCode.UNAVAILABLE:\n\t\t\treturn 'UNAVAILABLE';\n\t\tcase ExitCode.CANT_CREATE:\n\t\t\treturn 'CANT_CREATE';\n\t\tcase ExitCode.TEMP_FAIL:\n\t\t\treturn 'TEMP_FAIL';\n\t\tcase ExitCode.CONFIG:\n\t\t\treturn 'CONFIG';\n\t\tdefault: {\n\t\t\t// Proof-of-exhaustiveness — adding a new entry to `ExitCode`\n\t\t\t// without extending this switch fails compilation here.\n\t\t\tconst _exhaustive: never = code;\n\t\t\tthrow new Error(`Unknown ExitCode: ${String(_exhaustive)}`);\n\t\t}\n\t}\n};\n\n/** Schema-emit entry: full table of `(code, name, description)`. The\n * programmable `schema --json` command serializes this verbatim. */\nexport interface ExitCodeEntry {\n\treadonly code: ExitCode;\n\treadonly name: string;\n\treadonly description: string;\n}\n\nexport const exitCodeTable: ReadonlyArray<ExitCodeEntry> = [\n\t{ code: ExitCode.OK, name: 'OK', description: 'Successful termination.' },\n\t{\n\t\tcode: ExitCode.GENERIC,\n\t\tname: 'GENERIC',\n\t\tdescription: 'Generic failure; no specific code applies.',\n\t},\n\t{\n\t\tcode: ExitCode.SUPERVISOR_LIVE,\n\t\tname: 'SUPERVISOR_LIVE',\n\t\tdescription: 'Devstack: supervisor for the target stack is already live in another process.',\n\t},\n\t{\n\t\tcode: ExitCode.SNAPSHOT_NOT_FOUND,\n\t\tname: 'SNAPSHOT_NOT_FOUND',\n\t\tdescription: 'Devstack: requested snapshot name or id not found.',\n\t},\n\t{\n\t\tcode: ExitCode.SEED_MISMATCH,\n\t\tname: 'SEED_MISMATCH',\n\t\tdescription: 'Devstack: seed-manifest mismatch (chain identity diverges from snapshot).',\n\t},\n\t{\n\t\tcode: ExitCode.CONFIRM_REQUIRED,\n\t\tname: 'CONFIRM_REQUIRED',\n\t\tdescription: 'Devstack: destructive verb needs confirmation or the prompt was declined.',\n\t},\n\t{ code: ExitCode.USAGE, name: 'USAGE', description: 'Bad command-line usage.' },\n\t{ code: ExitCode.DATA_ERR, name: 'DATA_ERR', description: 'Input data malformed.' },\n\t{ code: ExitCode.NO_INPUT, name: 'NO_INPUT', description: 'Required input could not be opened.' },\n\t{\n\t\tcode: ExitCode.UNAVAILABLE,\n\t\tname: 'UNAVAILABLE',\n\t\tdescription: 'A required service (e.g. Docker daemon) is unavailable.',\n\t},\n\t{ code: ExitCode.SOFTWARE, name: 'SOFTWARE', description: 'Internal software error.' },\n\t{\n\t\tcode: ExitCode.CANT_CREATE,\n\t\tname: 'CANT_CREATE',\n\t\tdescription: 'Cannot create output (permissions, disk).',\n\t},\n\t{\n\t\tcode: ExitCode.TEMP_FAIL,\n\t\tname: 'TEMP_FAIL',\n\t\tdescription: 'Transient failure; retry may succeed.',\n\t},\n\t{ code: ExitCode.CONFIG, name: 'CONFIG', description: 'User configuration error.' },\n];\n"],"mappings":";;AAkBA,MAAa,WAAW;;CAEvB,IAAI;;CAEJ,SAAS;;;CAGT,iBAAiB;;CAEjB,oBAAoB;;;CAGpB,eAAe;;;;CAIf,kBAAkB;;;CAGlB,OAAO;;;CAGP,UAAU;;CAEV,UAAU;;;CAGV,UAAU;;;CAGV,aAAa;;;CAGb,aAAa;;;CAGb,WAAW;;;CAGX,QAAQ;
|
|
1
|
+
{"version":3,"file":"sysexits.mjs","names":["_exhaustive"],"sources":["../../../src/surfaces/cli/sysexits.ts"],"sourcesContent":["// CLI surface — sysexits.h exit codes.\n//\n// Architecture (distilled/20-cli.md § Invariants) requires a single\n// centralized table. Numbers are pinned, names are stable, new\n// devstack-domain codes are added at the END of the domain block (so\n// downstream scripts keying off numerics never shift).\n//\n// Reference: /usr/include/sysexits.h (BSD-derived). We use only the\n// subset that maps to CLI failure shapes; everything else collapses to\n// `EX_SOFTWARE` (70). The devstack-domain block (40-43) is a private\n// extension carved out below the standard 64-78 range so it cannot\n// collide with the OS table.\n//\n// Surface invariant: every CLI failure carries one of these codes in\n// the JSON envelope's `error.exitCode` AND drives `process.exitCode`.\n// \"1 for everything\" is explicitly disallowed by the architecture.\n\n/** Sysexits-named exit codes (numeric values are stable; do NOT reuse). */\nexport const ExitCode = {\n\t/** Successful termination. */\n\tOK: 0,\n\t/** Generic catch-all failure. Use only when no specific code applies. */\n\tGENERIC: 1,\n\t/** Devstack-domain: supervisor for the target stack is already live\n\t * in another process. Destructive verbs refuse with this code. */\n\tSUPERVISOR_LIVE: 40,\n\t/** Devstack-domain: requested snapshot name / id not found. */\n\tSNAPSHOT_NOT_FOUND: 41,\n\t/** Devstack-domain: seed manifest mismatch between current chain\n\t * identity and the snapshot/seed being restored. */\n\tSEED_MISMATCH: 42,\n\t/** Devstack-domain: destructive verb requires explicit confirm but\n\t * `--no-input` / non-TTY / no `--yes` is in effect, or the\n\t * interactive prompt was declined. */\n\tCONFIRM_REQUIRED: 43,\n\t/** Bad usage (unknown flag, malformed args, mutually-exclusive\n\t * flag pair, ambiguous reference). */\n\tUSAGE: 64,\n\t/** Input data malformed (config schema invalid, JSON parse error\n\t * inside a snapshot manifest, etc.). */\n\tDATA_ERR: 65,\n\t/** Cannot open input (config not found, snapshot file missing). */\n\tNO_INPUT: 66,\n\t/** Internal software error / unhandled defect. Default for\n\t * defects that escape Effect.catch. */\n\tSOFTWARE: 70,\n\t/** Service required by the CLI is unavailable (Docker daemon\n\t * unreachable, network down). */\n\tUNAVAILABLE: 69,\n\t/** Output file/directory cannot be created (permissions, disk\n\t * full). */\n\tCANT_CREATE: 73,\n\t/** Temporary failure; retry might succeed (lock contention,\n\t * transient daemon hiccup). */\n\tTEMP_FAIL: 75,\n\t/** Configuration error — the user's devstack.config.ts is wrong\n\t * in a way that prevents *any* verb from running. */\n\tCONFIG: 78,\n} as const;\n\nexport type ExitCode = (typeof ExitCode)[keyof typeof ExitCode];\n\n/** Human-readable identifier for an exit code. Used by the\n * `schema --json` command and by the envelope `error.code` field. */\nexport const exitCodeName = (code: ExitCode): string => {\n\tswitch (code) {\n\t\tcase ExitCode.OK:\n\t\t\treturn 'OK';\n\t\tcase ExitCode.GENERIC:\n\t\t\treturn 'GENERIC';\n\t\tcase ExitCode.SUPERVISOR_LIVE:\n\t\t\treturn 'SUPERVISOR_LIVE';\n\t\tcase ExitCode.SNAPSHOT_NOT_FOUND:\n\t\t\treturn 'SNAPSHOT_NOT_FOUND';\n\t\tcase ExitCode.SEED_MISMATCH:\n\t\t\treturn 'SEED_MISMATCH';\n\t\tcase ExitCode.CONFIRM_REQUIRED:\n\t\t\treturn 'CONFIRM_REQUIRED';\n\t\tcase ExitCode.USAGE:\n\t\t\treturn 'USAGE';\n\t\tcase ExitCode.DATA_ERR:\n\t\t\treturn 'DATA_ERR';\n\t\tcase ExitCode.NO_INPUT:\n\t\t\treturn 'NO_INPUT';\n\t\tcase ExitCode.SOFTWARE:\n\t\t\treturn 'SOFTWARE';\n\t\tcase ExitCode.UNAVAILABLE:\n\t\t\treturn 'UNAVAILABLE';\n\t\tcase ExitCode.CANT_CREATE:\n\t\t\treturn 'CANT_CREATE';\n\t\tcase ExitCode.TEMP_FAIL:\n\t\t\treturn 'TEMP_FAIL';\n\t\tcase ExitCode.CONFIG:\n\t\t\treturn 'CONFIG';\n\t\tdefault: {\n\t\t\t// Proof-of-exhaustiveness — adding a new entry to `ExitCode`\n\t\t\t// without extending this switch fails compilation here.\n\t\t\tconst _exhaustive: never = code;\n\t\t\tthrow new Error(`Unknown ExitCode: ${String(_exhaustive)}`);\n\t\t}\n\t}\n};\n\n/** Schema-emit entry: full table of `(code, name, description)`. The\n * programmable `schema --json` command serializes this verbatim. */\nexport interface ExitCodeEntry {\n\treadonly code: ExitCode;\n\treadonly name: string;\n\treadonly description: string;\n}\n\nexport const exitCodeTable: ReadonlyArray<ExitCodeEntry> = [\n\t{ code: ExitCode.OK, name: 'OK', description: 'Successful termination.' },\n\t{\n\t\tcode: ExitCode.GENERIC,\n\t\tname: 'GENERIC',\n\t\tdescription: 'Generic failure; no specific code applies.',\n\t},\n\t{\n\t\tcode: ExitCode.SUPERVISOR_LIVE,\n\t\tname: 'SUPERVISOR_LIVE',\n\t\tdescription: 'Devstack: supervisor for the target stack is already live in another process.',\n\t},\n\t{\n\t\tcode: ExitCode.SNAPSHOT_NOT_FOUND,\n\t\tname: 'SNAPSHOT_NOT_FOUND',\n\t\tdescription: 'Devstack: requested snapshot name or id not found.',\n\t},\n\t{\n\t\tcode: ExitCode.SEED_MISMATCH,\n\t\tname: 'SEED_MISMATCH',\n\t\tdescription: 'Devstack: seed-manifest mismatch (chain identity diverges from snapshot).',\n\t},\n\t{\n\t\tcode: ExitCode.CONFIRM_REQUIRED,\n\t\tname: 'CONFIRM_REQUIRED',\n\t\tdescription: 'Devstack: destructive verb needs confirmation or the prompt was declined.',\n\t},\n\t{ code: ExitCode.USAGE, name: 'USAGE', description: 'Bad command-line usage.' },\n\t{ code: ExitCode.DATA_ERR, name: 'DATA_ERR', description: 'Input data malformed.' },\n\t{ code: ExitCode.NO_INPUT, name: 'NO_INPUT', description: 'Required input could not be opened.' },\n\t{\n\t\tcode: ExitCode.UNAVAILABLE,\n\t\tname: 'UNAVAILABLE',\n\t\tdescription: 'A required service (e.g. Docker daemon) is unavailable.',\n\t},\n\t{ code: ExitCode.SOFTWARE, name: 'SOFTWARE', description: 'Internal software error.' },\n\t{\n\t\tcode: ExitCode.CANT_CREATE,\n\t\tname: 'CANT_CREATE',\n\t\tdescription: 'Cannot create output (permissions, disk).',\n\t},\n\t{\n\t\tcode: ExitCode.TEMP_FAIL,\n\t\tname: 'TEMP_FAIL',\n\t\tdescription: 'Transient failure; retry may succeed.',\n\t},\n\t{ code: ExitCode.CONFIG, name: 'CONFIG', description: 'User configuration error.' },\n];\n"],"mappings":";;AAkBA,MAAa,WAAW;;CAEvB,IAAI;;CAEJ,SAAS;;;CAGT,iBAAiB;;CAEjB,oBAAoB;;;CAGpB,eAAe;;;;CAIf,kBAAkB;;;CAGlB,OAAO;;;CAGP,UAAU;;CAEV,UAAU;;;CAGV,UAAU;;;CAGV,aAAa;;;CAGb,aAAa;;;CAGb,WAAW;;;CAGX,QAAQ;AACT;;;AAMA,MAAa,gBAAgB,SAA2B;CACvD,QAAQ,MAAR;EACC,KAAK,SAAS,IACb,OAAO;EACR,KAAK,SAAS,SACb,OAAO;EACR,KAAK,SAAS,iBACb,OAAO;EACR,KAAK,SAAS,oBACb,OAAO;EACR,KAAK,SAAS,eACb,OAAO;EACR,KAAK,SAAS,kBACb,OAAO;EACR,KAAK,SAAS,OACb,OAAO;EACR,KAAK,SAAS,UACb,OAAO;EACR,KAAK,SAAS,UACb,OAAO;EACR,KAAK,SAAS,UACb,OAAO;EACR,KAAK,SAAS,aACb,OAAO;EACR,KAAK,SAAS,aACb,OAAO;EACR,KAAK,SAAS,WACb,OAAO;EACR,KAAK,SAAS,QACb,OAAO;EACR,SAIC,MAAM,IAAI,MAAM,qBAAqB,OAAOA,IAAW,GAAG;CAE5D;AACD;AAUA,MAAa,gBAA8C;CAC1D;EAAE,MAAM,SAAS;EAAI,MAAM;EAAM,aAAa;CAA0B;CACxE;EACC,MAAM,SAAS;EACf,MAAM;EACN,aAAa;CACd;CACA;EACC,MAAM,SAAS;EACf,MAAM;EACN,aAAa;CACd;CACA;EACC,MAAM,SAAS;EACf,MAAM;EACN,aAAa;CACd;CACA;EACC,MAAM,SAAS;EACf,MAAM;EACN,aAAa;CACd;CACA;EACC,MAAM,SAAS;EACf,MAAM;EACN,aAAa;CACd;CACA;EAAE,MAAM,SAAS;EAAO,MAAM;EAAS,aAAa;CAA0B;CAC9E;EAAE,MAAM,SAAS;EAAU,MAAM;EAAY,aAAa;CAAwB;CAClF;EAAE,MAAM,SAAS;EAAU,MAAM;EAAY,aAAa;CAAsC;CAChG;EACC,MAAM,SAAS;EACf,MAAM;EACN,aAAa;CACd;CACA;EAAE,MAAM,SAAS;EAAU,MAAM;EAAY,aAAa;CAA2B;CACrF;EACC,MAAM,SAAS;EACf,MAAM;EACN,aAAa;CACd;CACA;EACC,MAAM,SAAS;EACf,MAAM;EACN,aAAa;CACd;CACA;EAAE,MAAM,SAAS;EAAQ,MAAM;EAAU,aAAa;CAA4B;AACnF"}
|
|
@@ -40,27 +40,6 @@ const App = ({ stateRef, events, publish }) => {
|
|
|
40
40
|
pendingLines.push(line);
|
|
41
41
|
scheduleFlush();
|
|
42
42
|
switch (event.tag) {
|
|
43
|
-
case "snapshot.captureStarted":
|
|
44
|
-
setSnapshotStatus({
|
|
45
|
-
tag: "running",
|
|
46
|
-
phase: "starting",
|
|
47
|
-
...event.snapshotId === void 0 ? {} : { snapshotId: event.snapshotId },
|
|
48
|
-
...event.name === void 0 ? {} : { name: event.name },
|
|
49
|
-
at: event.at
|
|
50
|
-
});
|
|
51
|
-
break;
|
|
52
|
-
case "snapshot.captureProgress":
|
|
53
|
-
setSnapshotStatus((prev) => ({
|
|
54
|
-
tag: "running",
|
|
55
|
-
phase: event.phase,
|
|
56
|
-
...event.snapshotId === void 0 ? prev?.tag === "running" && prev.snapshotId !== void 0 ? { snapshotId: prev.snapshotId } : {} : { snapshotId: event.snapshotId },
|
|
57
|
-
...event.name === void 0 ? prev?.tag === "running" && prev.name !== void 0 ? { name: prev.name } : {} : { name: event.name },
|
|
58
|
-
...event.detail === void 0 ? {} : { detail: event.detail },
|
|
59
|
-
...event.pausedContainers === void 0 ? {} : { pausedContainers: event.pausedContainers },
|
|
60
|
-
...event.totalContainers === void 0 ? {} : { totalContainers: event.totalContainers },
|
|
61
|
-
at: event.at
|
|
62
|
-
}));
|
|
63
|
-
break;
|
|
64
43
|
case "snapshot.captureSkipped":
|
|
65
44
|
setSnapshotStatus({
|
|
66
45
|
tag: "skipped",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.mjs","names":[],"sources":["../../../src/surfaces/tui/app.tsx"],"sourcesContent":["// Ink app root — the React tree mounted by `render()`.\n//\n// Reads from the `SubscriptionRef<SubscribableState>` from the\n// substrate's projection layer. The initial render samples the current\n// value synchronously; subsequent frame updates come from the\n// subscription. No polling loops, no setInterval-driven sampling.\n// The heartbeat component spins on its own timer for liveness, but\n// it does NOT trigger dashboard re-renders for projection data.\n//\n// Per architecture (distilled/21-tui § Learnings #3 + § Invariants):\n// - The renderer NEVER calls engine methods. Input handlers publish\n// typed `EngineCommand`s through the `publish` callback prop.\n// - Mount is process-scoped and survives engine cycle swaps; the\n// SubscriptionRef's lifecycle is decoupled from the engine cycle.\n// - Frame stability: SubscriptionRef updates already short-circuit\n// when reference equality holds (Effect's Ref impl).\n//\n// Runtime escape note: `Effect.runFork` is necessary at the\n// SubscriptionRef → React state boundary (React's hook model is\n// synchronous; Effect can't render). It is the ONLY escape this\n// surface uses, scoped to the App's mount lifetime. This is the\n// \"properly-scoped fiber on each surface\" pattern called out in\n// distilled/21-tui § Opportunities.\n\nimport { Effect, Fiber, Stream, SubscriptionRef } from 'effect';\nimport type React from 'react';\nimport { useEffect, useRef, useState } from 'react';\n\nimport type { EngineEvent } from '../../substrate/events.ts';\nimport type { SubscribableState } from '../../substrate/projection.ts';\nimport { Dashboard, type SnapshotStatus } from './dashboard.tsx';\nimport {\n\tappendEventLogLine,\n\tappendEventLogLines,\n\teventLogLineFromEvent,\n\tshutdownRequestedLine,\n\ttype EventLogLine,\n} from './event-log.ts';\nimport { InputHandler, type CommandPublisher } from './input.tsx';\n\nexport interface AppProps {\n\t/** The renderer-facing subscribable projection. */\n\treadonly stateRef: SubscriptionRef.SubscriptionRef<SubscribableState>;\n\t/** Live engine event stream. */\n\treadonly events: Stream.Stream<EngineEvent, never>;\n\t/** Typed command-publisher callback. */\n\treadonly publish: CommandPublisher;\n}\n\nexport const App = ({ stateRef, events, publish }: AppProps): React.JSX.Element => {\n\tconst [state, setState] = useState<SubscribableState>(() =>\n\t\tEffect.runSync(SubscriptionRef.get(stateRef)),\n\t);\n\tconst [eventLog, setEventLog] = useState<ReadonlyArray<EventLogLine>>([]);\n\tconst [snapshotPromptValue, setSnapshotPromptValue] = useState<string | null>(null);\n\tconst [snapshotStatus, setSnapshotStatus] = useState<SnapshotStatus | null>(null);\n\tconst eventSeq = useRef(0);\n\tconst shutdownLogged = useRef(false);\n\t// Latest projection rows for `sectionLookup`. Held in a ref so the\n\t// event-subscription effect doesn't re-fire when state changes — it\n\t// reads the up-to-date snapshot through the ref instead.\n\tconst rowsRef = useRef(state.rows);\n\trowsRef.current = state.rows;\n\n\tuseEffect(() => {\n\t\t// Stream.runForEach pulls each new state from the\n\t\t// SubscriptionRef and pushes it into React state. The fiber is\n\t\t// owned by this effect; cleanup interrupts it.\n\t\tconst fiber = Effect.runFork(\n\t\t\tStream.runForEach(SubscriptionRef.changes(stateRef), (next) =>\n\t\t\t\tEffect.sync(() => setState(next)),\n\t\t\t),\n\t\t);\n\t\treturn () => {\n\t\t\t// Interrupt the subscription fiber on unmount.\n\t\t\tEffect.runFork(Fiber.interrupt(fiber));\n\t\t};\n\t}, [stateRef]);\n\n\tuseEffect(() => {\n\t\tconst sectionLookup = (pluginKey: string) =>\n\t\t\trowsRef.current.find((row) => row.key === pluginKey)?.section;\n\t\t// Microtask batching: a burst of N events used to trigger N\n\t\t// `setEventLog` calls, each forcing a React render. We instead\n\t\t// accumulate derived lines in `pendingLines` and flush them\n\t\t// inside a single `queueMicrotask` callback — one `setEventLog`\n\t\t// per tick regardless of burst size. The sidecar `setSnapshotStatus`\n\t\t// updates stay per-event (they're idempotent and don't drive the\n\t\t// hot path).\n\t\tlet pendingLines: Array<EventLogLine | null> = [];\n\t\tlet flushScheduled = false;\n\t\tconst scheduleFlush = (): void => {\n\t\t\tif (flushScheduled) return;\n\t\t\tflushScheduled = true;\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tflushScheduled = false;\n\t\t\t\tif (pendingLines.length === 0) return;\n\t\t\t\tconst drained = pendingLines;\n\t\t\t\tpendingLines = [];\n\t\t\t\tsetEventLog((prev) => appendEventLogLines(prev, drained));\n\t\t\t});\n\t\t};\n\t\tconst fiber = Effect.runFork(\n\t\t\tStream.runForEach(events, (event) =>\n\t\t\t\tEffect.sync(() => {\n\t\t\t\t\tconst line = eventLogLineFromEvent(event, eventSeq.current++, sectionLookup);\n\t\t\t\t\tpendingLines.push(line);\n\t\t\t\t\tscheduleFlush();\n\t\t\t\t\tswitch (event.tag) {\n\t\t\t\t\t\tcase 'snapshot.captureStarted':\n\t\t\t\t\t\t\tsetSnapshotStatus({\n\t\t\t\t\t\t\t\ttag: 'running',\n\t\t\t\t\t\t\t\tphase: 'starting',\n\t\t\t\t\t\t\t\t...(event.snapshotId === undefined ? {} : { snapshotId: event.snapshotId }),\n\t\t\t\t\t\t\t\t...(event.name === undefined ? {} : { name: event.name }),\n\t\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'snapshot.captureProgress':\n\t\t\t\t\t\t\tsetSnapshotStatus((prev) => ({\n\t\t\t\t\t\t\t\ttag: 'running',\n\t\t\t\t\t\t\t\tphase: event.phase,\n\t\t\t\t\t\t\t\t...(event.snapshotId === undefined\n\t\t\t\t\t\t\t\t\t? prev?.tag === 'running' && prev.snapshotId !== undefined\n\t\t\t\t\t\t\t\t\t\t? { snapshotId: prev.snapshotId }\n\t\t\t\t\t\t\t\t\t\t: {}\n\t\t\t\t\t\t\t\t\t: { snapshotId: event.snapshotId }),\n\t\t\t\t\t\t\t\t...(event.name === undefined\n\t\t\t\t\t\t\t\t\t? prev?.tag === 'running' && prev.name !== undefined\n\t\t\t\t\t\t\t\t\t\t? { name: prev.name }\n\t\t\t\t\t\t\t\t\t\t: {}\n\t\t\t\t\t\t\t\t\t: { name: event.name }),\n\t\t\t\t\t\t\t\t...(event.detail === undefined ? {} : { detail: event.detail }),\n\t\t\t\t\t\t\t\t...(event.pausedContainers === undefined\n\t\t\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t\t\t: { pausedContainers: event.pausedContainers }),\n\t\t\t\t\t\t\t\t...(event.totalContainers === undefined\n\t\t\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t\t\t: { totalContainers: event.totalContainers }),\n\t\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'snapshot.captureSkipped':\n\t\t\t\t\t\t\tsetSnapshotStatus({\n\t\t\t\t\t\t\t\ttag: 'skipped',\n\t\t\t\t\t\t\t\treason: event.reason,\n\t\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'snapshot.captureFailed':\n\t\t\t\t\t\t\tsetSnapshotStatus({\n\t\t\t\t\t\t\t\ttag: 'failed',\n\t\t\t\t\t\t\t\t...(event.snapshotId === undefined ? {} : { snapshotId: event.snapshotId }),\n\t\t\t\t\t\t\t\t...(event.name === undefined ? {} : { name: event.name }),\n\t\t\t\t\t\t\t\tsummary: event.summary,\n\t\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'snapshot.captured':\n\t\t\t\t\t\t\tsetSnapshotStatus({\n\t\t\t\t\t\t\t\ttag: 'captured',\n\t\t\t\t\t\t\t\tsnapshotId: event.snapshotId,\n\t\t\t\t\t\t\t\t...(event.name === undefined ? {} : { name: event.name }),\n\t\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t),\n\t\t);\n\t\treturn () => {\n\t\t\tEffect.runFork(Fiber.interrupt(fiber));\n\t\t\t// Final flush: drain any batched lines synchronously so an\n\t\t\t// unmount immediately after a burst doesn't lose the tail.\n\t\t\tif (pendingLines.length > 0) {\n\t\t\t\tconst drained = pendingLines;\n\t\t\t\tpendingLines = [];\n\t\t\t\tsetEventLog((prev) => appendEventLogLines(prev, drained));\n\t\t\t}\n\t\t};\n\t}, [events]);\n\n\tuseEffect(() => {\n\t\tif (state.cycle.phase === 'shutting-down') {\n\t\t\tsetSnapshotPromptValue(null);\n\t\t\tsetSnapshotStatus(null);\n\t\t\tif (shutdownLogged.current) return;\n\t\t\tshutdownLogged.current = true;\n\t\t\tconst line = shutdownRequestedLine(Date.now(), eventSeq.current++);\n\t\t\tsetEventLog((prev) => appendEventLogLine(prev, line));\n\t\t\treturn;\n\t\t}\n\t\tshutdownLogged.current = false;\n\t}, [state.cycle.phase]);\n\n\treturn (\n\t\t<>\n\t\t\t<InputHandler\n\t\t\t\tpublish={publish}\n\t\t\t\tsnapshotPromptValue={snapshotPromptValue}\n\t\t\t\tonSnapshotPromptChange={setSnapshotPromptValue}\n\t\t\t/>\n\t\t\t<Dashboard\n\t\t\t\tstate={state}\n\t\t\t\teventLog={eventLog}\n\t\t\t\tsnapshotPromptValue={snapshotPromptValue}\n\t\t\t\tsnapshotStatus={snapshotStatus}\n\t\t\t/>\n\t\t</>\n\t);\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app.mjs","names":[],"sources":["../../../src/surfaces/tui/app.tsx"],"sourcesContent":["// Ink app root — the React tree mounted by `render()`.\n//\n// Reads from the `SubscriptionRef<SubscribableState>` from the\n// substrate's projection layer. The initial render samples the current\n// value synchronously; subsequent frame updates come from the\n// subscription. No polling loops, no setInterval-driven sampling.\n// The heartbeat component spins on its own timer for liveness, but\n// it does NOT trigger dashboard re-renders for projection data.\n//\n// Per architecture (distilled/21-tui § Learnings #3 + § Invariants):\n// - The renderer NEVER calls engine methods. Input handlers publish\n// typed `EngineCommand`s through the `publish` callback prop.\n// - Mount is process-scoped and survives engine cycle swaps; the\n// SubscriptionRef's lifecycle is decoupled from the engine cycle.\n// - Frame stability: SubscriptionRef updates already short-circuit\n// when reference equality holds (Effect's Ref impl).\n//\n// Runtime escape note: `Effect.runFork` is necessary at the\n// SubscriptionRef → React state boundary (React's hook model is\n// synchronous; Effect can't render). It is the ONLY escape this\n// surface uses, scoped to the App's mount lifetime. This is the\n// \"properly-scoped fiber on each surface\" pattern called out in\n// distilled/21-tui § Opportunities.\n\nimport { Effect, Fiber, Stream, SubscriptionRef } from 'effect';\nimport type React from 'react';\nimport { useEffect, useRef, useState } from 'react';\n\nimport type { EngineEvent } from '../../substrate/events.ts';\nimport type { SubscribableState } from '../../substrate/projection.ts';\nimport { Dashboard, type SnapshotStatus } from './dashboard.tsx';\nimport {\n\tappendEventLogLine,\n\tappendEventLogLines,\n\teventLogLineFromEvent,\n\tshutdownRequestedLine,\n\ttype EventLogLine,\n} from './event-log.ts';\nimport { InputHandler, type CommandPublisher } from './input.tsx';\n\nexport interface AppProps {\n\t/** The renderer-facing subscribable projection. */\n\treadonly stateRef: SubscriptionRef.SubscriptionRef<SubscribableState>;\n\t/** Live engine event stream. */\n\treadonly events: Stream.Stream<EngineEvent, never>;\n\t/** Typed command-publisher callback. */\n\treadonly publish: CommandPublisher;\n}\n\nexport const App = ({ stateRef, events, publish }: AppProps): React.JSX.Element => {\n\tconst [state, setState] = useState<SubscribableState>(() =>\n\t\tEffect.runSync(SubscriptionRef.get(stateRef)),\n\t);\n\tconst [eventLog, setEventLog] = useState<ReadonlyArray<EventLogLine>>([]);\n\tconst [snapshotPromptValue, setSnapshotPromptValue] = useState<string | null>(null);\n\tconst [snapshotStatus, setSnapshotStatus] = useState<SnapshotStatus | null>(null);\n\tconst eventSeq = useRef(0);\n\tconst shutdownLogged = useRef(false);\n\t// Latest projection rows for `sectionLookup`. Held in a ref so the\n\t// event-subscription effect doesn't re-fire when state changes — it\n\t// reads the up-to-date snapshot through the ref instead.\n\tconst rowsRef = useRef(state.rows);\n\trowsRef.current = state.rows;\n\n\tuseEffect(() => {\n\t\t// Stream.runForEach pulls each new state from the\n\t\t// SubscriptionRef and pushes it into React state. The fiber is\n\t\t// owned by this effect; cleanup interrupts it.\n\t\tconst fiber = Effect.runFork(\n\t\t\tStream.runForEach(SubscriptionRef.changes(stateRef), (next) =>\n\t\t\t\tEffect.sync(() => setState(next)),\n\t\t\t),\n\t\t);\n\t\treturn () => {\n\t\t\t// Interrupt the subscription fiber on unmount.\n\t\t\tEffect.runFork(Fiber.interrupt(fiber));\n\t\t};\n\t}, [stateRef]);\n\n\tuseEffect(() => {\n\t\tconst sectionLookup = (pluginKey: string) =>\n\t\t\trowsRef.current.find((row) => row.key === pluginKey)?.section;\n\t\t// Microtask batching: rather than one `setEventLog` per event (each\n\t\t// forcing a React render), accumulate derived lines in `pendingLines`\n\t\t// and flush them inside a single `queueMicrotask` callback — one\n\t\t// `setEventLog` per tick regardless of burst size. The sidecar\n\t\t// `setSnapshotStatus`\n\t\t// updates stay per-event (they're idempotent and don't drive the\n\t\t// hot path).\n\t\tlet pendingLines: Array<EventLogLine | null> = [];\n\t\tlet flushScheduled = false;\n\t\tconst scheduleFlush = (): void => {\n\t\t\tif (flushScheduled) return;\n\t\t\tflushScheduled = true;\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tflushScheduled = false;\n\t\t\t\tif (pendingLines.length === 0) return;\n\t\t\t\tconst drained = pendingLines;\n\t\t\t\tpendingLines = [];\n\t\t\t\tsetEventLog((prev) => appendEventLogLines(prev, drained));\n\t\t\t});\n\t\t};\n\t\tconst fiber = Effect.runFork(\n\t\t\tStream.runForEach(events, (event) =>\n\t\t\t\tEffect.sync(() => {\n\t\t\t\t\tconst line = eventLogLineFromEvent(event, eventSeq.current++, sectionLookup);\n\t\t\t\t\tpendingLines.push(line);\n\t\t\t\t\tscheduleFlush();\n\t\t\t\t\tswitch (event.tag) {\n\t\t\t\t\t\tcase 'snapshot.captureSkipped':\n\t\t\t\t\t\t\tsetSnapshotStatus({\n\t\t\t\t\t\t\t\ttag: 'skipped',\n\t\t\t\t\t\t\t\treason: event.reason,\n\t\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'snapshot.captureFailed':\n\t\t\t\t\t\t\tsetSnapshotStatus({\n\t\t\t\t\t\t\t\ttag: 'failed',\n\t\t\t\t\t\t\t\t...(event.snapshotId === undefined ? {} : { snapshotId: event.snapshotId }),\n\t\t\t\t\t\t\t\t...(event.name === undefined ? {} : { name: event.name }),\n\t\t\t\t\t\t\t\tsummary: event.summary,\n\t\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'snapshot.captured':\n\t\t\t\t\t\t\tsetSnapshotStatus({\n\t\t\t\t\t\t\t\ttag: 'captured',\n\t\t\t\t\t\t\t\tsnapshotId: event.snapshotId,\n\t\t\t\t\t\t\t\t...(event.name === undefined ? {} : { name: event.name }),\n\t\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t),\n\t\t);\n\t\treturn () => {\n\t\t\tEffect.runFork(Fiber.interrupt(fiber));\n\t\t\t// Final flush: drain any batched lines synchronously so an\n\t\t\t// unmount immediately after a burst doesn't lose the tail.\n\t\t\tif (pendingLines.length > 0) {\n\t\t\t\tconst drained = pendingLines;\n\t\t\t\tpendingLines = [];\n\t\t\t\tsetEventLog((prev) => appendEventLogLines(prev, drained));\n\t\t\t}\n\t\t};\n\t}, [events]);\n\n\tuseEffect(() => {\n\t\tif (state.cycle.phase === 'shutting-down') {\n\t\t\tsetSnapshotPromptValue(null);\n\t\t\tsetSnapshotStatus(null);\n\t\t\tif (shutdownLogged.current) return;\n\t\t\tshutdownLogged.current = true;\n\t\t\tconst line = shutdownRequestedLine(Date.now(), eventSeq.current++);\n\t\t\tsetEventLog((prev) => appendEventLogLine(prev, line));\n\t\t\treturn;\n\t\t}\n\t\tshutdownLogged.current = false;\n\t}, [state.cycle.phase]);\n\n\treturn (\n\t\t<>\n\t\t\t<InputHandler\n\t\t\t\tpublish={publish}\n\t\t\t\tsnapshotPromptValue={snapshotPromptValue}\n\t\t\t\tonSnapshotPromptChange={setSnapshotPromptValue}\n\t\t\t/>\n\t\t\t<Dashboard\n\t\t\t\tstate={state}\n\t\t\t\teventLog={eventLog}\n\t\t\t\tsnapshotPromptValue={snapshotPromptValue}\n\t\t\t\tsnapshotStatus={snapshotStatus}\n\t\t\t/>\n\t\t</>\n\t);\n};\n"],"mappings":"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"}
|
|
@@ -33,56 +33,8 @@ const snapshotLabel = (status) => {
|
|
|
33
33
|
if ("snapshotId" in status && status.snapshotId !== void 0) return status.snapshotId;
|
|
34
34
|
return "manual snapshot";
|
|
35
35
|
};
|
|
36
|
-
const snapshotPhaseLabel = (phase) => {
|
|
37
|
-
switch (phase) {
|
|
38
|
-
case "starting": return "starting";
|
|
39
|
-
case "quiescing": return "checking participants";
|
|
40
|
-
case "pausing": return "pausing containers";
|
|
41
|
-
case "paused": return "stack paused";
|
|
42
|
-
case "capturing-containers": return "capturing containers";
|
|
43
|
-
case "saving-images": return "saving images";
|
|
44
|
-
case "capturing-host-tree": return "capturing files";
|
|
45
|
-
case "saving-state": return "saving state";
|
|
46
|
-
case "saving-contributions": return "saving metadata";
|
|
47
|
-
case "writing-metadata": return "finalizing";
|
|
48
|
-
case "resuming": return "resuming stack";
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
const snapshotPhaseMeansPaused = (phase) => phase === "paused" || phase === "capturing-containers" || phase === "saving-images" || phase === "capturing-host-tree" || phase === "saving-state" || phase === "saving-contributions" || phase === "writing-metadata" || phase === "resuming";
|
|
52
36
|
const SnapshotStatusLine = ({ status }) => {
|
|
53
37
|
switch (status.tag) {
|
|
54
|
-
case "running": {
|
|
55
|
-
const paused = snapshotPhaseMeansPaused(status.phase);
|
|
56
|
-
const count = status.pausedContainers !== void 0 && status.totalContainers !== void 0 ? `${status.pausedContainers}/${status.totalContainers}` : null;
|
|
57
|
-
return /* @__PURE__ */ jsxs(Box, {
|
|
58
|
-
flexDirection: "row",
|
|
59
|
-
gap: 1,
|
|
60
|
-
marginTop: 1,
|
|
61
|
-
children: [
|
|
62
|
-
/* @__PURE__ */ jsx(Text, {
|
|
63
|
-
color: paused ? "yellow" : "cyan",
|
|
64
|
-
children: "Snapshot:"
|
|
65
|
-
}),
|
|
66
|
-
/* @__PURE__ */ jsx(Text, { children: snapshotLabel(status) }),
|
|
67
|
-
/* @__PURE__ */ jsx(Text, {
|
|
68
|
-
color: paused ? "yellow" : "cyan",
|
|
69
|
-
children: snapshotPhaseLabel(status.phase)
|
|
70
|
-
}),
|
|
71
|
-
paused && /* @__PURE__ */ jsx(Text, {
|
|
72
|
-
color: "yellow",
|
|
73
|
-
children: "stack paused"
|
|
74
|
-
}),
|
|
75
|
-
count !== null && /* @__PURE__ */ jsx(Text, {
|
|
76
|
-
dimColor: true,
|
|
77
|
-
children: count
|
|
78
|
-
}),
|
|
79
|
-
status.detail !== void 0 && /* @__PURE__ */ jsx(Text, {
|
|
80
|
-
dimColor: true,
|
|
81
|
-
children: status.detail
|
|
82
|
-
})
|
|
83
|
-
]
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
38
|
case "captured": return /* @__PURE__ */ jsxs(Box, {
|
|
87
39
|
flexDirection: "row",
|
|
88
40
|
gap: 1,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard.mjs","names":[],"sources":["../../../src/surfaces/tui/dashboard.tsx"],"sourcesContent":["// Dashboard — composes the visible TUI: header, rows, endpoints,\n// log tails, heartbeat.\n//\n// Reads ONLY the typed projection (`SubscribableState`). Calls the\n// pure derivation helpers in `display-derivation.ts` for every visible\n// cell. The dashboard does NOT subscribe to the SubscriptionRef\n// itself — `app.tsx` owns the subscription and feeds `state` in as a\n// prop. This keeps the dashboard pure-render-of-state, which is what\n// the architecture's \"frame stability\" invariant requires.\n\nimport { Box, Static, Text } from 'ink';\nimport type React from 'react';\n\nimport type { SnapshotCaptureProgressPhase } from '../../substrate/events.ts';\nimport type { SubscribableState } from '../../substrate/projection.ts';\nimport type { EventLogLine } from './event-log.ts';\nimport { Heartbeat } from './heartbeat.tsx';\nimport { ResourceTables } from './resource-table.tsx';\nimport { dashboardSummaryLine, deriveDashboardSummary } from './display-derivation.ts';\n\nconst phaseColor = (\n\tphase: SubscribableState['cycle']['phase'],\n): 'green' | 'yellow' | 'red' | 'white' => {\n\tswitch (phase) {\n\t\tcase 'running':\n\t\t\treturn 'green';\n\t\tcase 'booting':\n\t\tcase 'restarting':\n\t\t\treturn 'yellow';\n\t\tcase 'shutting-down':\n\t\t\treturn 'red';\n\t\tdefault:\n\t\t\treturn 'white';\n\t}\n};\n\nexport interface DashboardProps {\n\treadonly state: SubscribableState;\n\treadonly eventLog: ReadonlyArray<EventLogLine>;\n\treadonly snapshotPromptValue: string | null;\n\treadonly snapshotStatus: SnapshotStatus | null;\n}\n\nexport type SnapshotStatus =\n\t| {\n\t\t\treadonly tag: 'running';\n\t\t\treadonly phase: SnapshotCaptureProgressPhase | 'starting';\n\t\t\treadonly snapshotId?: string;\n\t\t\treadonly name?: string;\n\t\t\treadonly detail?: string;\n\t\t\treadonly pausedContainers?: number;\n\t\t\treadonly totalContainers?: number;\n\t\t\treadonly at: number;\n\t }\n\t| {\n\t\t\treadonly tag: 'captured';\n\t\t\treadonly snapshotId: string;\n\t\t\treadonly name?: string;\n\t\t\treadonly at: number;\n\t }\n\t| {\n\t\t\treadonly tag: 'skipped';\n\t\t\treadonly reason: 'already-running';\n\t\t\treadonly at: number;\n\t }\n\t| {\n\t\t\treadonly tag: 'failed';\n\t\t\treadonly snapshotId?: string;\n\t\t\treadonly name?: string;\n\t\t\treadonly summary: string;\n\t\t\treadonly at: number;\n\t };\n\nconst logMessageColor = (level: EventLogLine['level']): 'white' | 'yellow' | 'red' => {\n\tswitch (level) {\n\t\tcase 'info':\n\t\t\treturn 'white';\n\t\tcase 'warn':\n\t\t\treturn 'yellow';\n\t\tcase 'error':\n\t\t\treturn 'red';\n\t}\n};\n\nconst healthColor = (\n\thealth: ReturnType<typeof deriveDashboardSummary>['health'],\n): 'green' | 'yellow' | 'red' | 'white' => {\n\tswitch (health) {\n\t\tcase 'ready':\n\t\t\treturn 'green';\n\t\tcase 'active':\n\t\t\treturn 'yellow';\n\t\tcase 'blocked':\n\t\t\treturn 'red';\n\t\tcase 'empty':\n\t\t\treturn 'white';\n\t}\n};\n\nconst snapshotLabel = (status: SnapshotStatus): string => {\n\tif ('name' in status && status.name !== undefined) return status.name;\n\tif ('snapshotId' in status && status.snapshotId !== undefined) return status.snapshotId;\n\treturn 'manual snapshot';\n};\n\nconst snapshotPhaseLabel = (phase: SnapshotCaptureProgressPhase | 'starting'): string => {\n\tswitch (phase) {\n\t\tcase 'starting':\n\t\t\treturn 'starting';\n\t\tcase 'quiescing':\n\t\t\treturn 'checking participants';\n\t\tcase 'pausing':\n\t\t\treturn 'pausing containers';\n\t\tcase 'paused':\n\t\t\treturn 'stack paused';\n\t\tcase 'capturing-containers':\n\t\t\treturn 'capturing containers';\n\t\tcase 'saving-images':\n\t\t\treturn 'saving images';\n\t\tcase 'capturing-host-tree':\n\t\t\treturn 'capturing files';\n\t\tcase 'saving-state':\n\t\t\treturn 'saving state';\n\t\tcase 'saving-contributions':\n\t\t\treturn 'saving metadata';\n\t\tcase 'writing-metadata':\n\t\t\treturn 'finalizing';\n\t\tcase 'resuming':\n\t\t\treturn 'resuming stack';\n\t}\n};\n\nconst snapshotPhaseMeansPaused = (phase: SnapshotCaptureProgressPhase | 'starting'): boolean =>\n\tphase === 'paused' ||\n\tphase === 'capturing-containers' ||\n\tphase === 'saving-images' ||\n\tphase === 'capturing-host-tree' ||\n\tphase === 'saving-state' ||\n\tphase === 'saving-contributions' ||\n\tphase === 'writing-metadata' ||\n\tphase === 'resuming';\n\nconst SnapshotStatusLine = ({ status }: { readonly status: SnapshotStatus }): React.JSX.Element => {\n\tswitch (status.tag) {\n\t\tcase 'running': {\n\t\t\tconst paused = snapshotPhaseMeansPaused(status.phase);\n\t\t\tconst count =\n\t\t\t\tstatus.pausedContainers !== undefined && status.totalContainers !== undefined\n\t\t\t\t\t? `${status.pausedContainers}/${status.totalContainers}`\n\t\t\t\t\t: null;\n\t\t\treturn (\n\t\t\t\t<Box flexDirection=\"row\" gap={1} marginTop={1}>\n\t\t\t\t\t<Text color={paused ? 'yellow' : 'cyan'}>Snapshot:</Text>\n\t\t\t\t\t<Text>{snapshotLabel(status)}</Text>\n\t\t\t\t\t<Text color={paused ? 'yellow' : 'cyan'}>{snapshotPhaseLabel(status.phase)}</Text>\n\t\t\t\t\t{paused && <Text color=\"yellow\">stack paused</Text>}\n\t\t\t\t\t{count !== null && <Text dimColor>{count}</Text>}\n\t\t\t\t\t{status.detail !== undefined && <Text dimColor>{status.detail}</Text>}\n\t\t\t\t</Box>\n\t\t\t);\n\t\t}\n\t\tcase 'captured':\n\t\t\treturn (\n\t\t\t\t<Box flexDirection=\"row\" gap={1} marginTop={1}>\n\t\t\t\t\t<Text color=\"green\">Snapshot:</Text>\n\t\t\t\t\t<Text>{snapshotLabel(status)}</Text>\n\t\t\t\t\t<Text color=\"green\">saved</Text>\n\t\t\t\t\t<Text dimColor>{status.snapshotId}</Text>\n\t\t\t\t</Box>\n\t\t\t);\n\t\tcase 'skipped':\n\t\t\treturn (\n\t\t\t\t<Box flexDirection=\"row\" gap={1} marginTop={1}>\n\t\t\t\t\t<Text color=\"yellow\">Snapshot:</Text>\n\t\t\t\t\t<Text color=\"yellow\">capture already running</Text>\n\t\t\t\t</Box>\n\t\t\t);\n\t\tcase 'failed':\n\t\t\treturn (\n\t\t\t\t<Box flexDirection=\"row\" gap={1} marginTop={1}>\n\t\t\t\t\t<Text color=\"red\">Snapshot:</Text>\n\t\t\t\t\t<Text>{snapshotLabel(status)}</Text>\n\t\t\t\t\t<Text color=\"red\">failed</Text>\n\t\t\t\t\t<Text dimColor>{status.summary}</Text>\n\t\t\t\t</Box>\n\t\t\t);\n\t}\n};\n\nexport const Dashboard = ({\n\tstate,\n\teventLog,\n\tsnapshotPromptValue,\n\tsnapshotStatus,\n}: DashboardProps): React.JSX.Element => {\n\tconst { identity, cycle, rows, endpoints, accounts, packages } = state;\n\tconst summary = deriveDashboardSummary(state);\n\n\treturn (\n\t\t<Box flexDirection=\"column\">\n\t\t\t{eventLog.length > 0 && (\n\t\t\t\t<Static items={[...eventLog]}>\n\t\t\t\t\t{(entry) => (\n\t\t\t\t\t\t<Box key={entry.id} flexDirection=\"row\" gap={1}>\n\t\t\t\t\t\t\t<Text dimColor>{entry.time}</Text>\n\t\t\t\t\t\t\t<Text color={entry.scopeColor}>{entry.scope}</Text>\n\t\t\t\t\t\t\t<Text color={logMessageColor(entry.level)}>{entry.message}</Text>\n\t\t\t\t\t\t</Box>\n\t\t\t\t\t)}\n\t\t\t\t</Static>\n\t\t\t)}\n\n\t\t\t{state.stackBuild.length > 0 && (\n\t\t\t\t<Static items={[...state.stackBuild]}>\n\t\t\t\t\t{(entry, idx) => (\n\t\t\t\t\t\t<Text key={idx} dimColor>\n\t\t\t\t\t\t\t[build] {entry.pluginKey ?? '<stack>'} - {entry.phase} {entry.progress}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t)}\n\t\t\t\t</Static>\n\t\t\t)}\n\n\t\t\t{/* Header — identity + cycle + heartbeat */}\n\t\t\t<Box flexDirection=\"row\" gap={2} marginTop={1}>\n\t\t\t\t<Text bold color=\"cyan\">\n\t\t\t\t\t{identity.app}/{identity.stack}\n\t\t\t\t</Text>\n\t\t\t\t<Text dimColor>network={identity.network}</Text>\n\t\t\t\t<Text dimColor>cycle={cycle.id}</Text>\n\t\t\t\t<Text color={phaseColor(cycle.phase)}>{cycle.phase}</Text>\n\t\t\t\t<Heartbeat />\n\t\t\t</Box>\n\t\t\t<Box>\n\t\t\t\t<Text color={healthColor(summary.health)}>{dashboardSummaryLine(summary)}</Text>\n\t\t\t</Box>\n\n\t\t\t<Box flexDirection=\"column\" marginTop={1}>\n\t\t\t\t<ResourceTables rows={rows} endpoints={endpoints} accounts={accounts} packages={packages} />\n\t\t\t</Box>\n\n\t\t\t{snapshotPromptValue !== null && (\n\t\t\t\t<Box flexDirection=\"row\" gap={1} marginTop={1}>\n\t\t\t\t\t<Text color=\"cyan\">Snapshot name:</Text>\n\t\t\t\t\t<Text>{snapshotPromptValue.length === 0 ? '<auto>' : snapshotPromptValue}</Text>\n\t\t\t\t\t<Text inverse> </Text>\n\t\t\t\t\t<Text dimColor>Enter save Esc cancel</Text>\n\t\t\t\t</Box>\n\t\t\t)}\n\n\t\t\t{snapshotStatus !== null && <SnapshotStatusLine status={snapshotStatus} />}\n\n\t\t\t{/* Footer — commands. */}\n\t\t\t<Box flexDirection=\"row\" gap={2} marginTop={1}>\n\t\t\t\t<Text>[q] quit</Text>\n\t\t\t\t<Text>[r] restart stack</Text>\n\t\t\t\t<Text>[s] snapshot name</Text>\n\t\t\t</Box>\n\t\t</Box>\n\t);\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dashboard.mjs","names":[],"sources":["../../../src/surfaces/tui/dashboard.tsx"],"sourcesContent":["// Dashboard — composes the visible TUI: header, rows, endpoints,\n// log tails, heartbeat.\n//\n// Reads ONLY the typed projection (`SubscribableState`). Calls the\n// pure derivation helpers in `display-derivation.ts` for every visible\n// cell. The dashboard does NOT subscribe to the SubscriptionRef\n// itself — `app.tsx` owns the subscription and feeds `state` in as a\n// prop. This keeps the dashboard pure-render-of-state, which is what\n// the architecture's \"frame stability\" invariant requires.\n\nimport { Box, Static, Text } from 'ink';\nimport type React from 'react';\n\nimport type { SubscribableState } from '../../substrate/projection.ts';\nimport type { EventLogLine } from './event-log.ts';\nimport { Heartbeat } from './heartbeat.tsx';\nimport { ResourceTables } from './resource-table.tsx';\nimport { dashboardSummaryLine, deriveDashboardSummary } from './display-derivation.ts';\n\nconst phaseColor = (\n\tphase: SubscribableState['cycle']['phase'],\n): 'green' | 'yellow' | 'red' | 'white' => {\n\tswitch (phase) {\n\t\tcase 'running':\n\t\t\treturn 'green';\n\t\tcase 'booting':\n\t\tcase 'restarting':\n\t\t\treturn 'yellow';\n\t\tcase 'shutting-down':\n\t\t\treturn 'red';\n\t\tdefault:\n\t\t\treturn 'white';\n\t}\n};\n\nexport interface DashboardProps {\n\treadonly state: SubscribableState;\n\treadonly eventLog: ReadonlyArray<EventLogLine>;\n\treadonly snapshotPromptValue: string | null;\n\treadonly snapshotStatus: SnapshotStatus | null;\n}\n\nexport type SnapshotStatus =\n\t| {\n\t\t\treadonly tag: 'captured';\n\t\t\treadonly snapshotId: string;\n\t\t\treadonly name?: string;\n\t\t\treadonly at: number;\n\t }\n\t| {\n\t\t\treadonly tag: 'skipped';\n\t\t\treadonly reason: 'already-running';\n\t\t\treadonly at: number;\n\t }\n\t| {\n\t\t\treadonly tag: 'failed';\n\t\t\treadonly snapshotId?: string;\n\t\t\treadonly name?: string;\n\t\t\treadonly summary: string;\n\t\t\treadonly at: number;\n\t };\n\nconst logMessageColor = (level: EventLogLine['level']): 'white' | 'yellow' | 'red' => {\n\tswitch (level) {\n\t\tcase 'info':\n\t\t\treturn 'white';\n\t\tcase 'warn':\n\t\t\treturn 'yellow';\n\t\tcase 'error':\n\t\t\treturn 'red';\n\t}\n};\n\nconst healthColor = (\n\thealth: ReturnType<typeof deriveDashboardSummary>['health'],\n): 'green' | 'yellow' | 'red' | 'white' => {\n\tswitch (health) {\n\t\tcase 'ready':\n\t\t\treturn 'green';\n\t\tcase 'active':\n\t\t\treturn 'yellow';\n\t\tcase 'blocked':\n\t\t\treturn 'red';\n\t\tcase 'empty':\n\t\t\treturn 'white';\n\t}\n};\n\nconst snapshotLabel = (status: SnapshotStatus): string => {\n\tif ('name' in status && status.name !== undefined) return status.name;\n\tif ('snapshotId' in status && status.snapshotId !== undefined) return status.snapshotId;\n\treturn 'manual snapshot';\n};\n\nconst SnapshotStatusLine = ({ status }: { readonly status: SnapshotStatus }): React.JSX.Element => {\n\tswitch (status.tag) {\n\t\tcase 'captured':\n\t\t\treturn (\n\t\t\t\t<Box flexDirection=\"row\" gap={1} marginTop={1}>\n\t\t\t\t\t<Text color=\"green\">Snapshot:</Text>\n\t\t\t\t\t<Text>{snapshotLabel(status)}</Text>\n\t\t\t\t\t<Text color=\"green\">saved</Text>\n\t\t\t\t\t<Text dimColor>{status.snapshotId}</Text>\n\t\t\t\t</Box>\n\t\t\t);\n\t\tcase 'skipped':\n\t\t\treturn (\n\t\t\t\t<Box flexDirection=\"row\" gap={1} marginTop={1}>\n\t\t\t\t\t<Text color=\"yellow\">Snapshot:</Text>\n\t\t\t\t\t<Text color=\"yellow\">capture already running</Text>\n\t\t\t\t</Box>\n\t\t\t);\n\t\tcase 'failed':\n\t\t\treturn (\n\t\t\t\t<Box flexDirection=\"row\" gap={1} marginTop={1}>\n\t\t\t\t\t<Text color=\"red\">Snapshot:</Text>\n\t\t\t\t\t<Text>{snapshotLabel(status)}</Text>\n\t\t\t\t\t<Text color=\"red\">failed</Text>\n\t\t\t\t\t<Text dimColor>{status.summary}</Text>\n\t\t\t\t</Box>\n\t\t\t);\n\t}\n};\n\nexport const Dashboard = ({\n\tstate,\n\teventLog,\n\tsnapshotPromptValue,\n\tsnapshotStatus,\n}: DashboardProps): React.JSX.Element => {\n\tconst { identity, cycle, rows, endpoints, accounts, packages } = state;\n\tconst summary = deriveDashboardSummary(state);\n\n\treturn (\n\t\t<Box flexDirection=\"column\">\n\t\t\t{eventLog.length > 0 && (\n\t\t\t\t<Static items={[...eventLog]}>\n\t\t\t\t\t{(entry) => (\n\t\t\t\t\t\t<Box key={entry.id} flexDirection=\"row\" gap={1}>\n\t\t\t\t\t\t\t<Text dimColor>{entry.time}</Text>\n\t\t\t\t\t\t\t<Text color={entry.scopeColor}>{entry.scope}</Text>\n\t\t\t\t\t\t\t<Text color={logMessageColor(entry.level)}>{entry.message}</Text>\n\t\t\t\t\t\t</Box>\n\t\t\t\t\t)}\n\t\t\t\t</Static>\n\t\t\t)}\n\n\t\t\t{state.stackBuild.length > 0 && (\n\t\t\t\t<Static items={[...state.stackBuild]}>\n\t\t\t\t\t{(entry, idx) => (\n\t\t\t\t\t\t<Text key={idx} dimColor>\n\t\t\t\t\t\t\t[build] {entry.pluginKey ?? '<stack>'} - {entry.phase} {entry.progress}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t)}\n\t\t\t\t</Static>\n\t\t\t)}\n\n\t\t\t{/* Header — identity + cycle + heartbeat */}\n\t\t\t<Box flexDirection=\"row\" gap={2} marginTop={1}>\n\t\t\t\t<Text bold color=\"cyan\">\n\t\t\t\t\t{identity.app}/{identity.stack}\n\t\t\t\t</Text>\n\t\t\t\t<Text dimColor>network={identity.network}</Text>\n\t\t\t\t<Text dimColor>cycle={cycle.id}</Text>\n\t\t\t\t<Text color={phaseColor(cycle.phase)}>{cycle.phase}</Text>\n\t\t\t\t<Heartbeat />\n\t\t\t</Box>\n\t\t\t<Box>\n\t\t\t\t<Text color={healthColor(summary.health)}>{dashboardSummaryLine(summary)}</Text>\n\t\t\t</Box>\n\n\t\t\t<Box flexDirection=\"column\" marginTop={1}>\n\t\t\t\t<ResourceTables rows={rows} endpoints={endpoints} accounts={accounts} packages={packages} />\n\t\t\t</Box>\n\n\t\t\t{snapshotPromptValue !== null && (\n\t\t\t\t<Box flexDirection=\"row\" gap={1} marginTop={1}>\n\t\t\t\t\t<Text color=\"cyan\">Snapshot name:</Text>\n\t\t\t\t\t<Text>{snapshotPromptValue.length === 0 ? '<auto>' : snapshotPromptValue}</Text>\n\t\t\t\t\t<Text inverse> </Text>\n\t\t\t\t\t<Text dimColor>Enter save Esc cancel</Text>\n\t\t\t\t</Box>\n\t\t\t)}\n\n\t\t\t{snapshotStatus !== null && <SnapshotStatusLine status={snapshotStatus} />}\n\n\t\t\t{/* Footer — commands. */}\n\t\t\t<Box flexDirection=\"row\" gap={2} marginTop={1}>\n\t\t\t\t<Text>[q] quit</Text>\n\t\t\t\t<Text>[r] restart stack</Text>\n\t\t\t\t<Text>[s] snapshot name</Text>\n\t\t\t</Box>\n\t\t</Box>\n\t);\n};\n"],"mappings":"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"}
|