Mysten Incubation
Internals

Lifecycle

How the current runtime boots and stops a stack.

defineDevstack(...) is synchronous. It builds a static stack handle and performs composition-time checks. The runtime path starts when a surface consumes that handle.

Runtime surfaces:

  • devstack up starts a supervisor and stays attached.
  • devstack apply publishes apply.requested to the live supervisor when this stack is already attached; otherwise it starts the same supervisor path in one-shot mode. It re-emits the per-stack ids file and dev generated-extras — never the committed src/generated tree (that is devstack codegen).
  • runStack(stack, opts) embeds the supervisor in another TypeScript program.
import { Effect } from 'effect';
import { account, defineDevstack, runStack, sui } from '@mysten-incubation/devstack';

const stack = defineDevstack({ members: [sui(), account('alice')], stackName: 'embedded' });
const handle = runStack(stack, {
	runtimeRoot: '.devstack',
	identity: { app: 'demo', stack: 'embedded' },
	// Optional: the sanctioned typed seam for extending the run context.
	extendContext: (ctx) => Effect.succeed(ctx),
});

await Effect.runPromise(handle.start);
await Effect.runPromise(handle.stop);
await Effect.runPromise(handle.awaitShutdown);

extendContext is the sanctioned typed seam for layering extra services onto the run context: it receives the built-in plugin context and returns an Effect yielding an extended Context. It replaced the removed { layers } option — reach for it when an embedding program needs to inject its own capability into the supervised stack.

Boot order is derived from dependsOn edges. Members that need Sui depend on the shared sui resource, so the stack includes one concrete sui(...) provider. wallet({ accounts: 'all' }) is expanded after the full member list is known, so it depends on every account member in the final stack.

The supervisor claims roster.json while attached, publishes typed events, maintains a live projection, writes the manifest, emits the per-stack ids file and dev generated-extras, and serves commands from the attached TUI and filesystem command channel. It does not write the committed src/generated tree — that is devstack codegen's job. Shutdown is attached to the running process: quit the TUI or interrupt devstack up, then scope finalizers run and the roster claim is released.