@mysten-incubation/devstack 0.2.0 → 0.4.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 +1 -1
- package/dashboard-ui/assets/{grpc-a4usE3Nk.js → grpc-CpkDu4SA.js} +1 -1
- package/dashboard-ui/assets/{index-CRYJ4pru.js → index-jLPRmjst.js} +39 -33
- package/dashboard-ui/index.html +1 -1
- package/dist/api/inference-network.d.mts +5 -5
- package/dist/api/inference-network.mjs +5 -5
- package/dist/api/inference-network.mjs.map +1 -1
- package/dist/api/run-stack-internal.mjs +2 -3
- package/dist/api/run-stack-internal.mjs.map +1 -1
- package/dist/build-integrations/dapp-kit/index.d.mts +12 -0
- package/dist/build-integrations/dapp-kit/index.mjs +14 -1
- package/dist/build-integrations/dapp-kit/index.mjs.map +1 -1
- package/dist/build-integrations/playwright/config.d.mts +2 -1
- package/dist/build-integrations/playwright/config.mjs +1 -1
- package/dist/build-integrations/playwright/config.mjs.map +1 -1
- package/dist/build-integrations/playwright/errors.d.mts +1 -1
- package/dist/build-integrations/playwright/errors.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/wallet-context.d.mts +2 -1
- package/dist/build-integrations/playwright/wallet-context.mjs +141 -41
- package/dist/build-integrations/playwright/wallet-context.mjs.map +1 -1
- package/dist/build-integrations/runtime/dapp-kit-slot.mjs +1 -1
- package/dist/build-integrations/runtime/dapp-kit-slot.mjs.map +1 -1
- package/dist/build-integrations/vite/index.d.mts +82 -40
- package/dist/build-integrations/vite/index.mjs +281 -112
- package/dist/build-integrations/vite/index.mjs.map +1 -1
- package/dist/build-integrations/vitest/config.mjs +3 -4
- package/dist/build-integrations/vitest/config.mjs.map +1 -1
- package/dist/build-integrations/vitest/global-setup.mjs +8 -8
- package/dist/build-integrations/vitest/global-setup.mjs.map +1 -1
- package/dist/cli/doctor-probes.mjs +7 -2
- package/dist/cli/doctor-probes.mjs.map +1 -1
- package/dist/cli/main.mjs +5 -4
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/wirings/apply.mjs +0 -1
- package/dist/cli/wirings/apply.mjs.map +1 -1
- package/dist/cli/wirings/codegen.mjs +37 -38
- package/dist/cli/wirings/codegen.mjs.map +1 -1
- package/dist/cli/wirings/dump-deployment.mjs +141 -0
- package/dist/cli/wirings/dump-deployment.mjs.map +1 -0
- package/dist/cli/wirings/snapshot.mjs +0 -1
- package/dist/cli/wirings/snapshot.mjs.map +1 -1
- package/dist/cli/wirings/up.mjs +7 -0
- package/dist/cli/wirings/up.mjs.map +1 -1
- package/dist/contracts/codegenable.d.mts +22 -25
- package/dist/contracts/codegenable.mjs +35 -4
- package/dist/contracts/codegenable.mjs.map +1 -1
- package/dist/contracts/config-bindings.mjs +43 -18
- package/dist/contracts/config-bindings.mjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/orchestrators/boot.d.mts +0 -10
- package/dist/orchestrators/boot.mjs +24 -54
- package/dist/orchestrators/boot.mjs.map +1 -1
- package/dist/orchestrators/codegen/bindings.mjs.map +1 -1
- package/dist/orchestrators/codegen/config-runtime.mjs +137 -112
- package/dist/orchestrators/codegen/config-runtime.mjs.map +1 -1
- package/dist/orchestrators/codegen/deployment-network-file.mjs +130 -0
- package/dist/orchestrators/codegen/deployment-network-file.mjs.map +1 -0
- package/dist/orchestrators/codegen/deployment-strict.mjs +77 -0
- package/dist/orchestrators/codegen/deployment-strict.mjs.map +1 -0
- package/dist/orchestrators/codegen/deployment.d.mts +63 -0
- package/dist/orchestrators/codegen/deployment.mjs +153 -0
- package/dist/orchestrators/codegen/deployment.mjs.map +1 -0
- package/dist/orchestrators/codegen/errors.mjs +7 -9
- package/dist/orchestrators/codegen/errors.mjs.map +1 -1
- package/dist/orchestrators/codegen/format.mjs +20 -1
- package/dist/orchestrators/codegen/format.mjs.map +1 -1
- package/dist/orchestrators/codegen/paths.mjs +1 -8
- package/dist/orchestrators/codegen/paths.mjs.map +1 -1
- package/dist/orchestrators/codegen/service.mjs +369 -141
- package/dist/orchestrators/codegen/service.mjs.map +1 -1
- package/dist/orchestrators/layers.mjs +0 -1
- package/dist/orchestrators/layers.mjs.map +1 -1
- package/dist/orchestrators/network-options.d.mts +37 -35
- package/dist/orchestrators/network-options.mjs +13 -10
- package/dist/orchestrators/network-options.mjs.map +1 -1
- package/dist/plugins/account/codegen.d.mts +3 -4
- package/dist/plugins/account/codegen.mjs +5 -7
- package/dist/plugins/account/codegen.mjs.map +1 -1
- package/dist/plugins/account/index.mjs +1 -3
- package/dist/plugins/account/index.mjs.map +1 -1
- package/dist/plugins/coin/codegen.mjs +5 -5
- package/dist/plugins/coin/codegen.mjs.map +1 -1
- package/dist/plugins/coin/index.mjs.map +1 -1
- package/dist/plugins/dashboard/domain.mjs +18 -1
- package/dist/plugins/dashboard/domain.mjs.map +1 -1
- package/dist/plugins/dashboard/schema/root.mjs +5 -3
- package/dist/plugins/dashboard/schema/root.mjs.map +1 -1
- package/dist/plugins/dashboard/schema/types.mjs +15 -2
- package/dist/plugins/dashboard/schema/types.mjs.map +1 -1
- package/dist/plugins/deepbook/codegen.mjs +4 -4
- package/dist/plugins/deepbook/codegen.mjs.map +1 -1
- package/dist/plugins/deepbook/index.d.mts +7 -3
- package/dist/plugins/deepbook/index.mjs +3 -3
- package/dist/plugins/deepbook/index.mjs.map +1 -1
- package/dist/plugins/internal/codegen-helpers.mjs +0 -1
- package/dist/plugins/internal/codegen-helpers.mjs.map +1 -1
- package/dist/plugins/package/codegen.d.mts +1 -12
- package/dist/plugins/package/codegen.mjs +43 -25
- package/dist/plugins/package/codegen.mjs.map +1 -1
- package/dist/plugins/package/dep-resolution.mjs +1 -1
- package/dist/plugins/package/dep-resolution.mjs.map +1 -1
- package/dist/plugins/package/index.d.mts +14 -11
- package/dist/plugins/package/index.mjs +6 -7
- package/dist/plugins/package/index.mjs.map +1 -1
- package/dist/plugins/seal/codegen.mjs +3 -3
- package/dist/plugins/seal/codegen.mjs.map +1 -1
- package/dist/plugins/seal/index.mjs.map +1 -1
- package/dist/plugins/sui/codegen.mjs +5 -4
- package/dist/plugins/sui/codegen.mjs.map +1 -1
- package/dist/plugins/sui/index.d.mts +10 -10
- package/dist/plugins/sui/index.mjs +1 -2
- package/dist/plugins/sui/index.mjs.map +1 -1
- package/dist/plugins/sui/move-summary-runner.mjs +29 -2
- package/dist/plugins/sui/move-summary-runner.mjs.map +1 -1
- package/dist/plugins/wallet/codegen.d.mts +8 -12
- package/dist/plugins/wallet/codegen.mjs +22 -15
- package/dist/plugins/wallet/codegen.mjs.map +1 -1
- package/dist/plugins/wallet/index.d.mts +4 -3
- package/dist/plugins/wallet/index.mjs +1 -1
- package/dist/plugins/wallet/index.mjs.map +1 -1
- package/dist/plugins/wallet/service.d.mts +2 -2
- package/dist/plugins/wallet/service.mjs +2 -3
- package/dist/plugins/wallet/service.mjs.map +1 -1
- package/dist/plugins/walrus/codegen.mjs +4 -4
- package/dist/plugins/walrus/codegen.mjs.map +1 -1
- package/dist/plugins/walrus/index.mjs +1 -1
- package/dist/plugins/walrus/index.mjs.map +1 -1
- package/dist/substrate/manifest.d.mts +17 -22
- package/dist/substrate/manifest.mjs +4 -6
- package/dist/substrate/manifest.mjs.map +1 -1
- package/dist/substrate/plugin-ctx.d.mts +6 -6
- package/dist/substrate/plugin-ctx.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/liveness.mjs.map +1 -1
- package/dist/substrate/runtime/index.mjs +1 -0
- package/dist/substrate/runtime/lifecycle/file-watcher.d.mts +1 -0
- package/dist/substrate/runtime/lifecycle/file-watcher.mjs +54 -0
- package/dist/substrate/runtime/lifecycle/file-watcher.mjs.map +1 -0
- package/dist/substrate/runtime/lifecycle/index.mjs +1 -0
- package/dist/substrate/runtime/lifecycle/watch-attribution.mjs +76 -6
- package/dist/substrate/runtime/lifecycle/watch-attribution.mjs.map +1 -1
- package/dist/substrate/runtime/manifest/manifest.mjs.map +1 -1
- package/dist/substrate/runtime/paths.mjs +1 -1
- package/dist/substrate/runtime/supervisor/start-supervisor.mjs +2 -6
- package/dist/substrate/runtime/supervisor/start-supervisor.mjs.map +1 -1
- package/dist/surfaces/cli/command-tree.mjs +6 -6
- package/dist/surfaces/cli/command-tree.mjs.map +1 -1
- package/dist/surfaces/cli/index.mjs +6 -4
- package/dist/surfaces/cli/index.mjs.map +1 -1
- package/dist/surfaces/tui/plain-renderer.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/cli/wirings/dump-ids.mjs +0 -86
- package/dist/cli/wirings/dump-ids.mjs.map +0 -1
- package/dist/orchestrators/codegen/id-config.d.mts +0 -1
- package/dist/orchestrators/codegen/id-config.mjs +0 -107
- package/dist/orchestrators/codegen/id-config.mjs.map +0 -1
- package/dist/orchestrators/codegen/output-location.mjs +0 -32
- package/dist/orchestrators/codegen/output-location.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-bindings.mjs","names":[],"sources":["../../src/contracts/config-bindings.ts"],"sourcesContent":["// Unified config-binding contract.\n//\n// THE PROBLEM THIS SOLVES. A config-emitting plugin used to maintain TWO\n// near-duplicate projectors:\n// - a LIVE one (boot): bakes concrete resolved values (real ids, rpc\n// URLs) into the loadable id-config (`assembleIdConfig`), and\n// - a STATIC one (the stack-free `codegen` verb): emits\n// `rawExpr(resolve…())` into the committed `config.ts` so the tree\n// carries NO on-chain id.\n// Two hand-written projectors per plugin is error-prone: forget the static\n// path and the committed tree is incomplete (broken clean-clone build);\n// the fixed typed id-config channel also can't carry arbitrary plugin live\n// values (deepbook pool ids, coin types, walrus/seal endpoints).\n//\n// THE UNIFICATION. A plugin declares its `config.ts` contributions ONCE as\n// a `ConfigBindingSet`. BOTH paths are DERIVED from it:\n// - `configCodegenable(set, 'static')` → the committed-tree decl whose\n// aggregate emits `rawExpr(resolveValue(...))` / typed-sugar resolvers\n// (and pure literals as literals).\n// - `configCodegenable(set, { mode: 'live', state })` → the boot decl\n// whose aggregate carries concrete resolved values that feed ONLY the\n// loadable id-config (typed channel + the generic `values` channel) —\n// no per-stack generated source is written; the committed `src/generated`\n// tree stays the single bindings source.\n//\n// One declaration, two derivations — no parallel projectors to drift.\n\nimport { Effect } from 'effect';\n\nimport type { CodegenableDecl } from './codegenable.ts';\nimport { rawExpr } from './codegenable.ts';\nimport type { JsonValue } from '../orchestrators/codegen/id-config.ts';\n\n// -----------------------------------------------------------------------------\n// Binding shape\n// -----------------------------------------------------------------------------\n\n/** A typed-sugar resolver a binding may target instead of the generic\n * `resolveValue(namespace, key)` channel. Each maps to a `config-runtime.ts`\n * function: `id` → `resolveId(<arg>)`, `network` → `resolveNetwork()`,\n * `networks` → `resolveNetworks()`. Sugar bindings also feed the TYPED\n * id-config fields (`mvrOverrides`/`network`/`networks`), not the generic\n * `values` channel — that keeps `config.network`/`config.mvrOverrides`\n * readable by apps exactly as before. */\nexport type ConfigSugarResolver =\n\t| { readonly kind: 'id'; readonly mvrPlaceholder: string }\n\t| { readonly kind: 'network' }\n\t| { readonly kind: 'networks' };\n\n/**\n * One config-binding. A plugin returns a list of these ONCE; the framework\n * derives both the live and static behaviors from them.\n *\n * Variants:\n * - `literal`: the SAME value in both paths (e.g. the package `mvr`\n * placeholder string, a network NAME you decide is static). Emitted\n * verbatim in `config.ts`; mirrored into the live id-config too.\n * - `resolved`: runtime-resolved. STATIC emits a resolver `rawExpr`;\n * LIVE computes the concrete value via `live(state)` and routes it into\n * the id-config — through the typed channel for a `sugar` resolver, or\n * through the generic `values[namespace][key]` channel otherwise.\n */\nexport type ConfigBinding<State = unknown> =\n\t| {\n\t\t\treadonly variant: 'literal';\n\t\t\t/** Path into the `config.ts` object literal, e.g. `['network']`\n\t\t\t * or `['packages', 'connect_four', 'mvr']`. */\n\t\t\treadonly configPath: ReadonlyArray<string>;\n\t\t\t/** The literal value (identical in both paths). */\n\t\t\treadonly value: JsonValue;\n\t }\n\t| {\n\t\t\treadonly variant: 'resolved';\n\t\t\t/** Path into the `config.ts` object literal. */\n\t\t\treadonly configPath: ReadonlyArray<string>;\n\t\t\t/** Generic-channel coordinates. Always present so the live path\n\t\t\t * can populate `idConfig.values[namespace][key]` even for a\n\t\t\t * sugar-resolved binding (the sugar ALSO feeds the typed field;\n\t\t\t * `values` is harmless redundancy and keeps the guard simple). */\n\t\t\treadonly namespace: string;\n\t\t\treadonly key: string;\n\t\t\t/** When set, the static path emits the typed-sugar resolver\n\t\t\t * (`resolveId`/`resolveNetwork`/`resolveNetworks`) and the live\n\t\t\t * path additionally feeds the TYPED id-config field. When\n\t\t\t * omitted, the static path emits `resolveValue(namespace, key)`\n\t\t\t * and the live value lands ONLY in the generic `values` channel. */\n\t\t\treadonly sugar?: ConfigSugarResolver;\n\t\t\t/** The field's STATIC TypeScript type, as a source string (e.g.\n\t\t\t * `'string'`, `'string | null'`, or a structural literal type for a\n\t\t\t * composite). When set, the static path emits\n\t\t\t * `resolveValue(ns, key) as <tsType>` so the committed value carries\n\t\t\t * its concrete type instead of the `unknown` the generic channel\n\t\t\t * returns. Ignored for sugar bindings (those use the typed resolver\n\t\t\t * whose return type is already concrete). When omitted, the static\n\t\t\t * path emits a bare `resolveValue(ns, key)` (type `unknown`). */\n\t\t\treadonly tsType?: string;\n\t\t\t/** Compute the concrete value at boot from acquired plugin state.\n\t\t\t * Only invoked on the LIVE path. */\n\t\t\treadonly live: (state: State) => JsonValue;\n\t };\n\n/**\n * A plugin's full `config.ts` contribution, declared ONCE.\n *\n * `bucket` is always `'config.ts'` for the typed app config; carried as a\n * field so the orchestrator stays name-blind (it reads the bucket off the\n * decl rather than hard-coding it).\n */\nexport interface ConfigBindingSet<State = unknown> {\n\t/** Aggregate bucket the bindings fold into (always `'config.ts'` today;\n\t * a field so the orchestrator never hard-codes it). */\n\treadonly bucket: string;\n\t/** Diagnostic tag for span attributes (e.g. `'sui-network'`,\n\t * `'package'`). The orchestrator MUST NOT branch on it. */\n\treadonly kind: string;\n\t/** The emitter name the derived `CodegenableDecl` carries. */\n\treadonly emitterName: string;\n\t/** Optional standalone output path. The derived decl is `aggregateOnly`,\n\t * so no per-decl file is written; path-resolution only needs a non-empty,\n\t * per-bucket-unique string, which defaults to `bucket` when omitted. Set\n\t * it only when a standalone path would be genuinely meaningful. */\n\treadonly outputPath?: string;\n\t/** When `true`, the derived decl sets `allowEmitterNameRepetition`\n\t * (one decl per item, e.g. one `package` per published package). */\n\treadonly allowEmitterNameRepetition?: boolean;\n\t/** The bindings. */\n\treadonly bindings: ReadonlyArray<ConfigBinding<State>>;\n}\n\n// -----------------------------------------------------------------------------\n// Derivation\n// -----------------------------------------------------------------------------\n\n/** Set `value` at `path` inside `root`, creating intermediate objects. */\nconst setAtPath = (\n\troot: Record<string, unknown>,\n\tpath: ReadonlyArray<string>,\n\tvalue: unknown,\n): void => {\n\tlet cursor = root;\n\tfor (let i = 0; i < path.length - 1; i++) {\n\t\tconst segment = path[i]!;\n\t\tconst next = cursor[segment];\n\t\tif (typeof next === 'object' && next !== null && !Array.isArray(next)) {\n\t\t\tcursor = next as Record<string, unknown>;\n\t\t} else {\n\t\t\tconst created: Record<string, unknown> = {};\n\t\t\tcursor[segment] = created;\n\t\t\tcursor = created;\n\t\t}\n\t}\n\tcursor[path[path.length - 1]!] = value;\n};\n\n/** The `rawExpr` the STATIC path emits for a resolved binding. */\nconst staticExprFor = <State>(\n\tbinding: Extract<ConfigBinding<State>, { variant: 'resolved' }>,\n): ReturnType<typeof rawExpr> => {\n\tconst sugar = binding.sugar;\n\tif (sugar === undefined) {\n\t\tconst call = `resolveValue(${JSON.stringify(binding.namespace)}, ${JSON.stringify(binding.key)})`;\n\t\t// A `tsType` carries the field's concrete static type so the committed\n\t\t// value typechecks against the app's usage (the generic channel returns\n\t\t// `unknown`). Emit the call as a typed cast; bare otherwise.\n\t\treturn rawExpr(binding.tsType === undefined ? call : `${call} as ${binding.tsType}`);\n\t}\n\tswitch (sugar.kind) {\n\t\tcase 'id':\n\t\t\treturn rawExpr(`resolveId(${JSON.stringify(sugar.mvrPlaceholder)})`);\n\t\tcase 'network':\n\t\t\treturn rawExpr('resolveNetwork()');\n\t\tcase 'networks':\n\t\t\treturn rawExpr('resolveNetworks()');\n\t}\n};\n\n/** Build the STATIC (committed-tree) aggregate projection from a binding\n * set — `rawExpr(resolve…())` for resolved bindings, literals for the\n * rest. Pure: needs no acquired state. */\nexport const projectStaticConfig = <State>(\n\tset: ConfigBindingSet<State>,\n): Record<string, unknown> => {\n\tconst root: Record<string, unknown> = {};\n\tfor (const binding of set.bindings) {\n\t\tconst value = binding.variant === 'literal' ? binding.value : staticExprFor(binding);\n\t\tsetAtPath(root, binding.configPath, value);\n\t}\n\treturn root;\n};\n\n/** Build the LIVE (boot) aggregate projection from a binding set against\n * the acquired plugin state — concrete resolved values everywhere. */\nexport const projectLiveConfig = <State>(\n\tset: ConfigBindingSet<State>,\n\tstate: State,\n): Record<string, unknown> => {\n\tconst root: Record<string, unknown> = {};\n\tfor (const binding of set.bindings) {\n\t\tconst value = binding.variant === 'literal' ? binding.value : binding.live(state);\n\t\tsetAtPath(root, binding.configPath, value);\n\t}\n\treturn root;\n};\n\n/**\n * Derive the live `idConfig.values[namespace][key]` contributions of a\n * binding set. Only `resolved` bindings WITHOUT a `sugar` resolver land in\n * the generic channel (sugar bindings feed the typed id-config fields,\n * sliced from the live `config.ts` bucket by `idConfigFromBucket`). The\n * generic channel is the part the fixed typed schema can't carry.\n */\nexport const liveValuesOf = <State>(\n\tset: ConfigBindingSet<State>,\n\tstate: State,\n): Record<string, Record<string, JsonValue>> => {\n\tconst out: Record<string, Record<string, JsonValue>> = {};\n\tfor (const binding of set.bindings) {\n\t\tif (binding.variant !== 'resolved' || binding.sugar !== undefined) continue;\n\t\tconst ns = (out[binding.namespace] ??= {});\n\t\tns[binding.key] = binding.live(state);\n\t}\n\treturn out;\n};\n\n/**\n * Derive a `CodegenableDecl` from a binding set.\n *\n * `'static'` → the committed-tree decl (stack-free `codegen` verb). Its\n * aggregate emits `rawExpr(resolve…())` for resolved bindings.\n *\n * `{ mode: 'live', state }` → the boot decl. Its aggregate bakes concrete\n * values from `state`; boot's `assembleIdConfig` reads those back into the\n * loadable id-config (typed channel + the generic `values` channel).\n */\nexport const configCodegenable = <State, Emitter extends string = string>(\n\tset: ConfigBindingSet<State>,\n\thow: 'static' | { readonly mode: 'live'; readonly state: State },\n\toptions: {\n\t\t/** Extra `export const <name> = <value>` declarations to emit on the\n\t\t * decl's `emit` context, instead of the default placeholder export.\n\t\t * The package plugin uses this to export its `packageBindings` object\n\t\t * so the orchestrator's `isPackageBindings` seam can forward it to the\n\t\t * Move-bindings emitter. When omitted, a single minimal placeholder\n\t\t * export is emitted (the projection is what the aggregate folds). */\n\t\treadonly extraExports?: Readonly<Record<string, unknown>>;\n\t} = {},\n): CodegenableDecl<Emitter> => {\n\tconst live = how !== 'static';\n\tconst projected = live ? projectLiveConfig(set, how.state) : projectStaticConfig(set);\n\tconst idConfigValues = live ? liveValuesOf(set, how.state) : {};\n\tconst extraExports = options.extraExports;\n\treturn {\n\t\tkind: 'codegenable',\n\t\temitterName: set.emitterName as Emitter,\n\t\t// `aggregateOnly` never writes a standalone file; default the\n\t\t// path-resolution placeholder to the bucket name so plugins don't\n\t\t// invent dead paths.\n\t\toutputPath: set.outputPath ?? set.bucket,\n\t\taggregateOnly: true,\n\t\t...(set.allowEmitterNameRepetition === true ? { allowEmitterNameRepetition: true } : {}),\n\t\taggregate: {\n\t\t\tkind: set.kind,\n\t\t\tbucket: set.bucket,\n\t\t\t// The projection is precomputed above (pure over `set`/`state`);\n\t\t\t// the orchestrator calls `project(exported)` with the emitted map\n\t\t\t// but the value is already fixed, so we ignore the argument.\n\t\t\tproject: () => projected,\n\t\t\t// Only the live aggregate feeds the generic id-config channel.\n\t\t\t...(live && Object.keys(idConfigValues).length > 0 ? { idConfigValues } : {}),\n\t\t},\n\t\temit: (ctx) =>\n\t\t\tEffect.sync(() => {\n\t\t\t\tif (extraExports !== undefined) {\n\t\t\t\t\tfor (const [name, value] of Object.entries(extraExports)) {\n\t\t\t\t\t\tctx.exportConst(name, value);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// A placeholder export so the emitter runs; the projection is\n\t\t\t\t\t// what the aggregate folds. Kept minimal + name-stable.\n\t\t\t\t\tctx.exportConst('__configBindings', set.kind);\n\t\t\t\t}\n\t\t\t\treturn ctx.done();\n\t\t\t}),\n\t};\n};\n\n// -----------------------------------------------------------------------------\n// Sibling-keyed bucket bindings\n// -----------------------------------------------------------------------------\n//\n// The own-bucket service plugins (coin → `coins.ts`, deepbook → `deepbook.ts`,\n// seal → `seal.ts`) emit a name-keyed bucket where distinct instances deep-merge\n// into one `<bucket>.ts` exporting `{ <instanceKey>: { ...fields } }`. They\n// declare their per-instance contribution as a flat list of `BucketField`s\n// (each a structural literal or a runtime-resolved value rooted under the\n// instance key); the helpers below derive the `ConfigBindingSet` and both the\n// live/static decls from it, so there are no parallel projectors to drift.\n\n/** One field of an instance's bucket entry, classified as either a pure\n * STRUCTURAL literal (a name / mode / decimals — the same in both paths)\n * or a runtime-RESOLVED value (an on-chain id, coin type, or endpoint URL —\n * the static path emits `resolveValue`, the live path feeds the concrete\n * value into the id-config). The `key` is the leaf field name written under\n * the instance key in the bucket object literal. */\nexport type BucketField<State> =\n\t| { readonly key: string; readonly variant: 'literal'; readonly value: JsonValue }\n\t| {\n\t\t\treadonly key: string;\n\t\t\treadonly variant: 'resolved';\n\t\t\t/** `resolveValue(namespace, valueKey)` coordinates. `valueKey`\n\t\t\t * defaults to `key` when omitted. */\n\t\t\treadonly valueKey?: string;\n\t\t\t/** The field's STATIC TypeScript type as a source string (see\n\t\t\t * `ConfigBinding.tsType`). When set, the static path emits\n\t\t\t * `resolveValue(...) as <tsType>` so the committed value carries its\n\t\t\t * concrete type instead of `unknown`. */\n\t\t\treadonly tsType?: string;\n\t\t\treadonly live: (state: State) => JsonValue;\n\t };\n\nexport interface SiblingBucketSpec<State> {\n\t/** The aggregate bucket filename, e.g. `'coins.ts'`. */\n\treadonly bucket: string;\n\t/** Diagnostic kind tag (e.g. `'coin'`) — the orchestrator never\n\t * branches on it. */\n\treadonly kind: string;\n\t/** The emitter name the derived decl carries (literal, e.g.\n\t * `coin/<symbol>`). */\n\treadonly emitterName: string;\n\t/** Optional standalone output path. Defaults to `bucket` (the decl is\n\t * `aggregateOnly`, so no per-decl file is written). */\n\treadonly outputPath?: string;\n\t/** The instance key the entry lives under in the bucket object\n\t * (e.g. the coin symbol, the deepbook instance name). */\n\treadonly instanceKey: string;\n\t/** The `resolveValue` namespace shared by every resolved field\n\t * (e.g. `coin:<symbol>`, `deepbook:<name>`). */\n\treadonly namespace: string;\n\t/** The instance's fields. */\n\treadonly fields: ReadonlyArray<BucketField<State>>;\n\t/** When `true`, the derived decl sets `allowEmitterNameRepetition`\n\t * (sibling instances share an emitter-name prefix). */\n\treadonly allowEmitterNameRepetition?: boolean;\n}\n\n/** Convenience constructor for the keyed-bucket shape the service plugins\n * share (coin/deepbook/seal): every sibling instance keys under `<key>` in\n * `<bucket>`, with `emitterName = `<kind>/<key>``, `namespace = `<kind>:<key>``,\n * `instanceKey = <key>`, and `allowEmitterNameRepetition` (instances share the\n * `<kind>/` emitter prefix). Only `bucket`/`kind`/`key`/`fields` vary across\n * those plugins, so this keeps the `<kind>/<key>` + `<kind>:<key>` naming\n * convention in ONE place instead of re-spelling it per plugin. */\nexport const keyedBucketSpec = <State>(input: {\n\treadonly bucket: string;\n\treadonly kind: string;\n\treadonly key: string;\n\treadonly fields: ReadonlyArray<BucketField<State>>;\n}): SiblingBucketSpec<State> => ({\n\tbucket: input.bucket,\n\tkind: input.kind,\n\temitterName: `${input.kind}/${input.key}`,\n\tinstanceKey: input.key,\n\tnamespace: `${input.kind}:${input.key}`,\n\tallowEmitterNameRepetition: true,\n\tfields: input.fields,\n});\n\n/** Build the `ConfigBindingSet` for a sibling-keyed bucket instance. The\n * `configPath` of every binding is rooted at the instance key, so distinct\n * instances deep-merge into one `<bucket>.ts` exporting\n * `{ <instanceKey>: { ...fields } }`. */\nexport const siblingBucketBindings = <State>(\n\tspec: SiblingBucketSpec<State>,\n): ConfigBindingSet<State> => {\n\tconst bindings: Array<ConfigBinding<State>> = spec.fields.map((field) => {\n\t\tconst configPath = [spec.instanceKey, field.key] as const;\n\t\tif (field.variant === 'literal') {\n\t\t\treturn { variant: 'literal', configPath: [...configPath], value: field.value };\n\t\t}\n\t\treturn {\n\t\t\tvariant: 'resolved',\n\t\t\tconfigPath: [...configPath],\n\t\t\tnamespace: spec.namespace,\n\t\t\tkey: field.valueKey ?? field.key,\n\t\t\t// No `sugar` — these are generic `resolveValue` bindings (the typed\n\t\t\t// id-config channel only carries network/packages/mvrOverrides).\n\t\t\t...(field.tsType !== undefined ? { tsType: field.tsType } : {}),\n\t\t\tlive: field.live,\n\t\t};\n\t});\n\treturn {\n\t\tbucket: spec.bucket,\n\t\tkind: spec.kind,\n\t\temitterName: spec.emitterName,\n\t\t...(spec.outputPath !== undefined ? { outputPath: spec.outputPath } : {}),\n\t\t...(spec.allowEmitterNameRepetition === true ? { allowEmitterNameRepetition: true } : {}),\n\t\tbindings,\n\t};\n};\n\n/** Derive the LIVE bucket decl — feeds concrete values into the generic\n * id-config `values` channel (no per-stack generated file is written). */\nexport const liveBucketCodegen = <State>(\n\tspec: SiblingBucketSpec<State>,\n\tstate: State,\n): CodegenableDecl => configCodegenable(siblingBucketBindings(spec), { mode: 'live', state });\n\n/** Derive the STATIC (stack-free) bucket decl — emits\n * `resolveValue(namespace, key)` for resolved fields, literals for the\n * rest. The committed `<bucket>.ts` carries no baked runtime value. */\nexport const staticBucketCodegen = <State>(spec: SiblingBucketSpec<State>): CodegenableDecl =>\n\tconfigCodegenable(siblingBucketBindings(spec), 'static');\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config-bindings.mjs","names":[],"sources":["../../src/contracts/config-bindings.ts"],"sourcesContent":["// Unified config-binding contract.\n//\n// THE PROBLEM THIS SOLVES. A config-emitting plugin used to maintain TWO\n// near-duplicate projectors:\n// - a LIVE one (boot): bakes concrete resolved values (real ids, rpc\n// URLs) into the loadable deployment (`assembleDeployment`), and\n// - a STATIC one (the stack-free `codegen` verb): emits\n// `rawExpr(resolve…())` into the committed `config.ts` so the tree\n// carries NO on-chain id.\n// Two hand-written projectors per plugin is error-prone: forget the static\n// path and the committed tree is incomplete (broken clean-clone build);\n// the fixed typed deployment channel also can't carry arbitrary plugin live\n// values (deepbook pool ids, coin types, walrus/seal endpoints).\n//\n// THE UNIFICATION. A plugin declares its `config.ts` contributions ONCE as\n// a `ConfigBindingSet`. BOTH paths are DERIVED from it:\n// - `configCodegenable(set, 'static')` → the committed-tree decl whose\n// aggregate emits `rawExpr(requireValue(dep, ...))` / typed-sugar\n// deployment accessors (and pure literals as literals).\n// - `configCodegenable(set, { mode: 'live', state })` → the boot decl\n// whose aggregate carries concrete resolved values that feed ONLY the\n// loadable deployment (typed channel + the generic `values` channel) —\n// no per-stack generated source is written; the committed `src/generated`\n// tree stays the single bindings source.\n//\n// One declaration, two derivations — no parallel projectors to drift.\n\nimport { Effect } from 'effect';\n\nimport type { CodegenableDecl } from './codegenable.ts';\nimport { rawExpr } from './codegenable.ts';\nimport type { JsonValue } from '../orchestrators/codegen/deployment.ts';\n\n// -----------------------------------------------------------------------------\n// Binding shape\n// -----------------------------------------------------------------------------\n\n/** A typed-sugar resolver a binding may target instead of the generic\n * `requireValue(dep, namespace, key)` channel. Each maps to a deployment\n * accessor: `id` → `requireId(dep, <arg>)`, `network` → `dep.network`,\n * `networks` → `Object.fromEntries(__deployment.networkNames.map((n) =>\n * [n, __deployment.forNetwork(n)]))`, `mvrType` →\n * `` `${requireId(dep, \"<mvr>\")}::<typeSuffix>` `` (an MVR `types` override\n * entry). Sugar bindings also feed the TYPED\n * deployment fields (`mvrOverrides`/`network`/`networks`), not the generic\n * `values` channel — that keeps `config.network`/`config.mvrOverrides`\n * readable by apps exactly as before. */\nexport type ConfigSugarResolver =\n\t| { readonly kind: 'id'; readonly mvrPlaceholder: string }\n\t| { readonly kind: 'network' }\n\t| { readonly kind: 'networks' }\n\t| {\n\t\t\t/** An MVR `types` override entry. The static path emits the\n\t\t\t * per-network resolved type tag\n\t\t\t * `` `${requireId(dep, \"<mvrPlaceholder>\")}::<typeSuffix>` `` (the\n\t\t\t * `@local/<slug>` package prefix substituted with the active-network\n\t\t\t * package id); the live path's value is IGNORED by the live deployment\n\t\t\t * slice (`deploymentFromBucket` keeps `mvrOverrides.types: {}`), so the\n\t\t\t * committed `config.ts` is the only carrier of the declared types. */\n\t\t\treadonly kind: 'mvrType';\n\t\t\treadonly mvrPlaceholder: string;\n\t\t\t/** The `<module>::<Name>` suffix beneath the package prefix. */\n\t\t\treadonly typeSuffix: string;\n\t };\n\n/**\n * One config-binding. A plugin returns a list of these ONCE; the framework\n * derives both the live and static behaviors from them.\n *\n * Variants:\n * - `literal`: the SAME value in both paths (e.g. the package `mvr`\n * placeholder string, a network NAME you decide is static). Emitted\n * verbatim in `config.ts`; mirrored into the live deployment too.\n * - `resolved`: runtime-resolved. STATIC emits a resolver `rawExpr`;\n * LIVE computes the concrete value via `live(state)` and routes it into\n * the deployment — through the typed channel for a `sugar` resolver, or\n * through the generic `values[namespace][key]` channel otherwise.\n */\nexport type ConfigBinding<State = unknown> =\n\t| {\n\t\t\treadonly variant: 'literal';\n\t\t\t/** Path into the `config.ts` object literal, e.g. `['network']`\n\t\t\t * or `['packages', 'connect_four', 'mvr']`. */\n\t\t\treadonly configPath: ReadonlyArray<string>;\n\t\t\t/** The literal value (identical in both paths). */\n\t\t\treadonly value: JsonValue;\n\t }\n\t| {\n\t\t\treadonly variant: 'resolved';\n\t\t\t/** Path into the `config.ts` object literal. */\n\t\t\treadonly configPath: ReadonlyArray<string>;\n\t\t\t/** Generic-channel coordinates. Always present so the live path\n\t\t\t * can populate `deployment.values[namespace][key]` even for a\n\t\t\t * sugar-resolved binding (the sugar ALSO feeds the typed field;\n\t\t\t * `values` is harmless redundancy and keeps the guard simple). */\n\t\t\treadonly namespace: string;\n\t\t\treadonly key: string;\n\t\t\t/** When set, the static path emits the typed-sugar deployment\n\t\t\t * accessor (`requireId(dep, …)` / `dep.network` / the networks\n\t\t\t * `Object.fromEntries(...)` expr) and the live path additionally\n\t\t\t * feeds the TYPED deployment field. When omitted, the static path\n\t\t\t * emits `requireValue(dep, namespace, key)` and the live value lands\n\t\t\t * ONLY in the generic `values` channel. */\n\t\t\treadonly sugar?: ConfigSugarResolver;\n\t\t\t/** The field's STATIC TypeScript type, as a source string (e.g.\n\t\t\t * `'string'`, `'string | null'`, or a structural literal type for a\n\t\t\t * composite). When set, the static path emits\n\t\t\t * `requireValue<tsType>(dep, ns, key)` so the committed value carries\n\t\t\t * its concrete type instead of the `unknown` the generic channel\n\t\t\t * returns. Ignored for sugar bindings (those use the typed accessor\n\t\t\t * whose return type is already concrete). When omitted, the static\n\t\t\t * path emits a bare `requireValue(dep, ns, key)` (type `unknown`). */\n\t\t\treadonly tsType?: string;\n\t\t\t/** Compute the concrete value at boot from acquired plugin state.\n\t\t\t * Only invoked on the LIVE path. */\n\t\t\treadonly live: (state: State) => JsonValue;\n\t };\n\n/**\n * A plugin's full `config.ts` contribution, declared ONCE.\n *\n * `bucket` is always `'config.ts'` for the typed app config; carried as a\n * field so the orchestrator stays name-blind (it reads the bucket off the\n * decl rather than hard-coding it).\n */\nexport interface ConfigBindingSet<State = unknown> {\n\t/** Aggregate bucket the bindings fold into (always `'config.ts'` today;\n\t * a field so the orchestrator never hard-codes it). */\n\treadonly bucket: string;\n\t/** Diagnostic tag for span attributes (e.g. `'sui-network'`,\n\t * `'package'`). The orchestrator MUST NOT branch on it. */\n\treadonly kind: string;\n\t/** The emitter name the derived `CodegenableDecl` carries. */\n\treadonly emitterName: string;\n\t/** Optional standalone output path. The derived decl is `aggregateOnly`,\n\t * so no per-decl file is written; path-resolution only needs a non-empty,\n\t * per-bucket-unique string, which defaults to `bucket` when omitted. Set\n\t * it only when a standalone path would be genuinely meaningful. */\n\treadonly outputPath?: string;\n\t/** When `true`, the derived decl sets `allowEmitterNameRepetition`\n\t * (one decl per item, e.g. one `package` per published package). */\n\treadonly allowEmitterNameRepetition?: boolean;\n\t/** The bindings. */\n\treadonly bindings: ReadonlyArray<ConfigBinding<State>>;\n}\n\n// -----------------------------------------------------------------------------\n// Derivation\n// -----------------------------------------------------------------------------\n\n/** Set `value` at `path` inside `root`, creating intermediate objects. */\nconst setAtPath = (\n\troot: Record<string, unknown>,\n\tpath: ReadonlyArray<string>,\n\tvalue: unknown,\n): void => {\n\tlet cursor = root;\n\tfor (let i = 0; i < path.length - 1; i++) {\n\t\tconst segment = path[i]!;\n\t\tconst next = cursor[segment];\n\t\tif (typeof next === 'object' && next !== null && !Array.isArray(next)) {\n\t\t\tcursor = next as Record<string, unknown>;\n\t\t} else {\n\t\t\tconst created: Record<string, unknown> = {};\n\t\t\tcursor[segment] = created;\n\t\t\tcursor = created;\n\t\t}\n\t}\n\tcursor[path[path.length - 1]!] = value;\n};\n\n/** The `rawExpr` the STATIC path emits for a resolved binding. Reads off the\n * loaded deployment's active network — the emitted file carries a\n * `const dep = __deployment.forNetwork(__deployment.defaultNetwork);`\n * preamble (wired by the codegen orchestrator), so these expressions\n * reference `dep` / `__deployment` directly. */\nconst staticExprFor = <State>(\n\tbinding: Extract<ConfigBinding<State>, { variant: 'resolved' }>,\n): ReturnType<typeof rawExpr> => {\n\tconst sugar = binding.sugar;\n\tif (sugar === undefined) {\n\t\t// Generic channel: `requireValue<tsType>(dep, \"ns\", \"key\")`. The optional\n\t\t// `tsType` carries the field's concrete static type so the committed value\n\t\t// typechecks against the app's usage (the generic channel returns\n\t\t// `unknown`); emitted as a type argument on `requireValue`.\n\t\tconst typeArg = binding.tsType === undefined ? '' : `<${binding.tsType}>`;\n\t\tconst ns = JSON.stringify(binding.namespace);\n\t\tconst key = JSON.stringify(binding.key);\n\t\treturn rawExpr(`requireValue${typeArg}(dep, ${ns}, ${key})`);\n\t}\n\tswitch (sugar.kind) {\n\t\tcase 'id':\n\t\t\treturn rawExpr(`requireId(dep, ${JSON.stringify(sugar.mvrPlaceholder)})`);\n\t\tcase 'network':\n\t\t\treturn rawExpr('dep.network');\n\t\tcase 'networks':\n\t\t\treturn rawExpr(\n\t\t\t\t'Object.fromEntries(__deployment.networkNames.map((n) => [n, __deployment.forNetwork(n)]))',\n\t\t\t);\n\t\tcase 'mvrType':\n\t\t\t// `` `${requireId(dep, \"<mvr>\")}::<module>::<Name>` `` — the package\n\t\t\t// prefix substituted with the active-network resolved id, never baked.\n\t\t\treturn rawExpr(\n\t\t\t\t`\\`\\${requireId(dep, ${JSON.stringify(sugar.mvrPlaceholder)})}::${sugar.typeSuffix}\\``,\n\t\t\t);\n\t}\n};\n\n/** Build the STATIC (committed-tree) aggregate projection from a binding\n * set — `rawExpr(requireValue(dep, …)/requireId(dep, …)/dep.network/…)` for\n * resolved bindings, literals for the rest. Pure: needs no acquired state. */\nexport const projectStaticConfig = <State>(\n\tset: ConfigBindingSet<State>,\n): Record<string, unknown> => {\n\tconst root: Record<string, unknown> = {};\n\tfor (const binding of set.bindings) {\n\t\tconst value = binding.variant === 'literal' ? binding.value : staticExprFor(binding);\n\t\tsetAtPath(root, binding.configPath, value);\n\t}\n\treturn root;\n};\n\n/** Build the LIVE (boot) aggregate projection from a binding set against\n * the acquired plugin state — concrete resolved values everywhere. */\nexport const projectLiveConfig = <State>(\n\tset: ConfigBindingSet<State>,\n\tstate: State,\n): Record<string, unknown> => {\n\tconst root: Record<string, unknown> = {};\n\tfor (const binding of set.bindings) {\n\t\tconst value = binding.variant === 'literal' ? binding.value : binding.live(state);\n\t\tsetAtPath(root, binding.configPath, value);\n\t}\n\treturn root;\n};\n\n/**\n * Derive the live `deployment.values[namespace][key]` contributions of a\n * binding set. Only `resolved` bindings WITHOUT a `sugar` resolver land in\n * the generic channel (sugar bindings feed the typed deployment fields,\n * sliced from the live `config.ts` bucket by `deploymentFromBucket`). The\n * generic channel is the part the fixed typed schema can't carry.\n */\nexport const liveValuesOf = <State>(\n\tset: ConfigBindingSet<State>,\n\tstate: State,\n): Record<string, Record<string, JsonValue>> => {\n\tconst out: Record<string, Record<string, JsonValue>> = {};\n\tfor (const binding of set.bindings) {\n\t\tif (binding.variant !== 'resolved' || binding.sugar !== undefined) continue;\n\t\tconst ns = (out[binding.namespace] ??= {});\n\t\tns[binding.key] = binding.live(state);\n\t}\n\treturn out;\n};\n\n/**\n * Derive the STATIC TS type of each generic-channel (`values[ns][key]`)\n * contribution — `valueTypes[namespace][key] = '<tsType>'`. The SAME binding\n * subset `liveValuesOf` covers (every `resolved` binding WITHOUT a `sugar`\n * resolver — sugar bindings feed the typed deployment fields, not `values`),\n * but carries each field's declared `tsType` source string (defaulting to\n * `'unknown'`) instead of its live value. Pure over the binding set — the type\n * is config-known, so this is identical on the live and static paths. The\n * codegen orchestrator folds it into the strict `deployment.ts`'s required\n * `values` shape so a hand-written deployment is compile-checked for every\n * service value.\n */\nexport const valueTypesOf = <State>(\n\tset: ConfigBindingSet<State>,\n): Record<string, Record<string, string>> => {\n\tconst out: Record<string, Record<string, string>> = {};\n\tfor (const binding of set.bindings) {\n\t\tif (binding.variant !== 'resolved' || binding.sugar !== undefined) continue;\n\t\tconst ns = (out[binding.namespace] ??= {});\n\t\tns[binding.key] = binding.tsType ?? 'unknown';\n\t}\n\treturn out;\n};\n\n/**\n * Derive a `CodegenableDecl` from a binding set.\n *\n * `'static'` → the committed-tree decl (stack-free `codegen` verb). Its\n * aggregate emits `rawExpr(resolve…())` for resolved bindings.\n *\n * `{ mode: 'live', state }` → the boot decl. Its aggregate bakes concrete\n * values from `state`; boot's `assembleDeployment` reads those back into the\n * loadable deployment (typed channel + the generic `values` channel).\n */\nexport const configCodegenable = <State, Emitter extends string = string>(\n\tset: ConfigBindingSet<State>,\n\thow: 'static' | { readonly mode: 'live'; readonly state: State },\n\toptions: {\n\t\t/** Extra `export const <name> = <value>` declarations to emit on the\n\t\t * decl's `emit` context, instead of the default placeholder export.\n\t\t * The package plugin uses this to export its `packageBindings` object\n\t\t * so the orchestrator's `isPackageBindings` seam can forward it to the\n\t\t * Move-bindings emitter. When omitted, a single minimal placeholder\n\t\t * export is emitted (the projection is what the aggregate folds). */\n\t\treadonly extraExports?: Readonly<Record<string, unknown>>;\n\t} = {},\n): CodegenableDecl<Emitter> => {\n\tconst live = how !== 'static';\n\tconst projected = live ? projectLiveConfig(set, how.state) : projectStaticConfig(set);\n\tconst idConfigValues = live ? liveValuesOf(set, how.state) : {};\n\t// Present on BOTH paths — the TS type is config-known (resolution-\n\t// independent). Drives the strict `deployment.ts`'s required `values` shape.\n\tconst valueTypes = valueTypesOf(set);\n\tconst extraExports = options.extraExports;\n\treturn {\n\t\tkind: 'codegenable',\n\t\temitterName: set.emitterName as Emitter,\n\t\t// `aggregateOnly` never writes a standalone file; default the\n\t\t// path-resolution placeholder to the bucket name so plugins don't\n\t\t// invent dead paths.\n\t\toutputPath: set.outputPath ?? set.bucket,\n\t\taggregateOnly: true,\n\t\t...(set.allowEmitterNameRepetition === true ? { allowEmitterNameRepetition: true } : {}),\n\t\taggregate: {\n\t\t\tkind: set.kind,\n\t\t\tbucket: set.bucket,\n\t\t\t// The projection is precomputed above (pure over `set`/`state`);\n\t\t\t// the orchestrator calls `project(exported)` with the emitted map\n\t\t\t// but the value is already fixed, so we ignore the argument.\n\t\t\tproject: () => projected,\n\t\t\t// Only the live aggregate feeds the generic deployment channel.\n\t\t\t...(live && Object.keys(idConfigValues).length > 0 ? { idConfigValues } : {}),\n\t\t\t// The static `valueTypes` channel is present on BOTH paths (the\n\t\t\t// committed `codegen` verb runs the STATIC aggregates, so the strict\n\t\t\t// `deployment.ts`'s required `values` shape must be derivable there).\n\t\t\t...(Object.keys(valueTypes).length > 0 ? { valueTypes } : {}),\n\t\t},\n\t\temit: (ctx) =>\n\t\t\tEffect.sync(() => {\n\t\t\t\tif (extraExports !== undefined) {\n\t\t\t\t\tfor (const [name, value] of Object.entries(extraExports)) {\n\t\t\t\t\t\tctx.exportConst(name, value);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// A placeholder export so the emitter runs; the projection is\n\t\t\t\t\t// what the aggregate folds. Kept minimal + name-stable.\n\t\t\t\t\tctx.exportConst('__configBindings', set.kind);\n\t\t\t\t}\n\t\t\t\treturn ctx.done();\n\t\t\t}),\n\t};\n};\n\n// -----------------------------------------------------------------------------\n// Sibling-keyed bucket bindings\n// -----------------------------------------------------------------------------\n//\n// The own-bucket service plugins (coin → `coins.ts`, deepbook → `deepbook.ts`,\n// seal → `seal.ts`) emit a name-keyed bucket where distinct instances deep-merge\n// into one `<bucket>.ts` exporting `{ <instanceKey>: { ...fields } }`. They\n// declare their per-instance contribution as a flat list of `BucketField`s\n// (each a structural literal or a runtime-resolved value rooted under the\n// instance key); the helpers below derive the `ConfigBindingSet` and both the\n// live/static decls from it, so there are no parallel projectors to drift.\n\n/** One field of an instance's bucket entry, classified as either a pure\n * STRUCTURAL literal (a name / mode / decimals — the same in both paths)\n * or a runtime-RESOLVED value (an on-chain id, coin type, or endpoint URL —\n * the static path emits `requireValue(dep, …)`, the live path feeds the\n * concrete value into the deployment). The `key` is the leaf field name written\n * under the instance key in the bucket object literal. */\nexport type BucketField<State> =\n\t| { readonly key: string; readonly variant: 'literal'; readonly value: JsonValue }\n\t| {\n\t\t\treadonly key: string;\n\t\t\treadonly variant: 'resolved';\n\t\t\t/** `requireValue(dep, namespace, valueKey)` coordinates. `valueKey`\n\t\t\t * defaults to `key` when omitted. */\n\t\t\treadonly valueKey?: string;\n\t\t\t/** The field's STATIC TypeScript type as a source string (see\n\t\t\t * `ConfigBinding.tsType`). When set, the static path emits\n\t\t\t * `requireValue<tsType>(dep, …)` so the committed value carries its\n\t\t\t * concrete type instead of `unknown`. */\n\t\t\treadonly tsType?: string;\n\t\t\treadonly live: (state: State) => JsonValue;\n\t };\n\nexport interface SiblingBucketSpec<State> {\n\t/** The aggregate bucket filename, e.g. `'coins.ts'`. */\n\treadonly bucket: string;\n\t/** Diagnostic kind tag (e.g. `'coin'`) — the orchestrator never\n\t * branches on it. */\n\treadonly kind: string;\n\t/** The emitter name the derived decl carries (literal, e.g.\n\t * `coin/<symbol>`). */\n\treadonly emitterName: string;\n\t/** Optional standalone output path. Defaults to `bucket` (the decl is\n\t * `aggregateOnly`, so no per-decl file is written). */\n\treadonly outputPath?: string;\n\t/** The instance key the entry lives under in the bucket object\n\t * (e.g. the coin symbol, the deepbook instance name). */\n\treadonly instanceKey: string;\n\t/** The `requireValue` namespace shared by every resolved field\n\t * (e.g. `coin:<symbol>`, `deepbook:<name>`). */\n\treadonly namespace: string;\n\t/** The instance's fields. */\n\treadonly fields: ReadonlyArray<BucketField<State>>;\n\t/** When `true`, the derived decl sets `allowEmitterNameRepetition`\n\t * (sibling instances share an emitter-name prefix). */\n\treadonly allowEmitterNameRepetition?: boolean;\n}\n\n/** Convenience constructor for the keyed-bucket shape the service plugins\n * share (coin/deepbook/seal): every sibling instance keys under `<key>` in\n * `<bucket>`, with `emitterName = `<kind>/<key>``, `namespace = `<kind>:<key>``,\n * `instanceKey = <key>`, and `allowEmitterNameRepetition` (instances share the\n * `<kind>/` emitter prefix). Only `bucket`/`kind`/`key`/`fields` vary across\n * those plugins, so this keeps the `<kind>/<key>` + `<kind>:<key>` naming\n * convention in ONE place instead of re-spelling it per plugin. */\nexport const keyedBucketSpec = <State>(input: {\n\treadonly bucket: string;\n\treadonly kind: string;\n\treadonly key: string;\n\treadonly fields: ReadonlyArray<BucketField<State>>;\n}): SiblingBucketSpec<State> => ({\n\tbucket: input.bucket,\n\tkind: input.kind,\n\temitterName: `${input.kind}/${input.key}`,\n\tinstanceKey: input.key,\n\tnamespace: `${input.kind}:${input.key}`,\n\tallowEmitterNameRepetition: true,\n\tfields: input.fields,\n});\n\n/** Build the `ConfigBindingSet` for a sibling-keyed bucket instance. The\n * `configPath` of every binding is rooted at the instance key, so distinct\n * instances deep-merge into one `<bucket>.ts` exporting\n * `{ <instanceKey>: { ...fields } }`. */\nexport const siblingBucketBindings = <State>(\n\tspec: SiblingBucketSpec<State>,\n): ConfigBindingSet<State> => {\n\tconst bindings: Array<ConfigBinding<State>> = spec.fields.map((field) => {\n\t\tconst configPath = [spec.instanceKey, field.key] as const;\n\t\tif (field.variant === 'literal') {\n\t\t\treturn { variant: 'literal', configPath: [...configPath], value: field.value };\n\t\t}\n\t\treturn {\n\t\t\tvariant: 'resolved',\n\t\t\tconfigPath: [...configPath],\n\t\t\tnamespace: spec.namespace,\n\t\t\tkey: field.valueKey ?? field.key,\n\t\t\t// No `sugar` — these are generic `requireValue` bindings (the typed\n\t\t\t// deployment channel only carries network/packages/mvrOverrides).\n\t\t\t...(field.tsType !== undefined ? { tsType: field.tsType } : {}),\n\t\t\tlive: field.live,\n\t\t};\n\t});\n\treturn {\n\t\tbucket: spec.bucket,\n\t\tkind: spec.kind,\n\t\temitterName: spec.emitterName,\n\t\t...(spec.outputPath !== undefined ? { outputPath: spec.outputPath } : {}),\n\t\t...(spec.allowEmitterNameRepetition === true ? { allowEmitterNameRepetition: true } : {}),\n\t\tbindings,\n\t};\n};\n\n/** Derive the LIVE bucket decl — feeds concrete values into the generic\n * deployment `values` channel (no per-stack generated file is written). */\nexport const liveBucketCodegen = <State>(\n\tspec: SiblingBucketSpec<State>,\n\tstate: State,\n): CodegenableDecl => configCodegenable(siblingBucketBindings(spec), { mode: 'live', state });\n\n/** Derive the STATIC (stack-free) bucket decl — emits\n * `requireValue(dep, namespace, key)` for resolved fields, literals for the\n * rest. The committed `<bucket>.ts` carries no baked runtime value. */\nexport const staticBucketCodegen = <State>(spec: SiblingBucketSpec<State>): CodegenableDecl =>\n\tconfigCodegenable(siblingBucketBindings(spec), 'static');\n"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -14,11 +14,11 @@ import { retry_policy_exports } from "./substrate/runtime/retry-policy.mjs";
|
|
|
14
14
|
import { ContainerRuntimeService } from "./runtime/docker/service.mjs";
|
|
15
15
|
import { process_supervisor_exports } from "./substrate/runtime/process-supervisor.mjs";
|
|
16
16
|
import { PluginContext } from "./substrate/plugin-ctx.mjs";
|
|
17
|
+
import { DEFAULT_DEVSTACK_NETWORK, DEFAULT_STACK_NAME, DEVSTACK_NETWORK_NAMES, DevstackNetworkParseError, LOCAL_NETWORK_NAME, chainIdForNetwork, networkNameFromChain, parseDevstackNetwork, parseDevstackNetworkName, resolveAppName, resolveNetwork, resolveNetworkSync, resolveStackName, resolveStateDir } from "./api/inference-network.mjs";
|
|
17
18
|
import { http_probe_exports } from "./substrate/runtime/http-probe.mjs";
|
|
18
19
|
import { managed_container_exports } from "./substrate/runtime/managed-container.mjs";
|
|
19
20
|
import { config_validation_exports } from "./substrate/runtime/config-validation.mjs";
|
|
20
21
|
import { ManifestExtrasInvalid, ManifestExtrasLookupError } from "./substrate/manifest.mjs";
|
|
21
|
-
import { DEFAULT_DEVSTACK_NETWORK, DEFAULT_STACK_NAME, DEVSTACK_NETWORK_NAMES, DevstackNetworkParseError, LOCAL_NETWORK_NAME, chainIdForNetwork, networkNameFromChain, parseDevstackNetwork, parseDevstackNetworkName, resolveAppName, resolveNetwork, resolveNetworkSync, resolveStackName, resolveStateDir } from "./api/inference-network.mjs";
|
|
22
22
|
import { runStack } from "./api/run-stack.mjs";
|
|
23
23
|
import { projection } from "./api/define-capabilities.mjs";
|
|
24
24
|
import { defineModeNamespace } from "./api/mode-narrowed-factory.mjs";
|
|
@@ -4,16 +4,6 @@ import { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner
|
|
|
4
4
|
//#region src/orchestrators/boot.d.ts
|
|
5
5
|
interface ProductionCodegenOptions {
|
|
6
6
|
readonly appRoot?: string;
|
|
7
|
-
/** Resolved absolute path to the dev-only + secret `generated-extras`
|
|
8
|
-
* tree for this stack, threaded into `CodegenRoot.extrasDir` and
|
|
9
|
-
* recorded in the manifest as `codegen.extrasDir` for the
|
|
10
|
-
* `@devstack-dev` Vite alias. This is the ONLY tree boot's codegen
|
|
11
|
-
* writes (`emitExtras`); boot never emits the committed `src/generated`
|
|
12
|
-
* tree, so it pins no live `outputDir` — the `CodegenRoot.outputDir`
|
|
13
|
-
* the production path carries is an unwritten default. The committed
|
|
14
|
-
* tree is owned solely by the stack-free `codegen` verb (wired
|
|
15
|
-
* separately, where it resolves its own output path). */
|
|
16
|
-
readonly extrasDir?: string;
|
|
17
7
|
/** Forwarded verbatim to `@mysten/codegen`'s
|
|
18
8
|
* `generateFromPackageSummary` via `layerMystenMoveCodegen` — see
|
|
19
9
|
* `DevstackOptions['codegen']` for the full contract. Default `false`
|
|
@@ -26,8 +26,7 @@ import { CodegenWriteFailed } from "./codegen/errors.mjs";
|
|
|
26
26
|
import { MoveCodegenService, MoveSummaryRunnerService, layerMystenMoveCodegen } from "./codegen/bindings.mjs";
|
|
27
27
|
import { layerSuiMoveSummaryRunnerDocker } from "../plugins/sui/move-summary-runner.mjs";
|
|
28
28
|
import { CodegenPathsService, layerCodegenPaths, layerCodegenRoot } from "./codegen/paths.mjs";
|
|
29
|
-
import {
|
|
30
|
-
import { ID_CONFIG_FILENAME, writeIdConfig } from "./codegen/id-config.mjs";
|
|
29
|
+
import { DEPLOYMENT_FILENAME, writeDeployment } from "./codegen/deployment.mjs";
|
|
31
30
|
import { CodegenOrchestratorService, layerCodegenOrchestrator } from "./codegen/service.mjs";
|
|
32
31
|
import { DEFAULT_TRAEFIK_IMAGE, layerTraefikContainerOpsDocker } from "./router/traefik-container.mjs";
|
|
33
32
|
import { makeDefaultRouterProfile } from "./router/profile.mjs";
|
|
@@ -38,11 +37,10 @@ import { BUILT_IN_ENTRYPOINTS } from "../plugins/router-entrypoints.mjs";
|
|
|
38
37
|
import { ManifestExtrasLookupError, resolveManifestExtras } from "../substrate/manifest.mjs";
|
|
39
38
|
import { buildEnvelope, writeManifest } from "../substrate/runtime/manifest/manifest.mjs";
|
|
40
39
|
import "../substrate/runtime/manifest/index.mjs";
|
|
41
|
-
import { resolveNetworkOptions } from "./network-options.mjs";
|
|
42
40
|
import { CoinRegistryService, layerCoinRegistry } from "../plugins/coin/registry.mjs";
|
|
43
41
|
import { PackageRegistryService, layerPackageRegistry } from "../plugins/package/registry.mjs";
|
|
44
42
|
import { Context, Effect, FileSystem, Layer, Ref } from "effect";
|
|
45
|
-
import {
|
|
43
|
+
import { join, resolve } from "node:path";
|
|
46
44
|
import * as NodeFileSystem from "@effect/platform-node/NodeFileSystem";
|
|
47
45
|
import * as NodePath from "@effect/platform-node/NodePath";
|
|
48
46
|
import * as NodeChildProcessSpawner from "@effect/platform-node/NodeChildProcessSpawner";
|
|
@@ -113,28 +111,14 @@ const superviseStackEffect = (stack, identity, state, opts = {}) => Effect.gen(f
|
|
|
113
111
|
* The ONE boot seam that maps a stack's codegen config to the production
|
|
114
112
|
* codegen orchestrator options for a LIVE (`'ran'`) projection. Both
|
|
115
113
|
* composition entry points (`api/run-stack.ts` and `orchestrators/layers.ts`)
|
|
116
|
-
* call this
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
* two stacks never clobber. The committed `src/generated` tree is owned
|
|
121
|
-
* solely by the stack-free `codegen` verb. The resolved literal
|
|
122
|
-
* `outputDir`/`stackSubdir`/`extrasDir` flow into
|
|
123
|
-
* `layerProductionOrchestrators({ codegen })` unchanged — `paths.ts` keeps
|
|
124
|
-
* consuming literals (minimal blast radius).
|
|
125
|
-
*
|
|
126
|
-
* The per-stack inputs: the app root, the resolved effective stack
|
|
127
|
-
* (already through the explicit-`--stack` > `config.stackName` > inferred
|
|
128
|
-
* ladder), and the app's optional explicit `codegen` pins.
|
|
114
|
+
* call this. Boot writes no committed `src/generated` tree (owned solely by
|
|
115
|
+
* the stack-free `codegen` verb), so there is no live dev-output dir to
|
|
116
|
+
* resolve; only the app root + the pass-through phantom-type flag flow into
|
|
117
|
+
* `layerProductionOrchestrators({ codegen })`.
|
|
129
118
|
*/
|
|
130
119
|
const resolveProductionCodegenOptions = (input) => {
|
|
131
|
-
const resolved = resolveCodegenOutput({
|
|
132
|
-
appRoot: input.appRoot,
|
|
133
|
-
effectiveStack: input.effectiveStack
|
|
134
|
-
});
|
|
135
120
|
return {
|
|
136
121
|
appRoot: input.appRoot,
|
|
137
|
-
extrasDir: resolved.extrasDir,
|
|
138
122
|
...input.codegen?.includePhantomTypeParameters === void 0 ? {} : { includePhantomTypeParameters: input.codegen.includePhantomTypeParameters }
|
|
139
123
|
};
|
|
140
124
|
};
|
|
@@ -160,22 +144,13 @@ const layerManifestEndpointRegistry = Layer.effect(ManifestEndpointRegistryServi
|
|
|
160
144
|
}));
|
|
161
145
|
const productionRouterProfile = (options = {}) => makeDefaultRouterProfile(options);
|
|
162
146
|
/** `outputDir` for the `CodegenRoot` of a `layerProductionOrchestrators`
|
|
163
|
-
* composition
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
147
|
+
* composition — `<appRoot>/src/generated`. Boot's `assembleDeployment`
|
|
148
|
+
* writes no file here; the dev-`up` `emitBindings` refresh DOES re-emit
|
|
149
|
+
* this committed tree from the STATIC (id-free) contributions so an edited
|
|
150
|
+
* Move package's new shapes reach the app. `apply` / `runStack` pass no
|
|
151
|
+
* `emitBindings`, so they leave it untouched. The stack-free `codegen` verb
|
|
152
|
+
* owns the canonical emit (wired separately, where it pins its own path). */
|
|
169
153
|
const productionCodegenOutputDir = (appRoot) => resolve(appRoot, "src/generated");
|
|
170
|
-
/** Fallback `generated-extras` dir for the cold-start / no-config
|
|
171
|
-
* composition path (`buildDirectSnapshotLayers`). Callers that know
|
|
172
|
-
* their stack (`run-stack`, the verb wirings) pass the resolved
|
|
173
|
-
* per-stack value; this default only feeds direct-snapshot verbs that
|
|
174
|
-
* never run codegen. */
|
|
175
|
-
const productionCodegenExtrasDir = (appRoot, extrasDir) => {
|
|
176
|
-
const target = extrasDir ?? ".devstack/generated-extras";
|
|
177
|
-
return isAbsolute(target) ? target : resolve(appRoot, target);
|
|
178
|
-
};
|
|
179
154
|
const layerProductionOrchestrators = (router = {}) => {
|
|
180
155
|
const profile = productionRouterProfile();
|
|
181
156
|
return Layer.mergeAll(layerSnapshotOrchestrator, layerManifestEndpointRegistry, layerRouterService.pipe(Layer.provideMerge(Layer.mergeAll(layerEntrypointRegistry(BUILT_IN_ENTRYPOINTS), layerTraefikContainerOpsDocker, layerDockerUpstreamResolver(profile), layerRouterConfigLiteral({
|
|
@@ -185,8 +160,7 @@ const layerProductionOrchestrators = (router = {}) => {
|
|
|
185
160
|
routeReadinessProbe: { enabled: router.disabled !== true }
|
|
186
161
|
})))), layerCodegenOrchestrator, layerCodegenPaths.pipe(Layer.provideMerge(layerCodegenRoot({
|
|
187
162
|
outputDir: productionCodegenOutputDir(router.codegen?.appRoot ?? process.cwd()),
|
|
188
|
-
stackSubdir: null
|
|
189
|
-
extrasDir: productionCodegenExtrasDir(router.codegen?.appRoot ?? process.cwd(), router.codegen?.extrasDir)
|
|
163
|
+
stackSubdir: null
|
|
190
164
|
}))), layerSuiMoveSummaryRunnerDocker, layerMystenMoveCodegen({ includePhantomTypeParameters: router.codegen?.includePhantomTypeParameters }));
|
|
191
165
|
};
|
|
192
166
|
/** The single adapter for routable endpoints: ONE `ResolvedRoute` (the
|
|
@@ -345,13 +319,13 @@ const buildProductionPostAcquireHook = (options = {}) => Effect.gen(function* ()
|
|
|
345
319
|
const extras = yield* resolveManifestExtras(options.extras, makeManifestExtrasContext(ctx));
|
|
346
320
|
const routableEndpoints = yield* manifestEndpoints.entries;
|
|
347
321
|
const endpoints = [...routableEndpoints, ...operationalManifestEndpointEntries(ctx, routableEndpoints)];
|
|
348
|
-
const
|
|
349
|
-
outputPath:
|
|
322
|
+
const deployment = yield* codegen.assembleDeployment(String(ctx.identity.network)).pipe(Effect.mapError((cause) => new CodegenWriteFailed({
|
|
323
|
+
outputPath: DEPLOYMENT_FILENAME,
|
|
350
324
|
stage: "write",
|
|
351
325
|
cause
|
|
352
326
|
})));
|
|
353
|
-
const
|
|
354
|
-
yield*
|
|
327
|
+
const deploymentFile = join(stackPaths.stackRoot, DEPLOYMENT_FILENAME);
|
|
328
|
+
yield* writeDeployment(deploymentFile, deployment).pipe(Effect.provideService(FileSystem.FileSystem, fs));
|
|
355
329
|
yield* writeManifest(yield* buildEnvelope({
|
|
356
330
|
identity: {
|
|
357
331
|
app: ctx.identity.app,
|
|
@@ -360,16 +334,12 @@ const buildProductionPostAcquireHook = (options = {}) => Effect.gen(function* ()
|
|
|
360
334
|
},
|
|
361
335
|
endpoints,
|
|
362
336
|
extras,
|
|
363
|
-
codegen: {
|
|
364
|
-
extrasDir: paths.extrasDir,
|
|
365
|
-
idsFile
|
|
366
|
-
}
|
|
337
|
+
codegen: { deploymentFile }
|
|
367
338
|
}), join(stackPaths.stackRoot, "manifest.json")).pipe(Effect.provideService(FileSystem.FileSystem, fs));
|
|
368
|
-
const
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
extrasFiles.push(...extras.filesWritten, ...extras.filesChmod);
|
|
339
|
+
const bindingFiles = [];
|
|
340
|
+
if (options.emitBindings !== void 0) {
|
|
341
|
+
const emitted = yield* codegen.emitBindings(options.emitBindings).pipe(Effect.provideService(FileSystem.FileSystem, fs), Effect.provideService(CodegenPathsService, paths), Effect.provideService(MoveSummaryRunnerService, moveRunner), Effect.provideService(MoveCodegenService, moveCodegen));
|
|
342
|
+
bindingFiles.push(...emitted.filesWritten, ...emitted.filesChmod);
|
|
373
343
|
}
|
|
374
344
|
yield* postAcquireTasks.runAll;
|
|
375
345
|
return [{
|
|
@@ -378,7 +348,7 @@ const buildProductionPostAcquireHook = (options = {}) => Effect.gen(function* ()
|
|
|
378
348
|
at: Date.now()
|
|
379
349
|
}, {
|
|
380
350
|
tag: "codegen.emitted",
|
|
381
|
-
files: [
|
|
351
|
+
files: [deploymentFile, ...bindingFiles],
|
|
382
352
|
at: Date.now()
|
|
383
353
|
}];
|
|
384
354
|
});
|
|
@@ -421,7 +391,7 @@ const superviseStackWithProductionBoot = (stack, identity, state, opts = {}) =>
|
|
|
421
391
|
contributionDispatcher: yield* buildProductionContributionDispatcher(),
|
|
422
392
|
postAcquireHook: yield* buildProductionPostAcquireHook({
|
|
423
393
|
...opts.extras === void 0 ? {} : { extras: opts.extras },
|
|
424
|
-
...opts.
|
|
394
|
+
...opts.emitBindings === void 0 ? {} : { emitBindings: opts.emitBindings }
|
|
425
395
|
}),
|
|
426
396
|
...opts.lifetime === void 0 ? {} : { lifetime: opts.lifetime },
|
|
427
397
|
...opts.devstackVersion === void 0 ? {} : { devstackVersion: opts.devstackVersion },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boot.mjs","names":["Logger"],"sources":["../../src/orchestrators/boot.ts"],"sourcesContent":["// Single L3 boot seam.\n//\n// Consumed by both the CLI verb wirings (`cli/wirings/*`) and the\n// library-facing programmatic surface (`api/run-stack.ts`), plus the e2e\n// boot harness.\n//\n// Composes the substrate Layer stack (L0) + the Docker `ContainerRuntime`\n// adapter (L1), yields the substrate services into a `Context.Context<never>`\n// pluginContext, builds the projection ref, and runs `supervise()` inside a\n// scope. The production orchestrator assembly (Snapshot/Router/Codegen/\n// ManifestEndpoint) and the contribution-delivery dispatcher live here too —\n// the supervisor holds the dispatcher record opaquely (it never imports an\n// orchestrator service).\n//\n// Architecture: this is L3 (orchestrator-level). Layer composition that\n// assembles L0+L1 stacks belongs at L3/L4 — it can't live in `substrate/`\n// because it imports a concrete L1 adapter (Docker) by definition; and it\n// depends on L2 plugin internals (coin/package registries), so it can't live\n// at L1 runtime either. See ARCHITECTURE.md § \"Layer composition belongs at\n// L3/L4, not L0\" and § \"L1-never-imports-from-L2\".\n\nimport { Context, Effect, FileSystem, Layer, Ref, Scope, SubscriptionRef } from 'effect';\nimport { isAbsolute, join, resolve } from 'node:path';\nimport * as NodeFileSystem from '@effect/platform-node/NodeFileSystem';\nimport * as NodePath from '@effect/platform-node/NodePath';\nimport * as NodeChildProcessSpawner from '@effect/platform-node/NodeChildProcessSpawner';\nimport { ChildProcessSpawner } from 'effect/unstable/process/ChildProcessSpawner';\n\nimport type { Identity } from '../substrate/identity.ts';\nimport { CacheService, layerCache } from '../substrate/runtime/cache/index.ts';\nimport { LeaseBrokerService, layerLeaseBroker } from '../substrate/runtime/lease-broker/index.ts';\nimport {\n\tIdentityContext,\n\tRuntimeRoot,\n\tStackPathsService,\n\tlayerIdentity,\n\tlayerRuntimeRoot,\n\tlayerStackPaths,\n} from '../substrate/runtime/paths.ts';\nimport { PortBrokerService, layerPortBroker } from '../substrate/runtime/port-broker/index.ts';\nimport {\n\tStrategyRegistryService,\n\tlayerStrategyRegistry,\n} from '../substrate/runtime/strategy-registry/index.ts';\nimport {\n\tContainerRuntimeService,\n\tDockerSpawner,\n\tlayerContainerRuntimeDocker,\n\tlayerDockerCycleInitial,\n\tlayerDockerHostDefault,\n} from '../runtime/docker/index.ts';\nimport { readResolvedSync } from '../substrate/runtime/lifecycle/index.ts';\nimport { operationalEndpointEventsFromResolvedValue } from '../substrate/runtime/projection/operational-endpoints.ts';\nimport { Logger, layerLogger } from '../substrate/runtime/observability/index.ts';\nimport {\n\tPostAcquireTasksService,\n\tlayerPostAcquireTasks,\n} from '../substrate/runtime/post-acquire-tasks.ts';\nimport {\n\tallReadyOrTerminal,\n\tstartSupervisor,\n\ttype ContributionDispatcher,\n\ttype SupervisedStack,\n\ttype SupervisorCommandHandler,\n\ttype SupervisorHandle,\n\ttype SupervisorPostAcquireHook,\n} from '../substrate/runtime/supervisor/index.ts';\nimport type { ContributionDispatchContext } from '../substrate/runtime/supervisor/contribution-dispatcher.ts';\nimport type { SupervisorPostAcquireContext } from '../substrate/runtime/supervisor/index.ts';\n\nimport {\n\tlayerMystenMoveCodegen,\n\tMoveCodegenService,\n\tMoveSummaryRunnerService,\n} from './codegen/bindings.ts';\nimport { layerSuiMoveSummaryRunnerDocker } from '../plugins/sui/move-summary-runner.ts';\nimport { CodegenPathsService, layerCodegenPaths, layerCodegenRoot } from './codegen/paths.ts';\nimport { resolveCodegenOutput } from './codegen/output-location.ts';\nimport {\n\tCodegenOrchestratorService,\n\tlayerCodegenOrchestrator,\n\ttype Codegenable,\n} from './codegen/service.ts';\nimport { CodegenWriteFailed } from './codegen/errors.ts';\nimport { ID_CONFIG_FILENAME, writeIdConfig } from './codegen/id-config.ts';\nimport {\n\tDEFAULT_TRAEFIK_IMAGE,\n\tlayerDockerUpstreamResolver,\n\tlayerEntrypointRegistry,\n\tlayerRouterConfigLiteral,\n\tlayerRouterService,\n\tlayerTraefikContainerOpsDocker,\n\tRouterService,\n\ttype ResolvedRoute,\n} from './router/index.ts';\nimport { BUILT_IN_ENTRYPOINTS } from '../plugins/router-entrypoints.ts';\nimport {\n\tmakeDefaultRouterProfile,\n\ttype DefaultRouterProfileOptions,\n\ttype RouterProfile,\n} from './router/profile.ts';\nimport { layerSnapshotOrchestrator, SnapshotOrchestratorService } from './snapshot/index.ts';\nimport type { ProjectionDecl } from '../contracts/projection.ts';\nimport type { RoutableDecl } from '../contracts/routable.ts';\nimport type { SnapshotableDecl } from '../contracts/snapshotable.ts';\nimport type { StrategyContributorDecl } from '../contracts/strategy-contributor.ts';\nimport { endpointKey, type PluginKey } from '../substrate/brand.ts';\nimport type { EngineEvent } from '../substrate/events.ts';\nimport {\n\tbuildEnvelope,\n\tCURRENT_MANIFEST_VERSION,\n\twriteManifest,\n} from '../substrate/runtime/manifest/index.ts';\nimport {\n\tManifestExtrasLookupError,\n\tresolveManifestExtras,\n\ttype EndpointEntry,\n\ttype ManifestExtrasInput,\n} from '../substrate/manifest.ts';\nimport { resolveNetworkOptions } from './network-options.ts';\nimport { CoinRegistryService, layerCoinRegistry } from '../plugins/coin/registry.ts';\nimport { PackageRegistryService, layerPackageRegistry } from '../plugins/package/registry.ts';\n\n// ───────────────────────────────────────────────────────────────────────────\n// Substrate lifecycle\n// ───────────────────────────────────────────────────────────────────────────\n\n/** Substrate Layer stack for a single supervised run. Composes every L0\n * service the supervisor yields from its R-channel, plus the L1 Docker\n * `ContainerRuntime`. Built-in plugin services are layered outside\n * substrate and added through `extendContext`. */\nexport const buildSubstrateLayers = (identity: Identity, runtimeRoot: string) => {\n\t// DockerSpawner adapts platform-node's ChildProcessSpawner tag onto\n\t// the docker subsystem's local DockerSpawner tag (same shape; the\n\t// indirection only lets tests inject a stub).\n\tconst layerDockerSpawnerFromNode: Layer.Layer<DockerSpawner, never, ChildProcessSpawner> =\n\t\tLayer.effect(\n\t\t\tDockerSpawner,\n\t\t\tEffect.gen(function* () {\n\t\t\t\treturn yield* ChildProcessSpawner;\n\t\t\t}),\n\t\t);\n\n\tconst platformBase = Layer.mergeAll(\n\t\tlayerIdentity(identity),\n\t\tlayerRuntimeRoot(runtimeRoot),\n\t\tNodePath.layer,\n\t\tNodeFileSystem.layer,\n\t\tlayerDockerHostDefault,\n\t\tlayerDockerCycleInitial,\n\t\tlayerStrategyRegistry,\n\t);\n\n\tconst childProcessSpawnerWired = NodeChildProcessSpawner.layer.pipe(\n\t\tLayer.provideMerge(platformBase),\n\t);\n\tconst withStackPaths = layerStackPaths.pipe(Layer.provideMerge(childProcessSpawnerWired));\n\tconst withCache = layerCache.pipe(Layer.provideMerge(withStackPaths));\n\tconst withPortBroker = layerPortBroker.pipe(Layer.provideMerge(withCache));\n\tconst withLeaseBroker = layerLeaseBroker.pipe(Layer.provideMerge(withPortBroker));\n\tconst withSpawnerAdapter = layerDockerSpawnerFromNode.pipe(Layer.provideMerge(withLeaseBroker));\n\tconst withContainerRuntime = layerContainerRuntimeDocker.pipe(\n\t\tLayer.provideMerge(withSpawnerAdapter),\n\t);\n\tconst withPostAcquireTasks = layerPostAcquireTasks.pipe(Layer.provideMerge(withContainerRuntime));\n\treturn layerLogger.pipe(Layer.provideMerge(withPostAcquireTasks));\n};\n\n/** Build the opaque `Context.Context<never>` the supervisor hands to\n * every plugin's `acquire` body. Yields every substrate service the\n * Docker-backed substrate layer stack provides; downstream callers\n * may extend the context (e.g. layering the built-in plugin registries\n * via `extendBuiltInPluginContext`) before passing it to `supervise()`. */\nconst buildPluginContext = (): Effect.Effect<\n\tContext.Context<never>,\n\tnever,\n\t| IdentityContext\n\t| RuntimeRoot\n\t| StackPathsService\n\t| CacheService\n\t| StrategyRegistryService\n\t| ContainerRuntimeService\n\t| PortBrokerService\n\t| LeaseBrokerService\n\t| PostAcquireTasksService\n\t| Logger\n> =>\n\tEffect.gen(function* () {\n\t\tconst identityCtx = yield* IdentityContext;\n\t\tconst runtimeRootResolved = yield* RuntimeRoot;\n\t\tconst stackPaths = yield* StackPathsService;\n\t\tconst cache = yield* CacheService;\n\t\tconst registry = yield* StrategyRegistryService;\n\t\tconst containerRuntime = yield* ContainerRuntimeService;\n\t\tconst portBroker = yield* PortBrokerService;\n\t\tconst leaseBroker = yield* LeaseBrokerService;\n\t\tconst postAcquireTasks = yield* PostAcquireTasksService;\n\t\tconst logger = yield* Logger;\n\n\t\treturn Context.empty().pipe(\n\t\t\tContext.add(IdentityContext, identityCtx),\n\t\t\tContext.add(RuntimeRoot, runtimeRootResolved),\n\t\t\tContext.add(StackPathsService, stackPaths),\n\t\t\tContext.add(CacheService, cache),\n\t\t\tContext.add(StrategyRegistryService, registry),\n\t\t\tContext.add(ContainerRuntimeService, containerRuntime),\n\t\t\tContext.add(PortBrokerService, portBroker),\n\t\t\tContext.add(LeaseBrokerService, leaseBroker),\n\t\t\tContext.add(PostAcquireTasksService, postAcquireTasks),\n\t\t\tContext.add(Logger, logger),\n\t\t) as Context.Context<never>;\n\t});\n\n/** Options accepted by the supervised-run entrypoint. `lifetime`\n * selects long-running supervision versus a one-shot acquire/codegen\n * cycle. The `beforeInitialAcquire` hook runs inside the supervised\n * scope before the first acquire starts; live renderers use it to\n * subscribe to startup projection changes. The `withinScope` hook\n * runs after the first acquire completes.\n *\n * Generic `R` widens the hook R-channel so callers can yield\n * substrate services (e.g. `StackPathsService`) that are in scope at\n * the supervisor-boot site. */\nexport interface SuperviseStackOptions<R = Scope.Scope, ExtendR = never, HookE = never> {\n\treadonly lifetime?: 'long-running' | 'one-shot';\n\treadonly devstackVersion?: string;\n\treadonly beforeInitialAcquire?: (handle: SupervisorHandle) => Effect.Effect<void, HookE, R>;\n\treadonly withinScope?: (handle: SupervisorHandle) => Effect.Effect<void, HookE, R>;\n\treadonly commandHandler?: SupervisorCommandHandler;\n\treadonly contributionDispatcher?: ContributionDispatcher;\n\treadonly postAcquireHook?: SupervisorPostAcquireHook;\n\t/** Caller-supplied extension layered into `pluginContext` after the\n\t * default substrate context is built. Used by plugin-author Layer\n\t * composition (ARCHITECTURE.md § Plugin-author extension) and by\n\t * the CLI when it wants to inject the built-in plugin registries or\n\t * a custom Logger override. */\n\treadonly extendContext?: (\n\t\tctx: Context.Context<never>,\n\t) => Effect.Effect<Context.Context<never>, never, ExtendR>;\n}\n\n/** Effect that boots the supervisor for `stack` and blocks on the\n * supervisor's shutdown latch. Returns the final `SubscribableState`\n * snapshot so callers (CLI, library handle) can inspect post-shutdown\n * state. */\nexport const superviseStackEffect = <R = Scope.Scope, ExtendR = never, HookE = never>(\n\tstack: SupervisedStack,\n\tidentity: Identity,\n\tstate: SubscriptionRef.SubscriptionRef<import('../substrate/projection.ts').SubscribableState>,\n\topts: SuperviseStackOptions<R, ExtendR, HookE> = {},\n) =>\n\tEffect.gen(function* () {\n\t\treturn yield* Effect.scoped(\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst baseContext = yield* buildPluginContext();\n\t\t\t\tconst pluginContext =\n\t\t\t\t\topts.extendContext === undefined ? baseContext : yield* opts.extendContext(baseContext);\n\n\t\t\t\tconst startup = yield* startSupervisor(\n\t\t\t\t\tstack,\n\t\t\t\t\tidentity,\n\t\t\t\t\tstate,\n\t\t\t\t\tpluginContext,\n\t\t\t\t\topts.contributionDispatcher,\n\t\t\t\t\topts.commandHandler,\n\t\t\t\t\topts.postAcquireHook,\n\t\t\t\t\t{\n\t\t\t\t\t\tcommandLoop: opts.lifetime !== 'one-shot',\n\t\t\t\t\t\t...(opts.devstackVersion === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { devstackVersion: opts.devstackVersion }),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tconst { handle } = startup;\n\t\t\t\tif (opts.beforeInitialAcquire !== undefined) {\n\t\t\t\t\tyield* opts.beforeInitialAcquire(handle);\n\t\t\t\t}\n\t\t\t\tif (opts.lifetime === 'one-shot') {\n\t\t\t\t\t// `runInitialAcquire` runs `acquireFullGraph` to completion (every\n\t\t\t\t\t// node reaches a terminal status) before it returns. Gate the\n\t\t\t\t\t// one-shot `withinScope` on the SUPERVISOR-OWNED readiness signal\n\t\t\t\t\t// — `allReadyOrTerminal` (`ready || done`) — NOT a per-node\n\t\t\t\t\t// `awaitReady` watcher. A run-to-completion `task` node lands in\n\t\t\t\t\t// `done`; the registry contract admits a `done`-status node whose\n\t\t\t\t\t// `readyGate` is unresolved (only `markReady`/`markFailed` resolve\n\t\t\t\t\t// it), so a per-node gate HANGS on it. This is the SAME\n\t\t\t\t\t// `done`-tolerant gate S1 gave the long-running path; reading\n\t\t\t\t\t// statuses never suspends, so it is hang-free.\n\t\t\t\t\tyield* startup.runInitialAcquire;\n\t\t\t\t\tyield* allReadyOrTerminal(startup.handle.graph, startup.handle.registry);\n\t\t\t\t\tif (opts.withinScope !== undefined) {\n\t\t\t\t\t\tyield* opts.withinScope(handle);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst outcome = yield* Effect.raceFirst(\n\t\t\t\t\tstartup.runInitialAcquire.pipe(Effect.as('booted' as const)),\n\t\t\t\t\thandle.awaitShutdown.pipe(Effect.as('shutdown' as const)),\n\t\t\t\t);\n\t\t\t\tif (outcome === 'shutdown') {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (opts.withinScope !== undefined) {\n\t\t\t\t\tyield* opts.withinScope(handle);\n\t\t\t\t}\n\t\t\t\tyield* handle.awaitShutdown;\n\t\t\t}),\n\t\t);\n\t});\n\n// ───────────────────────────────────────────────────────────────────────────\n// Production orchestrator assembly\n// ───────────────────────────────────────────────────────────────────────────\n\nexport interface ProductionCodegenOptions {\n\treadonly appRoot?: string;\n\t/** Resolved absolute path to the dev-only + secret `generated-extras`\n\t * tree for this stack, threaded into `CodegenRoot.extrasDir` and\n\t * recorded in the manifest as `codegen.extrasDir` for the\n\t * `@devstack-dev` Vite alias. This is the ONLY tree boot's codegen\n\t * writes (`emitExtras`); boot never emits the committed `src/generated`\n\t * tree, so it pins no live `outputDir` — the `CodegenRoot.outputDir`\n\t * the production path carries is an unwritten default. The committed\n\t * tree is owned solely by the stack-free `codegen` verb (wired\n\t * separately, where it resolves its own output path). */\n\treadonly extrasDir?: string;\n\t/** Forwarded verbatim to `@mysten/codegen`'s\n\t * `generateFromPackageSummary` via `layerMystenMoveCodegen` — see\n\t * `DevstackOptions['codegen']` for the full contract. Default `false`\n\t * (`@mysten/codegen`'s own default): phantom-only structs render as\n\t * consts with the phantom placeholder baked into `.name`; `true`\n\t * renders them as factories whose required type arguments compose a\n\t * fully-qualified type tag. */\n\treadonly includePhantomTypeParameters?: boolean;\n}\n\n/**\n * The ONE boot seam that maps a stack's codegen config to the production\n * codegen orchestrator options for a LIVE (`'ran'`) projection. Both\n * composition entry points (`api/run-stack.ts` and `orchestrators/layers.ts`)\n * call this so the live output-dir decision (via `resolveCodegenOutput`)\n * is wired exactly once: EVERY live run — including what used to be the\n * \"primary\" stack — emits into `<appRoot>/.devstack/stacks/<stack>/generated`,\n * so the id-bearing live tree never lands in the committed source tree and\n * two stacks never clobber. The committed `src/generated` tree is owned\n * solely by the stack-free `codegen` verb. The resolved literal\n * `outputDir`/`stackSubdir`/`extrasDir` flow into\n * `layerProductionOrchestrators({ codegen })` unchanged — `paths.ts` keeps\n * consuming literals (minimal blast radius).\n *\n * The per-stack inputs: the app root, the resolved effective stack\n * (already through the explicit-`--stack` > `config.stackName` > inferred\n * ladder), and the app's optional explicit `codegen` pins.\n */\nexport const resolveProductionCodegenOptions = (input: {\n\treadonly appRoot: string;\n\treadonly effectiveStack: string;\n\treadonly codegen?:\n\t\t| {\n\t\t\t\treadonly includePhantomTypeParameters?: boolean;\n\t\t }\n\t\t| undefined;\n}): ProductionCodegenOptions => {\n\t// Every live run resolves its dev tree to\n\t// `<appRoot>/.devstack/stacks/<stack>/generated-extras` (the default\n\t// rule). Nothing is ever emitted into the live `generated` tree at boot\n\t// (boot writes only the per-stack `generated-extras` overlay +\n\t// `devstack-ids.json`), so there is no live `outputDir` to resolve — the\n\t// committed `src/generated` tree is owned solely by the stack-free\n\t// `codegen` verb (wired separately).\n\tconst resolved = resolveCodegenOutput({\n\t\tappRoot: input.appRoot,\n\t\teffectiveStack: input.effectiveStack,\n\t});\n\treturn {\n\t\tappRoot: input.appRoot,\n\t\textrasDir: resolved.extrasDir,\n\t\t// Pass-through verbatim — no resolution step; \"unset\" stays unset so\n\t\t// `@mysten/codegen`'s own default (false) applies at the call site.\n\t\t...(input.codegen?.includePhantomTypeParameters === undefined\n\t\t\t? {}\n\t\t\t: { includePhantomTypeParameters: input.codegen.includePhantomTypeParameters }),\n\t};\n};\n\nexport interface ProductionRouterOptions {\n\treadonly codegen?: ProductionCodegenOptions;\n\treadonly disabled?: boolean;\n}\n\nexport class ManifestEndpointRegistryService extends Context.Service<\n\tManifestEndpointRegistryService,\n\t{\n\t\treadonly register: (entry: EndpointEntry) => Effect.Effect<void, never, Scope.Scope>;\n\t\treadonly entries: Effect.Effect<ReadonlyArray<EndpointEntry>>;\n\t}\n>()('@devstack/orchestrators/ManifestEndpointRegistry') {}\n\nexport const layerManifestEndpointRegistry: Layer.Layer<ManifestEndpointRegistryService> =\n\tLayer.effect(\n\t\tManifestEndpointRegistryService,\n\t\tEffect.gen(function* () {\n\t\t\tconst entriesRef = yield* Ref.make<ReadonlyArray<EndpointEntry & { readonly seq: number }>>(\n\t\t\t\t[],\n\t\t\t);\n\t\t\tconst seqRef = yield* Ref.make(0);\n\n\t\t\tconst register = (entry: EndpointEntry): Effect.Effect<void, never, Scope.Scope> =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst seq = yield* Ref.updateAndGet(seqRef, (n) => n + 1);\n\t\t\t\t\tyield* Ref.update(entriesRef, (entries) => [...entries, { ...entry, seq }]);\n\t\t\t\t\tyield* Effect.addFinalizer(() =>\n\t\t\t\t\t\tRef.update(entriesRef, (entries) =>\n\t\t\t\t\t\t\tentries.filter((candidate) => candidate.seq !== seq),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t});\n\n\t\t\treturn ManifestEndpointRegistryService.of({\n\t\t\t\tregister,\n\t\t\t\tentries: Ref.get(entriesRef).pipe(\n\t\t\t\t\tEffect.map((entries) =>\n\t\t\t\t\t\tentries.map((entryWithSeq) => {\n\t\t\t\t\t\t\tconst { seq, ...entry } = entryWithSeq;\n\t\t\t\t\t\t\tvoid seq;\n\t\t\t\t\t\t\treturn entry;\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t});\n\t\t}),\n\t);\n\nexport const productionRouterProfile = (options: DefaultRouterProfileOptions = {}): RouterProfile =>\n\tmakeDefaultRouterProfile(options);\n\n/** `outputDir` for the `CodegenRoot` of a `layerProductionOrchestrators`\n * composition. The production codegen path NEVER emits the committed\n * `src/generated` tree (boot writes only `generated-extras` via\n * `emitExtras`), so this directory is never written — it only has to wire\n * a valid, non-crashing `CodegenRoot`. It resolves to `<appRoot>/src/generated`\n * by convention. The committed tree is owned solely by the stack-free\n * `codegen` verb (wired separately, where it pins its own output path). */\nconst productionCodegenOutputDir = (appRoot: string): string => resolve(appRoot, 'src/generated');\n\n/** Fallback `generated-extras` dir for the cold-start / no-config\n * composition path (`buildDirectSnapshotLayers`). Callers that know\n * their stack (`run-stack`, the verb wirings) pass the resolved\n * per-stack value; this default only feeds direct-snapshot verbs that\n * never run codegen. */\nconst productionCodegenExtrasDir = (appRoot: string, extrasDir: string | undefined): string => {\n\tconst target = extrasDir ?? '.devstack/generated-extras';\n\treturn isAbsolute(target) ? target : resolve(appRoot, target);\n};\n\nexport const layerProductionOrchestrators = (router: ProductionRouterOptions = {}) => {\n\tconst profile = productionRouterProfile();\n\treturn Layer.mergeAll(\n\t\tlayerSnapshotOrchestrator,\n\t\tlayerManifestEndpointRegistry,\n\t\tlayerRouterService.pipe(\n\t\t\tLayer.provideMerge(\n\t\t\t\tLayer.mergeAll(\n\t\t\t\t\tlayerEntrypointRegistry(BUILT_IN_ENTRYPOINTS),\n\t\t\t\t\tlayerTraefikContainerOpsDocker,\n\t\t\t\t\tlayerDockerUpstreamResolver(profile),\n\t\t\t\t\tlayerRouterConfigLiteral({\n\t\t\t\t\t\tdisabled: router.disabled ?? false,\n\t\t\t\t\t\tprofile,\n\t\t\t\t\t\timage: DEFAULT_TRAEFIK_IMAGE,\n\t\t\t\t\t\trouteReadinessProbe: {\n\t\t\t\t\t\t\tenabled: router.disabled !== true,\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t\t),\n\t\tlayerCodegenOrchestrator,\n\t\tlayerCodegenPaths.pipe(\n\t\t\tLayer.provideMerge(\n\t\t\t\tlayerCodegenRoot({\n\t\t\t\t\toutputDir: productionCodegenOutputDir(router.codegen?.appRoot ?? process.cwd()),\n\t\t\t\t\tstackSubdir: null,\n\t\t\t\t\textrasDir: productionCodegenExtrasDir(\n\t\t\t\t\t\trouter.codegen?.appRoot ?? process.cwd(),\n\t\t\t\t\t\trouter.codegen?.extrasDir,\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t\tlayerSuiMoveSummaryRunnerDocker,\n\t\tlayerMystenMoveCodegen({\n\t\t\tincludePhantomTypeParameters: router.codegen?.includePhantomTypeParameters,\n\t\t}),\n\t);\n};\n\n/** The single adapter for routable endpoints: ONE `ResolvedRoute` (the\n * router's post-mint source of truth) → ALL THREE sink-feeds at once —\n * the router's own `route`, the manifest `EndpointEntry`, and the\n * projection `endpoint.registered` event — derived from one shared\n * field-set so the three sinks can never diverge. The `routable`\n * dispatch body feeds each sink from the object this returns; there is\n * no second, third derivation off the route anywhere.\n *\n * It owns the url-derivation: `tcp` routes carry `tcp://127.0.0.1:port`,\n * everything else `http://hostname:port`. Consumers (codegen, manifest)\n * translate `tcp://` to their protocol-specific scheme (`postgres://`,\n * `redis://`, …).\n *\n * `ResolvedRoute` only carries `entrypointName`, so the endpoint name is\n * recovered from the original `decl.endpointName`; `pluginKey` is supplied\n * by the dispatcher (it is not in `ResolvedRoute`). Router-only fields\n * (`dispatchFileId`/`cors`/`upstreamUrl`) are kept ON `route` for the\n * router sink but discarded from the manifest/projection field-set — those\n * schemas do not consume them. */\nexport const endpointSinksFromRoute = (\n\tdecl: RoutableDecl,\n\troute: ResolvedRoute,\n\tpluginKey: PluginKey,\n\tregisteredAt = Date.now(),\n) => {\n\tconst url =\n\t\troute.wireProtocol === 'tcp'\n\t\t\t? `tcp://127.0.0.1:${route.entrypointPort}`\n\t\t\t: `http://${route.hostname}:${route.entrypointPort}`;\n\tconst common = {\n\t\tname: decl.endpointName,\n\t\turl,\n\t\tdisplayUrl: null,\n\t\twireProtocol: route.wireProtocol,\n\t} as const;\n\tconst endpointKeyString = `${pluginKey}:${decl.endpointName}`;\n\tconst event: Extract<EngineEvent, { readonly tag: 'endpoint.registered' }> = {\n\t\ttag: 'endpoint.registered',\n\t\tendpoint: {\n\t\t\t...common,\n\t\t\tendpointKey: endpointKey(endpointKeyString),\n\t\t\tpluginKey,\n\t\t\tregisteredAt,\n\t\t},\n\t};\n\treturn {\n\t\troute,\n\t\tmanifestEntry: {\n\t\t\t...common,\n\t\t\tendpointKey: endpointKeyString,\n\t\t\tpluginKey: String(pluginKey),\n\t\t},\n\t\tevent,\n\t};\n};\n\nconst manifestEndpointEntryFromOperationalEndpoint = (\n\tendpoint: Extract<EngineEvent, { readonly tag: 'endpoint.registered' }>['endpoint'],\n): EndpointEntry => ({\n\tendpointKey: String(endpoint.endpointKey),\n\tname: endpoint.name,\n\turl: endpoint.url,\n\tdisplayUrl: endpoint.displayUrl,\n\twireProtocol: endpoint.wireProtocol,\n\tpluginKey: String(endpoint.pluginKey),\n});\n\n/** Project a projection decl's `rowKey` (when absent) onto the\n * contributing plugin so projection consumers can attribute the row.\n * The payload stays opaque from the substrate's POV. */\nconst projectionDispatch = (\n\tdecl: ProjectionDecl,\n\tctx: ContributionDispatchContext,\n): Effect.Effect<void, never, never> => {\n\tconst payload = decl.event.payload;\n\tconst payloadWithRowKey =\n\t\tpayload !== null &&\n\t\ttypeof payload === 'object' &&\n\t\t'rowKey' in payload &&\n\t\t(payload as { rowKey: unknown }).rowKey === null\n\t\t\t? { ...payload, rowKey: ctx.pluginKey }\n\t\t\t: payload;\n\treturn ctx.publish({\n\t\t...decl.event,\n\t\tpayload: payloadWithRowKey,\n\t});\n};\n\n/** Register a strategy contribution on the scope-local registry, publish\n * `strategy.registered`, and arm a finalizer publishing\n * `strategy.unregistered`. */\nconst strategyContributorDispatch = (\n\tdecl: StrategyContributorDecl<string, unknown>,\n\tctx: ContributionDispatchContext,\n): Effect.Effect<void, never, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tyield* ctx.strategyRegistry.register(decl.capabilityKey, decl.strategy, {\n\t\t\tautoMounted: decl.autoMounted,\n\t\t\t...(decl.priority === undefined ? {} : { priority: decl.priority }),\n\t\t});\n\t\tyield* ctx.publish({\n\t\t\ttag: 'strategy.registered',\n\t\t\tcapabilityKey: decl.capabilityKey,\n\t\t\tautoMounted: decl.autoMounted,\n\t\t\tat: Date.now(),\n\t\t});\n\t\tyield* Effect.addFinalizer(() =>\n\t\t\tctx.publish({\n\t\t\t\ttag: 'strategy.unregistered',\n\t\t\t\tcapabilityKey: decl.capabilityKey,\n\t\t\t\tat: Date.now(),\n\t\t\t}),\n\t\t);\n\t});\n\n/**\n * Build the production `ContributionDispatcher` — the closed seam the\n * supervisor replays each plugin's buffered contributions through after\n * a successful `start`. Each method's body reads its backing orchestrator\n * service (Snapshot/Router/Codegen/ManifestEndpoint) ONCE here and closes\n * over it; the substrate supervisor holds the resulting record opaquely\n * (it never imports an orchestrator service).\n */\nexport const buildProductionContributionDispatcher = (): Effect.Effect<\n\tContributionDispatcher,\n\tnever,\n\t| SnapshotOrchestratorService\n\t| RouterService\n\t| CodegenOrchestratorService\n\t| ManifestEndpointRegistryService\n> =>\n\tEffect.gen(function* () {\n\t\tconst snapshot = yield* SnapshotOrchestratorService;\n\t\tconst router = yield* RouterService;\n\t\tconst codegen = yield* CodegenOrchestratorService;\n\t\tconst manifestEndpoints = yield* ManifestEndpointRegistryService;\n\t\treturn {\n\t\t\tsnapshotable: (decl: SnapshotableDecl, ctx) =>\n\t\t\t\tsnapshot.registerParticipant(ctx.pluginKey, decl),\n\t\t\troutable: (decl: RoutableDecl, ctx) =>\n\t\t\t\trouter.boot().pipe(\n\t\t\t\t\t// Router sink: `contributeRoute` writes the dispatch file +\n\t\t\t\t\t// publishes the route onto `applied`, returning the post-mint\n\t\t\t\t\t// `ResolvedRoute` — the ONE source of truth.\n\t\t\t\t\tEffect.andThen(router.contributeRoute(decl)),\n\t\t\t\t\tEffect.flatMap((route) => {\n\t\t\t\t\t\t// One adapter off that ResolvedRoute yields BOTH remaining\n\t\t\t\t\t\t// sink-feeds; feed manifest then projection. No second\n\t\t\t\t\t\t// derivation off the route lives anywhere.\n\t\t\t\t\t\tconst sinks = endpointSinksFromRoute(decl, route, ctx.pluginKey);\n\t\t\t\t\t\treturn manifestEndpoints\n\t\t\t\t\t\t\t.register(sinks.manifestEntry)\n\t\t\t\t\t\t\t.pipe(Effect.andThen(ctx.publish(sinks.event)));\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\tcodegenable: (decl: Codegenable, ctx) => codegen.registerContribution(ctx.pluginKey, decl),\n\t\t\tprojection: (decl: ProjectionDecl, ctx) => projectionDispatch(decl, ctx),\n\t\t\tstrategyContributor: (decl: StrategyContributorDecl<string, unknown>, ctx) =>\n\t\t\t\tstrategyContributorDispatch(decl, ctx),\n\t\t} satisfies ContributionDispatcher;\n\t});\n\nconst makeManifestExtrasContext = (ctx: SupervisorPostAcquireContext) => {\n\tconst resourceIdToKey = new Map<string, PluginKey>();\n\tfor (const [key, node] of ctx.graph.nodes) {\n\t\tresourceIdToKey.set(node.member.id, key);\n\t}\n\t// `lookup` throws `ManifestExtrasLookupError` synchronously from\n\t// inside the user-supplied `extras` factory.\n\t// `resolveManifestExtras` invokes that factory under `Effect.try`\n\t// with a typed `catch` mapper, so the throw promotes to the typed\n\t// failure channel — callers `catchTag('ManifestExtrasLookupError',\n\t// ...)` rather than reading the die-cause. Non-tagged throws stay\n\t// defects, preserving the previous semantics for genuine\n\t// programmer errors inside the factory body.\n\tconst lookup = (resourceId: string): unknown => {\n\t\tconst key = resourceIdToKey.get(resourceId);\n\t\tif (key === undefined) {\n\t\t\tthrow new ManifestExtrasLookupError({\n\t\t\t\tkind: 'unknown-resource',\n\t\t\t\tresourceId,\n\t\t\t});\n\t\t}\n\t\tconst resolved = readResolvedSync(ctx.registry, key);\n\t\tif (resolved === undefined) {\n\t\t\tthrow new ManifestExtrasLookupError({\n\t\t\t\tkind: 'unresolved-resource',\n\t\t\t\tresourceId,\n\t\t\t});\n\t\t}\n\t\treturn resolved;\n\t};\n\treturn {\n\t\tvalue: (resource: { readonly id: string }) => lookup(resource.id),\n\t};\n};\n\nconst operationalManifestEndpointEntries = (\n\tctx: SupervisorPostAcquireContext,\n\troutableEntries: ReadonlyArray<EndpointEntry>,\n): ReadonlyArray<EndpointEntry> => {\n\tconst routablePluginKeys = new Set(routableEntries.map((entry) => entry.pluginKey));\n\tconst registeredAt = Date.now();\n\tconst entries: EndpointEntry[] = [];\n\tfor (const [key] of ctx.graph.nodes) {\n\t\tif (routablePluginKeys.has(String(key))) continue;\n\t\tconst resolved = readResolvedSync(ctx.registry, key);\n\t\tif (resolved === undefined) continue;\n\t\tfor (const event of operationalEndpointEventsFromResolvedValue(key, resolved, registeredAt)) {\n\t\t\tentries.push(manifestEndpointEntryFromOperationalEndpoint(event.endpoint));\n\t\t}\n\t}\n\treturn entries;\n};\n\nexport const buildProductionPostAcquireHook = (\n\toptions: {\n\t\treadonly extras?: ManifestExtrasInput;\n\t\treadonly networkOptions?: Readonly<Record<string, unknown>>;\n\t} = {},\n): Effect.Effect<\n\tSupervisorPostAcquireHook,\n\tnever,\n\t| CodegenOrchestratorService\n\t| CodegenPathsService\n\t| FileSystem.FileSystem\n\t| StackPathsService\n\t| PostAcquireTasksService\n\t| ManifestEndpointRegistryService\n\t| MoveSummaryRunnerService\n\t| MoveCodegenService\n> =>\n\tEffect.gen(function* () {\n\t\tconst codegen = yield* CodegenOrchestratorService;\n\t\tconst paths = yield* CodegenPathsService;\n\t\tconst fs = yield* FileSystem.FileSystem;\n\t\tconst stackPaths = yield* StackPathsService;\n\t\tconst postAcquireTasks = yield* PostAcquireTasksService;\n\t\tconst manifestEndpoints = yield* ManifestEndpointRegistryService;\n\t\t// Yielded here (outside the per-ctx hook) so the conditional\n\t\t// `generated-extras` flush below can provide them to `emitExtras`.\n\t\tconst moveRunner = yield* MoveSummaryRunnerService;\n\t\tconst moveCodegen = yield* MoveCodegenService;\n\t\treturn (ctx) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst extras = yield* resolveManifestExtras(options.extras, makeManifestExtrasContext(ctx));\n\t\t\t\tconst routableEndpoints = yield* manifestEndpoints.entries;\n\t\t\t\tconst endpoints = [\n\t\t\t\t\t...routableEndpoints,\n\t\t\t\t\t...operationalManifestEndpointEntries(ctx, routableEndpoints),\n\t\t\t\t];\n\t\t\t\t// Boot no longer runs codegen. Its only job is to PRODUCE the\n\t\t\t\t// id-config (loadable on-chain ids), which the Vite plugin injects\n\t\t\t\t// via `__DEVSTACK_IDS__` in dev. The committed `src/generated` tree\n\t\t\t\t// is written ONLY by the stack-free `devstack codegen` verb.\n\t\t\t\t// Assemble the id-config from the SAME live-resolved contributions\n\t\t\t\t// that fed `config.ts` and write it to the gitignored\n\t\t\t\t// `.devstack/stacks/<stack>/`.\n\t\t\t\tconst idConfig = yield* codegen.assembleIdConfig(String(ctx.identity.network)).pipe(\n\t\t\t\t\tEffect.mapError(\n\t\t\t\t\t\t(cause) =>\n\t\t\t\t\t\t\tnew CodegenWriteFailed({\n\t\t\t\t\t\t\t\toutputPath: ID_CONFIG_FILENAME,\n\t\t\t\t\t\t\t\tstage: 'write',\n\t\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tconst idsFile = join(stackPaths.stackRoot, ID_CONFIG_FILENAME);\n\t\t\t\tyield* writeIdConfig(idsFile, idConfig).pipe(\n\t\t\t\t\tEffect.provideService(FileSystem.FileSystem, fs),\n\t\t\t\t);\n\t\t\t\tconst envelope = yield* buildEnvelope({\n\t\t\t\t\tidentity: {\n\t\t\t\t\t\tapp: ctx.identity.app,\n\t\t\t\t\t\tstack: ctx.identity.stack,\n\t\t\t\t\t\tnetwork: ctx.identity.network,\n\t\t\t\t\t},\n\t\t\t\t\tendpoints,\n\t\t\t\t\textras,\n\t\t\t\t\t// Record the dev-only `generated-extras` tree the\n\t\t\t\t\t// `@devstack-dev` Vite alias resolves and the live `idsFile`\n\t\t\t\t\t// the plugin injects as `__DEVSTACK_IDS__` — one decision, one\n\t\t\t\t\t// source of truth. Bindings are NOT recorded: `@generated`\n\t\t\t\t\t// always resolves to the committed `src/generated` tree written\n\t\t\t\t\t// by the stack-free `codegen` verb.\n\t\t\t\t\tcodegen: { extrasDir: paths.extrasDir, idsFile },\n\t\t\t\t});\n\t\t\t\tconst manifestPath = join(stackPaths.stackRoot, 'manifest.json');\n\t\t\t\tyield* writeManifest(envelope, manifestPath).pipe(\n\t\t\t\t\tEffect.provideService(FileSystem.FileSystem, fs),\n\t\t\t\t);\n\t\t\t\t// Conditionally flush the dev-only `generated-extras` tree\n\t\t\t\t// (dev wallet + accounts) — the ONE acquire-resolved surface the\n\t\t\t\t// stack-free `codegen` verb can't produce. Gated on the resolved\n\t\t\t\t// network's `devWallet` flag (per-network options, ON for every\n\t\t\t\t// network except live `mainnet`). When off, nothing is written\n\t\t\t\t// and the Vite plugin's `@devstack-dev` `load` hook no-ops.\n\t\t\t\tconst netOpts = resolveNetworkOptions(ctx.identity.network, options.networkOptions);\n\t\t\t\tconst extrasFiles: string[] = [];\n\t\t\t\tif (netOpts.devWallet) {\n\t\t\t\t\tconst extras = yield* codegen\n\t\t\t\t\t\t.emitExtras()\n\t\t\t\t\t\t.pipe(\n\t\t\t\t\t\t\tEffect.provideService(FileSystem.FileSystem, fs),\n\t\t\t\t\t\t\tEffect.provideService(CodegenPathsService, paths),\n\t\t\t\t\t\t\tEffect.provideService(MoveSummaryRunnerService, moveRunner),\n\t\t\t\t\t\t\tEffect.provideService(MoveCodegenService, moveCodegen),\n\t\t\t\t\t\t);\n\t\t\t\t\textrasFiles.push(...extras.filesWritten, ...extras.filesChmod);\n\t\t\t\t}\n\t\t\t\tyield* postAcquireTasks.runAll;\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\ttag: 'manifest.flushed' as const,\n\t\t\t\t\t\tmanifestVersion: CURRENT_MANIFEST_VERSION,\n\t\t\t\t\t\tat: Date.now(),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttag: 'codegen.emitted' as const,\n\t\t\t\t\t\tfiles: [idsFile, ...extrasFiles],\n\t\t\t\t\t\tat: Date.now(),\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t});\n\t});\n\n// ───────────────────────────────────────────────────────────────────────────\n// Built-in plugin runtime composition\n//\n// Depends on L2 plugin internals (coin/package registries), so it can't live\n// at L1 runtime — hence its home in this L3 boot module.\n// ───────────────────────────────────────────────────────────────────────────\n\n/** Built-in plugin runtime: the per-stack coin + package registries.\n * Coin auto-discovery from a fresh package publish now runs DIRECTLY in\n * the package plugin's `start` (folding the publish output into the\n * CoinRegistry), so the registries are the whole surface. */\nexport const layerBuiltInPluginRuntime: Layer.Layer<CoinRegistryService | PackageRegistryService> =\n\tLayer.mergeAll(layerCoinRegistry, layerPackageRegistry);\n\nexport const extendBuiltInPluginContext = (\n\tctx: Context.Context<never>,\n): Effect.Effect<\n\tContext.Context<never>,\n\tnever,\n\tCoinRegistryService | PackageRegistryService | SnapshotOrchestratorService | FileSystem.FileSystem\n> =>\n\tEffect.gen(function* () {\n\t\tconst coinRegistry = yield* CoinRegistryService;\n\t\tconst packageRegistry = yield* PackageRegistryService;\n\t\t// Thread the snapshot orchestrator + filesystem into the plugin\n\t\t// runtime context so the supervisor can populate the control-plane\n\t\t// `domain` surface (snapshot list/restore/delete, which never\n\t\t// round-trip through the void `publishCommand`). The\n\t\t// `ContainerRuntimeService` the domain also needs is already in the\n\t\t// base substrate plugin context.\n\t\tconst snapshotOrchestrator = yield* SnapshotOrchestratorService;\n\t\tconst fileSystem = yield* FileSystem.FileSystem;\n\t\treturn ctx.pipe(\n\t\t\tContext.add(CoinRegistryService, coinRegistry),\n\t\t\tContext.add(PackageRegistryService, packageRegistry),\n\t\t\tContext.add(SnapshotOrchestratorService, snapshotOrchestrator),\n\t\t\tContext.add(FileSystem.FileSystem, fileSystem),\n\t\t) as Context.Context<never>;\n\t});\n\n// ───────────────────────────────────────────────────────────────────────────\n// Production supervised-boot assembly — THE single dedup site\n// ───────────────────────────────────────────────────────────────────────────\n\n/** The per-caller inputs to {@link superviseStackWithProductionBoot} — the\n * fields that GENUINELY differ between the long-running programmatic seam\n * (`api/run-stack-internal.ts`) and the one-shot CLI verbs (`apply` /\n * `snapshot`). Everything else — the contribution dispatcher, the\n * post-acquire hook, and the built-in plugin-context extension — is\n * assembled identically by the helper, so it lives in ONE place. */\nexport interface ProductionBootOptions<HookR = Scope.Scope, HookE = never, ExtendR = never> {\n\t/** `'one-shot'` runs the acquire/codegen cycle then returns; the default\n\t * `'long-running'` supervises until shutdown. */\n\treadonly lifetime?: 'long-running' | 'one-shot';\n\treadonly devstackVersion?: string;\n\t/** Threaded into `buildProductionPostAcquireHook` — the stack's manifest\n\t * `extras`. All three callers pass `stack.options.extras`. */\n\treadonly extras?: ManifestExtrasInput;\n\t/** Threaded into `buildProductionPostAcquireHook` — the stack's\n\t * per-network options. The hook resolves the active network's slice to\n\t * decide whether to flush the dev-only `generated-extras` tree. All\n\t * three callers pass `stack.options.networkOptions`. */\n\treadonly networkOptions?: Readonly<Record<string, unknown>>;\n\t/** The resolved supervisor command handler (run-stack's snapshot bridge).\n\t * One-shot verbs run no command loop, so they pass nothing. */\n\treadonly commandHandler?: SupervisorCommandHandler;\n\treadonly beforeInitialAcquire?: (handle: SupervisorHandle) => Effect.Effect<void, HookE, HookR>;\n\treadonly withinScope?: (handle: SupervisorHandle) => Effect.Effect<void, HookE, HookR>;\n\t/** Caller plugin-context extension layered AFTER the built-in\n\t * (`extendBuiltInPluginContext`). Only the programmatic seam uses it (to\n\t * honor the public `runStack({ extendContext })`); the CLI verbs omit it\n\t * and get the built-in extension alone. */\n\treadonly extendContextAfterBuiltIn?: (\n\t\tctx: Context.Context<never>,\n\t) => Effect.Effect<Context.Context<never>, never, ExtendR>;\n}\n\n/**\n * THE single site that assembles the production supervised body. It builds\n * the contribution dispatcher + post-acquire hook + built-in plugin-context\n * extension ONCE and hands them to {@link superviseStackEffect}, then\n * provides {@link layerBuiltInPluginRuntime}. Before this helper, the same\n * three-piece assembly was hand-rolled in three call sites\n * (`api/run-stack-internal.ts`, `cli/wirings/apply.ts`,\n * `cli/wirings/snapshot.ts`); now they all route through here and only\n * supply what genuinely differs ({@link ProductionBootOptions}).\n *\n * Each caller keeps its OWN lifetime-specific wrapping: the programmatic\n * seam wraps the returned effect in a `forkDetach` handle (long-running);\n * the CLI verbs run it to completion with their existing teardown + result\n * semantics (one-shot). This helper does NOT collapse those — it only\n * dedups the assembly the `superviseStackEffect` call sites shared.\n *\n * The return type is inferred (like `superviseStackEffect`): its R-channel\n * is the union of every substrate/orchestrator service the dispatcher /\n * hook / extension read, MINUS the built-in registries `layerBuiltInPluginRuntime`\n * supplies, PLUS the caller hook `HookR` / extend `ExtendR` channels.\n */\nexport const superviseStackWithProductionBoot = <\n\tHookR = Scope.Scope,\n\tHookE = never,\n\tExtendR = never,\n>(\n\tstack: SupervisedStack,\n\tidentity: Identity,\n\tstate: SubscriptionRef.SubscriptionRef<import('../substrate/projection.ts').SubscribableState>,\n\topts: ProductionBootOptions<HookR, HookE, ExtendR> = {},\n) =>\n\tEffect.gen(function* () {\n\t\tconst contributionDispatcher = yield* buildProductionContributionDispatcher();\n\t\tconst postAcquireHook = yield* buildProductionPostAcquireHook({\n\t\t\t...(opts.extras === undefined ? {} : { extras: opts.extras }),\n\t\t\t...(opts.networkOptions === undefined ? {} : { networkOptions: opts.networkOptions }),\n\t\t});\n\t\tyield* superviseStackEffect(stack, identity, state, {\n\t\t\tcontributionDispatcher,\n\t\t\tpostAcquireHook,\n\t\t\t...(opts.lifetime === undefined ? {} : { lifetime: opts.lifetime }),\n\t\t\t...(opts.devstackVersion === undefined ? {} : { devstackVersion: opts.devstackVersion }),\n\t\t\t...(opts.commandHandler === undefined ? {} : { commandHandler: opts.commandHandler }),\n\t\t\t...(opts.beforeInitialAcquire === undefined\n\t\t\t\t? {}\n\t\t\t\t: { beforeInitialAcquire: opts.beforeInitialAcquire }),\n\t\t\t...(opts.withinScope === undefined ? {} : { withinScope: opts.withinScope }),\n\t\t\t// Built-in plugin-context extension ALWAYS runs; a caller extension\n\t\t\t// (the programmatic seam's `opts.extendContext`) chains AFTER it.\n\t\t\textendContext: (ctx) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst builtInContext = yield* extendBuiltInPluginContext(ctx);\n\t\t\t\t\treturn opts.extendContextAfterBuiltIn === undefined\n\t\t\t\t\t\t? builtInContext\n\t\t\t\t\t\t: yield* opts.extendContextAfterBuiltIn(builtInContext);\n\t\t\t\t}),\n\t\t}).pipe(Effect.provide(layerBuiltInPluginRuntime));\n\t});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"boot.mjs","names":["Logger"],"sources":["../../src/orchestrators/boot.ts"],"sourcesContent":["// Single L3 boot seam.\n//\n// Consumed by both the CLI verb wirings (`cli/wirings/*`) and the\n// library-facing programmatic surface (`api/run-stack.ts`), plus the e2e\n// boot harness.\n//\n// Composes the substrate Layer stack (L0) + the Docker `ContainerRuntime`\n// adapter (L1), yields the substrate services into a `Context.Context<never>`\n// pluginContext, builds the projection ref, and runs `supervise()` inside a\n// scope. The production orchestrator assembly (Snapshot/Router/Codegen/\n// ManifestEndpoint) and the contribution-delivery dispatcher live here too —\n// the supervisor holds the dispatcher record opaquely (it never imports an\n// orchestrator service).\n//\n// Architecture: this is L3 (orchestrator-level). Layer composition that\n// assembles L0+L1 stacks belongs at L3/L4 — it can't live in `substrate/`\n// because it imports a concrete L1 adapter (Docker) by definition; and it\n// depends on L2 plugin internals (coin/package registries), so it can't live\n// at L1 runtime either. See ARCHITECTURE.md § \"Layer composition belongs at\n// L3/L4, not L0\" and § \"L1-never-imports-from-L2\".\n\nimport { Context, Effect, FileSystem, Layer, Ref, Scope, SubscriptionRef } from 'effect';\nimport { join, resolve } from 'node:path';\nimport * as NodeFileSystem from '@effect/platform-node/NodeFileSystem';\nimport * as NodePath from '@effect/platform-node/NodePath';\nimport * as NodeChildProcessSpawner from '@effect/platform-node/NodeChildProcessSpawner';\nimport { ChildProcessSpawner } from 'effect/unstable/process/ChildProcessSpawner';\n\nimport type { Identity } from '../substrate/identity.ts';\nimport { CacheService, layerCache } from '../substrate/runtime/cache/index.ts';\nimport { LeaseBrokerService, layerLeaseBroker } from '../substrate/runtime/lease-broker/index.ts';\nimport {\n\tIdentityContext,\n\tRuntimeRoot,\n\tStackPathsService,\n\tlayerIdentity,\n\tlayerRuntimeRoot,\n\tlayerStackPaths,\n} from '../substrate/runtime/paths.ts';\nimport { PortBrokerService, layerPortBroker } from '../substrate/runtime/port-broker/index.ts';\nimport {\n\tStrategyRegistryService,\n\tlayerStrategyRegistry,\n} from '../substrate/runtime/strategy-registry/index.ts';\nimport {\n\tContainerRuntimeService,\n\tDockerSpawner,\n\tlayerContainerRuntimeDocker,\n\tlayerDockerCycleInitial,\n\tlayerDockerHostDefault,\n} from '../runtime/docker/index.ts';\nimport { readResolvedSync } from '../substrate/runtime/lifecycle/index.ts';\nimport { operationalEndpointEventsFromResolvedValue } from '../substrate/runtime/projection/operational-endpoints.ts';\nimport { Logger, layerLogger } from '../substrate/runtime/observability/index.ts';\nimport {\n\tPostAcquireTasksService,\n\tlayerPostAcquireTasks,\n} from '../substrate/runtime/post-acquire-tasks.ts';\nimport {\n\tallReadyOrTerminal,\n\tstartSupervisor,\n\ttype ContributionDispatcher,\n\ttype SupervisedStack,\n\ttype SupervisorCommandHandler,\n\ttype SupervisorHandle,\n\ttype SupervisorPostAcquireHook,\n} from '../substrate/runtime/supervisor/index.ts';\nimport type { ContributionDispatchContext } from '../substrate/runtime/supervisor/contribution-dispatcher.ts';\nimport type { SupervisorPostAcquireContext } from '../substrate/runtime/supervisor/index.ts';\n\nimport {\n\tlayerMystenMoveCodegen,\n\tMoveCodegenService,\n\tMoveSummaryRunnerService,\n} from './codegen/bindings.ts';\nimport { layerSuiMoveSummaryRunnerDocker } from '../plugins/sui/move-summary-runner.ts';\nimport { CodegenPathsService, layerCodegenPaths, layerCodegenRoot } from './codegen/paths.ts';\nimport {\n\tCodegenOrchestratorService,\n\tlayerCodegenOrchestrator,\n\ttype Codegenable,\n} from './codegen/service.ts';\nimport { CodegenWriteFailed } from './codegen/errors.ts';\nimport { DEPLOYMENT_FILENAME, writeDeployment } from './codegen/deployment.ts';\nimport {\n\tDEFAULT_TRAEFIK_IMAGE,\n\tlayerDockerUpstreamResolver,\n\tlayerEntrypointRegistry,\n\tlayerRouterConfigLiteral,\n\tlayerRouterService,\n\tlayerTraefikContainerOpsDocker,\n\tRouterService,\n\ttype ResolvedRoute,\n} from './router/index.ts';\nimport { BUILT_IN_ENTRYPOINTS } from '../plugins/router-entrypoints.ts';\nimport {\n\tmakeDefaultRouterProfile,\n\ttype DefaultRouterProfileOptions,\n\ttype RouterProfile,\n} from './router/profile.ts';\nimport { layerSnapshotOrchestrator, SnapshotOrchestratorService } from './snapshot/index.ts';\nimport type { ProjectionDecl } from '../contracts/projection.ts';\nimport type { RoutableDecl } from '../contracts/routable.ts';\nimport type { SnapshotableDecl } from '../contracts/snapshotable.ts';\nimport type { StrategyContributorDecl } from '../contracts/strategy-contributor.ts';\nimport { endpointKey, type PluginKey } from '../substrate/brand.ts';\nimport type { EngineEvent } from '../substrate/events.ts';\nimport {\n\tbuildEnvelope,\n\tCURRENT_MANIFEST_VERSION,\n\twriteManifest,\n} from '../substrate/runtime/manifest/index.ts';\nimport {\n\tManifestExtrasLookupError,\n\tresolveManifestExtras,\n\ttype EndpointEntry,\n\ttype ManifestExtrasInput,\n} from '../substrate/manifest.ts';\nimport { CoinRegistryService, layerCoinRegistry } from '../plugins/coin/registry.ts';\nimport { PackageRegistryService, layerPackageRegistry } from '../plugins/package/registry.ts';\n\n// ───────────────────────────────────────────────────────────────────────────\n// Substrate lifecycle\n// ───────────────────────────────────────────────────────────────────────────\n\n/** Substrate Layer stack for a single supervised run. Composes every L0\n * service the supervisor yields from its R-channel, plus the L1 Docker\n * `ContainerRuntime`. Built-in plugin services are layered outside\n * substrate and added through `extendContext`. */\nexport const buildSubstrateLayers = (identity: Identity, runtimeRoot: string) => {\n\t// DockerSpawner adapts platform-node's ChildProcessSpawner tag onto\n\t// the docker subsystem's local DockerSpawner tag (same shape; the\n\t// indirection only lets tests inject a stub).\n\tconst layerDockerSpawnerFromNode: Layer.Layer<DockerSpawner, never, ChildProcessSpawner> =\n\t\tLayer.effect(\n\t\t\tDockerSpawner,\n\t\t\tEffect.gen(function* () {\n\t\t\t\treturn yield* ChildProcessSpawner;\n\t\t\t}),\n\t\t);\n\n\tconst platformBase = Layer.mergeAll(\n\t\tlayerIdentity(identity),\n\t\tlayerRuntimeRoot(runtimeRoot),\n\t\tNodePath.layer,\n\t\tNodeFileSystem.layer,\n\t\tlayerDockerHostDefault,\n\t\tlayerDockerCycleInitial,\n\t\tlayerStrategyRegistry,\n\t);\n\n\tconst childProcessSpawnerWired = NodeChildProcessSpawner.layer.pipe(\n\t\tLayer.provideMerge(platformBase),\n\t);\n\tconst withStackPaths = layerStackPaths.pipe(Layer.provideMerge(childProcessSpawnerWired));\n\tconst withCache = layerCache.pipe(Layer.provideMerge(withStackPaths));\n\tconst withPortBroker = layerPortBroker.pipe(Layer.provideMerge(withCache));\n\tconst withLeaseBroker = layerLeaseBroker.pipe(Layer.provideMerge(withPortBroker));\n\tconst withSpawnerAdapter = layerDockerSpawnerFromNode.pipe(Layer.provideMerge(withLeaseBroker));\n\tconst withContainerRuntime = layerContainerRuntimeDocker.pipe(\n\t\tLayer.provideMerge(withSpawnerAdapter),\n\t);\n\tconst withPostAcquireTasks = layerPostAcquireTasks.pipe(Layer.provideMerge(withContainerRuntime));\n\treturn layerLogger.pipe(Layer.provideMerge(withPostAcquireTasks));\n};\n\n/** Build the opaque `Context.Context<never>` the supervisor hands to\n * every plugin's `acquire` body. Yields every substrate service the\n * Docker-backed substrate layer stack provides; downstream callers\n * may extend the context (e.g. layering the built-in plugin registries\n * via `extendBuiltInPluginContext`) before passing it to `supervise()`. */\nconst buildPluginContext = (): Effect.Effect<\n\tContext.Context<never>,\n\tnever,\n\t| IdentityContext\n\t| RuntimeRoot\n\t| StackPathsService\n\t| CacheService\n\t| StrategyRegistryService\n\t| ContainerRuntimeService\n\t| PortBrokerService\n\t| LeaseBrokerService\n\t| PostAcquireTasksService\n\t| Logger\n> =>\n\tEffect.gen(function* () {\n\t\tconst identityCtx = yield* IdentityContext;\n\t\tconst runtimeRootResolved = yield* RuntimeRoot;\n\t\tconst stackPaths = yield* StackPathsService;\n\t\tconst cache = yield* CacheService;\n\t\tconst registry = yield* StrategyRegistryService;\n\t\tconst containerRuntime = yield* ContainerRuntimeService;\n\t\tconst portBroker = yield* PortBrokerService;\n\t\tconst leaseBroker = yield* LeaseBrokerService;\n\t\tconst postAcquireTasks = yield* PostAcquireTasksService;\n\t\tconst logger = yield* Logger;\n\n\t\treturn Context.empty().pipe(\n\t\t\tContext.add(IdentityContext, identityCtx),\n\t\t\tContext.add(RuntimeRoot, runtimeRootResolved),\n\t\t\tContext.add(StackPathsService, stackPaths),\n\t\t\tContext.add(CacheService, cache),\n\t\t\tContext.add(StrategyRegistryService, registry),\n\t\t\tContext.add(ContainerRuntimeService, containerRuntime),\n\t\t\tContext.add(PortBrokerService, portBroker),\n\t\t\tContext.add(LeaseBrokerService, leaseBroker),\n\t\t\tContext.add(PostAcquireTasksService, postAcquireTasks),\n\t\t\tContext.add(Logger, logger),\n\t\t) as Context.Context<never>;\n\t});\n\n/** Options accepted by the supervised-run entrypoint. `lifetime`\n * selects long-running supervision versus a one-shot acquire/codegen\n * cycle. The `beforeInitialAcquire` hook runs inside the supervised\n * scope before the first acquire starts; live renderers use it to\n * subscribe to startup projection changes. The `withinScope` hook\n * runs after the first acquire completes.\n *\n * Generic `R` widens the hook R-channel so callers can yield\n * substrate services (e.g. `StackPathsService`) that are in scope at\n * the supervisor-boot site. */\nexport interface SuperviseStackOptions<R = Scope.Scope, ExtendR = never, HookE = never> {\n\treadonly lifetime?: 'long-running' | 'one-shot';\n\treadonly devstackVersion?: string;\n\treadonly beforeInitialAcquire?: (handle: SupervisorHandle) => Effect.Effect<void, HookE, R>;\n\treadonly withinScope?: (handle: SupervisorHandle) => Effect.Effect<void, HookE, R>;\n\treadonly commandHandler?: SupervisorCommandHandler;\n\treadonly contributionDispatcher?: ContributionDispatcher;\n\treadonly postAcquireHook?: SupervisorPostAcquireHook;\n\t/** Caller-supplied extension layered into `pluginContext` after the\n\t * default substrate context is built. Used by plugin-author Layer\n\t * composition (ARCHITECTURE.md § Plugin-author extension) and by\n\t * the CLI when it wants to inject the built-in plugin registries or\n\t * a custom Logger override. */\n\treadonly extendContext?: (\n\t\tctx: Context.Context<never>,\n\t) => Effect.Effect<Context.Context<never>, never, ExtendR>;\n}\n\n/** Effect that boots the supervisor for `stack` and blocks on the\n * supervisor's shutdown latch. Returns the final `SubscribableState`\n * snapshot so callers (CLI, library handle) can inspect post-shutdown\n * state. */\nexport const superviseStackEffect = <R = Scope.Scope, ExtendR = never, HookE = never>(\n\tstack: SupervisedStack,\n\tidentity: Identity,\n\tstate: SubscriptionRef.SubscriptionRef<import('../substrate/projection.ts').SubscribableState>,\n\topts: SuperviseStackOptions<R, ExtendR, HookE> = {},\n) =>\n\tEffect.gen(function* () {\n\t\treturn yield* Effect.scoped(\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst baseContext = yield* buildPluginContext();\n\t\t\t\tconst pluginContext =\n\t\t\t\t\topts.extendContext === undefined ? baseContext : yield* opts.extendContext(baseContext);\n\n\t\t\t\tconst startup = yield* startSupervisor(\n\t\t\t\t\tstack,\n\t\t\t\t\tidentity,\n\t\t\t\t\tstate,\n\t\t\t\t\tpluginContext,\n\t\t\t\t\topts.contributionDispatcher,\n\t\t\t\t\topts.commandHandler,\n\t\t\t\t\topts.postAcquireHook,\n\t\t\t\t\t{\n\t\t\t\t\t\tcommandLoop: opts.lifetime !== 'one-shot',\n\t\t\t\t\t\t...(opts.devstackVersion === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { devstackVersion: opts.devstackVersion }),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tconst { handle } = startup;\n\t\t\t\tif (opts.beforeInitialAcquire !== undefined) {\n\t\t\t\t\tyield* opts.beforeInitialAcquire(handle);\n\t\t\t\t}\n\t\t\t\tif (opts.lifetime === 'one-shot') {\n\t\t\t\t\t// `runInitialAcquire` runs `acquireFullGraph` to completion (every\n\t\t\t\t\t// node reaches a terminal status) before it returns. Gate the\n\t\t\t\t\t// one-shot `withinScope` on the SUPERVISOR-OWNED readiness signal\n\t\t\t\t\t// — `allReadyOrTerminal` (`ready || done`) — NOT a per-node\n\t\t\t\t\t// `awaitReady` watcher. A run-to-completion `task` node lands in\n\t\t\t\t\t// `done`; the registry contract admits a `done`-status node whose\n\t\t\t\t\t// `readyGate` is unresolved (only `markReady`/`markFailed` resolve\n\t\t\t\t\t// it), so a per-node gate HANGS on it. This is the SAME\n\t\t\t\t\t// `done`-tolerant gate S1 gave the long-running path; reading\n\t\t\t\t\t// statuses never suspends, so it is hang-free.\n\t\t\t\t\tyield* startup.runInitialAcquire;\n\t\t\t\t\tyield* allReadyOrTerminal(startup.handle.graph, startup.handle.registry);\n\t\t\t\t\tif (opts.withinScope !== undefined) {\n\t\t\t\t\t\tyield* opts.withinScope(handle);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst outcome = yield* Effect.raceFirst(\n\t\t\t\t\tstartup.runInitialAcquire.pipe(Effect.as('booted' as const)),\n\t\t\t\t\thandle.awaitShutdown.pipe(Effect.as('shutdown' as const)),\n\t\t\t\t);\n\t\t\t\tif (outcome === 'shutdown') {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (opts.withinScope !== undefined) {\n\t\t\t\t\tyield* opts.withinScope(handle);\n\t\t\t\t}\n\t\t\t\tyield* handle.awaitShutdown;\n\t\t\t}),\n\t\t);\n\t});\n\n// ───────────────────────────────────────────────────────────────────────────\n// Production orchestrator assembly\n// ───────────────────────────────────────────────────────────────────────────\n\nexport interface ProductionCodegenOptions {\n\treadonly appRoot?: string;\n\t/** Forwarded verbatim to `@mysten/codegen`'s\n\t * `generateFromPackageSummary` via `layerMystenMoveCodegen` — see\n\t * `DevstackOptions['codegen']` for the full contract. Default `false`\n\t * (`@mysten/codegen`'s own default): phantom-only structs render as\n\t * consts with the phantom placeholder baked into `.name`; `true`\n\t * renders them as factories whose required type arguments compose a\n\t * fully-qualified type tag. */\n\treadonly includePhantomTypeParameters?: boolean;\n}\n\n/**\n * The ONE boot seam that maps a stack's codegen config to the production\n * codegen orchestrator options for a LIVE (`'ran'`) projection. Both\n * composition entry points (`api/run-stack.ts` and `orchestrators/layers.ts`)\n * call this. Boot writes no committed `src/generated` tree (owned solely by\n * the stack-free `codegen` verb), so there is no live dev-output dir to\n * resolve; only the app root + the pass-through phantom-type flag flow into\n * `layerProductionOrchestrators({ codegen })`.\n */\nexport const resolveProductionCodegenOptions = (input: {\n\treadonly appRoot: string;\n\treadonly codegen?:\n\t\t| {\n\t\t\t\treadonly includePhantomTypeParameters?: boolean;\n\t\t }\n\t\t| undefined;\n}): ProductionCodegenOptions => {\n\t// Boot never emits the committed `src/generated` tree (that is owned\n\t// solely by the stack-free `codegen` verb); its only codegen writes are\n\t// the deployment file (values-only) and the dev-`up` bindings refresh.\n\t// So there is no live dev-output dir to resolve — only the app root + the\n\t// pass-through phantom-type flag flow through.\n\treturn {\n\t\tappRoot: input.appRoot,\n\t\t// Pass-through verbatim — no resolution step; \"unset\" stays unset so\n\t\t// `@mysten/codegen`'s own default (false) applies at the call site.\n\t\t...(input.codegen?.includePhantomTypeParameters === undefined\n\t\t\t? {}\n\t\t\t: { includePhantomTypeParameters: input.codegen.includePhantomTypeParameters }),\n\t};\n};\n\nexport interface ProductionRouterOptions {\n\treadonly codegen?: ProductionCodegenOptions;\n\treadonly disabled?: boolean;\n}\n\nexport class ManifestEndpointRegistryService extends Context.Service<\n\tManifestEndpointRegistryService,\n\t{\n\t\treadonly register: (entry: EndpointEntry) => Effect.Effect<void, never, Scope.Scope>;\n\t\treadonly entries: Effect.Effect<ReadonlyArray<EndpointEntry>>;\n\t}\n>()('@devstack/orchestrators/ManifestEndpointRegistry') {}\n\nexport const layerManifestEndpointRegistry: Layer.Layer<ManifestEndpointRegistryService> =\n\tLayer.effect(\n\t\tManifestEndpointRegistryService,\n\t\tEffect.gen(function* () {\n\t\t\tconst entriesRef = yield* Ref.make<ReadonlyArray<EndpointEntry & { readonly seq: number }>>(\n\t\t\t\t[],\n\t\t\t);\n\t\t\tconst seqRef = yield* Ref.make(0);\n\n\t\t\tconst register = (entry: EndpointEntry): Effect.Effect<void, never, Scope.Scope> =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst seq = yield* Ref.updateAndGet(seqRef, (n) => n + 1);\n\t\t\t\t\tyield* Ref.update(entriesRef, (entries) => [...entries, { ...entry, seq }]);\n\t\t\t\t\tyield* Effect.addFinalizer(() =>\n\t\t\t\t\t\tRef.update(entriesRef, (entries) =>\n\t\t\t\t\t\t\tentries.filter((candidate) => candidate.seq !== seq),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t});\n\n\t\t\treturn ManifestEndpointRegistryService.of({\n\t\t\t\tregister,\n\t\t\t\tentries: Ref.get(entriesRef).pipe(\n\t\t\t\t\tEffect.map((entries) =>\n\t\t\t\t\t\tentries.map((entryWithSeq) => {\n\t\t\t\t\t\t\tconst { seq, ...entry } = entryWithSeq;\n\t\t\t\t\t\t\tvoid seq;\n\t\t\t\t\t\t\treturn entry;\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t});\n\t\t}),\n\t);\n\nexport const productionRouterProfile = (options: DefaultRouterProfileOptions = {}): RouterProfile =>\n\tmakeDefaultRouterProfile(options);\n\n/** `outputDir` for the `CodegenRoot` of a `layerProductionOrchestrators`\n * composition — `<appRoot>/src/generated`. Boot's `assembleDeployment`\n * writes no file here; the dev-`up` `emitBindings` refresh DOES re-emit\n * this committed tree from the STATIC (id-free) contributions so an edited\n * Move package's new shapes reach the app. `apply` / `runStack` pass no\n * `emitBindings`, so they leave it untouched. The stack-free `codegen` verb\n * owns the canonical emit (wired separately, where it pins its own path). */\nconst productionCodegenOutputDir = (appRoot: string): string => resolve(appRoot, 'src/generated');\n\nexport const layerProductionOrchestrators = (router: ProductionRouterOptions = {}) => {\n\tconst profile = productionRouterProfile();\n\treturn Layer.mergeAll(\n\t\tlayerSnapshotOrchestrator,\n\t\tlayerManifestEndpointRegistry,\n\t\tlayerRouterService.pipe(\n\t\t\tLayer.provideMerge(\n\t\t\t\tLayer.mergeAll(\n\t\t\t\t\tlayerEntrypointRegistry(BUILT_IN_ENTRYPOINTS),\n\t\t\t\t\tlayerTraefikContainerOpsDocker,\n\t\t\t\t\tlayerDockerUpstreamResolver(profile),\n\t\t\t\t\tlayerRouterConfigLiteral({\n\t\t\t\t\t\tdisabled: router.disabled ?? false,\n\t\t\t\t\t\tprofile,\n\t\t\t\t\t\timage: DEFAULT_TRAEFIK_IMAGE,\n\t\t\t\t\t\trouteReadinessProbe: {\n\t\t\t\t\t\t\tenabled: router.disabled !== true,\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t\t),\n\t\tlayerCodegenOrchestrator,\n\t\tlayerCodegenPaths.pipe(\n\t\t\tLayer.provideMerge(\n\t\t\t\tlayerCodegenRoot({\n\t\t\t\t\toutputDir: productionCodegenOutputDir(router.codegen?.appRoot ?? process.cwd()),\n\t\t\t\t\tstackSubdir: null,\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t\tlayerSuiMoveSummaryRunnerDocker,\n\t\tlayerMystenMoveCodegen({\n\t\t\tincludePhantomTypeParameters: router.codegen?.includePhantomTypeParameters,\n\t\t}),\n\t);\n};\n\n/** The single adapter for routable endpoints: ONE `ResolvedRoute` (the\n * router's post-mint source of truth) → ALL THREE sink-feeds at once —\n * the router's own `route`, the manifest `EndpointEntry`, and the\n * projection `endpoint.registered` event — derived from one shared\n * field-set so the three sinks can never diverge. The `routable`\n * dispatch body feeds each sink from the object this returns; there is\n * no second, third derivation off the route anywhere.\n *\n * It owns the url-derivation: `tcp` routes carry `tcp://127.0.0.1:port`,\n * everything else `http://hostname:port`. Consumers (codegen, manifest)\n * translate `tcp://` to their protocol-specific scheme (`postgres://`,\n * `redis://`, …).\n *\n * `ResolvedRoute` only carries `entrypointName`, so the endpoint name is\n * recovered from the original `decl.endpointName`; `pluginKey` is supplied\n * by the dispatcher (it is not in `ResolvedRoute`). Router-only fields\n * (`dispatchFileId`/`cors`/`upstreamUrl`) are kept ON `route` for the\n * router sink but discarded from the manifest/projection field-set — those\n * schemas do not consume them. */\nexport const endpointSinksFromRoute = (\n\tdecl: RoutableDecl,\n\troute: ResolvedRoute,\n\tpluginKey: PluginKey,\n\tregisteredAt = Date.now(),\n) => {\n\tconst url =\n\t\troute.wireProtocol === 'tcp'\n\t\t\t? `tcp://127.0.0.1:${route.entrypointPort}`\n\t\t\t: `http://${route.hostname}:${route.entrypointPort}`;\n\tconst common = {\n\t\tname: decl.endpointName,\n\t\turl,\n\t\tdisplayUrl: null,\n\t\twireProtocol: route.wireProtocol,\n\t} as const;\n\tconst endpointKeyString = `${pluginKey}:${decl.endpointName}`;\n\tconst event: Extract<EngineEvent, { readonly tag: 'endpoint.registered' }> = {\n\t\ttag: 'endpoint.registered',\n\t\tendpoint: {\n\t\t\t...common,\n\t\t\tendpointKey: endpointKey(endpointKeyString),\n\t\t\tpluginKey,\n\t\t\tregisteredAt,\n\t\t},\n\t};\n\treturn {\n\t\troute,\n\t\tmanifestEntry: {\n\t\t\t...common,\n\t\t\tendpointKey: endpointKeyString,\n\t\t\tpluginKey: String(pluginKey),\n\t\t},\n\t\tevent,\n\t};\n};\n\nconst manifestEndpointEntryFromOperationalEndpoint = (\n\tendpoint: Extract<EngineEvent, { readonly tag: 'endpoint.registered' }>['endpoint'],\n): EndpointEntry => ({\n\tendpointKey: String(endpoint.endpointKey),\n\tname: endpoint.name,\n\turl: endpoint.url,\n\tdisplayUrl: endpoint.displayUrl,\n\twireProtocol: endpoint.wireProtocol,\n\tpluginKey: String(endpoint.pluginKey),\n});\n\n/** Project a projection decl's `rowKey` (when absent) onto the\n * contributing plugin so projection consumers can attribute the row.\n * The payload stays opaque from the substrate's POV. */\nconst projectionDispatch = (\n\tdecl: ProjectionDecl,\n\tctx: ContributionDispatchContext,\n): Effect.Effect<void, never, never> => {\n\tconst payload = decl.event.payload;\n\tconst payloadWithRowKey =\n\t\tpayload !== null &&\n\t\ttypeof payload === 'object' &&\n\t\t'rowKey' in payload &&\n\t\t(payload as { rowKey: unknown }).rowKey === null\n\t\t\t? { ...payload, rowKey: ctx.pluginKey }\n\t\t\t: payload;\n\treturn ctx.publish({\n\t\t...decl.event,\n\t\tpayload: payloadWithRowKey,\n\t});\n};\n\n/** Register a strategy contribution on the scope-local registry, publish\n * `strategy.registered`, and arm a finalizer publishing\n * `strategy.unregistered`. */\nconst strategyContributorDispatch = (\n\tdecl: StrategyContributorDecl<string, unknown>,\n\tctx: ContributionDispatchContext,\n): Effect.Effect<void, never, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tyield* ctx.strategyRegistry.register(decl.capabilityKey, decl.strategy, {\n\t\t\tautoMounted: decl.autoMounted,\n\t\t\t...(decl.priority === undefined ? {} : { priority: decl.priority }),\n\t\t});\n\t\tyield* ctx.publish({\n\t\t\ttag: 'strategy.registered',\n\t\t\tcapabilityKey: decl.capabilityKey,\n\t\t\tautoMounted: decl.autoMounted,\n\t\t\tat: Date.now(),\n\t\t});\n\t\tyield* Effect.addFinalizer(() =>\n\t\t\tctx.publish({\n\t\t\t\ttag: 'strategy.unregistered',\n\t\t\t\tcapabilityKey: decl.capabilityKey,\n\t\t\t\tat: Date.now(),\n\t\t\t}),\n\t\t);\n\t});\n\n/**\n * Build the production `ContributionDispatcher` — the closed seam the\n * supervisor replays each plugin's buffered contributions through after\n * a successful `start`. Each method's body reads its backing orchestrator\n * service (Snapshot/Router/Codegen/ManifestEndpoint) ONCE here and closes\n * over it; the substrate supervisor holds the resulting record opaquely\n * (it never imports an orchestrator service).\n */\nexport const buildProductionContributionDispatcher = (): Effect.Effect<\n\tContributionDispatcher,\n\tnever,\n\t| SnapshotOrchestratorService\n\t| RouterService\n\t| CodegenOrchestratorService\n\t| ManifestEndpointRegistryService\n> =>\n\tEffect.gen(function* () {\n\t\tconst snapshot = yield* SnapshotOrchestratorService;\n\t\tconst router = yield* RouterService;\n\t\tconst codegen = yield* CodegenOrchestratorService;\n\t\tconst manifestEndpoints = yield* ManifestEndpointRegistryService;\n\t\treturn {\n\t\t\tsnapshotable: (decl: SnapshotableDecl, ctx) =>\n\t\t\t\tsnapshot.registerParticipant(ctx.pluginKey, decl),\n\t\t\troutable: (decl: RoutableDecl, ctx) =>\n\t\t\t\trouter.boot().pipe(\n\t\t\t\t\t// Router sink: `contributeRoute` writes the dispatch file +\n\t\t\t\t\t// publishes the route onto `applied`, returning the post-mint\n\t\t\t\t\t// `ResolvedRoute` — the ONE source of truth.\n\t\t\t\t\tEffect.andThen(router.contributeRoute(decl)),\n\t\t\t\t\tEffect.flatMap((route) => {\n\t\t\t\t\t\t// One adapter off that ResolvedRoute yields BOTH remaining\n\t\t\t\t\t\t// sink-feeds; feed manifest then projection. No second\n\t\t\t\t\t\t// derivation off the route lives anywhere.\n\t\t\t\t\t\tconst sinks = endpointSinksFromRoute(decl, route, ctx.pluginKey);\n\t\t\t\t\t\treturn manifestEndpoints\n\t\t\t\t\t\t\t.register(sinks.manifestEntry)\n\t\t\t\t\t\t\t.pipe(Effect.andThen(ctx.publish(sinks.event)));\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\tcodegenable: (decl: Codegenable, ctx) => codegen.registerContribution(ctx.pluginKey, decl),\n\t\t\tprojection: (decl: ProjectionDecl, ctx) => projectionDispatch(decl, ctx),\n\t\t\tstrategyContributor: (decl: StrategyContributorDecl<string, unknown>, ctx) =>\n\t\t\t\tstrategyContributorDispatch(decl, ctx),\n\t\t} satisfies ContributionDispatcher;\n\t});\n\nconst makeManifestExtrasContext = (ctx: SupervisorPostAcquireContext) => {\n\tconst resourceIdToKey = new Map<string, PluginKey>();\n\tfor (const [key, node] of ctx.graph.nodes) {\n\t\tresourceIdToKey.set(node.member.id, key);\n\t}\n\t// `lookup` throws `ManifestExtrasLookupError` synchronously from\n\t// inside the user-supplied `extras` factory.\n\t// `resolveManifestExtras` invokes that factory under `Effect.try`\n\t// with a typed `catch` mapper, so the throw promotes to the typed\n\t// failure channel — callers `catchTag('ManifestExtrasLookupError',\n\t// ...)` rather than reading the die-cause. Non-tagged throws stay\n\t// defects, preserving the previous semantics for genuine\n\t// programmer errors inside the factory body.\n\tconst lookup = (resourceId: string): unknown => {\n\t\tconst key = resourceIdToKey.get(resourceId);\n\t\tif (key === undefined) {\n\t\t\tthrow new ManifestExtrasLookupError({\n\t\t\t\tkind: 'unknown-resource',\n\t\t\t\tresourceId,\n\t\t\t});\n\t\t}\n\t\tconst resolved = readResolvedSync(ctx.registry, key);\n\t\tif (resolved === undefined) {\n\t\t\tthrow new ManifestExtrasLookupError({\n\t\t\t\tkind: 'unresolved-resource',\n\t\t\t\tresourceId,\n\t\t\t});\n\t\t}\n\t\treturn resolved;\n\t};\n\treturn {\n\t\tvalue: (resource: { readonly id: string }) => lookup(resource.id),\n\t};\n};\n\nconst operationalManifestEndpointEntries = (\n\tctx: SupervisorPostAcquireContext,\n\troutableEntries: ReadonlyArray<EndpointEntry>,\n): ReadonlyArray<EndpointEntry> => {\n\tconst routablePluginKeys = new Set(routableEntries.map((entry) => entry.pluginKey));\n\tconst registeredAt = Date.now();\n\tconst entries: EndpointEntry[] = [];\n\tfor (const [key] of ctx.graph.nodes) {\n\t\tif (routablePluginKeys.has(String(key))) continue;\n\t\tconst resolved = readResolvedSync(ctx.registry, key);\n\t\tif (resolved === undefined) continue;\n\t\tfor (const event of operationalEndpointEventsFromResolvedValue(key, resolved, registeredAt)) {\n\t\t\tentries.push(manifestEndpointEntryFromOperationalEndpoint(event.endpoint));\n\t\t}\n\t}\n\treturn entries;\n};\n\nexport const buildProductionPostAcquireHook = (\n\toptions: {\n\t\treadonly extras?: ManifestExtrasInput;\n\t\t/** Dev-`up` only: the STATIC (id-free) codegen contributions to re-emit\n\t\t * the committed `src/generated` tree from when a Move-source edit\n\t\t * reacquires a package — the same decls the stack-free `codegen` verb\n\t\t * derives (`deriveContributions(stack.members)`), NOT the live ones\n\t\t * (which would bake on-chain ids into `config.ts`). Omitted for\n\t\t * `apply` / `runStack`, where the committed tree is an input. */\n\t\treadonly emitBindings?: ReadonlyArray<Codegenable>;\n\t} = {},\n): Effect.Effect<\n\tSupervisorPostAcquireHook,\n\tnever,\n\t| CodegenOrchestratorService\n\t| CodegenPathsService\n\t| FileSystem.FileSystem\n\t| StackPathsService\n\t| PostAcquireTasksService\n\t| ManifestEndpointRegistryService\n\t| MoveSummaryRunnerService\n\t| MoveCodegenService\n> =>\n\tEffect.gen(function* () {\n\t\tconst codegen = yield* CodegenOrchestratorService;\n\t\tconst paths = yield* CodegenPathsService;\n\t\tconst fs = yield* FileSystem.FileSystem;\n\t\tconst stackPaths = yield* StackPathsService;\n\t\tconst postAcquireTasks = yield* PostAcquireTasksService;\n\t\tconst manifestEndpoints = yield* ManifestEndpointRegistryService;\n\t\t// Yielded here (outside the per-ctx hook) so the dev-`up` bindings\n\t\t// refresh below can provide them to `emitBindings`.\n\t\tconst moveRunner = yield* MoveSummaryRunnerService;\n\t\tconst moveCodegen = yield* MoveCodegenService;\n\t\treturn (ctx) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst extras = yield* resolveManifestExtras(options.extras, makeManifestExtrasContext(ctx));\n\t\t\t\tconst routableEndpoints = yield* manifestEndpoints.entries;\n\t\t\t\tconst endpoints = [\n\t\t\t\t\t...routableEndpoints,\n\t\t\t\t\t...operationalManifestEndpointEntries(ctx, routableEndpoints),\n\t\t\t\t];\n\t\t\t\t// Boot no longer runs codegen. Its only job is to PRODUCE the\n\t\t\t\t// deployment (loadable on-chain ids), which the Vite plugin injects\n\t\t\t\t// via `__DEVSTACK_DEPLOYMENT__` in dev. The committed `src/generated` tree\n\t\t\t\t// is written ONLY by the stack-free `devstack codegen` verb.\n\t\t\t\t// Assemble the deployment from the SAME live-resolved contributions\n\t\t\t\t// that fed `config.ts` and write it to the gitignored\n\t\t\t\t// `.devstack/stacks/<stack>/`.\n\t\t\t\tconst deployment = yield* codegen.assembleDeployment(String(ctx.identity.network)).pipe(\n\t\t\t\t\tEffect.mapError(\n\t\t\t\t\t\t(cause) =>\n\t\t\t\t\t\t\tnew CodegenWriteFailed({\n\t\t\t\t\t\t\t\toutputPath: DEPLOYMENT_FILENAME,\n\t\t\t\t\t\t\t\tstage: 'write',\n\t\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tconst deploymentFile = join(stackPaths.stackRoot, DEPLOYMENT_FILENAME);\n\t\t\t\tyield* writeDeployment(deploymentFile, deployment).pipe(\n\t\t\t\t\tEffect.provideService(FileSystem.FileSystem, fs),\n\t\t\t\t);\n\t\t\t\tconst envelope = yield* buildEnvelope({\n\t\t\t\t\tidentity: {\n\t\t\t\t\t\tapp: ctx.identity.app,\n\t\t\t\t\t\tstack: ctx.identity.stack,\n\t\t\t\t\t\tnetwork: ctx.identity.network,\n\t\t\t\t\t},\n\t\t\t\t\tendpoints,\n\t\t\t\t\textras,\n\t\t\t\t\t// Record the live `deploymentFile` the plugin injects as\n\t\t\t\t\t// `__DEVSTACK_DEPLOYMENT__`. Bindings are NOT recorded:\n\t\t\t\t\t// `@generated` always resolves to the committed `src/generated`\n\t\t\t\t\t// tree written by the stack-free `codegen` verb. The dev-wallet\n\t\t\t\t\t// connection + dev accounts ride the deployment envelope's\n\t\t\t\t\t// `values` / `accounts` channels (no separate dev tree).\n\t\t\t\t\tcodegen: { deploymentFile },\n\t\t\t\t});\n\t\t\t\tconst manifestPath = join(stackPaths.stackRoot, 'manifest.json');\n\t\t\t\tyield* writeManifest(envelope, manifestPath).pipe(\n\t\t\t\t\tEffect.provideService(FileSystem.FileSystem, fs),\n\t\t\t\t);\n\t\t\t\t// Dev-`up` only: regenerate the committed `src/generated` tree from\n\t\t\t\t// the STATIC (id-free) contributions so an edited Move package's new\n\t\t\t\t// struct/function shapes reach the app (Vite HMRs the changed TS)\n\t\t\t\t// WITHOUT baking the live on-chain id into `config.ts`.\n\t\t\t\t// `runEmitCycle` is content-addressed, so the initial boot and any\n\t\t\t\t// no-op reacquire leave the tree (and its mtimes) untouched.\n\t\t\t\tconst bindingFiles: string[] = [];\n\t\t\t\tif (options.emitBindings !== undefined) {\n\t\t\t\t\tconst emitted = yield* codegen\n\t\t\t\t\t\t.emitBindings(options.emitBindings)\n\t\t\t\t\t\t.pipe(\n\t\t\t\t\t\t\tEffect.provideService(FileSystem.FileSystem, fs),\n\t\t\t\t\t\t\tEffect.provideService(CodegenPathsService, paths),\n\t\t\t\t\t\t\tEffect.provideService(MoveSummaryRunnerService, moveRunner),\n\t\t\t\t\t\t\tEffect.provideService(MoveCodegenService, moveCodegen),\n\t\t\t\t\t\t);\n\t\t\t\t\tbindingFiles.push(...emitted.filesWritten, ...emitted.filesChmod);\n\t\t\t\t}\n\t\t\t\tyield* postAcquireTasks.runAll;\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\ttag: 'manifest.flushed' as const,\n\t\t\t\t\t\tmanifestVersion: CURRENT_MANIFEST_VERSION,\n\t\t\t\t\t\tat: Date.now(),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttag: 'codegen.emitted' as const,\n\t\t\t\t\t\tfiles: [deploymentFile, ...bindingFiles],\n\t\t\t\t\t\tat: Date.now(),\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t});\n\t});\n\n// ───────────────────────────────────────────────────────────────────────────\n// Built-in plugin runtime composition\n//\n// Depends on L2 plugin internals (coin/package registries), so it can't live\n// at L1 runtime — hence its home in this L3 boot module.\n// ───────────────────────────────────────────────────────────────────────────\n\n/** Built-in plugin runtime: the per-stack coin + package registries.\n * Coin auto-discovery from a fresh package publish now runs DIRECTLY in\n * the package plugin's `start` (folding the publish output into the\n * CoinRegistry), so the registries are the whole surface. */\nexport const layerBuiltInPluginRuntime: Layer.Layer<CoinRegistryService | PackageRegistryService> =\n\tLayer.mergeAll(layerCoinRegistry, layerPackageRegistry);\n\nexport const extendBuiltInPluginContext = (\n\tctx: Context.Context<never>,\n): Effect.Effect<\n\tContext.Context<never>,\n\tnever,\n\tCoinRegistryService | PackageRegistryService | SnapshotOrchestratorService | FileSystem.FileSystem\n> =>\n\tEffect.gen(function* () {\n\t\tconst coinRegistry = yield* CoinRegistryService;\n\t\tconst packageRegistry = yield* PackageRegistryService;\n\t\t// Thread the snapshot orchestrator + filesystem into the plugin\n\t\t// runtime context so the supervisor can populate the control-plane\n\t\t// `domain` surface (snapshot list/restore/delete, which never\n\t\t// round-trip through the void `publishCommand`). The\n\t\t// `ContainerRuntimeService` the domain also needs is already in the\n\t\t// base substrate plugin context.\n\t\tconst snapshotOrchestrator = yield* SnapshotOrchestratorService;\n\t\tconst fileSystem = yield* FileSystem.FileSystem;\n\t\treturn ctx.pipe(\n\t\t\tContext.add(CoinRegistryService, coinRegistry),\n\t\t\tContext.add(PackageRegistryService, packageRegistry),\n\t\t\tContext.add(SnapshotOrchestratorService, snapshotOrchestrator),\n\t\t\tContext.add(FileSystem.FileSystem, fileSystem),\n\t\t) as Context.Context<never>;\n\t});\n\n// ───────────────────────────────────────────────────────────────────────────\n// Production supervised-boot assembly — THE single dedup site\n// ───────────────────────────────────────────────────────────────────────────\n\n/** The per-caller inputs to {@link superviseStackWithProductionBoot} — the\n * fields that GENUINELY differ between the long-running programmatic seam\n * (`api/run-stack-internal.ts`) and the one-shot CLI verbs (`apply` /\n * `snapshot`). Everything else — the contribution dispatcher, the\n * post-acquire hook, and the built-in plugin-context extension — is\n * assembled identically by the helper, so it lives in ONE place. */\nexport interface ProductionBootOptions<HookR = Scope.Scope, HookE = never, ExtendR = never> {\n\t/** `'one-shot'` runs the acquire/codegen cycle then returns; the default\n\t * `'long-running'` supervises until shutdown. */\n\treadonly lifetime?: 'long-running' | 'one-shot';\n\treadonly devstackVersion?: string;\n\t/** Threaded into `buildProductionPostAcquireHook` — the stack's manifest\n\t * `extras`. All three callers pass `stack.options.extras`. */\n\treadonly extras?: ManifestExtrasInput;\n\t/** Dev-`up` only: the STATIC (id-free) codegen contributions used to\n\t * regenerate the committed `src/generated` tree in the post-acquire hook\n\t * when a Move-source edit reacquires a package. Threaded from the `up`\n\t * seam (`deriveContributions(stack.members)`); `apply` / `snapshot` leave\n\t * it off so they never rewrite the committed tree. */\n\treadonly emitBindings?: ReadonlyArray<Codegenable>;\n\t/** The resolved supervisor command handler (run-stack's snapshot bridge).\n\t * One-shot verbs run no command loop, so they pass nothing. */\n\treadonly commandHandler?: SupervisorCommandHandler;\n\treadonly beforeInitialAcquire?: (handle: SupervisorHandle) => Effect.Effect<void, HookE, HookR>;\n\treadonly withinScope?: (handle: SupervisorHandle) => Effect.Effect<void, HookE, HookR>;\n\t/** Caller plugin-context extension layered AFTER the built-in\n\t * (`extendBuiltInPluginContext`). Only the programmatic seam uses it (to\n\t * honor the public `runStack({ extendContext })`); the CLI verbs omit it\n\t * and get the built-in extension alone. */\n\treadonly extendContextAfterBuiltIn?: (\n\t\tctx: Context.Context<never>,\n\t) => Effect.Effect<Context.Context<never>, never, ExtendR>;\n}\n\n/**\n * THE single site that assembles the production supervised body. It builds\n * the contribution dispatcher + post-acquire hook + built-in plugin-context\n * extension ONCE and hands them to {@link superviseStackEffect}, then\n * provides {@link layerBuiltInPluginRuntime}. Before this helper, the same\n * three-piece assembly was hand-rolled in three call sites\n * (`api/run-stack-internal.ts`, `cli/wirings/apply.ts`,\n * `cli/wirings/snapshot.ts`); now they all route through here and only\n * supply what genuinely differs ({@link ProductionBootOptions}).\n *\n * Each caller keeps its OWN lifetime-specific wrapping: the programmatic\n * seam wraps the returned effect in a `forkDetach` handle (long-running);\n * the CLI verbs run it to completion with their existing teardown + result\n * semantics (one-shot). This helper does NOT collapse those — it only\n * dedups the assembly the `superviseStackEffect` call sites shared.\n *\n * The return type is inferred (like `superviseStackEffect`): its R-channel\n * is the union of every substrate/orchestrator service the dispatcher /\n * hook / extension read, MINUS the built-in registries `layerBuiltInPluginRuntime`\n * supplies, PLUS the caller hook `HookR` / extend `ExtendR` channels.\n */\nexport const superviseStackWithProductionBoot = <\n\tHookR = Scope.Scope,\n\tHookE = never,\n\tExtendR = never,\n>(\n\tstack: SupervisedStack,\n\tidentity: Identity,\n\tstate: SubscriptionRef.SubscriptionRef<import('../substrate/projection.ts').SubscribableState>,\n\topts: ProductionBootOptions<HookR, HookE, ExtendR> = {},\n) =>\n\tEffect.gen(function* () {\n\t\tconst contributionDispatcher = yield* buildProductionContributionDispatcher();\n\t\tconst postAcquireHook = yield* buildProductionPostAcquireHook({\n\t\t\t...(opts.extras === undefined ? {} : { extras: opts.extras }),\n\t\t\t...(opts.emitBindings === undefined ? {} : { emitBindings: opts.emitBindings }),\n\t\t});\n\t\tyield* superviseStackEffect(stack, identity, state, {\n\t\t\tcontributionDispatcher,\n\t\t\tpostAcquireHook,\n\t\t\t...(opts.lifetime === undefined ? {} : { lifetime: opts.lifetime }),\n\t\t\t...(opts.devstackVersion === undefined ? {} : { devstackVersion: opts.devstackVersion }),\n\t\t\t...(opts.commandHandler === undefined ? {} : { commandHandler: opts.commandHandler }),\n\t\t\t...(opts.beforeInitialAcquire === undefined\n\t\t\t\t? {}\n\t\t\t\t: { beforeInitialAcquire: opts.beforeInitialAcquire }),\n\t\t\t...(opts.withinScope === undefined ? {} : { withinScope: opts.withinScope }),\n\t\t\t// Built-in plugin-context extension ALWAYS runs; a caller extension\n\t\t\t// (the programmatic seam's `opts.extendContext`) chains AFTER it.\n\t\t\textendContext: (ctx) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst builtInContext = yield* extendBuiltInPluginContext(ctx);\n\t\t\t\t\treturn opts.extendContextAfterBuiltIn === undefined\n\t\t\t\t\t\t? builtInContext\n\t\t\t\t\t\t: yield* opts.extendContextAfterBuiltIn(builtInContext);\n\t\t\t\t}),\n\t\t}).pipe(Effect.provide(layerBuiltInPluginRuntime));\n\t});\n"],"mappings":"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"}
|