@mysten-incubation/devstack 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dashboard-ui/assets/{grpc-a4usE3Nk.js → grpc-Clz0oOtc.js} +1 -1
- package/dashboard-ui/assets/{index-CRYJ4pru.js → index-Cmqv9kiU.js} +39 -33
- package/dashboard-ui/index.html +1 -1
- package/dist/api/run-stack-internal.mjs +1 -0
- package/dist/api/run-stack-internal.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/vite/index.d.mts +39 -9
- package/dist/build-integrations/vite/index.mjs +47 -11
- 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/cli/doctor-probes.mjs +7 -2
- package/dist/cli/doctor-probes.mjs.map +1 -1
- package/dist/cli/main.mjs +2 -2
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/wirings/codegen.mjs +35 -35
- package/dist/cli/wirings/codegen.mjs.map +1 -1
- package/dist/cli/wirings/up.mjs +7 -0
- package/dist/cli/wirings/up.mjs.map +1 -1
- package/dist/orchestrators/boot.mjs +12 -2
- package/dist/orchestrators/boot.mjs.map +1 -1
- package/dist/orchestrators/codegen/service.mjs +23 -8
- package/dist/orchestrators/codegen/service.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 +2 -2
- 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/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/sui/index.d.mts +10 -10
- package/dist/plugins/sui/move-summary-runner.mjs +29 -2
- package/dist/plugins/sui/move-summary-runner.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/supervisor/start-supervisor.mjs +2 -6
- package/dist/substrate/runtime/supervisor/start-supervisor.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli/wirings/up.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { claim, heartbeatFiber, release } from "../../substrate/runtime/cross-process/roster.mjs";
|
|
2
|
+
import { startFileWatcher } from "../../substrate/runtime/lifecycle/file-watcher.mjs";
|
|
2
3
|
import { StackPathsService } from "../../substrate/runtime/paths.mjs";
|
|
3
4
|
import { computeSnapshotGraphInputFromStack } from "../../orchestrators/snapshot/descriptor.mjs";
|
|
4
5
|
import { recoverInterruptedRestore } from "../../orchestrators/snapshot/interrupted-restore.mjs";
|
|
@@ -19,6 +20,7 @@ import { makeConfigLoader } from "./config-loader.mjs";
|
|
|
19
20
|
import { findCliSupervisorLiveError, identityValueFor, resolvedIdentityForStack } from "./identity.mjs";
|
|
20
21
|
import { installCommandChannelBridge } from "./up-ipc.mjs";
|
|
21
22
|
import { provideFileSystem } from "./provide-file-system.mjs";
|
|
23
|
+
import { deriveContributions } from "./codegen.mjs";
|
|
22
24
|
import { Cause, Effect, Exit, FileSystem, Queue, Stream } from "effect";
|
|
23
25
|
import { dirname, resolve } from "node:path";
|
|
24
26
|
//#region src/cli/wirings/up.ts
|
|
@@ -180,6 +182,10 @@ const buildUpBootBundle = (input) => {
|
|
|
180
182
|
yield* Queue.offer(rendererEvents, event);
|
|
181
183
|
yield* commandChannel.publishEvent(event);
|
|
182
184
|
}))));
|
|
185
|
+
yield* startFileWatcher({
|
|
186
|
+
watchIndex: h.supervisor.watchIndex,
|
|
187
|
+
notifyWatchFire: h.supervisor.notifyWatchFire
|
|
188
|
+
});
|
|
183
189
|
}),
|
|
184
190
|
withinScope: (h) => Effect.gen(function* () {
|
|
185
191
|
if (snapshotCache === void 0 || !refreshSnapshotCache) return;
|
|
@@ -282,6 +288,7 @@ const runUpLive = (configPath, identity, options) => {
|
|
|
282
288
|
appRoot,
|
|
283
289
|
runtimeRoot: effectiveIdentity.runtimeRoot,
|
|
284
290
|
codegen: stack.options.codegen,
|
|
291
|
+
emitBindings: deriveContributions(stack.members),
|
|
285
292
|
commandHandler,
|
|
286
293
|
boot
|
|
287
294
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"up.mjs","names":["resolvePath"],"sources":["../../../src/cli/wirings/up.ts"],"sourcesContent":["// `devstack up` verb wiring.\n//\n// Wires the substrate Layer stack, supervisor, attached renderer, and\n// in-process TUI command queue. The Effect runs as the outer Node fiber\n// so SIGINT reaches scope finalizers (see surfaces/cli/index.ts\n// architecture invariant).\n//\n// Logger layer: `Logger.layer([])` (silent). `up` owns the TUI, which is\n// the operator-facing output channel; routing structured `Effect.log*`\n// records to stderr would scribble on top of the live ink renderer in\n// human mode and would duplicate the structured event stream the plain\n// renderer already emits in non-TTY mode. The sibling `apply` verb (no\n// TUI) uses `Logger.consolePretty()` because its consumer is CI.\n\nimport { dirname, resolve as resolvePath } from 'node:path';\n\nimport { Cause, Effect, Exit, FileSystem, Queue, Scope, Stream } from 'effect';\n\nimport type { Identity } from '../../substrate/identity.ts';\nimport type { EngineEvent } from '../../substrate/events.ts';\nimport { StackPathsService } from '../../substrate/runtime/paths.ts';\nimport {\n\tclaim,\n\theartbeatFiber,\n\trelease,\n\ttype SupervisedStack,\n\ttype SupervisorCommandHandler,\n} from '../../substrate/runtime/index.ts';\nimport {\n\tcollectLifecyclePruneInventory,\n\tdefaultLifecyclePruneSelection,\n\tDEFAULT_LIFECYCLE_PRUNE_RESOURCES,\n\trunLifecyclePrune,\n} from '../../orchestrators/lifecycle-prune/index.ts';\nimport {\n\tcomputeSnapshotGraphInputFromStack,\n\trecoverInterruptedRestore,\n\tSnapshotOrchestratorService,\n} from '../../orchestrators/snapshot/index.ts';\nimport type { Stack } from '../../api/define-devstack.ts';\nimport {\n\trunStackWithBoot,\n\ttype CommandHandlerFactory,\n\ttype RunStackBootBag,\n} from '../../api/run-stack-internal.ts';\nimport type { BootError } from '../../api/run-stack.ts';\nimport {\n\ttype CliError,\n\tCliInternalError,\n\tCliSnapshotNotFoundError,\n\tCliSupervisorLiveError,\n\tCliUsageError,\n\ttype GlobalFlags,\n} from '../../surfaces/cli/index.ts';\nimport type { CommandResult } from '../../surfaces/cli/commands/index.ts';\nimport { ExitCode } from '../../surfaces/cli/sysexits.ts';\nimport { makeTuiSurface } from '../../surfaces/tui/index.ts';\nimport type { LoadedConfig } from '../../surfaces/cli/commands/config-loader.ts';\n\nimport { cliErrorFromConfigExit } from '../bail.ts';\nimport { makeQueueCommandPublisher, resolveUpRendererMode } from '../up-lifecycle.ts';\nimport { makeConfigLoader } from './config-loader.ts';\nimport { makeSnapshotReader } from '../snapshot-reader.ts';\nimport {\n\tfindCliSupervisorLiveError,\n\tidentityValueFor,\n\tresolvedIdentityForStack,\n\ttype ResolvedIdentity,\n} from './identity.ts';\nimport { installCommandChannelBridge } from './up-ipc.ts';\nimport { provideFileSystem } from './provide-file-system.ts';\nimport { readDevstackVersion } from './read-devstack-version.ts';\n\nconst rosterPathsFor = (stackRoot: string) => ({\n\tstackLockFile: resolvePath(stackRoot, 'stack.lock'),\n\trosterFile: resolvePath(stackRoot, 'roster.json'),\n});\n\n// -----------------------------------------------------------------------------\n// Supervisor command handler — snapshot/wipe/prune injected dispatch\n// -----------------------------------------------------------------------------\n\n/** Build the snapshot/wipe/prune `commandHandler` as a FACTORY the seam\n * resolves against its LIVE substrate (see `CommandHandlerFactory`). The\n * factory yields the seam's `SnapshotOrchestratorService` + `FileSystem` —\n * the SAME orchestrator instance the supervisor's contribution dispatcher\n * registers live participants on, so an operator `snapshot save` captures\n * real chain/blob/db state, not an empty set — and returns a handler\n * (R = `never`, as the command loop requires) that closes over them\n * directly. No Deferred hand-off: the seam runs this factory before\n * `startSupervisor` consumes the handler. */\nconst makeSnapshotCommandHandler = (params: {\n\treadonly runtimeRoot: string;\n\treadonly stack: SupervisedStack;\n\treadonly devstackVersion: string;\n}): CommandHandlerFactory =>\n\tEffect.gen(function* () {\n\t\tconst snapshot = yield* SnapshotOrchestratorService;\n\t\tconst fs = yield* FileSystem.FileSystem;\n\t\tconst computeGraphInput = computeSnapshotGraphInputFromStack({\n\t\t\tstack: params.stack,\n\t\t\tdevstackVersion: params.devstackVersion,\n\t\t});\n\t\tconst handler: SupervisorCommandHandler = (cmd) => {\n\t\t\tswitch (cmd.tag) {\n\t\t\t\tcase 'snapshot.capture':\n\t\t\t\t\t// The L3 capture is the bounce's gather → stop → commit → retag\n\t\t\t\t\t// → hard-rm half; the RESUME (recreate + wait-write-ready) is the\n\t\t\t\t\t// command-loop's converge after this handler succeeds (it owns the\n\t\t\t\t\t// graph), mirroring restore. So no `resume` is injected here.\n\t\t\t\t\treturn provideFileSystem(\n\t\t\t\t\t\tfs,\n\t\t\t\t\t\tcomputeGraphInput.pipe(\n\t\t\t\t\t\t\tEffect.flatMap((graphInput) =>\n\t\t\t\t\t\t\t\tsnapshot.capture({\n\t\t\t\t\t\t\t\t\tid: cmd.snapshotId,\n\t\t\t\t\t\t\t\t\t...(cmd.name === undefined ? {} : { label: cmd.name }),\n\t\t\t\t\t\t\t\t\tgraphInput,\n\t\t\t\t\t\t\t\t\t...(cmd.replaceExisting === true ? { replaceExistingLabel: true } : {}),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t).pipe(\n\t\t\t\t\t\tEffect.map((meta) => [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttag: 'snapshot.captured',\n\t\t\t\t\t\t\t\tsnapshotId: meta.id,\n\t\t\t\t\t\t\t\t...(meta.label === null ? {} : { name: meta.label }),\n\t\t\t\t\t\t\t\tat: Date.now(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]),\n\t\t\t\t\t);\n\t\t\t\tcase 'snapshot.restore':\n\t\t\t\t\treturn provideFileSystem(\n\t\t\t\t\t\tfs,\n\t\t\t\t\t\tcomputeGraphInput.pipe(\n\t\t\t\t\t\t\tEffect.flatMap((currentGraphInput) =>\n\t\t\t\t\t\t\t\tsnapshot.restore({\n\t\t\t\t\t\t\t\t\tid: cmd.snapshotId,\n\t\t\t\t\t\t\t\t\tcurrentGraphInput,\n\t\t\t\t\t\t\t\t\tgraphInputMismatchPolicy: 'warn',\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t).pipe(\n\t\t\t\t\t\tEffect.map((meta) => [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttag: 'snapshot.restored',\n\t\t\t\t\t\t\t\tsnapshotId: meta.id,\n\t\t\t\t\t\t\t\tat: Date.now(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]),\n\t\t\t\t\t);\n\t\t\t\tcase 'snapshot.list':\n\t\t\t\t\treturn provideFileSystem(fs, snapshot.list).pipe(Effect.as([]));\n\t\t\t\tcase 'snapshot.delete':\n\t\t\t\t\treturn provideFileSystem(fs, snapshot.delete(cmd.snapshotId)).pipe(Effect.as([]));\n\t\t\t\tcase 'wipe.requested':\n\t\t\t\t\treturn provideFileSystem(fs, snapshot.wipe({})).pipe(Effect.as([]));\n\t\t\t\tcase 'prune.requested':\n\t\t\t\t\t// Route to the same orchestrator the offline `devstack prune`\n\t\t\t\t\t// verb uses (`runLifecyclePrune`), NOT the snapshot-orchestrator\n\t\t\t\t\t// prune (which only cleans the snapshot catalog and would leave\n\t\t\t\t\t// stale containers/networks/volumes/images behind for an attached\n\t\t\t\t\t// supervisor — silent under-prune is the bug we're closing).\n\t\t\t\t\t// Live supervisor implies the current stack's group is live and\n\t\t\t\t\t// therefore excluded from the default selection — exactly the\n\t\t\t\t\t// invariant the live-attached `prune` needs (operator can prune\n\t\t\t\t\t// sibling stacks under the same Docker daemon without touching\n\t\t\t\t\t// the running one).\n\t\t\t\t\treturn collectLifecyclePruneInventory({ runtimeRoot: params.runtimeRoot }).pipe(\n\t\t\t\t\t\tEffect.flatMap((inventory) =>\n\t\t\t\t\t\t\trunLifecyclePrune(\n\t\t\t\t\t\t\t\t{ runtimeRoot: params.runtimeRoot },\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tgroupKeys: defaultLifecyclePruneSelection(\n\t\t\t\t\t\t\t\t\t\tinventory,\n\t\t\t\t\t\t\t\t\t\tDEFAULT_LIFECYCLE_PRUNE_RESOURCES,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tresources: DEFAULT_LIFECYCLE_PRUNE_RESOURCES,\n\t\t\t\t\t\t\t\t\tdryRun: false,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tEffect.as([]),\n\t\t\t\t\t);\n\t\t\t\tdefault:\n\t\t\t\t\treturn Effect.succeed([]);\n\t\t\t}\n\t\t};\n\t\treturn handler;\n\t});\n\nconst installLiveSupervisorRoster = (params: {\n\treadonly stackRoot: string;\n\treadonly app: string;\n\treadonly stack: string;\n}): Effect.Effect<void, unknown, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst paths = rosterPathsFor(params.stackRoot);\n\t\tconst claimed = yield* claim(paths);\n\t\tif (!claimed.soleHolder) {\n\t\t\tyield* release(paths).pipe(Effect.catch(() => Effect.void));\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew CliSupervisorLiveError({\n\t\t\t\t\tapp: params.app,\n\t\t\t\t\tstack: params.stack,\n\t\t\t\t\thint: 'use `devstack apply` from another shell, or choose a different --stack name',\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tyield* Effect.addFinalizer(() => release(paths).pipe(Effect.catch(() => Effect.void)));\n\t\tyield* Effect.forkScoped(heartbeatFiber(paths));\n\t});\n\n// -----------------------------------------------------------------------------\n// CLI boot bundle — the `commandHandler` + `boot` hooks the seam consumes\n// -----------------------------------------------------------------------------\n\nexport interface UpBootBundleInput {\n\treadonly stack: SupervisedStack;\n\treadonly identityValue: Identity;\n\treadonly runtimeRoot: string;\n\treadonly devstackVersion: string;\n\treadonly rendererMode: import('../../surfaces/tui/mode-detect.ts').RendererMode;\n\treadonly startFromSnapshot?: {\n\t\treadonly id: string;\n\t\treadonly stalePolicy: 'warn' | 'block' | 'clean-start';\n\t};\n\treadonly snapshotCache?: {\n\t\treadonly name: string;\n\t\treadonly existingSnapshotId?: string;\n\t};\n}\n\nexport interface UpBootBundle {\n\treadonly commandHandler: CommandHandlerFactory;\n\treadonly boot: RunStackBootBag;\n}\n\ntype StartFromSnapshot = NonNullable<UpBootBundleInput['startFromSnapshot']>;\ntype SnapshotCache = NonNullable<UpBootBundleInput['snapshotCache']>;\n\n/**\n * Build the CLI's boot concerns as a VALUE bundle the seam consumes — the\n * snapshot/wipe/prune `commandHandler` plus the `beforeInitialAcquire`\n * (recover → IPC bridge → roster claim → TUI mount + event tee). Pure\n * value construction: no substrate is touched here; the hooks pull the\n * SEAM's substrate services at boot (they run inside the supervised scope).\n *\n * Extracted from `runUpLive` so the Docker-free CLI-boot smoke test drives\n * the EXACT bundle the production path feeds `runStackWithBoot` — the only\n * non-e2e gate on the cutover (`main.test.ts` only runs `up --help`).\n */\nexport const buildUpBootBundle = (input: UpBootBundleInput): UpBootBundle => {\n\tconst {\n\t\tstack,\n\t\tidentityValue,\n\t\truntimeRoot,\n\t\tdevstackVersion,\n\t\trendererMode,\n\t\tstartFromSnapshot,\n\t\tsnapshotCache,\n\t} = input;\n\n\tconst computeGraphInput = computeSnapshotGraphInputFromStack({ stack, devstackVersion });\n\tlet refreshSnapshotCache =\n\t\tsnapshotCache !== undefined && snapshotCache.existingSnapshotId === undefined;\n\n\t// The snapshot/wipe/prune `commandHandler` — a FACTORY the seam resolves\n\t// against its LIVE substrate (the seam runs it before `startSupervisor`\n\t// consumes the handler). The factory closes over the seam's ONE\n\t// `SnapshotOrchestratorService` instance — the same one the supervisor's\n\t// contribution dispatcher registers live participants on — so an operator\n\t// `snapshot save` captures the LIVE chain/blob/db state, not an empty set\n\t// off a sibling orchestrator. No Deferred hand-off.\n\tconst commandHandler = makeSnapshotCommandHandler({ runtimeRoot, stack, devstackVersion });\n\n\tconst boot: RunStackBootBag = {\n\t\tdevstackVersion,\n\t\tbeforeInitialAcquire: (h) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\t// The seam's substrate services — the SAME instances the\n\t\t\t\t// `commandHandler` factory closed over and the supervisor uses,\n\t\t\t\t// driven here for the recover/IPC/roster/TUI work.\n\t\t\t\tconst snapshot = yield* SnapshotOrchestratorService;\n\t\t\t\tconst fs = yield* FileSystem.FileSystem;\n\t\t\t\tconst stackPaths = yield* StackPathsService;\n\t\t\t\t// Resume any restore interrupted by a hard kill / power-loss\n\t\t\t\t// between the atomic swap and the end of the image-promotion\n\t\t\t\t// handoff (the interrupted-restore sentinel rode the swap into\n\t\t\t\t// the live root and was never cleared). Runs BEFORE any plugin\n\t\t\t\t// acquire so a half-promoted image set is reconciled before any\n\t\t\t\t// L2 lookup observes the runtime root. No-op when the sentinel\n\t\t\t\t// is absent (the clean-boot case); idempotent re-run of restore\n\t\t\t\t// when present.\n\t\t\t\t//\n\t\t\t\t// `restore({ id })` passes NO participants on purpose: this\n\t\t\t\t// hook fires BEFORE the initial acquire registers any snapshot\n\t\t\t\t// participant, so there is no live stack to contribute identity.\n\t\t\t\t// `runRestore` reads the empty participant set as \"no live\n\t\t\t\t// stack\" and skips ONLY the cross-plugin contribution guard\n\t\t\t\t// (the runtime + snapshot-emptiness guards still fire). With a\n\t\t\t\t// participants-required guard this recovery could never clear\n\t\t\t\t// the sentinel — it failed `IdentityMissingLive` every boot.\n\t\t\t\tyield* recoverInterruptedRestore({\n\t\t\t\t\tliveRoot: stackPaths.stackRoot,\n\t\t\t\t\trestoreSnapshot: (id) =>\n\t\t\t\t\t\tcomputeGraphInput.pipe(\n\t\t\t\t\t\t\tEffect.flatMap((currentGraphInput) =>\n\t\t\t\t\t\t\t\tsnapshot.restore({\n\t\t\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\t\t\tcurrentGraphInput,\n\t\t\t\t\t\t\t\t\tgraphInputMismatchPolicy: 'warn',\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t});\n\t\t\t\tif (snapshotCache !== undefined) {\n\t\t\t\t\tif (snapshotCache.existingSnapshotId === undefined) {\n\t\t\t\t\t\tyield* Effect.logWarning(\n\t\t\t\t\t\t\t`snapshot cache ${snapshotCache.name} was not found; boot will refresh it`,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst graphInput = yield* computeGraphInput;\n\t\t\t\t\t\tconst catalog = yield* provideFileSystem(fs, snapshot.list);\n\t\t\t\t\t\tconst entry = catalog.find(\n\t\t\t\t\t\t\t(snapshotEntry) => snapshotEntry.id === snapshotCache.existingSnapshotId,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst snapshotGraphInputId = entry?.metadata?.graphInput.graphInputId ?? null;\n\t\t\t\t\t\tif (snapshotGraphInputId === graphInput.graphInputId) {\n\t\t\t\t\t\t\trefreshSnapshotCache = false;\n\t\t\t\t\t\t\tyield* provideFileSystem(\n\t\t\t\t\t\t\t\tfs,\n\t\t\t\t\t\t\t\tsnapshot.restore({\n\t\t\t\t\t\t\t\t\tid: snapshotCache.existingSnapshotId,\n\t\t\t\t\t\t\t\t\tcurrentGraphInput: graphInput,\n\t\t\t\t\t\t\t\t\tgraphInputMismatchPolicy: 'block',\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\trefreshSnapshotCache = true;\n\t\t\t\t\t\t\tyield* Effect.logWarning(\n\t\t\t\t\t\t\t\t`snapshot cache ${snapshotCache.name} graph input is stale or unreadable; boot will refresh it`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (startFromSnapshot !== undefined) {\n\t\t\t\t\tconst graphInput = yield* computeGraphInput;\n\t\t\t\t\tif (startFromSnapshot.stalePolicy === 'clean-start') {\n\t\t\t\t\t\tconst catalog = yield* provideFileSystem(fs, snapshot.list);\n\t\t\t\t\t\tconst entry = catalog.find(\n\t\t\t\t\t\t\t(snapshotEntry) => snapshotEntry.id === startFromSnapshot.id,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst snapshotGraphInputId = entry?.metadata?.graphInput.graphInputId ?? null;\n\t\t\t\t\t\tif (snapshotGraphInputId !== graphInput.graphInputId) {\n\t\t\t\t\t\t\tyield* Effect.logWarning(\n\t\t\t\t\t\t\t\t`snapshot ${startFromSnapshot.id} graph input is stale; clean-start policy skipped restore`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tyield* provideFileSystem(\n\t\t\t\t\t\t\t\tfs,\n\t\t\t\t\t\t\t\tsnapshot.restore({\n\t\t\t\t\t\t\t\t\tid: startFromSnapshot.id,\n\t\t\t\t\t\t\t\t\tcurrentGraphInput: graphInput,\n\t\t\t\t\t\t\t\t\tgraphInputMismatchPolicy: 'block',\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tyield* provideFileSystem(\n\t\t\t\t\t\t\tfs,\n\t\t\t\t\t\t\tsnapshot.restore({\n\t\t\t\t\t\t\t\tid: startFromSnapshot.id,\n\t\t\t\t\t\t\t\tcurrentGraphInput: graphInput,\n\t\t\t\t\t\t\t\tgraphInputMismatchPolicy: startFromSnapshot.stalePolicy,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst commandChannel = yield* installCommandChannelBridge({\n\t\t\t\t\tstackRoot: stackPaths.stackRoot,\n\t\t\t\t\thandle: h.supervisor,\n\t\t\t\t});\n\t\t\t\tyield* installLiveSupervisorRoster({\n\t\t\t\t\tstackRoot: stackPaths.stackRoot,\n\t\t\t\t\tapp: String(identityValue.app),\n\t\t\t\t\tstack: String(identityValue.stack),\n\t\t\t\t});\n\t\t\t\tconst rendererEvents = yield* Queue.unbounded<EngineEvent>();\n\t\t\t\tconst renderer = makeTuiSurface({\n\t\t\t\t\tmode: rendererMode,\n\t\t\t\t\tpublishCommand: makeQueueCommandPublisher(h.commands),\n\t\t\t\t\t// Opt-in quiet plain stream (readiness/endpoint/codegen\n\t\t\t\t\t// milestones + warns/errors only). Set by embedded consumers\n\t\t\t\t\t// that pipe `devstack up` output through another tool — the\n\t\t\t\t\t// Playwright `webServer` (see `devstackPlaywrightWebServer`)\n\t\t\t\t\t// — where the full per-event firehose reads as `[WebServer]`\n\t\t\t\t\t// noise. No effect on a TTY (`ink`) or normal CI `plain` run.\n\t\t\t\t\tquiet: process.env.DEVSTACK_PLAIN_QUIET === '1',\n\t\t\t\t});\n\t\t\t\tyield* Effect.addFinalizer(() => renderer.flush.pipe(Effect.catch(() => Effect.void)));\n\t\t\t\tyield* Effect.forkScoped(\n\t\t\t\t\trenderer.mount(h.state, Stream.fromQueue(rendererEvents)).pipe(\n\t\t\t\t\t\tEffect.catch((cause) =>\n\t\t\t\t\t\t\tEffect.sync(() => {\n\t\t\t\t\t\t\t\tprocess.stderr.write(`renderer failed: ${cause.detail ?? String(cause)}\\n`);\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tyield* Effect.forkScoped(\n\t\t\t\t\th.events.pipe(\n\t\t\t\t\t\tStream.runForEach((event) =>\n\t\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\t\tyield* Queue.offer(rendererEvents, event);\n\t\t\t\t\t\t\t\tyield* commandChannel.publishEvent(event);\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}),\n\t\twithinScope: (h) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tif (snapshotCache === undefined || !refreshSnapshotCache) return;\n\t\t\t\tyield* h.supervisor.runCommand({\n\t\t\t\t\ttag: 'snapshot.capture',\n\t\t\t\t\tname: snapshotCache.name,\n\t\t\t\t\treplaceExisting: true,\n\t\t\t\t});\n\t\t\t}),\n\t};\n\n\treturn { commandHandler, boot };\n};\n\n/**\n * Run `devstack up`. Wires the substrate Layer stack, supervisor,\n * attached renderer, and in-process TUI command queue. The Effect runs\n * as the outer Node fiber so SIGINT reaches scope finalizers.\n *\n * Returns a typed `CommandResult` / fails with a typed `CliError` so\n * the dispatcher's `emitFailure` renders the envelope (JSON mode) or\n * human-mode stderr line. Wirings MUST NOT write raw bytes to\n * `process.stderr` or mutate `process.exitCode` for terminal failures —\n * the dispatcher owns the projection.\n */\nexport const runUpLive = (\n\tconfigPath: string | undefined,\n\tidentity: ResolvedIdentity,\n\toptions: {\n\t\treadonly renderer: GlobalFlags['renderer'];\n\t\treadonly stdoutIsTty: boolean;\n\t\treadonly fromSnapshot?: string;\n\t\treadonly snapshotCache?: string;\n\t\treadonly snapshotStalePolicy?: GlobalFlags['snapshotStalePolicy'];\n\t},\n): Effect.Effect<CommandResult, CliError> => {\n\tconst loader = makeConfigLoader();\n\treturn Effect.gen(function* () {\n\t\tif (options.fromSnapshot !== undefined && options.snapshotCache !== undefined) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew CliUsageError({\n\t\t\t\t\tmessage: '--snapshot-cache cannot be combined with --from-snapshot',\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tif (options.snapshotCache !== undefined && options.snapshotStalePolicy !== undefined) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew CliUsageError({\n\t\t\t\t\tmessage: '--snapshot-stale is only valid with --from-snapshot',\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tconst loadExit = yield* Effect.exit(loader.load(configPath));\n\t\tif (Exit.isFailure(loadExit)) {\n\t\t\treturn yield* Effect.fail(cliErrorFromConfigExit(loadExit));\n\t\t}\n\t\tconst loaded = loadExit.value;\n\t\tconst publicStack = (\n\t\t\tloaded as LoadedConfig & {\n\t\t\t\treadonly stack: Stack<SupervisedStack['members']>;\n\t\t\t}\n\t\t).stack;\n\t\tconst stack = (loaded as LoadedConfig & { readonly engine: SupervisedStack }).engine;\n\n\t\t// Re-derive the identity against the EFFECTIVE stack (explicit\n\t\t// `--stack`/`$DEVSTACK_STACK` > `config.stackName` > inferred) so\n\t\t// the roster lock, command channel, and container/router naming all\n\t\t// target the same stack the operator selected — matching what\n\t\t// `snapshot.ts` already does. Without this, an explicit `--stack`\n\t\t// would boot the supervisor under the config's `stackName` and a\n\t\t// concurrent default-stack `up` would falsely collide on the live\n\t\t// supervisor (`error: supervisor live for <app>/<stack>`, exit 40).\n\t\tconst effectiveIdentity = resolvedIdentityForStack(identity, stack);\n\t\tconst identityValue: Identity = identityValueFor(effectiveIdentity);\n\t\tconst appRoot = dirname(loaded.resolvedConfigPath);\n\n\t\tconst devstackVersion = readDevstackVersion({ fallback: '0.0.0' });\n\t\tconst rendererMode = resolveUpRendererMode({\n\t\t\tcliRenderer: options.renderer,\n\t\t\tstackRenderer: stack.options.renderer,\n\t\t\tstdoutIsTty: options.stdoutIsTty,\n\t\t});\n\t\tlet startFromSnapshot: StartFromSnapshot | undefined;\n\t\tlet snapshotCache: SnapshotCache | undefined;\n\t\tif (options.fromSnapshot !== undefined) {\n\t\t\tconst resolved = yield* makeSnapshotReader({ stackRoot: effectiveIdentity.stackRoot })\n\t\t\t\t.resolve(options.fromSnapshot)\n\t\t\t\t.pipe(\n\t\t\t\t\tEffect.mapError(\n\t\t\t\t\t\t(cause) =>\n\t\t\t\t\t\t\tnew CliInternalError({\n\t\t\t\t\t\t\t\tmessage: 'snapshot lookup failed',\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\tswitch (resolved.tag) {\n\t\t\t\tcase 'found':\n\t\t\t\t\tstartFromSnapshot = {\n\t\t\t\t\t\tid: resolved.entry.snapshotId,\n\t\t\t\t\t\tstalePolicy: options.snapshotStalePolicy ?? 'warn',\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'not-found':\n\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\tnew CliSnapshotNotFoundError({ snapshotRef: options.fromSnapshot }),\n\t\t\t\t\t);\n\t\t\t\tcase 'ambiguous':\n\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\tnew CliUsageError({\n\t\t\t\t\t\t\tmessage: `snapshot reference is ambiguous: ${resolved.snapshotRef}`,\n\t\t\t\t\t\t\thint: `matches: ${resolved.matches.map((entry) => entry.snapshotId).join(', ')}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (options.snapshotCache !== undefined) {\n\t\t\tconst resolved = yield* makeSnapshotReader({ stackRoot: effectiveIdentity.stackRoot })\n\t\t\t\t.resolve(options.snapshotCache)\n\t\t\t\t.pipe(\n\t\t\t\t\tEffect.mapError(\n\t\t\t\t\t\t(cause) =>\n\t\t\t\t\t\t\tnew CliInternalError({\n\t\t\t\t\t\t\t\tmessage: 'snapshot lookup failed',\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\tswitch (resolved.tag) {\n\t\t\t\tcase 'found':\n\t\t\t\t\tsnapshotCache = {\n\t\t\t\t\t\tname: options.snapshotCache,\n\t\t\t\t\t\texistingSnapshotId: resolved.entry.snapshotId,\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'not-found':\n\t\t\t\t\tsnapshotCache = { name: options.snapshotCache };\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'ambiguous':\n\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\tnew CliUsageError({\n\t\t\t\t\t\t\tmessage: `snapshot reference is ambiguous: ${resolved.snapshotRef}`,\n\t\t\t\t\t\t\thint: `matches: ${resolved.matches.map((entry) => entry.snapshotId).join(', ')}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// The CLI concerns (snapshot/wipe/prune `commandHandler` + the\n\t\t// recover/roster/IPC/TUI boot hooks) as a value bundle — the\n\t\t// EXACT thing the seam consumes, extracted so the Docker-free CLI-boot\n\t\t// smoke test can drive the real bundle (see `test/cli/up-boot-smoke`).\n\t\tconst { commandHandler, boot } = buildUpBootBundle({\n\t\t\tstack,\n\t\t\tidentityValue,\n\t\t\truntimeRoot: effectiveIdentity.runtimeRoot,\n\t\t\tdevstackVersion,\n\t\t\trendererMode,\n\t\t\t...(startFromSnapshot === undefined ? {} : { startFromSnapshot }),\n\t\t\t...(snapshotCache === undefined ? {} : { snapshotCache }),\n\t\t});\n\n\t\t// The ONE boot seam. `runStackWithBoot` owns the substrate Layer\n\t\t// composition, the contribution dispatcher + post-acquire hook +\n\t\t// `extendContext` assembly, the projection ref, and the\n\t\t// forkDetach/Deferred boot lifecycle — `up` no longer forks its own\n\t\t// parallel orchestration. The CLI concerns (recover/roster/IPC/TUI\n\t\t// + snapshot handler) are passed as injected hooks + `commandHandler`.\n\t\tconst handle = runStackWithBoot(publicStack, {\n\t\t\tidentity: {\n\t\t\t\tapp: String(identityValue.app),\n\t\t\t\tstack: String(identityValue.stack),\n\t\t\t\tnetwork: String(identityValue.network),\n\t\t\t},\n\t\t\tappRoot,\n\t\t\truntimeRoot: effectiveIdentity.runtimeRoot,\n\t\t\tcodegen: stack.options.codegen,\n\t\t\tcommandHandler,\n\t\t\tboot,\n\t\t});\n\n\t\t// The outer fiber BLOCKS on `awaitShutdown` so SIGINT reaches the\n\t\t// supervisor's in-scope signal handler (forked inside `startSupervisor`)\n\t\t// and drives teardown through the command-channel/latch — the same path\n\t\t// the CLI used as the outer fiber before the cutover. `Effect.scoped`\n\t\t// owns the supervised scope so the TUI flush finalizer + roster release\n\t\t// run on scope close.\n\t\t//\n\t\t// Errors project through the seam's DISCRIMINATED channels — no\n\t\t// `matchCauseEffect` re-discrimination:\n\t\t// - `handle.start` fails ⇒ BOOT-time `BootError`. Extract a\n\t\t// `CliSupervisorLiveError` (roster-claim loss) for exit 40; else\n\t\t// wrap as `CliInternalError`.\n\t\t// - `handle.awaitShutdown` fails ⇒ MID-RUN cause. Wrap as\n\t\t// `CliInternalError` (boot already succeeded by then).\n\t\treturn yield* Effect.scoped(\n\t\t\tEffect.gen(function* () {\n\t\t\t\tyield* handle.start.pipe(\n\t\t\t\t\tEffect.catch((bootError: BootError) => {\n\t\t\t\t\t\tconst live = findCliSupervisorLiveError(bootError.cause);\n\t\t\t\t\t\treturn Effect.fail(\n\t\t\t\t\t\t\tlive ??\n\t\t\t\t\t\t\t\tnew CliInternalError({\n\t\t\t\t\t\t\t\t\tmessage: 'stack failed',\n\t\t\t\t\t\t\t\t\tcause: Cause.pretty(bootError.cause),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tyield* handle.awaitShutdown.pipe(\n\t\t\t\t\tEffect.catchCause(\n\t\t\t\t\t\t(cause): Effect.Effect<never, CliError> =>\n\t\t\t\t\t\t\tEffect.fail(\n\t\t\t\t\t\t\t\tnew CliInternalError({\n\t\t\t\t\t\t\t\t\tmessage: 'stack failed',\n\t\t\t\t\t\t\t\t\tcause: Cause.pretty(cause as Cause.Cause<unknown>),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn { exitCode: ExitCode.OK } satisfies CommandResult;\n\t\t\t}),\n\t\t);\n\t});\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"up.mjs","names":["resolvePath"],"sources":["../../../src/cli/wirings/up.ts"],"sourcesContent":["// `devstack up` verb wiring.\n//\n// Wires the substrate Layer stack, supervisor, attached renderer, and\n// in-process TUI command queue. The Effect runs as the outer Node fiber\n// so SIGINT reaches scope finalizers (see surfaces/cli/index.ts\n// architecture invariant).\n//\n// Logger layer: `Logger.layer([])` (silent). `up` owns the TUI, which is\n// the operator-facing output channel; routing structured `Effect.log*`\n// records to stderr would scribble on top of the live ink renderer in\n// human mode and would duplicate the structured event stream the plain\n// renderer already emits in non-TTY mode. The sibling `apply` verb (no\n// TUI) uses `Logger.consolePretty()` because its consumer is CI.\n\nimport { dirname, resolve as resolvePath } from 'node:path';\n\nimport { Cause, Effect, Exit, FileSystem, Queue, Scope, Stream } from 'effect';\n\nimport type { Identity } from '../../substrate/identity.ts';\nimport type { EngineEvent } from '../../substrate/events.ts';\nimport { StackPathsService } from '../../substrate/runtime/paths.ts';\nimport {\n\tclaim,\n\theartbeatFiber,\n\trelease,\n\tstartFileWatcher,\n\ttype SupervisedStack,\n\ttype SupervisorCommandHandler,\n} from '../../substrate/runtime/index.ts';\nimport {\n\tcollectLifecyclePruneInventory,\n\tdefaultLifecyclePruneSelection,\n\tDEFAULT_LIFECYCLE_PRUNE_RESOURCES,\n\trunLifecyclePrune,\n} from '../../orchestrators/lifecycle-prune/index.ts';\nimport {\n\tcomputeSnapshotGraphInputFromStack,\n\trecoverInterruptedRestore,\n\tSnapshotOrchestratorService,\n} from '../../orchestrators/snapshot/index.ts';\nimport type { Stack } from '../../api/define-devstack.ts';\nimport {\n\trunStackWithBoot,\n\ttype CommandHandlerFactory,\n\ttype RunStackBootBag,\n} from '../../api/run-stack-internal.ts';\nimport type { BootError } from '../../api/run-stack.ts';\nimport {\n\ttype CliError,\n\tCliInternalError,\n\tCliSnapshotNotFoundError,\n\tCliSupervisorLiveError,\n\tCliUsageError,\n\ttype GlobalFlags,\n} from '../../surfaces/cli/index.ts';\nimport type { CommandResult } from '../../surfaces/cli/commands/index.ts';\nimport { ExitCode } from '../../surfaces/cli/sysexits.ts';\nimport { makeTuiSurface } from '../../surfaces/tui/index.ts';\nimport type { LoadedConfig } from '../../surfaces/cli/commands/config-loader.ts';\n\nimport { cliErrorFromConfigExit } from '../bail.ts';\nimport { makeQueueCommandPublisher, resolveUpRendererMode } from '../up-lifecycle.ts';\nimport { makeConfigLoader } from './config-loader.ts';\nimport { makeSnapshotReader } from '../snapshot-reader.ts';\nimport {\n\tfindCliSupervisorLiveError,\n\tidentityValueFor,\n\tresolvedIdentityForStack,\n\ttype ResolvedIdentity,\n} from './identity.ts';\nimport { installCommandChannelBridge } from './up-ipc.ts';\nimport { provideFileSystem } from './provide-file-system.ts';\nimport { deriveContributions } from './codegen.ts';\nimport { readDevstackVersion } from './read-devstack-version.ts';\n\nconst rosterPathsFor = (stackRoot: string) => ({\n\tstackLockFile: resolvePath(stackRoot, 'stack.lock'),\n\trosterFile: resolvePath(stackRoot, 'roster.json'),\n});\n\n// -----------------------------------------------------------------------------\n// Supervisor command handler — snapshot/wipe/prune injected dispatch\n// -----------------------------------------------------------------------------\n\n/** Build the snapshot/wipe/prune `commandHandler` as a FACTORY the seam\n * resolves against its LIVE substrate (see `CommandHandlerFactory`). The\n * factory yields the seam's `SnapshotOrchestratorService` + `FileSystem` —\n * the SAME orchestrator instance the supervisor's contribution dispatcher\n * registers live participants on, so an operator `snapshot save` captures\n * real chain/blob/db state, not an empty set — and returns a handler\n * (R = `never`, as the command loop requires) that closes over them\n * directly. No Deferred hand-off: the seam runs this factory before\n * `startSupervisor` consumes the handler. */\nconst makeSnapshotCommandHandler = (params: {\n\treadonly runtimeRoot: string;\n\treadonly stack: SupervisedStack;\n\treadonly devstackVersion: string;\n}): CommandHandlerFactory =>\n\tEffect.gen(function* () {\n\t\tconst snapshot = yield* SnapshotOrchestratorService;\n\t\tconst fs = yield* FileSystem.FileSystem;\n\t\tconst computeGraphInput = computeSnapshotGraphInputFromStack({\n\t\t\tstack: params.stack,\n\t\t\tdevstackVersion: params.devstackVersion,\n\t\t});\n\t\tconst handler: SupervisorCommandHandler = (cmd) => {\n\t\t\tswitch (cmd.tag) {\n\t\t\t\tcase 'snapshot.capture':\n\t\t\t\t\t// The L3 capture is the bounce's gather → stop → commit → retag\n\t\t\t\t\t// → hard-rm half; the RESUME (recreate + wait-write-ready) is the\n\t\t\t\t\t// command-loop's converge after this handler succeeds (it owns the\n\t\t\t\t\t// graph), mirroring restore. So no `resume` is injected here.\n\t\t\t\t\treturn provideFileSystem(\n\t\t\t\t\t\tfs,\n\t\t\t\t\t\tcomputeGraphInput.pipe(\n\t\t\t\t\t\t\tEffect.flatMap((graphInput) =>\n\t\t\t\t\t\t\t\tsnapshot.capture({\n\t\t\t\t\t\t\t\t\tid: cmd.snapshotId,\n\t\t\t\t\t\t\t\t\t...(cmd.name === undefined ? {} : { label: cmd.name }),\n\t\t\t\t\t\t\t\t\tgraphInput,\n\t\t\t\t\t\t\t\t\t...(cmd.replaceExisting === true ? { replaceExistingLabel: true } : {}),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t).pipe(\n\t\t\t\t\t\tEffect.map((meta) => [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttag: 'snapshot.captured',\n\t\t\t\t\t\t\t\tsnapshotId: meta.id,\n\t\t\t\t\t\t\t\t...(meta.label === null ? {} : { name: meta.label }),\n\t\t\t\t\t\t\t\tat: Date.now(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]),\n\t\t\t\t\t);\n\t\t\t\tcase 'snapshot.restore':\n\t\t\t\t\treturn provideFileSystem(\n\t\t\t\t\t\tfs,\n\t\t\t\t\t\tcomputeGraphInput.pipe(\n\t\t\t\t\t\t\tEffect.flatMap((currentGraphInput) =>\n\t\t\t\t\t\t\t\tsnapshot.restore({\n\t\t\t\t\t\t\t\t\tid: cmd.snapshotId,\n\t\t\t\t\t\t\t\t\tcurrentGraphInput,\n\t\t\t\t\t\t\t\t\tgraphInputMismatchPolicy: 'warn',\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t).pipe(\n\t\t\t\t\t\tEffect.map((meta) => [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttag: 'snapshot.restored',\n\t\t\t\t\t\t\t\tsnapshotId: meta.id,\n\t\t\t\t\t\t\t\tat: Date.now(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]),\n\t\t\t\t\t);\n\t\t\t\tcase 'snapshot.list':\n\t\t\t\t\treturn provideFileSystem(fs, snapshot.list).pipe(Effect.as([]));\n\t\t\t\tcase 'snapshot.delete':\n\t\t\t\t\treturn provideFileSystem(fs, snapshot.delete(cmd.snapshotId)).pipe(Effect.as([]));\n\t\t\t\tcase 'wipe.requested':\n\t\t\t\t\treturn provideFileSystem(fs, snapshot.wipe({})).pipe(Effect.as([]));\n\t\t\t\tcase 'prune.requested':\n\t\t\t\t\t// Route to the same orchestrator the offline `devstack prune`\n\t\t\t\t\t// verb uses (`runLifecyclePrune`), NOT the snapshot-orchestrator\n\t\t\t\t\t// prune (which only cleans the snapshot catalog and would leave\n\t\t\t\t\t// stale containers/networks/volumes/images behind for an attached\n\t\t\t\t\t// supervisor — silent under-prune is the bug we're closing).\n\t\t\t\t\t// Live supervisor implies the current stack's group is live and\n\t\t\t\t\t// therefore excluded from the default selection — exactly the\n\t\t\t\t\t// invariant the live-attached `prune` needs (operator can prune\n\t\t\t\t\t// sibling stacks under the same Docker daemon without touching\n\t\t\t\t\t// the running one).\n\t\t\t\t\treturn collectLifecyclePruneInventory({ runtimeRoot: params.runtimeRoot }).pipe(\n\t\t\t\t\t\tEffect.flatMap((inventory) =>\n\t\t\t\t\t\t\trunLifecyclePrune(\n\t\t\t\t\t\t\t\t{ runtimeRoot: params.runtimeRoot },\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tgroupKeys: defaultLifecyclePruneSelection(\n\t\t\t\t\t\t\t\t\t\tinventory,\n\t\t\t\t\t\t\t\t\t\tDEFAULT_LIFECYCLE_PRUNE_RESOURCES,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tresources: DEFAULT_LIFECYCLE_PRUNE_RESOURCES,\n\t\t\t\t\t\t\t\t\tdryRun: false,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tEffect.as([]),\n\t\t\t\t\t);\n\t\t\t\tdefault:\n\t\t\t\t\treturn Effect.succeed([]);\n\t\t\t}\n\t\t};\n\t\treturn handler;\n\t});\n\nconst installLiveSupervisorRoster = (params: {\n\treadonly stackRoot: string;\n\treadonly app: string;\n\treadonly stack: string;\n}): Effect.Effect<void, unknown, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst paths = rosterPathsFor(params.stackRoot);\n\t\tconst claimed = yield* claim(paths);\n\t\tif (!claimed.soleHolder) {\n\t\t\tyield* release(paths).pipe(Effect.catch(() => Effect.void));\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew CliSupervisorLiveError({\n\t\t\t\t\tapp: params.app,\n\t\t\t\t\tstack: params.stack,\n\t\t\t\t\thint: 'use `devstack apply` from another shell, or choose a different --stack name',\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tyield* Effect.addFinalizer(() => release(paths).pipe(Effect.catch(() => Effect.void)));\n\t\tyield* Effect.forkScoped(heartbeatFiber(paths));\n\t});\n\n// -----------------------------------------------------------------------------\n// CLI boot bundle — the `commandHandler` + `boot` hooks the seam consumes\n// -----------------------------------------------------------------------------\n\nexport interface UpBootBundleInput {\n\treadonly stack: SupervisedStack;\n\treadonly identityValue: Identity;\n\treadonly runtimeRoot: string;\n\treadonly devstackVersion: string;\n\treadonly rendererMode: import('../../surfaces/tui/mode-detect.ts').RendererMode;\n\treadonly startFromSnapshot?: {\n\t\treadonly id: string;\n\t\treadonly stalePolicy: 'warn' | 'block' | 'clean-start';\n\t};\n\treadonly snapshotCache?: {\n\t\treadonly name: string;\n\t\treadonly existingSnapshotId?: string;\n\t};\n}\n\nexport interface UpBootBundle {\n\treadonly commandHandler: CommandHandlerFactory;\n\treadonly boot: RunStackBootBag;\n}\n\ntype StartFromSnapshot = NonNullable<UpBootBundleInput['startFromSnapshot']>;\ntype SnapshotCache = NonNullable<UpBootBundleInput['snapshotCache']>;\n\n/**\n * Build the CLI's boot concerns as a VALUE bundle the seam consumes — the\n * snapshot/wipe/prune `commandHandler` plus the `beforeInitialAcquire`\n * (recover → IPC bridge → roster claim → TUI mount + event tee). Pure\n * value construction: no substrate is touched here; the hooks pull the\n * SEAM's substrate services at boot (they run inside the supervised scope).\n *\n * Extracted from `runUpLive` so the Docker-free CLI-boot smoke test drives\n * the EXACT bundle the production path feeds `runStackWithBoot` — the only\n * non-e2e gate on the cutover (`main.test.ts` only runs `up --help`).\n */\nexport const buildUpBootBundle = (input: UpBootBundleInput): UpBootBundle => {\n\tconst {\n\t\tstack,\n\t\tidentityValue,\n\t\truntimeRoot,\n\t\tdevstackVersion,\n\t\trendererMode,\n\t\tstartFromSnapshot,\n\t\tsnapshotCache,\n\t} = input;\n\n\tconst computeGraphInput = computeSnapshotGraphInputFromStack({ stack, devstackVersion });\n\tlet refreshSnapshotCache =\n\t\tsnapshotCache !== undefined && snapshotCache.existingSnapshotId === undefined;\n\n\t// The snapshot/wipe/prune `commandHandler` — a FACTORY the seam resolves\n\t// against its LIVE substrate (the seam runs it before `startSupervisor`\n\t// consumes the handler). The factory closes over the seam's ONE\n\t// `SnapshotOrchestratorService` instance — the same one the supervisor's\n\t// contribution dispatcher registers live participants on — so an operator\n\t// `snapshot save` captures the LIVE chain/blob/db state, not an empty set\n\t// off a sibling orchestrator. No Deferred hand-off.\n\tconst commandHandler = makeSnapshotCommandHandler({ runtimeRoot, stack, devstackVersion });\n\n\tconst boot: RunStackBootBag = {\n\t\tdevstackVersion,\n\t\tbeforeInitialAcquire: (h) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\t// The seam's substrate services — the SAME instances the\n\t\t\t\t// `commandHandler` factory closed over and the supervisor uses,\n\t\t\t\t// driven here for the recover/IPC/roster/TUI work.\n\t\t\t\tconst snapshot = yield* SnapshotOrchestratorService;\n\t\t\t\tconst fs = yield* FileSystem.FileSystem;\n\t\t\t\tconst stackPaths = yield* StackPathsService;\n\t\t\t\t// Resume any restore interrupted by a hard kill / power-loss\n\t\t\t\t// between the atomic swap and the end of the image-promotion\n\t\t\t\t// handoff (the interrupted-restore sentinel rode the swap into\n\t\t\t\t// the live root and was never cleared). Runs BEFORE any plugin\n\t\t\t\t// acquire so a half-promoted image set is reconciled before any\n\t\t\t\t// L2 lookup observes the runtime root. No-op when the sentinel\n\t\t\t\t// is absent (the clean-boot case); idempotent re-run of restore\n\t\t\t\t// when present.\n\t\t\t\t//\n\t\t\t\t// `restore({ id })` passes NO participants on purpose: this\n\t\t\t\t// hook fires BEFORE the initial acquire registers any snapshot\n\t\t\t\t// participant, so there is no live stack to contribute identity.\n\t\t\t\t// `runRestore` reads the empty participant set as \"no live\n\t\t\t\t// stack\" and skips ONLY the cross-plugin contribution guard\n\t\t\t\t// (the runtime + snapshot-emptiness guards still fire). With a\n\t\t\t\t// participants-required guard this recovery could never clear\n\t\t\t\t// the sentinel — it failed `IdentityMissingLive` every boot.\n\t\t\t\tyield* recoverInterruptedRestore({\n\t\t\t\t\tliveRoot: stackPaths.stackRoot,\n\t\t\t\t\trestoreSnapshot: (id) =>\n\t\t\t\t\t\tcomputeGraphInput.pipe(\n\t\t\t\t\t\t\tEffect.flatMap((currentGraphInput) =>\n\t\t\t\t\t\t\t\tsnapshot.restore({\n\t\t\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\t\t\tcurrentGraphInput,\n\t\t\t\t\t\t\t\t\tgraphInputMismatchPolicy: 'warn',\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t});\n\t\t\t\tif (snapshotCache !== undefined) {\n\t\t\t\t\tif (snapshotCache.existingSnapshotId === undefined) {\n\t\t\t\t\t\tyield* Effect.logWarning(\n\t\t\t\t\t\t\t`snapshot cache ${snapshotCache.name} was not found; boot will refresh it`,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst graphInput = yield* computeGraphInput;\n\t\t\t\t\t\tconst catalog = yield* provideFileSystem(fs, snapshot.list);\n\t\t\t\t\t\tconst entry = catalog.find(\n\t\t\t\t\t\t\t(snapshotEntry) => snapshotEntry.id === snapshotCache.existingSnapshotId,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst snapshotGraphInputId = entry?.metadata?.graphInput.graphInputId ?? null;\n\t\t\t\t\t\tif (snapshotGraphInputId === graphInput.graphInputId) {\n\t\t\t\t\t\t\trefreshSnapshotCache = false;\n\t\t\t\t\t\t\tyield* provideFileSystem(\n\t\t\t\t\t\t\t\tfs,\n\t\t\t\t\t\t\t\tsnapshot.restore({\n\t\t\t\t\t\t\t\t\tid: snapshotCache.existingSnapshotId,\n\t\t\t\t\t\t\t\t\tcurrentGraphInput: graphInput,\n\t\t\t\t\t\t\t\t\tgraphInputMismatchPolicy: 'block',\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\trefreshSnapshotCache = true;\n\t\t\t\t\t\t\tyield* Effect.logWarning(\n\t\t\t\t\t\t\t\t`snapshot cache ${snapshotCache.name} graph input is stale or unreadable; boot will refresh it`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (startFromSnapshot !== undefined) {\n\t\t\t\t\tconst graphInput = yield* computeGraphInput;\n\t\t\t\t\tif (startFromSnapshot.stalePolicy === 'clean-start') {\n\t\t\t\t\t\tconst catalog = yield* provideFileSystem(fs, snapshot.list);\n\t\t\t\t\t\tconst entry = catalog.find(\n\t\t\t\t\t\t\t(snapshotEntry) => snapshotEntry.id === startFromSnapshot.id,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst snapshotGraphInputId = entry?.metadata?.graphInput.graphInputId ?? null;\n\t\t\t\t\t\tif (snapshotGraphInputId !== graphInput.graphInputId) {\n\t\t\t\t\t\t\tyield* Effect.logWarning(\n\t\t\t\t\t\t\t\t`snapshot ${startFromSnapshot.id} graph input is stale; clean-start policy skipped restore`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tyield* provideFileSystem(\n\t\t\t\t\t\t\t\tfs,\n\t\t\t\t\t\t\t\tsnapshot.restore({\n\t\t\t\t\t\t\t\t\tid: startFromSnapshot.id,\n\t\t\t\t\t\t\t\t\tcurrentGraphInput: graphInput,\n\t\t\t\t\t\t\t\t\tgraphInputMismatchPolicy: 'block',\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tyield* provideFileSystem(\n\t\t\t\t\t\t\tfs,\n\t\t\t\t\t\t\tsnapshot.restore({\n\t\t\t\t\t\t\t\tid: startFromSnapshot.id,\n\t\t\t\t\t\t\t\tcurrentGraphInput: graphInput,\n\t\t\t\t\t\t\t\tgraphInputMismatchPolicy: startFromSnapshot.stalePolicy,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst commandChannel = yield* installCommandChannelBridge({\n\t\t\t\t\tstackRoot: stackPaths.stackRoot,\n\t\t\t\t\thandle: h.supervisor,\n\t\t\t\t});\n\t\t\t\tyield* installLiveSupervisorRoster({\n\t\t\t\t\tstackRoot: stackPaths.stackRoot,\n\t\t\t\t\tapp: String(identityValue.app),\n\t\t\t\t\tstack: String(identityValue.stack),\n\t\t\t\t});\n\t\t\t\tconst rendererEvents = yield* Queue.unbounded<EngineEvent>();\n\t\t\t\tconst renderer = makeTuiSurface({\n\t\t\t\t\tmode: rendererMode,\n\t\t\t\t\tpublishCommand: makeQueueCommandPublisher(h.commands),\n\t\t\t\t\t// Opt-in quiet plain stream (readiness/endpoint/codegen\n\t\t\t\t\t// milestones + warns/errors only). Set by embedded consumers\n\t\t\t\t\t// that pipe `devstack up` output through another tool — the\n\t\t\t\t\t// Playwright `webServer` (see `devstackPlaywrightWebServer`)\n\t\t\t\t\t// — where the full per-event firehose reads as `[WebServer]`\n\t\t\t\t\t// noise. No effect on a TTY (`ink`) or normal CI `plain` run.\n\t\t\t\t\tquiet: process.env.DEVSTACK_PLAIN_QUIET === '1',\n\t\t\t\t});\n\t\t\t\tyield* Effect.addFinalizer(() => renderer.flush.pipe(Effect.catch(() => Effect.void)));\n\t\t\t\tyield* Effect.forkScoped(\n\t\t\t\t\trenderer.mount(h.state, Stream.fromQueue(rendererEvents)).pipe(\n\t\t\t\t\t\tEffect.catch((cause) =>\n\t\t\t\t\t\t\tEffect.sync(() => {\n\t\t\t\t\t\t\t\tprocess.stderr.write(`renderer failed: ${cause.detail ?? String(cause)}\\n`);\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tyield* Effect.forkScoped(\n\t\t\t\t\th.events.pipe(\n\t\t\t\t\t\tStream.runForEach((event) =>\n\t\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\t\tyield* Queue.offer(rendererEvents, event);\n\t\t\t\t\t\t\t\tyield* commandChannel.publishEvent(event);\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\t// L0 file watcher — dev-only. Drives the supervisor's\n\t\t\t\t// `notifyWatchFire` on edits to any plugin's declared `watch`\n\t\t\t\t// paths (today: the package plugin's Move sources), which\n\t\t\t\t// issues a selective restart → re-produce. Forked into the\n\t\t\t\t// supervised scope so it tears down on shutdown.\n\t\t\t\tyield* startFileWatcher({\n\t\t\t\t\twatchIndex: h.supervisor.watchIndex,\n\t\t\t\t\tnotifyWatchFire: h.supervisor.notifyWatchFire,\n\t\t\t\t});\n\t\t\t}),\n\t\twithinScope: (h) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tif (snapshotCache === undefined || !refreshSnapshotCache) return;\n\t\t\t\tyield* h.supervisor.runCommand({\n\t\t\t\t\ttag: 'snapshot.capture',\n\t\t\t\t\tname: snapshotCache.name,\n\t\t\t\t\treplaceExisting: true,\n\t\t\t\t});\n\t\t\t}),\n\t};\n\n\treturn { commandHandler, boot };\n};\n\n/**\n * Run `devstack up`. Wires the substrate Layer stack, supervisor,\n * attached renderer, and in-process TUI command queue. The Effect runs\n * as the outer Node fiber so SIGINT reaches scope finalizers.\n *\n * Returns a typed `CommandResult` / fails with a typed `CliError` so\n * the dispatcher's `emitFailure` renders the envelope (JSON mode) or\n * human-mode stderr line. Wirings MUST NOT write raw bytes to\n * `process.stderr` or mutate `process.exitCode` for terminal failures —\n * the dispatcher owns the projection.\n */\nexport const runUpLive = (\n\tconfigPath: string | undefined,\n\tidentity: ResolvedIdentity,\n\toptions: {\n\t\treadonly renderer: GlobalFlags['renderer'];\n\t\treadonly stdoutIsTty: boolean;\n\t\treadonly fromSnapshot?: string;\n\t\treadonly snapshotCache?: string;\n\t\treadonly snapshotStalePolicy?: GlobalFlags['snapshotStalePolicy'];\n\t},\n): Effect.Effect<CommandResult, CliError> => {\n\tconst loader = makeConfigLoader();\n\treturn Effect.gen(function* () {\n\t\tif (options.fromSnapshot !== undefined && options.snapshotCache !== undefined) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew CliUsageError({\n\t\t\t\t\tmessage: '--snapshot-cache cannot be combined with --from-snapshot',\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tif (options.snapshotCache !== undefined && options.snapshotStalePolicy !== undefined) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew CliUsageError({\n\t\t\t\t\tmessage: '--snapshot-stale is only valid with --from-snapshot',\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tconst loadExit = yield* Effect.exit(loader.load(configPath));\n\t\tif (Exit.isFailure(loadExit)) {\n\t\t\treturn yield* Effect.fail(cliErrorFromConfigExit(loadExit));\n\t\t}\n\t\tconst loaded = loadExit.value;\n\t\tconst publicStack = (\n\t\t\tloaded as LoadedConfig & {\n\t\t\t\treadonly stack: Stack<SupervisedStack['members']>;\n\t\t\t}\n\t\t).stack;\n\t\tconst stack = (loaded as LoadedConfig & { readonly engine: SupervisedStack }).engine;\n\n\t\t// Re-derive the identity against the EFFECTIVE stack (explicit\n\t\t// `--stack`/`$DEVSTACK_STACK` > `config.stackName` > inferred) so\n\t\t// the roster lock, command channel, and container/router naming all\n\t\t// target the same stack the operator selected — matching what\n\t\t// `snapshot.ts` already does. Without this, an explicit `--stack`\n\t\t// would boot the supervisor under the config's `stackName` and a\n\t\t// concurrent default-stack `up` would falsely collide on the live\n\t\t// supervisor (`error: supervisor live for <app>/<stack>`, exit 40).\n\t\tconst effectiveIdentity = resolvedIdentityForStack(identity, stack);\n\t\tconst identityValue: Identity = identityValueFor(effectiveIdentity);\n\t\tconst appRoot = dirname(loaded.resolvedConfigPath);\n\n\t\tconst devstackVersion = readDevstackVersion({ fallback: '0.0.0' });\n\t\tconst rendererMode = resolveUpRendererMode({\n\t\t\tcliRenderer: options.renderer,\n\t\t\tstackRenderer: stack.options.renderer,\n\t\t\tstdoutIsTty: options.stdoutIsTty,\n\t\t});\n\t\tlet startFromSnapshot: StartFromSnapshot | undefined;\n\t\tlet snapshotCache: SnapshotCache | undefined;\n\t\tif (options.fromSnapshot !== undefined) {\n\t\t\tconst resolved = yield* makeSnapshotReader({ stackRoot: effectiveIdentity.stackRoot })\n\t\t\t\t.resolve(options.fromSnapshot)\n\t\t\t\t.pipe(\n\t\t\t\t\tEffect.mapError(\n\t\t\t\t\t\t(cause) =>\n\t\t\t\t\t\t\tnew CliInternalError({\n\t\t\t\t\t\t\t\tmessage: 'snapshot lookup failed',\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\tswitch (resolved.tag) {\n\t\t\t\tcase 'found':\n\t\t\t\t\tstartFromSnapshot = {\n\t\t\t\t\t\tid: resolved.entry.snapshotId,\n\t\t\t\t\t\tstalePolicy: options.snapshotStalePolicy ?? 'warn',\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'not-found':\n\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\tnew CliSnapshotNotFoundError({ snapshotRef: options.fromSnapshot }),\n\t\t\t\t\t);\n\t\t\t\tcase 'ambiguous':\n\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\tnew CliUsageError({\n\t\t\t\t\t\t\tmessage: `snapshot reference is ambiguous: ${resolved.snapshotRef}`,\n\t\t\t\t\t\t\thint: `matches: ${resolved.matches.map((entry) => entry.snapshotId).join(', ')}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (options.snapshotCache !== undefined) {\n\t\t\tconst resolved = yield* makeSnapshotReader({ stackRoot: effectiveIdentity.stackRoot })\n\t\t\t\t.resolve(options.snapshotCache)\n\t\t\t\t.pipe(\n\t\t\t\t\tEffect.mapError(\n\t\t\t\t\t\t(cause) =>\n\t\t\t\t\t\t\tnew CliInternalError({\n\t\t\t\t\t\t\t\tmessage: 'snapshot lookup failed',\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\tswitch (resolved.tag) {\n\t\t\t\tcase 'found':\n\t\t\t\t\tsnapshotCache = {\n\t\t\t\t\t\tname: options.snapshotCache,\n\t\t\t\t\t\texistingSnapshotId: resolved.entry.snapshotId,\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'not-found':\n\t\t\t\t\tsnapshotCache = { name: options.snapshotCache };\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'ambiguous':\n\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\tnew CliUsageError({\n\t\t\t\t\t\t\tmessage: `snapshot reference is ambiguous: ${resolved.snapshotRef}`,\n\t\t\t\t\t\t\thint: `matches: ${resolved.matches.map((entry) => entry.snapshotId).join(', ')}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// The CLI concerns (snapshot/wipe/prune `commandHandler` + the\n\t\t// recover/roster/IPC/TUI boot hooks) as a value bundle — the\n\t\t// EXACT thing the seam consumes, extracted so the Docker-free CLI-boot\n\t\t// smoke test can drive the real bundle (see `test/cli/up-boot-smoke`).\n\t\tconst { commandHandler, boot } = buildUpBootBundle({\n\t\t\tstack,\n\t\t\tidentityValue,\n\t\t\truntimeRoot: effectiveIdentity.runtimeRoot,\n\t\t\tdevstackVersion,\n\t\t\trendererMode,\n\t\t\t...(startFromSnapshot === undefined ? {} : { startFromSnapshot }),\n\t\t\t...(snapshotCache === undefined ? {} : { snapshotCache }),\n\t\t});\n\n\t\t// The ONE boot seam. `runStackWithBoot` owns the substrate Layer\n\t\t// composition, the contribution dispatcher + post-acquire hook +\n\t\t// `extendContext` assembly, the projection ref, and the\n\t\t// forkDetach/Deferred boot lifecycle — `up` no longer forks its own\n\t\t// parallel orchestration. The CLI concerns (recover/roster/IPC/TUI\n\t\t// + snapshot handler) are passed as injected hooks + `commandHandler`.\n\t\tconst handle = runStackWithBoot(publicStack, {\n\t\t\tidentity: {\n\t\t\t\tapp: String(identityValue.app),\n\t\t\t\tstack: String(identityValue.stack),\n\t\t\t\tnetwork: String(identityValue.network),\n\t\t\t},\n\t\t\tappRoot,\n\t\t\truntimeRoot: effectiveIdentity.runtimeRoot,\n\t\t\tcodegen: stack.options.codegen,\n\t\t\t// Dev loop: a Move-source edit fires the watcher → reacquires the\n\t\t\t// package (new id) → this regenerates the committed bindings so the\n\t\t\t// app sees the new shapes. Pass the STATIC (id-free) contributions —\n\t\t\t// the same the stack-free `codegen` verb uses — so the regen NEVER\n\t\t\t// bakes the live on-chain id into the committed `config.ts`. `apply` /\n\t\t\t// `runStack` leave it off.\n\t\t\temitBindings: deriveContributions(stack.members),\n\t\t\tcommandHandler,\n\t\t\tboot,\n\t\t});\n\n\t\t// The outer fiber BLOCKS on `awaitShutdown` so SIGINT reaches the\n\t\t// supervisor's in-scope signal handler (forked inside `startSupervisor`)\n\t\t// and drives teardown through the command-channel/latch — the same path\n\t\t// the CLI used as the outer fiber before the cutover. `Effect.scoped`\n\t\t// owns the supervised scope so the TUI flush finalizer + roster release\n\t\t// run on scope close.\n\t\t//\n\t\t// Errors project through the seam's DISCRIMINATED channels — no\n\t\t// `matchCauseEffect` re-discrimination:\n\t\t// - `handle.start` fails ⇒ BOOT-time `BootError`. Extract a\n\t\t// `CliSupervisorLiveError` (roster-claim loss) for exit 40; else\n\t\t// wrap as `CliInternalError`.\n\t\t// - `handle.awaitShutdown` fails ⇒ MID-RUN cause. Wrap as\n\t\t// `CliInternalError` (boot already succeeded by then).\n\t\treturn yield* Effect.scoped(\n\t\t\tEffect.gen(function* () {\n\t\t\t\tyield* handle.start.pipe(\n\t\t\t\t\tEffect.catch((bootError: BootError) => {\n\t\t\t\t\t\tconst live = findCliSupervisorLiveError(bootError.cause);\n\t\t\t\t\t\treturn Effect.fail(\n\t\t\t\t\t\t\tlive ??\n\t\t\t\t\t\t\t\tnew CliInternalError({\n\t\t\t\t\t\t\t\t\tmessage: 'stack failed',\n\t\t\t\t\t\t\t\t\tcause: Cause.pretty(bootError.cause),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tyield* handle.awaitShutdown.pipe(\n\t\t\t\t\tEffect.catchCause(\n\t\t\t\t\t\t(cause): Effect.Effect<never, CliError> =>\n\t\t\t\t\t\t\tEffect.fail(\n\t\t\t\t\t\t\t\tnew CliInternalError({\n\t\t\t\t\t\t\t\t\tmessage: 'stack failed',\n\t\t\t\t\t\t\t\t\tcause: Cause.pretty(cause as Cause.Cause<unknown>),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn { exitCode: ExitCode.OK } satisfies CommandResult;\n\t\t\t}),\n\t\t);\n\t});\n};\n"],"mappings":"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"}
|
|
@@ -371,6 +371,11 @@ const buildProductionPostAcquireHook = (options = {}) => Effect.gen(function* ()
|
|
|
371
371
|
const extras = yield* codegen.emitExtras().pipe(Effect.provideService(FileSystem.FileSystem, fs), Effect.provideService(CodegenPathsService, paths), Effect.provideService(MoveSummaryRunnerService, moveRunner), Effect.provideService(MoveCodegenService, moveCodegen));
|
|
372
372
|
extrasFiles.push(...extras.filesWritten, ...extras.filesChmod);
|
|
373
373
|
}
|
|
374
|
+
const bindingFiles = [];
|
|
375
|
+
if (options.emitBindings !== void 0) {
|
|
376
|
+
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));
|
|
377
|
+
bindingFiles.push(...emitted.filesWritten, ...emitted.filesChmod);
|
|
378
|
+
}
|
|
374
379
|
yield* postAcquireTasks.runAll;
|
|
375
380
|
return [{
|
|
376
381
|
tag: "manifest.flushed",
|
|
@@ -378,7 +383,11 @@ const buildProductionPostAcquireHook = (options = {}) => Effect.gen(function* ()
|
|
|
378
383
|
at: Date.now()
|
|
379
384
|
}, {
|
|
380
385
|
tag: "codegen.emitted",
|
|
381
|
-
files: [
|
|
386
|
+
files: [
|
|
387
|
+
idsFile,
|
|
388
|
+
...extrasFiles,
|
|
389
|
+
...bindingFiles
|
|
390
|
+
],
|
|
382
391
|
at: Date.now()
|
|
383
392
|
}];
|
|
384
393
|
});
|
|
@@ -421,7 +430,8 @@ const superviseStackWithProductionBoot = (stack, identity, state, opts = {}) =>
|
|
|
421
430
|
contributionDispatcher: yield* buildProductionContributionDispatcher(),
|
|
422
431
|
postAcquireHook: yield* buildProductionPostAcquireHook({
|
|
423
432
|
...opts.extras === void 0 ? {} : { extras: opts.extras },
|
|
424
|
-
...opts.networkOptions === void 0 ? {} : { networkOptions: opts.networkOptions }
|
|
433
|
+
...opts.networkOptions === void 0 ? {} : { networkOptions: opts.networkOptions },
|
|
434
|
+
...opts.emitBindings === void 0 ? {} : { emitBindings: opts.emitBindings }
|
|
425
435
|
}),
|
|
426
436
|
...opts.lifetime === void 0 ? {} : { lifetime: opts.lifetime },
|
|
427
437
|
...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 { 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\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 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\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: [idsFile, ...extrasFiles, ...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/** 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/** 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.networkOptions === undefined ? {} : { networkOptions: opts.networkOptions }),\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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"}
|
|
@@ -247,13 +247,15 @@ const runEmitCycleInner = (input, paths) => Effect.gen(function* () {
|
|
|
247
247
|
importExtension: input.bindingsImportExtension
|
|
248
248
|
});
|
|
249
249
|
else yield* Effect.logInfo("codegen: no package contributions; skipping Move-to-TS bindings step.");
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
250
|
+
if (fileEmitters.some((d) => d.aggregateOnly !== true && declLocation(d) === "generated") || aggregateFiles.some((a) => a.location === "generated")) {
|
|
251
|
+
const sensitivePaths = [...fileEmitters.filter((d) => d.sensitive === true && d.aggregateOnly !== true && declLocation(d) === "generated").map((d) => d.outputPath), ...aggregateFiles.filter((a) => a.sensitive && a.location === "generated").map((a) => a.outputPath)];
|
|
252
|
+
yield* writeGitignore({
|
|
253
|
+
path: paths.gitignoreFile,
|
|
254
|
+
sensitivePaths,
|
|
255
|
+
parentMode: parentModeFor(paths.gitignoreFile),
|
|
256
|
+
trackTree: input.trackTree === true
|
|
257
|
+
});
|
|
258
|
+
}
|
|
257
259
|
return {
|
|
258
260
|
filesWritten,
|
|
259
261
|
filesUnchanged,
|
|
@@ -544,10 +546,23 @@ const layerCodegenOrchestrator = Layer.effect(CodegenOrchestratorService, Effect
|
|
|
544
546
|
}, paths);
|
|
545
547
|
}));
|
|
546
548
|
});
|
|
549
|
+
const emitBindings = (contributions) => Effect.gen(function* () {
|
|
550
|
+
if (contributions.length === 0) return {
|
|
551
|
+
filesWritten: [],
|
|
552
|
+
filesUnchanged: [],
|
|
553
|
+
filesChmod: [],
|
|
554
|
+
bindings: null
|
|
555
|
+
};
|
|
556
|
+
return yield* runEmitCycle({
|
|
557
|
+
contributions,
|
|
558
|
+
trackTree: true
|
|
559
|
+
});
|
|
560
|
+
});
|
|
547
561
|
return CodegenOrchestratorService.of({
|
|
548
562
|
registerContribution,
|
|
549
563
|
assembleIdConfig,
|
|
550
|
-
emitExtras
|
|
564
|
+
emitExtras,
|
|
565
|
+
emitBindings
|
|
551
566
|
});
|
|
552
567
|
}));
|
|
553
568
|
//#endregion
|