@dxos/app-framework 0.14.0 → 0.16.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/CHANGELOG.md +73 -0
- package/dist/lib/App.mjs +1 -2
- package/dist/lib/Hooks.mjs +1 -2
- package/dist/lib/chunk-App.mjs +11 -0
- package/dist/lib/chunk-App.mjs.map +1 -0
- package/dist/lib/chunk-Cli.mjs +8 -0
- package/dist/lib/chunk-Cli.mjs.map +1 -0
- package/dist/lib/chunk-Devtools.mjs +112 -0
- package/dist/lib/chunk-Devtools.mjs.map +1 -0
- package/dist/lib/chunk-Hooks2.mjs +35 -0
- package/dist/lib/chunk-Hooks2.mjs.map +1 -0
- package/dist/lib/chunk-PluginManagerProvider.mjs +12 -0
- package/dist/lib/chunk-PluginManagerProvider.mjs.map +1 -0
- package/dist/lib/chunk-ProcessManagerPlugin.mjs +3 -3
- package/dist/lib/chunk-ProcessManagerPlugin.mjs.map +1 -1
- package/dist/lib/chunk-Role.mjs +19 -0
- package/dist/lib/chunk-Role.mjs.map +1 -0
- package/dist/lib/chunk-SharedPackages.mjs +11 -0
- package/dist/lib/chunk-SharedPackages.mjs.map +1 -0
- package/dist/lib/chunk-Surface.mjs.map +1 -1
- package/dist/lib/chunk-Surface2.mjs +37 -0
- package/dist/lib/chunk-Surface2.mjs.map +1 -0
- package/dist/lib/chunk-SurfaceManager.mjs +3 -3
- package/dist/lib/chunk-SurfaceManager.mjs.map +1 -1
- package/dist/lib/chunk-activation-event.mjs +86 -0
- package/dist/lib/chunk-activation-event.mjs.map +1 -0
- package/dist/lib/chunk-activation-events.mjs +66 -0
- package/dist/lib/chunk-activation-events.mjs.map +1 -0
- package/dist/lib/chunk-capabilities.mjs +202 -0
- package/dist/lib/chunk-capabilities.mjs.map +1 -0
- package/dist/lib/chunk-capability-manager.mjs +203 -0
- package/dist/lib/chunk-capability-manager.mjs.map +1 -0
- package/dist/lib/chunk-capability2.mjs +2 -2
- package/dist/lib/chunk-capability2.mjs.map +1 -1
- package/dist/lib/chunk-history-tracker.mjs +1 -1
- package/dist/lib/chunk-hooks.mjs +5 -5
- package/dist/lib/chunk-hooks.mjs.map +1 -1
- package/dist/lib/chunk-plugin-asset-cache.mjs +28 -0
- package/dist/lib/chunk-plugin-asset-cache.mjs.map +1 -0
- package/dist/lib/chunk-plugin-manager.mjs +68 -35
- package/dist/lib/chunk-plugin-manager.mjs.map +1 -1
- package/dist/lib/chunk-plugin-manager2.mjs +22 -0
- package/dist/lib/chunk-plugin-manager2.mjs.map +1 -0
- package/dist/lib/chunk-plugin-manifest.mjs +126 -0
- package/dist/lib/chunk-plugin-manifest.mjs.map +1 -0
- package/dist/lib/chunk-plugin.mjs +354 -0
- package/dist/lib/chunk-plugin.mjs.map +1 -0
- package/dist/lib/chunk-process-manager-capability.mjs +11 -10
- package/dist/lib/chunk-process-manager-capability.mjs.map +1 -1
- package/dist/lib/chunk-registry.mjs.map +1 -1
- package/dist/lib/chunk-undo-mapping.mjs +47 -0
- package/dist/lib/{plugin-process-manager/history/undo-mapping.mjs.map → chunk-undo-mapping.mjs.map} +1 -1
- package/dist/lib/chunk-undo-registry.mjs +22 -0
- package/dist/lib/{plugin-process-manager/history/undo-registry.mjs.map → chunk-undo-registry.mjs.map} +1 -1
- package/dist/lib/chunk-url-loader.mjs +345 -0
- package/dist/lib/chunk-url-loader.mjs.map +1 -0
- package/dist/lib/cli.mjs +3 -3
- package/dist/lib/cli.mjs.map +1 -1
- package/dist/lib/common/Role.mjs +1 -19
- package/dist/lib/common/activation-events.mjs +1 -57
- package/dist/lib/common/capabilities.mjs +1 -202
- package/dist/lib/config.mjs +1 -2
- package/dist/lib/core/activation-event.mjs +1 -86
- package/dist/lib/core/capability-manager.mjs +1 -203
- package/dist/lib/core/capability.mjs +1 -2
- package/dist/lib/core/plugin-asset-cache.mjs +1 -28
- package/dist/lib/core/plugin-manager.mjs +2 -19
- package/dist/lib/core/plugin-manifest.mjs +1 -126
- package/dist/lib/core/plugin.mjs +1 -354
- package/dist/lib/core/registry.mjs +1 -2
- package/dist/lib/core/url-loader.mjs +1 -345
- package/dist/lib/index.mjs +19 -19
- package/dist/lib/ns/App.mjs +2 -11
- package/dist/lib/ns/Cli.mjs +2 -8
- package/dist/lib/ns/Devtools.mjs +1 -112
- package/dist/lib/ns/Hooks.mjs +2 -35
- package/dist/lib/ns/PluginManagerProvider.mjs +2 -12
- package/dist/lib/ns/SharedPackages.mjs +2 -11
- package/dist/lib/ns/Surface.mjs +2 -35
- package/dist/lib/ns/Translations.mjs +1 -2
- package/dist/lib/plugin-cli.mjs +2 -4
- package/dist/lib/plugin-cli.mjs.map +1 -1
- package/dist/lib/plugin-process-manager/ProcessManagerPlugin.mjs +1 -2
- package/dist/lib/plugin-process-manager/history/history-tracker.mjs +1 -2
- package/dist/lib/plugin-process-manager/history/undo-mapping.mjs +1 -47
- package/dist/lib/plugin-process-manager/history/undo-registry.mjs +1 -22
- package/dist/lib/testing/react.mjs +1 -1
- package/dist/lib/testing/react.mjs.map +1 -1
- package/dist/lib/testing.mjs +5 -5
- package/dist/lib/testing.mjs.map +1 -1
- package/dist/lib/vite-plugin.mjs +3 -3
- package/dist/lib/vite-plugin.mjs.map +1 -1
- package/dist/types/src/common/activation-events.d.ts +8 -0
- package/dist/types/src/common/activation-events.d.ts.map +1 -1
- package/dist/types/src/core/plugin-manager/manager-state.d.ts.map +1 -1
- package/dist/types/src/core/plugin-manager/module-loader.d.ts +0 -10
- package/dist/types/src/core/plugin-manager/module-loader.d.ts.map +1 -1
- package/dist/types/src/core/plugin-manager/plugin-manager.d.ts.map +1 -1
- package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -1
- package/dist/types/src/ui/hooks/useApp.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +32 -32
- package/src/common/activation-events.ts +9 -0
- package/src/core/plugin-manager/manager-state.ts +14 -12
- package/src/core/plugin-manager/module-loader.ts +43 -7
- package/src/core/plugin-manager/plugin-manager.ts +2 -1
- package/src/plugin-process-manager/process-manager-capability.test.ts +66 -1
- package/src/plugin-process-manager/process-manager-capability.ts +22 -2
- package/src/ui/components/Surface/SurfaceComponent.stories.tsx +9 -7
- package/src/ui/hooks/useApp.tsx +2 -1
- package/src/vite-plugin/boot-loader/loader-app/boot-loader.css +19 -1
- package/dist/lib/common/Role.mjs.map +0 -1
- package/dist/lib/common/activation-events.mjs.map +0 -1
- package/dist/lib/common/capabilities.mjs.map +0 -1
- package/dist/lib/core/activation-event.mjs.map +0 -1
- package/dist/lib/core/capability-manager.mjs.map +0 -1
- package/dist/lib/core/plugin-asset-cache.mjs.map +0 -1
- package/dist/lib/core/plugin-manager.mjs.map +0 -1
- package/dist/lib/core/plugin-manifest.mjs.map +0 -1
- package/dist/lib/core/plugin.mjs.map +0 -1
- package/dist/lib/core/url-loader.mjs.map +0 -1
- package/dist/lib/ns/App.mjs.map +0 -1
- package/dist/lib/ns/Cli.mjs.map +0 -1
- package/dist/lib/ns/Devtools.mjs.map +0 -1
- package/dist/lib/ns/Hooks.mjs.map +0 -1
- package/dist/lib/ns/PluginManagerProvider.mjs.map +0 -1
- package/dist/lib/ns/SharedPackages.mjs.map +0 -1
- package/dist/lib/ns/Surface.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk-plugin-manager.mjs","names":[],"sources":["../../src/core/plugin-manager/activation-graph.ts","../../src/core/plugin-manager/idle.ts","../../src/core/plugin-manager/manager-types.ts","../../src/core/plugin-manager/module-loader.ts","../../src/core/plugin-manager/activation-scheduler.ts","../../src/core/plugin-manager/manager-state.ts","../../src/core/plugin-manager/plugin-catalog.ts","../../src/core/plugin-manager/plugin-manager.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Option from 'effect/Option';\n\nimport * as GraphEdge from '@dxos/graph/GraphEdge';\nimport * as GraphModel from '@dxos/graph/GraphModel';\nimport * as GraphNode from '@dxos/graph/GraphNode';\n\nimport type * as Capability from '../capability.ts';\nimport type * as Plugin from '../plugin.ts';\n\n//\n// Pure ordering logic for the activation scheduler, built on the shared `@dxos/graph` model.\n// Everything here is side-effect free and operates on explicit inputs so the scheduler's\n// decisions can be read — and tested — independently of manager state.\n//\n// This module's vocabulary (kept out of the rest of the manager):\n//\n// - A ROUND is one graph: nodes carry the modules being considered for activation, edges point\n// provider -> consumer and carry the capability identifier that induced them.\n// - Edge KIND distinguishes ordering strength:\n// - `hard`: an unsatisfied singleton require; the consumer must not run before the provider.\n// - `soft`: a multi require; ordering is best-effort so same-round contributions are visible\n// to consumers that read the collection once at startup (multi requires never block).\n// - A WAVE is a batch of modules with no ordering edges among them: waves run one after\n// another, and the modules within a wave run concurrently.\n//\n\nexport type EdgeKind = 'hard' | 'soft';\n\nexport type ActivationNode = GraphNode.Of<Plugin.PluginModule>;\nexport type ActivationEdge = GraphEdge.Of<{ capability: string }>;\nexport type ActivationGraphModel = GraphModel.GraphModel<ActivationNode, ActivationEdge>;\n\nexport type CycleEntry = { module: string; capability: string };\n\nconst makeModel = (modules: readonly Plugin.PluginModule[]): ActivationGraphModel => {\n const model = new GraphModel.GraphModel<ActivationNode, ActivationEdge>();\n modules.forEach((module) => model.addNode({ id: module.id, data: module }));\n return model;\n};\n\n/** Parallel edges (same pair, different capability) need distinct ids. */\nconst edgeId = (kind: EdgeKind, source: string, target: string, capability: string): string =>\n `${kind}|${source}|${capability}|${target}`;\n\nconst addEdge = (\n model: ActivationGraphModel,\n kind: EdgeKind,\n source: string,\n target: string,\n capability: string,\n): void => {\n model.addEdge({ id: edgeId(kind, source, target, capability), type: kind, source, target, data: { capability } });\n};\n\nexport type SelectRunnableInputs = {\n candidates: readonly Plugin.PluginModule[];\n /** Module ids excluded up front (e.g. duplicate singleton providers). */\n excluded: ReadonlySet<string>;\n /** Whether a singleton capability already has a contribution. */\n isSatisfied: (capability: Capability.AnyTag) => boolean;\n /** This round's singleton provider for a capability identifier, if any. */\n providerOf: (identifier: string) => string | undefined;\n /** Already-active module ids (an active provider resolves via the bounded waitFor bridge). */\n activeIds: readonly string[];\n /** Whether ANY registered module (active or not, fired or not) provides this capability. */\n anyRegisteredProvider: (identifier: string) => boolean;\n};\n\nexport type SelectRunnableResult = {\n runnable: Plugin.PluginModule[];\n /** Requires with no possible provider at all — a configuration error for the caller to report. */\n missing: Array<{ module: Plugin.PluginModule; capability: string }>;\n /** Modules left out of this round (including the `missing` ones), with the require that made\n * them wait — a later round reconsiders them once the provider becomes available. */\n waiting: Array<{ module: Plugin.PluginModule; capability: string }>;\n};\n\n/**\n * Selects the candidates that can run this round: a module is runnable when every unsatisfied\n * singleton require is provided by another runnable candidate or an already-active module.\n * Everything else waits for a later round (e.g. providers gated on an event that has not fired\n * yet). Multi requires never block. Requires with no possible provider at all are returned in\n * `missing`.\n *\n * Removing one module can strand its dependents, so removals propagate: dropping a provider\n * re-checks exactly the modules that relied on it within the round, until the selection is\n * stable.\n */\nexport const selectRunnableModules = ({\n candidates,\n excluded,\n isSatisfied,\n providerOf,\n activeIds,\n anyRegisteredProvider,\n}: SelectRunnableInputs): SelectRunnableResult => {\n const selected = new Map(\n candidates.filter((module) => !excluded.has(module.id)).map((module) => [module.id, module]),\n );\n const missing: SelectRunnableResult['missing'] = [];\n const waiting: SelectRunnableResult['waiting'] = [];\n\n // In-round reliance edges: provider id -> the modules (and requires) that count on it. Only\n // these need re-checking when a provider drops out.\n const consumersOf = new Map<string, Array<{ module: Plugin.PluginModule; capability: string }>>();\n const removalQueue: string[] = [];\n const remove = (module: Plugin.PluginModule, capability: string): void => {\n if (!selected.delete(module.id)) {\n return;\n }\n waiting.push({ module, capability });\n removalQueue.push(module.id);\n };\n\n // First pass: drop modules whose provider is outside the round and not active; record\n // in-round reliance edges for everything else.\n for (const module of [...selected.values()]) {\n for (const capability of module.activation.requires) {\n if (capability.arity === 'multi' || isSatisfied(capability)) {\n continue;\n }\n const provider = providerOf(capability.identifier);\n if (provider !== undefined && selected.has(provider)) {\n const consumers = consumersOf.get(provider) ?? [];\n consumers.push({ module, capability: capability.identifier });\n consumersOf.set(provider, consumers);\n continue;\n }\n if (provider !== undefined && activeIds.includes(provider)) {\n // Active provider whose capability was conditionally skipped: the consumer resolves it\n // via the bounded waitFor bridge.\n continue;\n }\n if (provider === undefined && !anyRegisteredProvider(capability.identifier)) {\n missing.push({ module, capability: capability.identifier });\n }\n // A provider exists but is not in play (event not fired, module in a different chain,\n // plugin disabled): wait until a later round unlocks it.\n remove(module, capability.identifier);\n break;\n }\n }\n\n // Propagate: a removed provider strands the modules that relied on it, transitively.\n for (let next = removalQueue.shift(); next !== undefined; next = removalQueue.shift()) {\n for (const consumer of consumersOf.get(next) ?? []) {\n remove(consumer.module, consumer.capability);\n }\n }\n\n return { runnable: [...selected.values()], missing, waiting };\n};\n\n/**\n * Builds a round's ordering graph. Hard edges gate a consumer on its unsatisfied singleton\n * providers within the round; soft edges order a consumer after the round's multi providers.\n */\nexport const buildRoundGraph = (\n modules: readonly Plugin.PluginModule[],\n {\n isSatisfied,\n providerOf,\n }: {\n isSatisfied: (capability: Capability.AnyTag) => boolean;\n providerOf: (identifier: string) => string | undefined;\n },\n): ActivationGraphModel => {\n const model = makeModel(modules);\n const multiProviders = new Map<string, string[]>();\n for (const module of modules) {\n for (const capability of module.activation.provides) {\n if (capability.arity === 'multi') {\n const providers = multiProviders.get(capability.identifier) ?? [];\n providers.push(module.id);\n multiProviders.set(capability.identifier, providers);\n }\n }\n }\n for (const module of modules) {\n for (const capability of module.activation.requires) {\n if (capability.arity === 'multi') {\n for (const provider of multiProviders.get(capability.identifier) ?? []) {\n if (provider !== module.id) {\n addEdge(model, 'soft', provider, module.id, capability.identifier);\n }\n }\n continue;\n }\n if (isSatisfied(capability)) {\n continue;\n }\n const provider = providerOf(capability.identifier);\n if (provider !== undefined && model.findNode(provider) !== undefined) {\n addEdge(model, 'hard', provider, module.id, capability.identifier);\n }\n }\n }\n return model;\n};\n\n/**\n * Builds the singleton require -> provider graph across the given modules regardless of event\n * gating or satisfaction — used to surface capability cycles that span activation events (two\n * modules on different events requiring each other's provides would otherwise pend forever).\n */\nexport const buildSingletonGraph = (modules: readonly Plugin.PluginModule[]): ActivationGraphModel => {\n const model = makeModel(modules);\n const providersByCapability = new Map<string, string[]>();\n for (const module of modules) {\n for (const capability of module.activation.provides) {\n if (capability.arity !== 'single') {\n continue;\n }\n const providers = providersByCapability.get(capability.identifier) ?? [];\n providers.push(module.id);\n providersByCapability.set(capability.identifier, providers);\n }\n }\n for (const module of modules) {\n for (const capability of module.activation.requires) {\n if (capability.arity === 'multi') {\n continue;\n }\n for (const provider of providersByCapability.get(capability.identifier) ?? []) {\n if (provider !== module.id) {\n addEdge(model, 'hard', provider, module.id, capability.identifier);\n }\n }\n }\n }\n return model;\n};\n\nconst edgeOfKind =\n (kinds: readonly EdgeKind[]) =>\n (edge: ActivationEdge): boolean =>\n kinds.some((kind) => kind === edge.type);\n\n/**\n * Topological activation waves over the given edge kinds (modules in the same wave have no edges\n * among them and activate concurrently). Returns `undefined` when the restricted graph is cyclic.\n */\nexport const computeActivationWaves = (\n model: ActivationGraphModel,\n kinds: readonly EdgeKind[],\n): Plugin.PluginModule[][] | undefined =>\n Option.getOrUndefined(\n Option.map(model.topoLevels(edgeOfKind(kinds)), (levels) =>\n levels.map((level) => level.map((id) => model.getNode(id).data)),\n ),\n );\n\n/**\n * Finds one cycle in the graph (restricted to the given edge kinds) for diagnostics: each entry\n * is a module and the capability identifier on its outgoing edge within the cycle.\n */\nexport const findCyclePath = (model: ActivationGraphModel, kinds: readonly EdgeKind[]): CycleEntry[] =>\n model.findCycle(edgeOfKind(kinds)).map((step) => ({ module: step.node, capability: step.edge.data.capability }));\n\n/** Ids of the providers the module must not run before (its incoming hard edges). */\nexport const requiredProviderIds = (model: ActivationGraphModel, moduleId: string): string[] =>\n model.filterEdges({ target: moduleId, type: 'hard' }).map((edge) => edge.source);\n\n/** Whether the graph carries any soft (multi-capability) ordering edges. */\nexport const hasSoftEdges = (model: ActivationGraphModel): boolean => model.edges.some((edge) => edge.type === 'soft');\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\n/**\n * Backstop for the idle wait. An aggressive timeout fires mid-render and floods the main thread\n * ahead of first paint, which is the cost this wait exists to avoid; this only rescues a host\n * that never goes idle at all.\n */\nconst IDLE_TIMEOUT = 15_000;\n\n/**\n * Backstop for the paint wait, for hosts where frames never come — a backgrounded tab does not\n * run `requestAnimationFrame`, and the idle wave must not be lost to that.\n */\nconst PAINT_TIMEOUT = 2_000;\n\n/**\n * Completes after the shell has painted. Two frames: the first callback runs before paint, the\n * second after it. Without this the idle timeout below can expire mid-render-pipeline, flooding\n * the main thread ahead of first paint — precisely the cost the wait exists to avoid.\n */\nconst afterPaint: Effect.Effect<void> = Effect.suspend(() => {\n if (typeof requestAnimationFrame !== 'function') {\n return Effect.void;\n }\n return Effect.callback<void>((resume) => {\n let inner: number | undefined;\n const outer = requestAnimationFrame(() => {\n inner = requestAnimationFrame(() => resume(Effect.void));\n });\n return Effect.sync(() => {\n cancelAnimationFrame(outer);\n inner !== undefined && cancelAnimationFrame(inner);\n });\n }).pipe(\n Effect.timeout(PAINT_TIMEOUT),\n Effect.catch(() => Effect.void),\n );\n});\n\n/**\n * Whether the host has a paint the idle wave should yield to. False under node and workerd, where\n * {@link whenIdle} completes immediately — so forking the wave there buys nothing and only leaves\n * it unfinished when `start()` returns.\n */\nexport const hostYieldsToPaint = (): boolean => typeof requestIdleCallback === 'function';\n\n/**\n * Completes once the host is idle, so work scheduled behind it lands after the shell has painted\n * rather than competing with it.\n */\nexport const whenIdle: Effect.Effect<void> = Effect.suspend(() => {\n if (!hostYieldsToPaint()) {\n return Effect.void;\n }\n return afterPaint.pipe(\n Effect.andThen(\n Effect.callback<void>((resume) => {\n const handle = requestIdleCallback(() => resume(Effect.void), { timeout: IDLE_TIMEOUT });\n return Effect.sync(() => cancelIdleCallback(handle));\n }),\n ),\n );\n});\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Duration from 'effect/Duration';\n\nimport { BaseError } from '@dxos/errors';\n\n//\n// Types and errors shared between the plugin manager's collaborating units (module loader,\n// activation scheduler, catalog). Canonical public access stays on the `PluginManager`\n// namespace, which re-exports everything here.\n//\n\n/**\n * Tagged error for failures during the constructor-launched core/enabled\n * `enable()` chain. Surfaces via the manager's `activate` wait on\n * initialization so a caller blocked on initialization gets a typed\n * failure (with the original error preserved as `cause`) instead of an\n * untyped `Error`.\n */\nexport class PluginInitializationError extends BaseError.extend(\n 'PluginInitializationError',\n 'Plugin manager initialization failed',\n) {}\n\n/**\n * Tagged error raised when a plugin exceeds its configured load or activation\n * timeout. The plugin manager records the failure on the `failed` atom and\n * auto-disables the plugin so that one stuck remote does not stall app boot.\n * `context.id` is the plugin id, `context.phase` is `'load'` or `'activation'`.\n */\nexport class PluginTimeoutError extends BaseError.extend('PluginTimeoutError', 'Plugin operation timed out') {}\n\n/** Phase of the plugin lifecycle in which the failure was observed. */\nexport type PluginFailurePhase = 'load' | 'activation';\n\n/** Why the plugin entered a failed state. */\nexport type PluginFailureReason = 'timeout' | 'error';\n\n/**\n * Record of a plugin that failed to load or activate. Surfaced via the\n * manager's `failed` atom so registry / UI consumers can flag unhealthy\n * plugins (e.g. a remote host that has gone offline) rather than leaving the\n * app in a half-broken state.\n */\nexport type PluginFailure = {\n readonly id: string;\n readonly phase: PluginFailurePhase;\n readonly reason: PluginFailureReason;\n readonly error: Error;\n /** `Date.now()` when the failure was recorded. */\n readonly timestamp: number;\n};\n\n/** Default deadline for resolving a lazy plugin's dynamic import. */\nexport const DEFAULT_LOAD_TIMEOUT = Duration.seconds(30);\n\n/** Default deadline for a single module's `activate()` body. */\nexport const DEFAULT_ACTIVATION_TIMEOUT = Duration.seconds(30);\n\nexport type ActivationMessage = {\n event: string;\n state: 'activating' | 'activated' | 'error';\n /** Module ID when the message pertains to a specific module activation. */\n module?: string;\n error?: Error;\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Cause from 'effect/Cause';\nimport * as Context from 'effect/Context';\nimport * as Deferred from 'effect/Deferred';\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport * as Exit from 'effect/Exit';\nimport * as Fiber from 'effect/Fiber';\nimport * as PubSub from 'effect/PubSub';\nimport * as Scope from 'effect/Scope';\nimport * as Semaphore from 'effect/Semaphore';\n\nimport * as Performance from '@dxos/effect/Performance';\nimport { log } from '@dxos/log';\n\nimport { Capabilities } from '../../common/index.ts';\nimport * as ActivationEvent from '../activation-event.ts';\nimport * as CapabilityManager from '../capability-manager.ts';\nimport * as Capability from '../capability.ts';\nimport { CapabilityNotFoundError, ProvidesMismatchError } from '../errors.ts';\nimport * as Plugin from '../plugin.ts';\nimport { type ManagerState } from './manager-state.ts';\nimport { type PluginFailurePhase, PluginTimeoutError } from './manager-types.ts';\n\n/**\n * Yields the host's event loop before a module body runs. Effect's scheduler drains its run queue\n * within one macrotask, so a wave of cache-hit module activations otherwise fuses into one\n * multi-second long task that blocks paint and input (measured: 2 s max task, ~4.7 s TBT at boot).\n *\n * Prefers `scheduler.yield()` (input-priority aware); falls back to a MessageChannel hop, which is\n * a real macrotask boundary without `setTimeout`'s clamp. The fallback is `Effect.callback` rather\n * than a hand-built promise so an interrupt closes the ports instead of leaking a channel per\n * yield — this runs between every module activation, so a few hundred times at boot.\n */\nexport const yieldToHost: Effect.Effect<void> = Effect.suspend(() => {\n const scheduler = globalThis.scheduler;\n // Feature-tested, not just presence-checked: Chromium shipped `postTask` before `yield`.\n if (typeof scheduler?.yield === 'function') {\n return Effect.promise(() => scheduler.yield());\n }\n if (typeof MessageChannel === 'undefined') {\n return Effect.void;\n }\n return Effect.callback<void>((resume) => {\n const { port1, port2 } = new MessageChannel();\n const close = () => {\n port1.close();\n port2.close();\n };\n port1.onmessage = () => {\n close();\n resume(Effect.void);\n };\n port2.postMessage(null);\n return Effect.sync(close);\n });\n});\n\n/**\n * Owns the per-module load pipeline and its bookkeeping: memoized loads (id -> Deferred),\n * per-module semaphores, activation scopes, and the contributed-capability index. Every\n * activation path (dependency round, event wave, on-demand pull) converges on {@link load};\n * concurrent paths await the same deferred, and {@link contribute} is idempotent per module.\n *\n * Module bodies run with the manager as the ambient `Plugin.Service`; the loader carries that\n * as a typed requirement (`R = Plugin.Service`) rather than holding a manager reference — the\n * manager satisfies it once at its public boundary.\n */\nexport class ModuleLoader {\n readonly #memo = new Map<Plugin.PluginModule['id'], Deferred.Deferred<Capability.Any[], Error>>();\n readonly #semaphores = new Map<Plugin.PluginModule['id'], Semaphore.Semaphore>();\n readonly #scopes = new Map<string, Scope.Closeable>();\n readonly #contributed = new Map<string, Capability.Any[]>();\n readonly #state: ManagerState;\n readonly #capabilities: CapabilityManager.CapabilityManager;\n readonly #activationTimeout: Duration.Input;\n readonly #yieldToHost: Effect.Effect<void>;\n\n constructor(\n state: ManagerState,\n capabilities: CapabilityManager.CapabilityManager,\n activationTimeout: Duration.Input,\n /** Injected so the host yield is explicit at the composition root, and swappable in tests. */\n yieldToHostEffect: Effect.Effect<void> = yieldToHost,\n ) {\n this.#state = state;\n this.#capabilities = capabilities;\n this.#activationTimeout = activationTimeout;\n this.#yieldToHost = yieldToHostEffect;\n }\n\n /** Whether the module's load has started (memoized) — settled or not. */\n isLoading(moduleId: string): boolean {\n return this.#memo.has(moduleId);\n }\n\n /** Whether the module's capabilities have been ingested into the registry. */\n hasContributed(moduleId: string): boolean {\n return this.#contributed.has(moduleId);\n }\n\n /**\n * Loads a module exactly once. `parentEvent` is the activation event that first triggered\n * the load — included in `activating`/`activated` messages so subscribers (e.g. the boot\n * loader's status listener) can associate a module with its triggering event; later paths\n * await the cached deferred without re-publishing.\n */\n load = (module: Plugin.PluginModule, parentEvent: string): Effect.Effect<Capability.Any[], Error, Plugin.Service> =>\n Effect.gen({ self: this }, function* () {\n const semaphore = this.#semaphore(module.id);\n\n // Atomically check-and-set under per-module semaphore to prevent race conditions.\n const deferredToAwait = yield* Effect.gen({ self: this }, function* () {\n const existing = this.#memo.get(module.id);\n if (existing) {\n return existing;\n }\n\n // First caller - create deferred, store it, and start loading in background.\n const deferred = yield* Deferred.make<Capability.Any[], Error>();\n this.#memo.set(module.id, deferred);\n\n const scope = yield* Scope.make();\n\n // Fork the load to run in background, completing the deferred when done.\n const fiber = yield* Effect.forkDetach(\n this.#runActivation(module, parentEvent, scope).pipe(\n Effect.tap((result) => Deferred.succeed(deferred, result)),\n Effect.catchCause((cause) =>\n this.#recordActivationFailure(module, parentEvent, cause).pipe(\n Effect.flatMap((error) => Deferred.fail(deferred, error)),\n ),\n ),\n ),\n );\n yield* this.#state.fibers.trackForked(fiber);\n\n return deferred;\n }).pipe(semaphore.withPermits(1));\n\n // Wait for result outside the semaphore so multiple waiters can proceed concurrently.\n return yield* Deferred.await(deferredToAwait);\n });\n\n /**\n * Awaits an in-flight load without starting one. A module with no memoized load — never\n * started, or deactivated mid-wait (deactivation clears the memo) — counts as settled;\n * joining via {@link load} instead would RESTART such a module (e.g. re-activating a\n * timed-out module of an auto-disabled plugin).\n */\n awaitSettled(moduleId: string): Effect.Effect<void> {\n const deferred = this.#memo.get(moduleId);\n return deferred ? Deferred.await(deferred).pipe(Effect.ignore, Effect.asVoid) : Effect.void;\n }\n\n /**\n * Awaits every in-flight load until none remain, to a fixpoint (a settling load can start\n * new ones). Returns whether anything was pending. Used by streaming startup: forked\n * enable-chain passes load modules outside `start()`'s own passes, and the ready signal\n * must not publish while any of them are mid-load.\n */\n awaitAllSettled(): Effect.Effect<boolean> {\n return Effect.gen({ self: this }, function* () {\n let waited = false;\n for (;;) {\n const pending: Deferred.Deferred<any, Error>[] = [];\n for (const deferred of this.#memo.values()) {\n if (!(yield* Deferred.isDone(deferred))) {\n pending.push(deferred);\n }\n }\n if (pending.length === 0) {\n return waited;\n }\n waited = true;\n yield* Effect.all(\n pending.map((deferred) => Deferred.await(deferred).pipe(Effect.ignore)),\n { concurrency: 'unbounded', discard: true },\n );\n }\n });\n }\n\n /**\n * Ingests a module's expanded capabilities into the registry and marks it active. A module\n * may be reached by more than one activation path; the load is memoized, so contribution is\n * memoized too.\n */\n contribute(module: Plugin.PluginModule, capabilities: Capability.Any[]): Effect.Effect<void, Error> {\n return Effect.gen({ self: this }, function* () {\n if (this.#contributed.has(module.id)) {\n return;\n }\n capabilities.forEach((capability) => {\n this.#capabilities.contribute({ module: module.id, ...capability });\n });\n this.#state.markActive(module.id);\n this.#contributed.set(module.id, capabilities);\n });\n }\n\n /** Removes the module's contributions and closes its scope (running its finalizers). */\n deactivate(module: Plugin.PluginModule): Effect.Effect<boolean, Error> {\n return Effect.gen({ self: this }, function* () {\n const id = module.id;\n log('deactivating', { id });\n this.#memo.delete(id);\n\n const capabilities = this.#contributed.get(id);\n if (capabilities) {\n for (const capability of capabilities) {\n this.#capabilities.remove(capability.interface, capability.implementation);\n }\n this.#contributed.delete(id);\n }\n\n const scope = this.#scopes.get(id);\n if (scope) {\n yield* Scope.close(scope, Exit.void);\n this.#scopes.delete(id);\n }\n\n this.#state.markInactive(id);\n\n log('deactivated', { id });\n return true;\n });\n }\n\n /** Shutdown: drop all memoized loads and close every activation scope. */\n clear(): Effect.Effect<void> {\n return Effect.gen({ self: this }, function* () {\n this.#memo.clear();\n for (const scope of this.#scopes.values()) {\n yield* Scope.close(scope, Exit.void);\n }\n this.#scopes.clear();\n });\n }\n\n /**\n * Builds the Effect context for a module's declared requires: singleton capabilities\n * resolve to their implementation (waiting — bounded by the activation timeout — for\n * concurrent providers), multi capabilities to their live contributions view.\n */\n #resolveRequires(module: Plugin.PluginModule): Effect.Effect<Context.Context<never>, Error> {\n return Effect.gen({ self: this }, function* () {\n const spec = module.activation;\n if (spec.requires.length === 0) {\n return Context.empty();\n }\n\n const services = new Map<string, unknown>();\n for (const capability of spec.requires) {\n if (capability.arity === 'multi') {\n services.set(capability.key, this.#capabilities.contributions(capability));\n continue;\n }\n const [existing] = this.#capabilities.getAll(capability);\n const implementation =\n existing !== undefined\n ? existing\n : yield* this.#capabilities.waitFor(capability).pipe(\n Effect.timeoutOrElse({\n duration: this.#activationTimeout,\n orElse: () =>\n Effect.fail(\n new CapabilityNotFoundError({\n identifier: capability.identifier,\n registered: this.#capabilities.listRegisteredIdentifiers(),\n }),\n ),\n }),\n );\n services.set(capability.key, implementation);\n }\n return Context.makeUnsafe(services);\n });\n }\n\n #semaphore(moduleId: Plugin.PluginModule['id']): Semaphore.Semaphore {\n let semaphore = this.#semaphores.get(moduleId);\n if (!semaphore) {\n semaphore = Semaphore.makeUnsafe(1);\n this.#semaphores.set(moduleId, semaphore);\n }\n return semaphore;\n }\n\n /**\n * The activation pipeline for one module: settle in-flight multi providers, build the\n * requires context, run the module's activate under the activation timeout, validate the\n * result against the declared provides, and expand it to registry entries. Instrumented\n * with a span, a slow-activation warning, and a devtools track entry.\n */\n /**\n * A surface rendering is the demand signal for its own plugin: the feature is now in use, so\n * the contributions other plugins target at it (editor extensions, variants, integrations)\n * should load. Firing here rather than from a blanket post-startup sweep is what keeps an\n * unvisited feature's code off the wire entirely.\n *\n * Forked, not awaited: contributions are read through the reactive capability atoms, so a\n * consumer re-renders when they land, and awaiting here would deadlock a surface behind\n * modules that may themselves resolve surfaces. Re-firing an already-fired event is a no-op\n * in the manager, so no dedup is needed at this call site.\n */\n #fireOwnStartForSurface(\n capabilities: readonly Capability.Any[],\n pluginId: string | undefined,\n ): Effect.Effect<void, never, Plugin.Service> {\n if (!pluginId || !capabilities.some((capability) => capability.interface === Capabilities.ReactSurface)) {\n return Effect.void;\n }\n return Effect.gen(function* () {\n const manager = yield* Plugin.Service;\n yield* manager.activate(ActivationEvent.pluginStart(pluginId)).pipe(\n Effect.catch((error) =>\n Effect.sync(() => log.warn('plugin start event failed', { pluginId, error: String(error) })),\n ),\n Effect.forkDetach,\n );\n });\n }\n\n #runActivation(\n module: Plugin.PluginModule,\n parentEvent: string,\n scope: Scope.Closeable,\n ): Effect.Effect<Capability.Any[], Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n log('loading module', { module: module.id, parentEvent });\n performance.mark(`module:${module.id}:start`);\n // Separate mark: the profiler reads `module:` as a measure, and a measure drops mark detail.\n performance.mark(`module-cause:${module.id}`, { detail: { event: parentEvent } });\n yield* PubSub.publish(this.#state.activation, { event: parentEvent, state: 'activating', module: module.id });\n const pluginId = this.#state.pluginIdOfModule(module.id);\n yield* this.#awaitProvidersInFlight(module);\n const requiresContext = yield* this.#resolveRequires(module);\n // One host yield per module keeps activation tasks under the long-task threshold;\n // counted as wait, not run, by the split below.\n yield* this.#yieldToHost;\n // Wait/run split: `module:<id>` spans the whole pipeline, so scheduling delay (in-flight\n // providers + requires resolution) is indistinguishable from work without these sub-measures.\n performance.mark(`module:${module.id}:run`);\n performance.measure(`module-wait:${module.id}`, `module:${module.id}:start`, `module:${module.id}:run`);\n const [duration, capabilities] = yield* module.activate().pipe(\n Effect.provide(requiresContext),\n Effect.provideService(Capability.Service, this.#capabilities),\n Effect.provideService(Capability.CurrentModuleId, module.id),\n Effect.updateService(Capability.ActivatingModuleIds, (ids) => new Set([...ids, module.id])),\n\n Scope.provide(scope),\n // Cap activation so a single misbehaving module can't hold the\n // event chain open. On timeout the failure is recorded against\n // the plugin and surfaced as `PluginTimeoutError`.\n Effect.timeoutOrElse({\n duration: this.#activationTimeout,\n orElse: () =>\n Effect.fail(\n new PluginTimeoutError({\n context: { id: pluginId ?? module.id, module: module.id, phase: 'activation' as PluginFailurePhase },\n }),\n ),\n }),\n Effect.timed,\n );\n const normalized = CapabilityManager.normalizeActivateResult(capabilities);\n yield* this.#validateProvides(module, normalized);\n\n this.#scopes.set(module.id, scope);\n const elapsed = Duration.toMillis(duration);\n performance.mark(`module:${module.id}:end`);\n performance.measure(`module:${module.id}`, `module:${module.id}:start`, `module:${module.id}:end`);\n performance.measure(`module-run:${module.id}`, `module:${module.id}:run`, `module:${module.id}:end`);\n yield* PubSub.publish(this.#state.activation, { event: parentEvent, state: 'activated', module: module.id });\n\n log('loaded module', {\n module: module.id,\n parentEvent,\n elapsed,\n failed: false,\n });\n const expanded = CapabilityManager.expandContributions(normalized);\n yield* this.#fireOwnStartForSurface(expanded, pluginId);\n return expanded;\n }).pipe(\n Effect.tapCause(() => Scope.close(scope, Exit.void)),\n Effect.withSpan('ModuleLoader.load', { attributes: { 'dx.module.id': module.id } }),\n together(\n Effect.sleep(Duration.seconds(10)).pipe(\n Effect.andThen(\n Effect.sync(() => log.warn(`module is taking a long time to activate`, { module: module.id })),\n ),\n ),\n ),\n Performance.addTrackEntry({\n name: module.id,\n devtools: {\n dataType: 'track-entry',\n track: 'Module Activation',\n trackGroup: 'Composer',\n color: 'primary',\n },\n }),\n );\n }\n\n /**\n * Waits for providers of this module's multi requires whose load has already started in a\n * concurrent round, and ingests their contributions before this module's activate runs.\n * Round-internal ordering only covers providers inside one round — a provider mid-load in a\n * concurrent round (the startup dependency pass while an event-triggered pull runs) is\n * dropped from the pulled round's candidates entirely, so without this a consumer that reads\n * the collection once at startup (e.g. the process manager's `Capabilities.LayerSpec`\n * collection) races the provider's contribution. Bounded by the activation timeout so a\n * multi-capability require cycle (legal — multi requires never block) degrades to the old\n * behaviour instead of deadlocking.\n */\n #awaitProvidersInFlight(module: Plugin.PluginModule): Effect.Effect<void> {\n return Effect.gen({ self: this }, function* () {\n const multiIdentifiers = new Set(\n module.activation.requires\n .filter((capability) => capability.arity === 'multi')\n .map((capability) => capability.identifier),\n );\n if (multiIdentifiers.size === 0) {\n return;\n }\n const inflight = this.#state\n .getModules()\n .filter(\n (provider) =>\n provider.id !== module.id &&\n !this.#contributed.has(provider.id) &&\n this.#memo.has(provider.id) &&\n provider.activation.provides.some((provided) => multiIdentifiers.has(provided.identifier)),\n );\n if (inflight.length === 0) {\n return;\n }\n log('waiting for in-flight multi providers', { module: module.id, providers: inflight.map((m) => m.id) });\n yield* Effect.forEach(\n inflight,\n (provider) =>\n Effect.gen({ self: this }, function* () {\n const deferred = this.#memo.get(provider.id);\n if (deferred === undefined) {\n return;\n }\n const capabilities = yield* Deferred.await(deferred);\n // Idempotent (memoized per module): the provider's own round contributes the same\n // entries as a no-op when it gets there.\n yield* this.contribute(provider, capabilities);\n }).pipe(\n // A provider that failed to activate resolves to nothing here; its failure is\n // recorded and surfaced by its own load fiber.\n Effect.ignore,\n ),\n { concurrency: 'unbounded', discard: true },\n ).pipe(\n Effect.timeout(this.#activationTimeout),\n Effect.catch(() =>\n Effect.sync(() =>\n log.warn('proceeding without in-flight multi providers', {\n module: module.id,\n providers: inflight.map((m) => m.id),\n }),\n ),\n ),\n );\n });\n }\n\n /**\n * Runtime provides validation (the authoritative check; the type-level one is best-effort).\n * Validated on the raw items so an empty provideAll still counts as covering its capability.\n * Undeclared contributions fail (they would bypass dependency ordering); missing ones only\n * warn — a provider may legitimately decide at runtime not to contribute (consumers then\n * surface a bounded CapabilityNotFoundError instead of silently proceeding).\n */\n #validateProvides(\n module: Plugin.PluginModule,\n normalized: Array<Capability.Any | Capability.AnyContribution>,\n ): Effect.Effect<void, ProvidesMismatchError> {\n const declared = new Set(module.activation.provides.map((capability) => capability.identifier));\n const returned = new Set(\n normalized.map((item) =>\n CapabilityManager.isContribution(item) ? item.capability.identifier : item.interface.identifier,\n ),\n );\n const missing = [...declared].filter((identifier) => !returned.has(identifier));\n const undeclared = [...returned].filter((identifier) => !declared.has(identifier));\n if (undeclared.length > 0) {\n return Effect.fail(new ProvidesMismatchError({ module: module.id, missing, undeclared }));\n }\n if (missing.length > 0) {\n log.warn('module did not contribute all declared capabilities', { module: module.id, missing });\n }\n return Effect.void;\n }\n\n /**\n * Failure bookkeeping for a module whose activation failed or died: logs the cause, records\n * the failure against the owning plugin, and publishes an error activation message —\n * symmetric with the 'activating'/'activated' messages so boot UIs observe a failed module,\n * not just a silent stall (the manager's auto-disable policy also watches these messages).\n * Returns the normalized error for the caller to fail the memoized deferred with.\n */\n #recordActivationFailure(\n module: Plugin.PluginModule,\n parentEvent: string,\n cause: Cause.Cause<Error>,\n ): Effect.Effect<Error> {\n return Effect.gen({ self: this }, function* () {\n const error = Cause.squash(cause);\n const errorMessage = error instanceof Error ? error.message : String(error);\n const missingCapability = error instanceof CapabilityNotFoundError ? error.context.identifier : undefined;\n log.error('module failed to activate', {\n module: module.id,\n parentEvent,\n missingCapability,\n registeredCapabilities: this.#capabilities.listRegisteredIdentifiers(),\n error: errorMessage,\n stack: error instanceof Error ? error.stack : undefined,\n isDefect: !Cause.hasFails(cause),\n });\n const normalizedError = error instanceof Error ? error : new Error(String(error));\n const pluginId = this.#state.pluginIdOfModule(module.id);\n if (pluginId !== undefined) {\n this.#state.recordFailure(pluginId, 'activation', normalizedError);\n }\n yield* PubSub.publish(this.#state.activation, {\n event: parentEvent,\n state: 'error',\n module: module.id,\n error: normalizedError,\n });\n return normalizedError;\n });\n }\n}\n\n/**\n * Runs an effect concurrently with another effect.\n * If the first effect completes, the second effect is interrupted.\n */\n// TODO(dmaretskyi): Effect.race > Effect.asVoid\nexport const together =\n <R1>(togetherEffect: Effect.Effect<void, never, R1>) =>\n <A, E, R2>(effect: Effect.Effect<A, E, R2>): Effect.Effect<A, E, R1 | R2> =>\n Effect.gen(function* () {\n const togetherFiber = yield* Effect.forkChild(togetherEffect);\n const result = yield* effect;\n yield* Fiber.interrupt(togetherFiber);\n return result;\n });\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Array from 'effect/Array';\nimport * as Deferred from 'effect/Deferred';\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport * as Fiber from 'effect/Fiber';\nimport * as PubSub from 'effect/PubSub';\nimport * as Ref from 'effect/Ref';\n\nimport * as Performance from '@dxos/effect/Performance';\nimport { log } from '@dxos/log';\n\nimport { ActivationEvents } from '../../common/index.ts';\nimport * as ActivationEvent from '../activation-event.ts';\nimport type * as CapabilityManager from '../capability-manager.ts';\nimport * as Capability from '../capability.ts';\nimport { DependencyCycleError, DuplicateProviderError, MissingProviderError } from '../errors.ts';\nimport type * as Plugin from '../plugin.ts';\nimport * as ActivationGraph from './activation-graph.ts';\nimport { hostYieldsToPaint, whenIdle } from './idle.ts';\nimport { type ManagerState } from './manager-state.ts';\nimport { type ModuleLoader, together } from './module-loader.ts';\n\n/**\n * The activation lifecycle engine: owns {@link start} / {@link activate} /\n * {@link deactivatePlugin} / {@link resetEvent} and decides when each module's `activate`\n * runs. Every module names a wave via `activatesOn` (defaulting to Idle), and two paths\n * drive them:\n *\n * - {@link runDependencyPass}: rounds over the capability graph (vocabulary and ordering logic\n * in `activation-graph.ts`), repeated until nothing new is runnable — each round's\n * contributions (or a concurrent event wave's) can unlock modules that were waiting. A fired\n * event stays fired, so a module whose wave has passed stays eligible in later rounds.\n * - Event dispatch: a module parks until its `activatesOn` fires, then runs as an event wave;\n * providers of its requires are pulled on demand first, scoped to waves that have fired.\n *\n * Structural problems (cycles, duplicate or missing singleton providers) put the offending\n * plugins into an error state and exclude their modules; everything independent proceeds.\n */\nexport class ActivationScheduler {\n /** Per-wave activation concurrency cap — see the note at the `#executeWaves` call site. */\n static readonly WAVE_CONCURRENCY = 16;\n\n /** Events currently mid-activation (an `allOf` gate counts them as already fired). */\n readonly #activatingEvents = Effect.runSync(Ref.make<string[]>([]));\n /** Modules currently claimed by an event wave (excluded from re-matching). */\n readonly #activatingModules = Effect.runSync(Ref.make<string[]>([]));\n readonly #state: ManagerState;\n readonly #capabilities: CapabilityManager.CapabilityManager;\n readonly #loader: ModuleLoader;\n readonly #whenIdle: Effect.Effect<void>;\n /** False when the host supplied its own idle gate, which makes its completion the host's business. */\n readonly #ownsIdleGate: boolean;\n\n constructor(\n state: ManagerState,\n capabilities: CapabilityManager.CapabilityManager,\n loader: ModuleLoader,\n whenIdleEffect: Effect.Effect<void> = whenIdle,\n ) {\n this.#state = state;\n this.#capabilities = capabilities;\n this.#loader = loader;\n this.#whenIdle = whenIdleEffect;\n this.#ownsIdleGate = whenIdleEffect === whenIdle;\n }\n\n /**\n * Runs startup: the capability-dependency resolution pass for dependency-mode modules,\n * concurrently with the event dispatch for any module explicitly targeting the Startup\n * event. The event-level Startup `activated` message publishes only after both passes\n * complete. Idempotent — subsequent calls activate whatever registered since.\n *\n * Streaming: activation does NOT wait for the constructor's full enable chain. `started`\n * flips immediately and a pass runs over whatever has registered; each still-in-flight\n * `enable()` runs its own incremental pass on completion (see `PluginCatalog`), so early\n * definitions (e.g. the client) begin activating while later ones are still importing.\n * The ready signal below still waits for the complete set.\n */\n start(): Effect.Effect<boolean, Error, Plugin.Service> {\n return Effect.withFiber<boolean, Error, Plugin.Service>((fiber) =>\n this.#start(fiber).pipe(Effect.ensuring(this.#state.fibers.untrack(fiber))),\n );\n }\n\n #start(fiber: Fiber.Fiber<unknown, unknown>): Effect.Effect<boolean, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n if (yield* this.#state.isShuttingDown()) {\n log('skipping start during shutdown');\n return false;\n }\n\n // Tracked for the whole call: the startup wave runs in the early streaming pass as well as\n // the complete one, so shutdown must be able to interrupt either.\n yield* this.#state.fibers.track(fiber);\n\n // With streaming, activation work is spread across this call's passes AND the enable\n // chain's incremental passes — the return value reports whether anything activated.\n const activeBefore = this.#state.getActiveIds().length;\n\n yield* Ref.set(this.#state.started, true);\n // Early pass over already-registered modules. Failures here are re-evaluated by the\n // complete pass below, so they log rather than fail start.\n yield* this.runDependencyPass().pipe(\n Effect.catch((error) => Effect.sync(() => log.warn('streaming startup pass failed', { error: String(error) }))),\n );\n\n // The complete pass and the Startup event wait for the enable chain: the ready signal\n // must reflect the full registry (see the note in `activate`).\n yield* Deferred.await(this.#state.initialized);\n\n const key = ActivationEvent.eventKey(ActivationEvent.Startup);\n\n // A capability cycle spanning event boundaries would leave both chains pending\n // forever. Surface the lock (error state on the involved plugins) and continue —\n // the cycle members simply never activate; everything else proceeds.\n yield* this.#reportGlobalCycle();\n\n // The startup wave and the dependency pass are the same thing: the pass already admits every\n // module whose wave is firing, so dispatching the event alongside it would claim the same\n // modules twice. An undeclared `activatesOn` normalizes to Idle, so what runs here is the\n // modules that asked for Startup plus the baseline providers they pull.\n this.#state.clearPendingReset(key);\n // Graph-level failures (missing provider, duplicate provider, cycle) fail the start call;\n // publish them so boot UIs surface the root cause instead of a silent hang behind their\n // own watchdog.\n const ranAny = yield* this.runDependencyPass().pipe(\n Effect.tapError((error) =>\n Effect.gen({ self: this }, function* () {\n log.error('dependency activation failed', { error: String(error) });\n yield* PubSub.publish(this.#state.activation, { event: key, state: 'error', error });\n }),\n ),\n );\n\n // The enable chain forked its incremental passes, so loads may still be in flight outside\n // the passes above. Ready must reflect a settled world — alternate between awaiting\n // in-flight loads and mop-up passes until neither does any work.\n for (;;) {\n const settledAny = yield* this.#loader.awaitAllSettled();\n const ranAny = yield* this.runDependencyPass().pipe(\n Effect.catch((error) =>\n Effect.sync(() => {\n log.warn('startup mop-up pass failed', { error: String(error) });\n return false;\n }),\n ),\n );\n if (!settledAny && !ranAny) {\n break;\n }\n }\n\n // The event-level Startup `activated` message (no `module` field) is the app-ready\n // signal (see useApp); it must not publish before the startup wave finishes.\n this.#state.markEventFired(key);\n yield* PubSub.publish(this.#state.activation, { event: key, state: 'activated' });\n // Releases the events that were dispatched while this wave ran (see `activate`).\n yield* Deferred.succeed(this.#state.startupComplete, undefined);\n\n // The idle wave belongs to the manager rather than to each host: it is an app-framework\n // event, and a host that owned the wait would re-implement it (and could forget to).\n // In a browser it is forked so `start` returns at ready and the contributions gated on it\n // land after first paint instead of competing with it; tracked, because the wave sits behind\n // a wait of up to 15s and an untracked daemon outlives `shutdown()` — dispatching Idle into a\n // manager that has already reset re-activates modules after teardown. A headless host has no\n // paint to lose the race to and completes `whenIdle` immediately, so forking there would only\n // let `start()` return before the wave ran.\n // Inlining is only safe for the gate this module owns, whose headless branch completes\n // immediately. A host that passes its own gate decides when (or whether) idle arrives —\n // `Effect.never` is a legitimate \"do not run the idle wave\" — and awaiting that inline would\n // hang `start()` rather than defer a wave.\n if (hostYieldsToPaint() || !this.#ownsIdleGate) {\n yield* this.#state.fibers.trackForked(yield* this.#activateWhenIdle().pipe(Effect.forkDetach));\n } else {\n yield* this.#activateWhenIdle();\n }\n\n return this.#state.getActiveIds().length > activeBefore || ranAny;\n });\n }\n\n /**\n * Fires the idle wave once the host goes idle. Failures are logged rather than propagated:\n * the wave carries registration contributions, so one broken plugin must not take down an\n * app that is already interactive.\n */\n #activateWhenIdle(): Effect.Effect<void, never, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n yield* this.#whenIdle;\n yield* this.activate(ActivationEvents.Idle).pipe(\n Effect.catch((error) => Effect.sync(() => log.warn('idle activation failed', { error: String(error) }))),\n );\n });\n }\n\n /**\n * Runs an activation event end to end. Startup delegates to {@link start}; anything else\n * waits for the manager's initialization, then dispatches the event.\n */\n activate(\n event: ActivationEvent.ActivationEvent | string,\n params?: { before?: string; after?: string },\n ): Effect.Effect<boolean, Error, Plugin.Service> {\n const key = typeof event === 'string' ? event : ActivationEvent.eventKey(event);\n const startupKey = ActivationEvent.eventKey(ActivationEvent.Startup);\n return Effect.gen({ self: this }, function* () {\n // Startup is not a plain event: it triggers the dependency pass alongside the event\n // dispatch. Delegating keeps useApp/harness/cli call sites unchanged.\n if (key === startupKey) {\n return yield* this.start();\n }\n\n if (yield* this.#state.isShuttingDown()) {\n log('skipping activation during shutdown', { key, ...params });\n return false;\n }\n\n // Startup provides the baseline capabilities, so a module activating on an event dispatched\n // mid-startup could otherwise find a require unsatisfied purely by timing. Waiting also keeps\n // the wave out of startup's settle check, which would hold `ready` behind unrelated work.\n if ((yield* Ref.get(this.#state.started)) && !this.#state.eventFired(startupKey)) {\n log('deferring activation until startup completes', { key, ...params });\n yield* Deferred.await(this.#state.startupComplete);\n }\n\n // Re-dispatching a fired event is already a no-op — an active module is never re-selected —\n // but the instrumentation below is not free (two marks, a devtools track entry, a forked\n // warning timer), and demand events are fired from reactive paths that re-evaluate freely.\n // Bail before paying for a dispatch that has nothing to activate. The module scan is still\n // required: modules register after the fact under streaming start, so a fired event can\n // have newly-eligible modules. A fired event implies the wait below already completed once,\n // so the scan is safe this early.\n if (this.#state.eventFired(key)) {\n const activatingEvents = yield* Ref.get(this.#activatingEvents);\n const activatingModules = yield* Ref.get(this.#activatingModules);\n if (this.#getModulesForActivation(key, activatingEvents, activatingModules).length === 0) {\n log('no modules to activate', { key, ...params });\n return false;\n }\n }\n\n // Dispatch-latency split: `requested` → `initialized` is registration wait; `initialized`\n // → the wave's `event:` measure is provider-join wait (in-flight round-1 loads).\n performance.mark(`milestone:dispatch:${key}:requested`);\n\n // Wait for the constructor's core/enabled `enable()` chain — including\n // any async dynamic imports for lazy plugins — to finish registering\n // modules. Without this, dispatching to an empty module set is the\n // observable symptom of the race.\n yield* Deferred.await(this.#state.initialized);\n performance.mark(`milestone:dispatch:${key}:initialized`);\n\n return yield* Effect.withFiber<boolean, Error, Plugin.Service>((fiber) =>\n this.#activateEvent(key, params, fiber).pipe(\n together(\n Effect.sleep(Duration.seconds(15)).pipe(\n Effect.andThen(Effect.sync(() => log.warn('event activation is taking a long time', { event: key }))),\n ),\n ),\n Performance.addTrackEntry({\n name: key,\n devtools: {\n dataType: 'track-entry',\n track: 'Event Activation',\n trackGroup: 'Composer',\n color: 'primary',\n },\n }),\n ),\n );\n });\n }\n\n /**\n * Deactivates all of a plugin's modules. Active modules elsewhere that require a singleton\n * capability provided by this plugin are deactivated first (reverse activation order) and\n * marked for reactivation when a provider returns.\n */\n deactivatePlugin(id: string): Effect.Effect<boolean, Error> {\n return Effect.gen({ self: this }, function* () {\n const plugin = this.#state.getPlugin(id);\n if (!plugin) {\n return false;\n }\n\n const modules = plugin.modules;\n\n const dependents = this.#collectCapabilityDependents(modules);\n for (const dependent of dependents) {\n yield* this.#loader.deactivate(dependent);\n this.#state.reactivateOnNextPass.add(dependent.id);\n }\n\n const results = yield* Effect.all(\n modules.map((module) => this.#loader.deactivate(module)),\n { concurrency: 'unbounded' },\n );\n return results.every((result) => result);\n });\n }\n\n /**\n * Re-activates the modules that were activated by the event.\n */\n resetEvent(event: ActivationEvent.ActivationEvent | string): Effect.Effect<boolean, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n const key = typeof event === 'string' ? event : ActivationEvent.eventKey(event);\n log('reset', { key });\n const modules = this.#state.getActiveModulesByEvent(key);\n const results = yield* Effect.all(\n modules.map((module) => this.#loader.deactivate(module)),\n { concurrency: 'unbounded' },\n );\n\n if (results.every((result) => result)) {\n return yield* this.activate(key);\n } else {\n return false;\n }\n });\n }\n\n /** Shutdown support: forget in-flight event/module claims. */\n clearClaims(): Effect.Effect<void> {\n return Effect.all([Ref.set(this.#activatingEvents, []), Ref.set(this.#activatingModules, [])]).pipe(Effect.asVoid);\n }\n\n /**\n * Runs one activation event: matches parked event-mode modules (an `allOf` module joins once\n * all its events have fired), pulls their inactive dependency providers on demand, activates\n * them, then re-runs the dependency pass so contributions made here can unlock modules that\n * were waiting.\n */\n #activateEvent(\n key: string,\n params: { before?: string; after?: string } | undefined,\n fiber: Fiber.Fiber<unknown, unknown>,\n opts?: { suppressEventMessage?: boolean },\n ): Effect.Effect<boolean, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n yield* this.#state.fibers.track(fiber);\n log('activating', { key, ...params });\n yield* Ref.update(this.#activatingEvents, (activating) => Array.append(activating, key));\n this.#state.clearPendingReset(key);\n\n const activatingEvents = yield* Ref.get(this.#activatingEvents);\n const activatingModules = yield* Ref.get(this.#activatingModules);\n const modules = this.#getModulesForActivation(key, activatingEvents, activatingModules);\n if (modules.length === 0) {\n log('no modules to activate', { key });\n this.#state.markEventFired(key);\n return false;\n }\n\n // Modules resolve their requires on demand: inactive providers of unsatisfied singleton\n // requires are activated first (transitively).\n yield* this.#pullDependencyProviders(modules, key);\n const activated = yield* this.#activateModulesForEvent(key, modules, opts);\n\n // Follow-up pass: contributions made by this event may unlock modules that were waiting\n // on them. Cheap no-op when nothing became runnable.\n if (yield* this.#state.isStarted()) {\n yield* this.runDependencyPass({});\n }\n\n return activated;\n }).pipe(\n Effect.ensuring(\n Effect.all([\n this.#state.fibers.untrack(fiber),\n Ref.update(this.#activatingEvents, (activating) => Array.filter(activating, (event) => event !== key)),\n ]),\n ),\n );\n }\n\n /**\n * Activates inactive modules in dependency order of the capability graph, in rounds,\n * repeated until a round activates nothing new. Candidates are dependency-mode modules plus\n * event-mode modules whose `activatesOn` events have already fired; modules whose singleton\n * requires cannot be satisfied by this pass WAIT — they are reconsidered by the next round\n * (each round of contributions, and each event wave, can unlock them). With\n * `candidateModules`, the first round is scoped to those modules (plus any marked for\n * reactivation); follow-up rounds consider the full pool unless `scopedToCandidates` keeps\n * them scoped — demand pulls and event waves must not become drain workers for the whole\n * startup pool (that serializes event dispatch behind unrelated startup work).\n *\n * Structural problems — duplicate singleton providers within a round, capability cycles,\n * or a singleton requirement no registered module of any mode could ever provide — put\n * the offending plugins into an error state (the `failed` atom, plus an error activation\n * message) and the pass continues with everything else. Individual module activation\n * failures are recorded per plugin (via the loader) and skip that module's transitive\n * dependents without aborting independent modules.\n */\n runDependencyPass(options?: {\n candidateModules?: Plugin.PluginModule[];\n scopedToCandidates?: boolean;\n }): Effect.Effect<boolean, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n let scoped = options?.candidateModules;\n let ranAny = false;\n let allSucceeded = true;\n // Contributions made by one round (or concurrently by event waves) can make modules that\n // were waiting runnable, so keep running rounds until one activates nothing. Each round\n // activates at least one module or ends the loop, so this terminates.\n for (;;) {\n const round = yield* this.#runRound(scoped);\n if (round === undefined) {\n break;\n }\n ranAny = true;\n allSucceeded = allSucceeded && round;\n // Follow-up rounds consider everything that might have been unlocked — unless scoped:\n // a demand pull draining the full pool would block its event wave on unrelated work.\n scoped = options?.scopedToCandidates ? options?.candidateModules : undefined;\n }\n\n // A round filters out anything a concurrent round started loading (awaiting it inside the\n // round could deadlock), so the loop can end while those loads are still settling. Every\n // caller reads the registry straight after and relies on \"pass resolved => candidates\n // contributed\", so join them here. Bounded: each load settles under the activation timeout.\n const candidates = options?.candidateModules;\n if (candidates !== undefined) {\n const settling = (yield* this.#notActivatingHere(candidates)).filter((module) =>\n this.#loader.isLoading(module.id),\n );\n if (settling.length > 0) {\n yield* Effect.all(\n settling.map((module) => this.#loader.awaitSettled(module.id)),\n { concurrency: 'unbounded', discard: true },\n );\n }\n }\n return ranAny && allSucceeded;\n });\n }\n\n /**\n * Detects capability cycles across the FULL module set, regardless of event gating.\n * Two modules on different activation events that require each other's provides would\n * otherwise wait forever (neither chain can start); this surfaces the lock at startup:\n * the members are put into an error state and excluded — they simply never activate,\n * and everything else proceeds.\n */\n #reportGlobalCycle(): Effect.Effect<void> {\n return Effect.gen({ self: this }, function* () {\n const graph = ActivationGraph.buildSingletonGraph(this.#state.getModules());\n if (ActivationGraph.computeActivationWaves(graph, ['hard']) !== undefined) {\n return;\n }\n const path = ActivationGraph.findCyclePath(graph, ['hard']);\n yield* this.#reportStructuralError(\n path.map((entry) => entry.module),\n new DependencyCycleError({ path }),\n );\n path.forEach((entry) => this.#state.structurallyFailed.add(entry.module));\n });\n }\n\n /**\n * Collects active modules (outside the given set) whose declared requires include a\n * singleton capability provided by the given modules, transitively. Returned in reverse\n * activation order, which is reverse topological order (safe deactivation order).\n */\n #collectCapabilityDependents(modules: readonly Plugin.PluginModule[]): Plugin.PluginModule[] {\n const active = this.#state.getActiveIds();\n const allModules = this.#state.getModules();\n const ownIds = new Set(modules.map((module) => module.id));\n const providedIds = new Set<string>();\n const collectProvides = (module: Plugin.PluginModule) => {\n for (const capability of module.activation.provides) {\n if (capability.arity === 'single') {\n providedIds.add(capability.identifier);\n }\n }\n };\n modules.filter((module) => active.includes(module.id)).forEach(collectProvides);\n\n const dependents = new Map<string, Plugin.PluginModule>();\n let changed = providedIds.size > 0;\n while (changed) {\n changed = false;\n for (const module of allModules) {\n if (ownIds.has(module.id) || dependents.has(module.id) || !active.includes(module.id)) {\n continue;\n }\n if (module.activation.requires.some((capability) => providedIds.has(capability.identifier))) {\n dependents.set(module.id, module);\n collectProvides(module);\n changed = true;\n }\n }\n }\n\n const order = this.#state.getActiveIds();\n return [...dependents.values()].sort((a, b) => order.indexOf(b.id) - order.indexOf(a.id));\n }\n\n #activateModulesForEvent(\n key: string,\n modules: Plugin.PluginModule[],\n opts?: { suppressEventMessage?: boolean },\n ): Effect.Effect<boolean, Error, Plugin.Service> {\n const activatingModuleIds = modules.map((module) => module.id);\n return Effect.gen({ self: this }, function* () {\n yield* Ref.update(this.#activatingModules, (activating) => Array.appendAll(activating, activatingModuleIds));\n\n log('activation wave', { event: key, modules: activatingModuleIds });\n performance.mark(`event:${key}:start`);\n yield* PubSub.publish(this.#state.activation, { event: key, state: 'activating' });\n\n // Same-event provider/consumer pairs are topologically ordered with per-module\n // contribution via the capability-graph machinery. Scoped: the post-wave pass in\n // `#activateEvent` handles unlocking, so the wave never drains the startup pool.\n yield* this.runDependencyPass({ candidateModules: modules, scopedToCandidates: true });\n\n // A matched module may be mid-load via a concurrent wave (the round filters it as\n // `isLoading` to avoid in-round deadlocks). Await those loads before reporting the event\n // activated — demand pulls rely on \"activate resolved ⇒ matched modules contributed\"\n // (a lookup retry that runs earlier misses the handlers and fails a one-shot invocation).\n // Bounded: every load settles its deferred under the activation timeout.\n const inFlight = (yield* this.#notActivatingHere(modules)).filter((module) => this.#loader.isLoading(module.id));\n if (inFlight.length > 0) {\n yield* Effect.all(\n inFlight.map((module) => this.#loader.awaitSettled(module.id)),\n { concurrency: 'unbounded', discard: true },\n );\n }\n this.#state.markEventFired(key);\n\n performance.mark(`event:${key}:end`);\n performance.measure(`event:${key}`, `event:${key}:start`, `event:${key}:end`);\n // `start()` suppresses the event-level message for Startup and publishes it itself\n // once the concurrent dependency pass has also completed (the useApp ready gate).\n if (!opts?.suppressEventMessage) {\n yield* PubSub.publish(this.#state.activation, { event: key, state: 'activated' });\n }\n log('activated', { key });\n\n return true;\n }).pipe(\n Effect.ensuring(\n Ref.update(this.#activatingModules, (activating) =>\n Array.filter(activating, (module) => !activatingModuleIds.includes(module)),\n ),\n ),\n );\n }\n\n #getModulesForActivation(\n key: string,\n activatingEvents: string[],\n activatingModules: string[],\n ): Plugin.PluginModule[] {\n return this.#state.getInactiveModulesByEvent(key).filter((module) => {\n const spec = module.activation;\n const allOf = ActivationEvent.isAllOf(spec.activatesOn);\n if (!allOf) {\n return true;\n }\n\n // Check to see if all of the events in the `allOf` have been fired.\n // An event can be considered \"fired\" if it is in the `eventsFired` list or if it is currently being activated.\n const events = ActivationEvent.getEvents(spec.activatesOn).filter(\n (event) => ActivationEvent.eventKey(event) !== key,\n );\n return (\n events.every(\n (event) =>\n this.#state.eventFired(ActivationEvent.eventKey(event)) ||\n activatingEvents.includes(ActivationEvent.eventKey(event)),\n ) && !activatingModules.includes(module.id)\n );\n });\n }\n\n /**\n * Records a structural dependency-graph error against a plugin and publishes it on the\n * activation stream (so boot UIs surface it) without aborting the pass.\n */\n #reportStructuralError(moduleIds: string[], error: Error): Effect.Effect<void> {\n return Effect.gen({ self: this }, function* () {\n log.error('dependency graph error', { error: String(error), modules: moduleIds });\n const plugins = new Set<string>();\n for (const moduleId of moduleIds) {\n const pluginId = this.#state.pluginIdOfModule(moduleId);\n if (pluginId !== undefined) {\n plugins.add(pluginId);\n }\n }\n plugins.forEach((pluginId) => this.#state.recordFailure(pluginId, 'activation', error));\n yield* PubSub.publish(this.#state.activation, {\n event: ActivationEvent.eventKey(ActivationEvent.Startup),\n state: 'error',\n error,\n });\n });\n }\n\n /**\n * Whether a module's wave has fired: every event for an `all-of` declaration, any one for a\n * plain or `one-of` declaration. A fired event stays fired, so this stays true for the rest of\n * the session once the module's wave has passed.\n *\n * `activating` is the wave currently being dispatched, counted as fired: an event is marked\n * fired only once its modules have settled, so without this the wave's own modules would be\n * excluded from the very round activating them.\n */\n #waveFired(module: Plugin.PluginModule, activating?: string): boolean {\n const { activatesOn } = module.activation;\n const events = ActivationEvent.getEvents(activatesOn).map(ActivationEvent.eventKey);\n const fired = (event: string) => event === activating || this.#state.eventFired(event);\n return ActivationEvent.isAllOf(activatesOn) ? events.every(fired) : events.some(fired);\n }\n\n /**\n * Whether a module can activate now: its wave has already fired, or it declared Startup. The\n * catalog uses this to pick which of a newly enabled plugin's modules join an incremental pass;\n * the rest wait for their event.\n *\n * Deliberately NOT `#isBaselineWave`, which also admits Idle. Candidates handed to\n * `runDependencyPass` are EXPLICIT candidates and bypass the `#waveFired` gate in `#runRound`, so\n * admitting idle-default modules here would activate them eagerly during boot for any plugin\n * whose `enable()` lands after `started` flips — the dominant path in Composer, where lazy plugin\n * stubs enable over seconds while Startup dispatches milliseconds after mount. That would make\n * deferral depend on an enable/start race and defeat the idle default entirely. Idle stays in the\n * baseline for PROVIDER PULLS only (see {@link ActivationScheduler.#isBaselineWave}).\n */\n isEligible(module: Plugin.PluginModule): boolean {\n return this.#waveFired(module) || this.#declaresStartup(module);\n }\n\n /** Whether the module explicitly names the Startup wave. */\n #declaresStartup(module: Plugin.PluginModule): boolean {\n const startup = ActivationEvent.eventKey(ActivationEvent.Startup);\n return ActivationEvent.getEvents(module.activation.activatesOn).map(ActivationEvent.eventKey).includes(startup);\n }\n\n /**\n * Whether a module sits in the baseline wave — `Startup u Idle`. A module there is pullable as a\n * provider by any wave, whether or not its own wave has run; explicitly gated providers stay\n * wave-scoped, which is what keeps two mutually-exclusive providers of one capability from both\n * being candidates.\n *\n * Idle is in the baseline because it is what omitting `activatesOn` normalizes to: scoping\n * un-annotated modules to their own wave would make every un-annotated provider invisible to the\n * startup pass, so `ClientPlugin`'s `Client` would not initialize until idle. Modules declaring\n * `Startup` explicitly lose nothing — their wave fires first, so `#waveFired` covers them after.\n */\n #isBaselineWave(module: Plugin.PluginModule): boolean {\n const baseline = [ActivationEvent.Startup, ActivationEvent.Idle].map(ActivationEvent.eventKey);\n return ActivationEvent.getEvents(module.activation.activatesOn)\n .map(ActivationEvent.eventKey)\n .some((event) => baseline.includes(event));\n }\n\n /**\n * Drops the modules whose `activate` bodies this fiber is running inside. A body that fires an\n * activation event is a caller of the wave, so awaiting its own load is a circular wait that\n * ends only at the activation timeout — recorded as a `PluginTimeoutError` and read by the\n * failure supervisor as a broken plugin, which then disables it. Their contributions are simply\n * not visible to this wave; the body contributes them when it returns.\n */\n #notActivatingHere(modules: Plugin.PluginModule[]): Effect.Effect<Plugin.PluginModule[]> {\n return Effect.gen(function* () {\n const activating = yield* Capability.ActivatingModuleIds;\n if (activating.size === 0) {\n return modules;\n }\n return modules.filter((module) => !activating.has(module.id));\n });\n }\n\n /**\n * One topological activation round. Returns `undefined` when nothing is runnable.\n */\n #runRound(\n candidateModules: Plugin.PluginModule[] | undefined,\n ): Effect.Effect<boolean | undefined, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n const key = ActivationEvent.eventKey(ActivationEvent.Startup);\n const active = this.#state.getActiveIds();\n const allModules = this.#state.getModules();\n\n // During the streaming bootstrap the provider's plugin definition may simply not have\n // registered yet — the module waits and the post-initialization pass re-evaluates;\n // a missing provider is structural only once the registry is complete.\n const registryComplete = yield* Deferred.isDone(this.#state.initialized);\n\n const reactivations = allModules.filter((module) => this.#state.reactivateOnNextPass.has(module.id));\n // Explicitly passed candidates are trusted to be triggered (an event wave passes its\n // matched modules before the event is marked fired); pooled candidates must have their\n // events already fired.\n const explicit = new Set((candidateModules ?? []).map((module) => module.id));\n const pool = candidateModules ? [...candidateModules, ...reactivations] : allModules;\n // Explicit candidates are a snapshot taken when the wave started, so a plugin disabled\n // mid-wave (auto-disable after a module failure is the common case) leaves de-registered\n // modules in it; re-loading one would restart the very activation that just failed.\n const registered = new Set(allModules.map((module) => module.id));\n const seen = new Set<string>();\n const candidates = pool.filter((module) => {\n if (\n !registered.has(module.id) ||\n active.includes(module.id) ||\n seen.has(module.id) ||\n this.#state.structurallyFailed.has(module.id) ||\n // Already loading via another path (memoized): awaiting it here could deadlock —\n // e.g. a cascade triggered by an event wave that an in-flight module itself fired.\n this.#loader.isLoading(module.id)\n ) {\n return false;\n }\n // A multi require is a collection, so \"satisfied\" is only meaningful once every plugin\n // definition has registered — a consumer admitted during the streaming window snapshots\n // whatever happens to have contributed so far (the process manager's one-shot\n // `Capabilities.LayerSpec` read is how this surfaced). Which providers are still to come\n // is unknowable mid-registration, so these wait for the complete pass wholesale; this is\n // the ordering they had before streaming.\n if (!registryComplete && module.activation.requires.some((capability) => capability.arity === 'multi')) {\n return false;\n }\n if (!explicit.has(module.id) && !this.#waveFired(module, key)) {\n return false;\n }\n seen.add(module.id);\n return true;\n });\n if (candidates.length === 0) {\n return undefined;\n }\n\n // Singleton provider index across candidates and already-active typed modules.\n // The duplicate check spans only modules in play, so mutually-exclusive event-gated\n // alternatives (only one has fired) do not trip it. Duplicates put both providers into\n // an error state and exclude them; their dependents wait.\n const providerIndex = new Map<string, string>();\n const structurallyExcluded = new Set<string>();\n const activeTypedModules = allModules.filter((module) => active.includes(module.id));\n for (const module of [...activeTypedModules, ...candidates]) {\n for (const capability of module.activation.provides) {\n if (capability.arity !== 'single') {\n continue;\n }\n const existing = providerIndex.get(capability.identifier);\n if (existing !== undefined && existing !== module.id) {\n const error = new DuplicateProviderError({\n capability: capability.identifier,\n providers: [existing, module.id],\n });\n yield* this.#reportStructuralError([existing, module.id], error);\n structurallyExcluded.add(existing);\n structurallyExcluded.add(module.id);\n this.#state.structurallyFailed.add(existing);\n this.#state.structurallyFailed.add(module.id);\n providerIndex.delete(capability.identifier);\n continue;\n }\n providerIndex.set(capability.identifier, module.id);\n }\n }\n\n // Does ANY registered module (active or not, fired or not) provide this?\n const anyRegisteredProvider = (identifier: string): boolean =>\n allModules.some((module) => module.activation.provides.some((provided) => provided.identifier === identifier));\n\n // Pure selection: everything that waits here is reconsidered by a later round; requires\n // with no possible provider at all are a configuration error recorded against the\n // requiring plugin.\n const { runnable, missing, waiting } = ActivationGraph.selectRunnableModules({\n candidates,\n excluded: structurallyExcluded,\n isSatisfied: (capability) => this.#capabilities.getAll(capability).length > 0,\n providerOf: (identifier) => providerIndex.get(identifier),\n activeIds: [...active],\n anyRegisteredProvider,\n });\n for (const waits of waiting) {\n log('module waiting on capability', { module: waits.module.id, capability: waits.capability });\n }\n for (const miss of missing) {\n if (!registryComplete) {\n log('module waiting on unregistered provider', { module: miss.module.id, capability: miss.capability });\n continue;\n }\n yield* this.#reportStructuralError(\n [miss.module.id],\n new MissingProviderError({\n capability: miss.capability,\n requiredBy: [miss.module.id],\n registered: this.#capabilities.listRegisteredIdentifiers(),\n }),\n );\n this.#state.structurallyFailed.add(miss.module.id);\n }\n if (runnable.length === 0) {\n return undefined;\n }\n runnable.forEach((module) => this.#state.reactivateOnNextPass.delete(module.id));\n\n const graph = ActivationGraph.buildRoundGraph(runnable, {\n isSatisfied: (capability) => this.#capabilities.getAll(capability).length > 0,\n providerOf: (identifier) => providerIndex.get(identifier),\n });\n\n const ordered = yield* this.#orderRoundBreakingCycles(graph);\n if (ordered === undefined) {\n return undefined;\n }\n const { waves, cycleFailed } = ordered;\n log('dependency activation waves', {\n waves: waves.map((wave) => wave.map((module) => module.id)),\n });\n\n return yield* this.#executeWaves(waves, graph, cycleFailed, key);\n });\n }\n\n /**\n * Orders a round's graph into activation waves (see `activation-graph.ts` for the terms),\n * repeatedly removing required-edge cycles (recorded as an error state on the involved\n * plugins; their dependents skip via the failed set) until the remaining graph is acyclic.\n * Best-effort ordering edges are then layered on top: if they cycle, the round falls back to\n * required-edge order wholesale. Returns `undefined` when nothing survives cycle removal.\n */\n #orderRoundBreakingCycles(\n graph: ActivationGraph.ActivationGraphModel,\n ): Effect.Effect<{ waves: Plugin.PluginModule[][]; cycleFailed: Set<string> } | undefined, Error> {\n return Effect.gen({ self: this }, function* () {\n const cycleFailed = new Set<string>();\n let hardWaves = ActivationGraph.computeActivationWaves(graph, ['hard']);\n while (hardWaves === undefined) {\n const path = ActivationGraph.findCyclePath(graph, ['hard']);\n yield* this.#reportStructuralError(\n path.map((entry) => entry.module),\n new DependencyCycleError({ path }),\n );\n const members = path.map((entry) => entry.module);\n members.forEach((member) => {\n cycleFailed.add(member);\n this.#state.structurallyFailed.add(member);\n });\n graph.removeNodes(members);\n if (graph.nodes.length === 0) {\n return undefined;\n }\n hardWaves = ActivationGraph.computeActivationWaves(graph, ['hard']);\n }\n\n const combinedWaves = ActivationGraph.computeActivationWaves(graph, ['hard', 'soft']);\n if (combinedWaves === undefined && ActivationGraph.hasSoftEdges(graph)) {\n log('multi-capability soft ordering dropped (cycle)', { modules: graph.nodes.map((node) => node.id) });\n }\n return { waves: combinedWaves ?? hardWaves, cycleFailed };\n });\n }\n\n /**\n * Activates a round wave by wave (modules within a wave run concurrently). A module whose\n * required provider failed is skipped and marked failed so its own dependents skip too;\n * independent modules proceed. Cycle members arrive pre-failed so their dependents skip as\n * well. Returns whether every module in the round activated.\n */\n #executeWaves(\n waves: Plugin.PluginModule[][],\n graph: ActivationGraph.ActivationGraphModel,\n preFailed: Set<string>,\n key: string,\n ): Effect.Effect<boolean, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n const failed = new Set<string>(preFailed);\n const providersOf = (moduleId: string): string[] => ActivationGraph.requiredProviderIds(graph, moduleId);\n // Singleton providers gate dependents (in this round or a later pass), so under the\n // concurrency cap they claim the first slots instead of queuing behind leaf modules.\n const singletonProvides = (module: Plugin.PluginModule): number =>\n module.activation.provides.filter((capability) => capability.arity === 'single').length;\n let allSucceeded = true;\n for (const wave of waves) {\n const ordered = [...wave].sort((a, b) => singletonProvides(b) - singletonProvides(a));\n yield* Effect.all(\n ordered.map((module) =>\n Effect.gen({ self: this }, function* () {\n if (providersOf(module.id).some((provider) => failed.has(provider))) {\n log.warn('skipping module: provider failed', { module: module.id });\n failed.add(module.id);\n allSucceeded = false;\n return;\n }\n const result = yield* this.#activateModule(module, key).pipe(Effect.result);\n if (result._tag === 'Failure') {\n failed.add(module.id);\n allSucceeded = false;\n }\n }),\n ),\n // Bounded: a 350-wide unbounded fan-out oversubscribes import/parse and stretches\n // every module's wall clock (the measured contention plateau); small waves and\n // tests (which gate concurrent modules on each other) stay fully concurrent.\n { concurrency: ActivationScheduler.WAVE_CONCURRENCY },\n );\n }\n return allSucceeded;\n });\n }\n\n /**\n * Loads and contributes a single dependency-mode module. Contribution happens as the module\n * completes (not batched per wave), so singleton gating is exactly wave ordering.\n */\n #activateModule(module: Plugin.PluginModule, parentEvent: string): Effect.Effect<void, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n if (this.#state.getActiveIds().includes(module.id)) {\n return;\n }\n const capabilities = yield* this.#loader.load(module, parentEvent);\n yield* this.#loader.contribute(module, capabilities);\n });\n }\n\n /**\n * Activates the inactive dependency-mode providers (transitively) of the given modules'\n * unsatisfied singleton requires, plus any inactive dependency-mode providers of their\n * multi requires. Used before running event-mode modules so their requires resolve on\n * demand.\n *\n * Multi requires never gate (they resolve to whatever is currently contributed), but a\n * pulled provider that takes a one-shot snapshot of a multi capability (e.g. the process\n * manager's `Capabilities.LayerSpec` collection) needs its fellow multi providers activated\n * in the *same* scoped round so the round's ordering can land them first — otherwise a\n * narrow pull (this provider alone) skips that ordering entirely and the snapshot can be\n * taken before sibling providers have contributed.\n */\n #pullDependencyProviders(\n modules: Plugin.PluginModule[],\n activating?: string,\n ): Effect.Effect<void, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n const active = this.#state.getActiveIds();\n const allModules = this.#state.getModules();\n const providerIndex = new Map<string, Plugin.PluginModule>();\n const multiProviderIndex = new Map<string, Plugin.PluginModule[]>();\n for (const module of allModules) {\n // Wave-scoped, with the baseline wave always in scope: an explicitly gated provider is\n // pullable only once its own wave has fired, so two providers of the same singleton\n // capability gated on mutually exclusive events are never both candidates.\n if ((!this.#waveFired(module, activating) && !this.#isBaselineWave(module)) || active.includes(module.id)) {\n continue;\n }\n for (const capability of module.activation.provides) {\n if (capability.arity === 'single') {\n if (!providerIndex.has(capability.identifier)) {\n providerIndex.set(capability.identifier, module);\n }\n } else {\n const providers = multiProviderIndex.get(capability.identifier) ?? [];\n providers.push(module);\n multiProviderIndex.set(capability.identifier, providers);\n }\n }\n }\n if (providerIndex.size === 0 && multiProviderIndex.size === 0) {\n return;\n }\n\n const needed = new Map<string, Plugin.PluginModule>();\n const visit = (requires: readonly Capability.AnyTag[]) => {\n for (const capability of requires) {\n if (capability.arity === 'multi') {\n for (const provider of multiProviderIndex.get(capability.identifier) ?? []) {\n if (!needed.has(provider.id)) {\n needed.set(provider.id, provider);\n visit(provider.activation.requires);\n }\n }\n continue;\n }\n if (this.#capabilities.getAll(capability).length > 0) {\n continue;\n }\n const provider = providerIndex.get(capability.identifier);\n if (provider && !needed.has(provider.id)) {\n needed.set(provider.id, provider);\n visit(provider.activation.requires);\n }\n }\n };\n for (const module of modules) {\n visit(module.activation.requires);\n }\n\n if (needed.size > 0) {\n log('pulling dependency providers', { modules: [...needed.keys()] });\n // Providers already mid-load (e.g. via the concurrent startup pass) are joined, not\n // re-drained — the scoped round below filters them as `isLoading` and would otherwise\n // return before their capabilities land.\n const inFlight = (yield* this.#notActivatingHere([...needed.values()])).filter((module) =>\n this.#loader.isLoading(module.id),\n );\n if (inFlight.length > 0) {\n yield* Effect.all(\n inFlight.map((module) => this.#loader.awaitSettled(module.id)),\n { concurrency: 'unbounded', discard: true },\n );\n }\n yield* this.runDependencyPass({ candidateModules: [...needed.values()], scopedToCandidates: true });\n }\n });\n }\n}\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Deferred from 'effect/Deferred';\nimport * as Effect from 'effect/Effect';\nimport * as Fiber from 'effect/Fiber';\nimport * as PubSub from 'effect/PubSub';\nimport * as Atom from 'effect/reactivity/Atom';\nimport type * as Registry from 'effect/reactivity/AtomRegistry';\nimport * as Ref from 'effect/Ref';\n\nimport { log } from '@dxos/log';\n\nimport * as ActivationEvent from '../activation-event.ts';\nimport type * as Plugin from '../plugin.ts';\nimport {\n type ActivationMessage,\n type PluginFailure,\n type PluginFailurePhase,\n type PluginFailureReason,\n type PluginInitializationError,\n PluginTimeoutError,\n} from './manager-types.ts';\n\n/**\n * The plugin manager's shared substrate, owned by no single unit: the observable state, the\n * activation status channel, the fiber tracker, and the lifecycle flags the manager and its\n * collaborating units (catalog, scheduler, loader) coordinate through. One object with named\n * operations instead of per-unit getter and setter callbacks: this IS shared mutable state, and\n * giving it a single home makes the sharing visible and its invariants enforceable.\n *\n * The atoms are the manager's public reactive surface (exposed via the `PluginManager`\n * interface); everything else is internal bookkeeping.\n */\nexport class ManagerState {\n /** All registered plugins (enabled or not). */\n readonly plugins: Atom.Writable<Plugin.Plugin[]>;\n /** Ids of system plugins (snapshot of the initial set; never disabled). */\n readonly core: Atom.Writable<string[]>;\n /** Ids of enabled plugins. */\n readonly enabled: Atom.Writable<string[]>;\n /** Modules of enabled plugins. */\n readonly modules: Atom.Writable<Plugin.PluginModule[]>;\n /** Ids of modules whose activate has completed and contributed. */\n readonly active: Atom.Writable<string[]>;\n /** Activation events that have fired. */\n readonly eventsFired: Atom.Writable<string[]>;\n /** Events whose modules changed after the event fired — replayed on the next enable. */\n readonly pendingReset: Atom.Writable<string[]>;\n /** Plugins that failed to load or activate (latest failure per id). */\n readonly failed: Atom.Writable<PluginFailure[]>;\n /** Ids of currently-registered dev-sourced plugins. */\n readonly devPluginIds: Atom.Writable<string[]>;\n\n /** Status channel: `activating`/`activated`/`error` messages per event and module. */\n readonly activation = Effect.runSync(PubSub.unbounded<ActivationMessage>());\n /** Fibers forked by the units, so shutdown can interrupt in-flight work. */\n readonly fibers = new FiberTracker();\n /**\n * Completed when the constructor's core/enabled `enable()` chain has registered all\n * modules; event dispatch awaits it so lazy plugin imports can't race activation.\n */\n readonly initialized = Effect.runSync(Deferred.make<void, PluginInitializationError>());\n /** Whether `start()` has run — gates incremental activation on later enables. */\n readonly started = Effect.runSync(Ref.make(false));\n /**\n * Completed when the Startup wave has finished; events dispatched mid-startup await it so their\n * modules can rely on every startup capability. Reset by {@link clearEventsFired}.\n */\n startupComplete = Effect.runSync(Deferred.make<void>());\n /** Set for the duration of `shutdown()` — new starts/activations are skipped meanwhile. */\n readonly shuttingDown = Effect.runSync(Ref.make(false));\n /**\n * Modules deactivated because a singleton capability they require lost its provider\n * (provider plugin disabled). Re-included as candidates in the next dependency pass.\n */\n readonly reactivateOnNextPass = new Set<string>();\n /**\n * Modules in a structural error state (cycle member, duplicate provider, impossible\n * require): excluded from activation rounds until a plugin-set change re-evaluates them.\n */\n readonly structurallyFailed = new Set<string>();\n\n readonly #registry: Registry.AtomRegistry;\n\n constructor(\n registry: Registry.AtomRegistry,\n initial: { plugins: readonly Plugin.Plugin[]; core: readonly string[]; enabled: readonly string[] },\n ) {\n this.#registry = registry;\n this.plugins = Atom.make<Plugin.Plugin[]>([...initial.plugins]).pipe(Atom.keepAlive);\n this.core = Atom.make<string[]>([...initial.core]).pipe(Atom.keepAlive);\n this.enabled = Atom.make<string[]>([...initial.enabled]).pipe(Atom.keepAlive);\n this.modules = Atom.make<Plugin.PluginModule[]>([]).pipe(Atom.keepAlive);\n this.active = Atom.make<string[]>([]).pipe(Atom.keepAlive);\n this.eventsFired = Atom.make<string[]>([]).pipe(Atom.keepAlive);\n this.pendingReset = Atom.make<string[]>([]).pipe(Atom.keepAlive);\n this.failed = Atom.make<PluginFailure[]>([]).pipe(Atom.keepAlive);\n this.devPluginIds = Atom.make<string[]>([]).pipe(Atom.keepAlive);\n }\n\n /** Generic read of any atom through the manager's registry. */\n read<T>(atom: Atom.Atom<T>): T {\n return this.#registry.get(atom);\n }\n\n #update<T>(atom: Atom.Writable<T>, fn: (value: T) => T): void {\n this.#registry.set(atom, fn(this.#registry.get(atom)));\n }\n\n //\n // Plugins.\n //\n\n getPlugins(): readonly Plugin.Plugin[] {\n return this.read(this.plugins);\n }\n\n getPlugin(id: string): Plugin.Plugin | undefined {\n return this.getPlugins().find((plugin) => plugin.meta.profile.key === id);\n }\n\n registerPlugin(plugin: Plugin.Plugin): void {\n log('add plugin', { id: plugin.meta.profile.key });\n // TODO(wittjosiah): Find a way to add a warning for duplicate plugins that doesn't cause log spam.\n this.#update(this.plugins, (plugins) => (plugins.includes(plugin) ? plugins : [...plugins, plugin]));\n }\n\n /** Swaps the plugin registered under the id (lazy resolution, dev shadowing). */\n replacePlugin(id: string, plugin: Plugin.Plugin): void {\n this.#update(this.plugins, (plugins) => plugins.map((p) => (p.meta.profile.key === id ? plugin : p)));\n }\n\n unregisterPlugin(id: string): void {\n log('remove plugin', { id });\n this.#update(this.plugins, (plugins) => plugins.filter((plugin) => plugin.meta.profile.key !== id));\n }\n\n isCore(id: string): boolean {\n return this.read(this.core).includes(id);\n }\n\n isEnabled(id: string): boolean {\n return this.read(this.enabled).includes(id);\n }\n\n markEnabled(id: string): void {\n this.#update(this.enabled, (enabled) => (enabled.includes(id) ? enabled : [...enabled, id]));\n }\n\n markDisabled(id: string): void {\n this.#update(this.enabled, (enabled) => enabled.filter((item) => item !== id));\n }\n\n markDevPlugin(id: string): void {\n this.#update(this.devPluginIds, (ids) => (ids.includes(id) ? ids : [...ids, id]));\n }\n\n unmarkDevPlugin(id: string): void {\n this.#update(this.devPluginIds, (ids) => ids.filter((existing) => existing !== id));\n }\n\n //\n // Modules.\n //\n\n getModules(): readonly Plugin.PluginModule[] {\n return this.read(this.modules);\n }\n\n addModule(module: Plugin.PluginModule): void {\n log('add module', { id: module.id });\n // TODO(wittjosiah): Find a way to add a warning for duplicate modules that doesn't cause log spam.\n // Dedup by id, not reference: re-resolving a lazy plugin yields fresh module objects for\n // the same ids, and double-registration would double-activate.\n this.#update(this.modules, (modules) =>\n modules.some((existing) => existing.id === module.id) ? modules : [...modules, module],\n );\n }\n\n removeModule(id: string): void {\n log('remove module', { id });\n this.#update(this.modules, (modules) => modules.filter((module) => module.id !== id));\n }\n\n pluginIdOfModule(moduleId: string): string | undefined {\n return this.getPlugins().find((plugin) => plugin.modules.some((module) => module.id === moduleId))?.meta.profile\n .key;\n }\n\n getActiveIds(): readonly string[] {\n return this.read(this.active);\n }\n\n isActive(moduleId: string): boolean {\n return this.getActiveIds().includes(moduleId);\n }\n\n markActive(moduleId: string): void {\n this.#update(this.active, (ids) => [...ids, moduleId]);\n }\n\n markInactive(moduleId: string): void {\n this.#update(this.active, (ids) => ids.filter((id) => id !== moduleId));\n }\n\n getActiveModules(): Plugin.PluginModule[] {\n const active = this.getActiveIds();\n return this.getModules().filter((module) => active.includes(module.id));\n }\n\n getInactiveModules(): Plugin.PluginModule[] {\n const active = this.getActiveIds();\n return this.getModules().filter((module) => !active.includes(module.id));\n }\n\n getActiveModulesByEvent(key: string): Plugin.PluginModule[] {\n return this.getActiveModules().filter((module) =>\n ActivationEvent.getEvents(module.activation.activatesOn).map(ActivationEvent.eventKey).includes(key),\n );\n }\n\n getInactiveModulesByEvent(key: string): Plugin.PluginModule[] {\n return this.getInactiveModules().filter((module) =>\n ActivationEvent.getEvents(module.activation.activatesOn).map(ActivationEvent.eventKey).includes(key),\n );\n }\n\n //\n // Activation events.\n //\n\n eventFired(key: string): boolean {\n return this.read(this.eventsFired).includes(key);\n }\n\n markEventFired(key: string): void {\n if (!this.eventFired(key)) {\n this.#update(this.eventsFired, (events) => [...events, key]);\n }\n }\n\n clearEventsFired(): void {\n this.#update(this.eventsFired, () => []);\n this.startupComplete = Effect.runSync(Deferred.make<void>());\n }\n\n isStarted(): Effect.Effect<boolean> {\n return Ref.get(this.started);\n }\n\n isShuttingDown(): Effect.Effect<boolean> {\n return Ref.get(this.shuttingDown);\n }\n\n //\n // Pending reset: events that already fired but whose module set changed (a plugin was\n // enabled after the fact) — replayed so the new modules activate.\n //\n\n getPendingReset(): readonly string[] {\n return this.read(this.pendingReset);\n }\n\n markPendingResetFor(module: Plugin.PluginModule): void {\n const activationEvents = ActivationEvent.getEvents(module.activation.activatesOn)\n .map(ActivationEvent.eventKey)\n .filter((key) => this.eventFired(key));\n\n const pendingReset = [...new Set(activationEvents)].filter((event) => !this.getPendingReset().includes(event));\n if (pendingReset.length > 0) {\n log('pending reset', { events: pendingReset });\n this.#update(this.pendingReset, (current) => [...current, ...pendingReset]);\n }\n }\n\n clearPendingReset(key: string): void {\n if (this.getPendingReset().includes(key)) {\n this.#update(this.pendingReset, (pending) => pending.filter((event) => event !== key));\n }\n }\n\n clearAllPendingReset(): void {\n this.#update(this.pendingReset, () => []);\n }\n\n //\n // Failures.\n //\n\n getFailures(): readonly PluginFailure[] {\n return this.read(this.failed);\n }\n\n /**\n * Records a failure for a plugin. Latest failure wins so the registry UI always sees the\n * most recent reason. Walks the `cause` chain when checking for timeouts: lazy-load\n * timeouts arrive wrapped in `LazyPluginError` (the timeout is the cause), but the\n * operator-visible reason should still be `'timeout'`.\n */\n recordFailure(id: string, phase: PluginFailurePhase, error: Error): void {\n const reason: PluginFailureReason = isTimeoutCause(error) ? 'timeout' : 'error';\n const failure: PluginFailure = { id, phase, reason, error, timestamp: Date.now() };\n // `LazyPluginError`'s own message says only that resolution failed; the import's rejection is\n // the cause, and without it a load failure is undiagnosable from the console alone.\n const cause = error.cause instanceof Error ? error.cause.message : undefined;\n log.warn('plugin failed to activate', { id, phase, reason, error: error.message, cause });\n this.#update(this.failed, (current) => [...current.filter((entry) => entry.id !== id), failure]);\n }\n\n clearFailure(id: string): boolean {\n if (!this.getFailures().some((failure) => failure.id === id)) {\n return false;\n }\n this.#update(this.failed, (current) => current.filter((failure) => failure.id !== id));\n return true;\n }\n}\n\n/**\n * Tracks fibers forked by the manager's units so shutdown can interrupt in-flight work.\n */\nexport class FiberTracker {\n readonly #fibers = Effect.runSync(Ref.make<Array<Fiber.Fiber<unknown, unknown>>>([]));\n\n track(fiber: Fiber.Fiber<unknown, unknown>): Effect.Effect<void> {\n return Ref.update(this.#fibers, (fibers) => [...fibers, fiber]);\n }\n\n untrack(fiber: Fiber.Fiber<unknown, unknown>): Effect.Effect<void> {\n return Ref.update(this.#fibers, (fibers) => fibers.filter((existing) => existing !== fiber));\n }\n\n /** Fire-and-forget: fork the effect and track the fiber until it settles. */\n fork(effect: Effect.Effect<unknown>): void {\n const fiber = Effect.runFork(effect);\n Effect.runSync(this.track(fiber));\n Effect.runFork(Fiber.await(fiber).pipe(Effect.andThen(() => this.untrack(fiber))));\n }\n\n /**\n * Registers a fiber forked inside an Effect, untracking it when it settles. The counterpart to\n * {@link fork} for effects that need the ambient context (`Plugin.Service`), which `runFork`\n * cannot supply.\n */\n trackForked(fiber: Fiber.Fiber<unknown, unknown>): Effect.Effect<void> {\n return Effect.gen({ self: this }, function* () {\n yield* this.track(fiber);\n yield* Effect.forkDetach(Fiber.await(fiber).pipe(Effect.andThen(() => this.untrack(fiber))));\n });\n }\n\n interruptAll(): Effect.Effect<void> {\n return Effect.gen({ self: this }, function* () {\n const fibers = yield* Ref.get(this.#fibers);\n yield* Effect.forEach(fibers, (fiber) => Fiber.interrupt(fiber), { concurrency: 'unbounded', discard: true });\n yield* Ref.set(this.#fibers, []);\n });\n }\n}\n\n/**\n * True when `error` (or anything along its `cause` chain) is a {@link PluginTimeoutError}.\n * Lazy-load timeouts wrap the timeout inside `LazyPluginError`, so a shallow check on the\n * outer error misses them. Bounded depth so a circular chain can't loop forever.\n */\nconst isTimeoutCause = (error: unknown, depth = 0): boolean => {\n if (depth > 5 || !(error instanceof Error)) {\n return false;\n }\n if (PluginTimeoutError.is(error)) {\n return true;\n }\n return isTimeoutCause((error as Error & { cause?: unknown }).cause, depth + 1);\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Deferred from 'effect/Deferred';\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport * as PubSub from 'effect/PubSub';\nimport * as Semaphore from 'effect/Semaphore';\n\nimport { log } from '@dxos/log';\n\nimport * as ActivationEvent from '../activation-event.ts';\nimport * as Plugin from '../plugin.ts';\nimport type * as PluginRegistry from '../registry.ts';\nimport { type ActivationScheduler } from './activation-scheduler.ts';\nimport { type ManagerState } from './manager-state.ts';\nimport { type PluginFailurePhase, PluginTimeoutError } from './manager-types.ts';\n\n/** Host configuration passed through from `ManagerOptions`. */\nexport type PluginCatalogOptions = {\n pluginLoader: (id: string) => Effect.Effect<{ plugin: Plugin.Plugin; dev?: boolean }, Error>;\n loadTimeout: Duration.Input;\n onRemove?: (id: string) => Effect.Effect<void, unknown>;\n};\n\n/**\n * The plugin catalog: add / enable / disable / remove, lazy plugin resolution, dev-plugin\n * shadowing, and the declared-dependency closure (`getDependencies` / `getDependents`).\n * Enabling resolves declared dependencies (installing registry-catalog-only entries), enables\n * in dependency-first order, and — after startup — runs an incremental activation pass for the\n * newly enabled modules. Disabling tears down dependents first, delegating plugin-level\n * deactivation to the scheduler.\n */\nexport class PluginCatalog {\n /** Coalesces concurrent lazy-plugin resolutions per plugin id. */\n readonly #resolving = new Map<string, Deferred.Deferred<Plugin.Plugin, Plugin.LazyPluginError>>();\n /** Serializes enable/disable per plugin id — see {@link PluginCatalog.#lifecycle}. */\n readonly #lifecycles = new Map<string, Semaphore.Semaphore>();\n /** Dev-sourced plugin ids, with the shadowed original (if any) for restoration on remove. */\n readonly #devPlugins = new Map<string, { shadow?: { plugin: Plugin.Plugin; wasEnabled: boolean } }>();\n readonly #state: ManagerState;\n readonly #scheduler: ActivationScheduler;\n readonly #pluginRegistry: PluginRegistry.Manager;\n readonly #options: PluginCatalogOptions;\n\n constructor(\n state: ManagerState,\n scheduler: ActivationScheduler,\n pluginRegistry: PluginRegistry.Manager,\n options: PluginCatalogOptions,\n ) {\n this.#state = state;\n this.#scheduler = scheduler;\n this.#pluginRegistry = pluginRegistry;\n this.#options = options;\n }\n\n /**\n * Fire-and-forget disable of a failed plugin. Forked because a failure can\n * happen mid-activation chain — yielding a `disable` inline would deadlock\n * on the shared semaphores. Core plugins are skipped (the host opted into\n * them being non-removable; the failure record is enough signal).\n */\n scheduleAutoDisable(id: string): void {\n if (import.meta.env.DEV && import.meta.env.MODE !== 'test') {\n // Transient HMR failures must not persist; skip auto-disable in dev server.\n return;\n }\n if (!this.#state.isCore(id) && this.#state.isEnabled(id)) {\n this.#state.fibers.fork(\n this.disable(id).pipe(\n Effect.tap(() => Effect.sync(() => log.error('plugin auto-disabled', { id }))),\n Effect.tapError((error) => Effect.sync(() => log.warn('auto-disable failed', { id, error }))),\n Effect.ignore,\n ),\n );\n }\n }\n\n /**\n * The per-plugin enable/disable lock.\n *\n * `#disableOne` flips the `enabled` atom before it tears anything down, so without this an\n * `enable` reacting to that atom re-registers the plugin's modules and the in-flight disable\n * then de-registers them again — the plugin ends up enabled with no modules. Auto-disable\n * forks precisely so taking this lock cannot deadlock an activation chain.\n */\n #lifecycle(id: string): Semaphore.Semaphore {\n let semaphore = this.#lifecycles.get(id);\n if (!semaphore) {\n semaphore = Semaphore.makeUnsafe(1);\n this.#lifecycles.set(id, semaphore);\n }\n return semaphore;\n }\n\n /** Whether the id is currently dev-sourced. */\n isDev(id: string): boolean {\n return this.#devPlugins.has(id);\n }\n\n /**\n * Marks `id` as dev-sourced. If the plugin displaced an existing one, pass\n * the shadow snapshot so `remove` can restore it. Repeat calls (e.g. a dev\n * plugin reload) preserve the original shadow target — restoration always\n * unwinds back to the real underlying plugin, never an intermediate dev build.\n */\n #markDev(id: string, shadow?: { plugin: Plugin.Plugin; wasEnabled: boolean }): void {\n if (this.#devPlugins.has(id)) {\n return;\n }\n this.#devPlugins.set(id, { shadow });\n this.#state.markDevPlugin(id);\n }\n\n /** Drops the dev-plugin entry and returns its shadow data (if any) for restoration. */\n #unmarkDev(id: string): { plugin: Plugin.Plugin; wasEnabled: boolean } | undefined {\n const entry = this.#devPlugins.get(id);\n this.#devPlugins.delete(id);\n this.#state.unmarkDevPlugin(id);\n return entry?.shadow;\n }\n\n //\n // Plugin catalog — dependency closure, add / enable / remove / disable, dev plugins.\n //\n\n getDependencies(id: string, opts?: { transitive?: boolean }): readonly string[] {\n const transitive = opts?.transitive !== false;\n if (!transitive) {\n return this.#directDependencies(id);\n }\n const walk = this.#computeDependencyClosure(id);\n // Drop the target itself; callers asked for its dependencies, not the\n // closure including the root.\n return walk.order.filter((depId) => depId !== id);\n }\n\n getDependents(id: string, opts?: { transitive?: boolean; enabledOnly?: boolean }): readonly string[] {\n return this.#collectDependents(id, {\n transitive: opts?.transitive !== false,\n enabledOnly: opts?.enabledOnly === true,\n });\n }\n\n /**\n * Adds a plugin to the manager via the plugin loader.\n * The plugin is registered but not enabled; call `enable` separately to activate it.\n * @param id The id of the plugin.\n */\n add(id: string): Effect.Effect<Plugin.Plugin, Error> {\n return Effect.gen({ self: this }, function* () {\n log('add plugin', { id });\n const { plugin, dev = false } = yield* this.#options.pluginLoader(id);\n const pluginId = plugin.meta.profile.key;\n const existing = this.#state.getPlugin(pluginId);\n\n if (dev && existing && existing !== plugin) {\n // Shadow path: a plugin with this id is already registered (a builtin,\n // a registry install, or a previous dev load). Disable it, stash it,\n // and swap the dev plugin into the same id slot. The dialog will call\n // `enable(pluginId)` next, which activates the dev plugin's modules.\n // Marking as dev is a no-op when the id is already tracked, so a dev-plugin\n // reload (after editing source) keeps the *original* shadow target —\n // removal restores the real underlying plugin, not an intermediate build.\n const wasEnabled = this.#state.isEnabled(pluginId);\n if (wasEnabled) {\n yield* this.disable(pluginId);\n }\n this.#markDev(pluginId, { plugin: existing, wasEnabled });\n this.#state.replacePlugin(pluginId, plugin);\n } else {\n this.#state.registerPlugin(plugin);\n if (dev) {\n this.#markDev(pluginId);\n }\n }\n\n return plugin;\n });\n }\n\n /**\n * Enables a plugin.\n * @param id The id of the plugin.\n * @param opts See {@link PluginManager.enable}.\n */\n enable(id: string, opts?: { resolveDependencies?: boolean }): Effect.Effect<boolean, Error, Plugin.Service> {\n const resolveDependencies = opts?.resolveDependencies !== false;\n return Effect.gen({ self: this }, function* () {\n log('enable plugin', { id, resolveDependencies });\n\n if (!resolveDependencies) {\n return yield* this.#enableOne(id);\n }\n\n // If the root id is unknown to both the registered set and the catalog,\n // fall back to the silent `_enableOne` path (which returns `false`).\n // This preserves the prior contract for persisted `enabled` entries\n // whose plugins are no longer bundled, instead of recording a confusing\n // \"missing self-dependency\" failure.\n if (!this.#state.getPlugin(id) && !this.#getCatalogEntry(id)) {\n return yield* this.#enableOne(id);\n }\n\n // Compute the transitive closure across registered plugins and catalog\n // entries. Missing or cyclic entries are recorded as failures and the\n // target plugin is left disabled.\n const walk = this.#computeDependencyClosure(id);\n if (walk.cycle) {\n this.#state.recordFailure(\n id,\n 'load',\n new Plugin.PluginDependencyError({ context: { id, reason: 'cycle', path: walk.cycle } }),\n );\n return false;\n }\n if (walk.missing.length > 0) {\n this.#state.recordFailure(\n id,\n 'load',\n new Plugin.PluginDependencyError({ context: { id, reason: 'missing', missing: walk.missing } }),\n );\n return false;\n }\n\n // Install any catalog-only entries before enabling them. `add` may also\n // discover further declared deps once the plugin's real meta is loaded;\n // we re-walk after each install to absorb those.\n let queue = walk.toInstall.slice();\n const installed = new Set<string>();\n for (let next = queue.shift(); next !== undefined; next = queue.shift()) {\n if (installed.has(next) || this.#state.getPlugin(next)) {\n continue;\n }\n const installResult = yield* this.add(next).pipe(Effect.result);\n if (installResult._tag === 'Failure') {\n this.#state.recordFailure(\n id,\n 'load',\n new Plugin.PluginDependencyError({\n context: { id, reason: 'install-failed', dependency: next },\n cause: installResult.failure,\n }),\n );\n return false;\n }\n installed.add(next);\n const rewalk = this.#computeDependencyClosure(id);\n if (rewalk.cycle) {\n this.#state.recordFailure(\n id,\n 'load',\n new Plugin.PluginDependencyError({ context: { id, reason: 'cycle', path: rewalk.cycle } }),\n );\n return false;\n }\n if (rewalk.missing.length > 0) {\n this.#state.recordFailure(\n id,\n 'load',\n new Plugin.PluginDependencyError({ context: { id, reason: 'missing', missing: rewalk.missing } }),\n );\n return false;\n }\n queue = rewalk.toInstall.filter((depId) => !installed.has(depId));\n }\n\n // Enable in dependency-first order. `_enableOne` is idempotent on the\n // enabled atom so previously-enabled deps short-circuit.\n const order = this.#computeDependencyClosure(id).order;\n let succeeded = false;\n for (const depId of order) {\n const ok = yield* this.#enableOne(depId);\n if (depId === id) {\n succeeded = ok;\n }\n }\n return succeeded;\n });\n }\n\n /**\n * Enables a single plugin without consulting its declared dependencies.\n * Used by {@link PluginCatalog.enable} as the leaf step after closure resolution, and\n * directly when callers pass `{ resolveDependencies: false }`.\n *\n * The underlying operations (module registration and pending-reset marking,\n * `activate`) are all idempotent, so this method is safe to call multiple\n * times for the same id. The constructor's bootstrap path relies on this:\n * the persisted `enabled` ids are written into `_enabledAtom` up front, so\n * the very first `enable(id)` for those plugins sees `alreadyEnabled`-style\n * state but still needs to perform the module registration and activation.\n */\n #enableOne(id: string): Effect.Effect<boolean, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n const stub = this.#state.getPlugin(id);\n if (!stub) {\n return false;\n }\n\n // Clear any prior failure record so a retry starts from a clean slate.\n // The failure stays on the atom only if this attempt also fails. Structural\n // exclusions are re-evaluated too: a newly enabled plugin may resolve them.\n this.#state.clearFailure(id);\n this.#state.structurallyFailed.clear();\n\n const plugin = yield* this.#resolveLazy(stub);\n\n this.#state.markEnabled(id);\n\n plugin.modules.forEach((module) => {\n this.#state.addModule(module);\n this.#state.markPendingResetFor(module);\n });\n\n log('pending reset', { events: [...this.#state.getPendingReset()] });\n // Replay events that already fired so the newly registered modules activate. Startup is\n // excluded: `activate` delegates it to `start()`, which would re-run the full unscoped\n // passes, re-publish the event-level `activated` message that gates app-ready, and fork a\n // second idle daemon — once per enable. The scoped pass below covers this plugin's\n // baseline-wave modules, which is all the replay was reaching for.\n const startupKey = ActivationEvent.eventKey(ActivationEvent.Startup);\n const replay = this.#state.getPendingReset().filter((event) => event !== startupKey);\n this.#state.clearPendingReset(startupKey);\n yield* Effect.all(\n replay.map((event) => this.#scheduler.activate(event)),\n { concurrency: 'unbounded' },\n );\n\n // After startup, a newly enabled module whose wave has already passed activates\n // incrementally against the already-contributed capability set. Failures are scoped to\n // this plugin. Modules still waiting on an unfired event are excluded — they activate\n // when it fires, and the pending-reset dispatch above replays the ones that already did.\n if (yield* this.#state.isStarted()) {\n const pass = this.#scheduler\n .runDependencyPass({\n candidateModules: plugin.modules.filter((module) => this.#scheduler.isEligible(module)),\n })\n .pipe(\n Effect.result,\n Effect.map((result) => {\n if (result._tag === 'Failure') {\n this.#state.recordFailure(id, 'activation', result.failure);\n }\n }),\n );\n // Streaming bootstrap: fork so `enable` (and thus `initialized`, which event dispatch\n // awaits) completes on REGISTRATION — awaiting here would serialize the entire startup\n // fan-out into the enable chain. `start()` waits for loads to settle before ready.\n if (yield* Deferred.isDone(this.#state.initialized)) {\n yield* pass;\n // A plugin enabled after boot missed every host fire of its own start event, and the\n // pending-reset replay above only covers events that fired — so fire it here, or the\n // plugin's start-gated modules would never activate.\n yield* this.#scheduler\n .activate(ActivationEvent.pluginStart(id))\n .pipe(Effect.catch((error) => Effect.sync(() => this.#state.recordFailure(id, 'activation', error))));\n } else {\n // Tracked so `shutdown()` interrupts an incremental pass still running from the\n // bootstrap enable chain.\n yield* this.#state.fibers.trackForked(yield* pass.pipe(Effect.forkDetach));\n }\n }\n\n return true;\n }).pipe(this.#lifecycle(id).withPermits(1));\n }\n\n /**\n * Resolves a lazy plugin stub (returned by {@link Plugin.lazy}) to its\n * loaded form and swaps it into `_pluginsAtom`. Returns the input unchanged\n * when the plugin is already resolved, so callers can `yield*` this\n * unconditionally. The lazy stub carries `meta` synchronously but its\n * `modules` list is empty until the loader resolves; the swap ensures\n * subsequent enable/disable operations see the resolved plugin.\n *\n * Concurrent calls for the same id are coalesced:\n * the first caller starts the resolution, every subsequent caller awaits\n * the same `Deferred`. On failure we publish a `lazy:<id>` error message\n * and skip the atom swap so the failure is observable to the activation\n * subscriber and a retry can be attempted.\n */\n #resolveLazy(plugin: Plugin.Plugin): Effect.Effect<Plugin.Plugin, Plugin.LazyPluginError> {\n return Effect.gen({ self: this }, function* () {\n if (!Plugin.isLazy(plugin)) {\n return plugin;\n }\n const id = plugin.meta.profile.key;\n\n const existing = this.#resolving.get(id);\n if (existing) {\n return yield* Deferred.await(existing);\n }\n const deferred = yield* Deferred.make<Plugin.Plugin, Plugin.LazyPluginError>();\n this.#resolving.set(id, deferred);\n\n return yield* Effect.gen({ self: this }, function* () {\n log('resolving lazy plugin', { id });\n yield* PubSub.publish(this.#state.activation, { event: '', state: 'activating', module: `lazy:${id}` });\n // The plugin-definition chunk import is startup work that predates any module\n // activation; measured so the profiler can attribute it per plugin.\n performance.mark(`plugin-load:${id}:start`);\n const resolvedPlugin = yield* Plugin.resolveLazy(plugin).pipe(\n // Cap how long a remote import can hang. Without this the host can\n // sit on a pending dynamic `import()` indefinitely if the plugin's\n // server is unreachable, which stalls every caller awaiting\n // `enable(id)` and (transitively) the manager's initialization.\n Effect.timeoutOrElse({\n duration: this.#options.loadTimeout,\n orElse: () =>\n Effect.fail(\n new Plugin.LazyPluginError({\n context: { id, reason: 'load-failed' },\n cause: new PluginTimeoutError({ context: { id, phase: 'load' as PluginFailurePhase } }),\n }),\n ),\n }),\n );\n performance.mark(`plugin-load:${id}:end`);\n performance.measure(`plugin-load:${id}`, `plugin-load:${id}:start`, `plugin-load:${id}:end`);\n this.#state.replacePlugin(id, resolvedPlugin);\n yield* PubSub.publish(this.#state.activation, { event: '', state: 'activated', module: `lazy:${id}` });\n return resolvedPlugin;\n }).pipe(\n Effect.tapError((error) =>\n Effect.gen({ self: this }, function* () {\n yield* PubSub.publish(this.#state.activation, { event: '', state: 'error', module: `lazy:${id}`, error });\n this.#state.recordFailure(id, 'load', error);\n this.scheduleAutoDisable(id);\n }),\n ),\n Effect.tap((value) => Deferred.succeed(deferred, value)),\n Effect.tapCause((cause) => Deferred.failCause(deferred, cause)),\n Effect.ensuring(Effect.sync(() => this.#resolving.delete(id))),\n );\n });\n }\n\n /**\n * Removes a plugin from the manager.\n * @param id The id of the plugin.\n * @param opts See {@link PluginManager.remove}.\n */\n remove(id: string, opts?: { cascade?: boolean }): Effect.Effect<boolean, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n log('remove plugin', { id });\n const wasDev = this.#devPlugins.has(id);\n const disabled = yield* this.disable(id, opts);\n if (!disabled) {\n return false;\n }\n\n this.#state.unregisterPlugin(id);\n if (this.#options.onRemove) {\n this.#state.fibers.fork(\n this.#options.onRemove(id).pipe(\n Effect.tapError((error) => Effect.sync(() => log.warn('plugin remove hook failed', { id, error }))),\n Effect.ignore,\n ),\n );\n }\n\n // If a dev plugin was shadowing an existing plugin, reinstate the\n // original now that the dev plugin is gone. Re-enable only if the\n // original was enabled at shadow time — preserving the user's intent\n // for plugins they had explicitly disabled before iterating on a dev\n // build.\n if (wasDev) {\n const shadow = this.#unmarkDev(id);\n if (shadow) {\n this.#state.registerPlugin(shadow.plugin);\n if (shadow.wasEnabled) {\n yield* this.enable(id);\n }\n }\n }\n return true;\n });\n }\n\n /**\n * Disables a plugin.\n * @param id The id of the plugin.\n * @param opts See {@link PluginManager.disable}.\n */\n disable(id: string, { cascade = true }: { cascade?: boolean } = {}): Effect.Effect<boolean, Error> {\n return Effect.gen({ self: this }, function* () {\n log('disable plugin', { id, cascade });\n if (this.#state.isCore(id)) {\n return false;\n }\n\n const plugin = this.#state.getPlugin(id);\n if (!plugin) {\n return false;\n }\n\n if (cascade) {\n const enabledDependents = this.#collectDependents(id, { transitive: true, enabledOnly: true });\n if (enabledDependents.length > 0) {\n const coreDependent = enabledDependents.find((dependentId) => this.#state.isCore(dependentId));\n if (coreDependent) {\n return yield* Effect.fail(\n new Plugin.PluginDependencyError({\n context: { id, reason: 'core-dependent', coreDependent },\n }),\n );\n }\n // Disable transitive dependents first (leaves before root). The\n // walk returns them in dependents-before-deps order — exactly what\n // we want for teardown.\n for (const dependentId of enabledDependents) {\n yield* this.#disableOne(dependentId);\n }\n }\n }\n\n yield* this.#disableOne(id);\n return true;\n });\n }\n\n /**\n * Disables a single plugin without consulting its dependents. Used by\n * {@link PluginCatalog.disable} after the dependents pass has run (or been skipped via\n * `cascade: false`).\n */\n #disableOne(id: string): Effect.Effect<boolean, Error> {\n return Effect.gen({ self: this }, function* () {\n if (this.#state.isCore(id)) {\n return false;\n }\n const plugin = this.#state.getPlugin(id);\n if (!plugin) {\n return false;\n }\n const enabledIndex = this.#state.read(this.#state.enabled).findIndex((enabled) => enabled === id);\n if (enabledIndex !== -1) {\n this.#state.markDisabled(id);\n yield* this.#scheduler.deactivatePlugin(id);\n plugin.modules.forEach((module) => {\n this.#state.removeModule(module.id);\n });\n }\n return true;\n }).pipe(this.#lifecycle(id).withPermits(1));\n }\n\n /** Entries of the cached registry catalog. */\n #catalogEntries(): readonly Plugin.Meta[] {\n return this.#state.read(this.#pluginRegistry.plugins).entries;\n }\n\n /** Looks up an id in the cached registry catalog, returning the entry or `undefined`. */\n #getCatalogEntry(id: string): Plugin.Meta | undefined {\n return this.#catalogEntries().find((entry) => entry.profile.key === id);\n }\n\n /**\n * Returns the direct `dependsOn` declarations for an id, drawing from the\n * registered plugin's meta when available and falling back to the registry\n * catalog entry. Unknown ids return an empty list (callers detect \"missing\"\n * separately).\n */\n #directDependencies(id: string): string[] {\n const plugin = this.#state.getPlugin(id);\n if (plugin) {\n return [...(plugin.meta.profile.dependsOn ?? [])];\n }\n const catalog = this.#getCatalogEntry(id);\n return catalog?.profile.dependsOn ? [...catalog.profile.dependsOn] : [];\n }\n\n /**\n * Computes the transitive dependency closure for an id.\n *\n * Walks {@link #directDependencies} (registered plugins ∪ catalog entries).\n * Returns:\n * - `order`: closure including the root in dependency-first topological order.\n * - `missing`: ids in the closure that are neither registered nor in the catalog.\n * - `toInstall`: ids in the closure that are in the catalog but not yet registered.\n * - `cycle`: when a cycle is detected, the cycle path; otherwise `undefined`.\n */\n #computeDependencyClosure(id: string): {\n order: string[];\n missing: string[];\n toInstall: string[];\n cycle?: string[];\n } {\n const order: string[] = [];\n const visited = new Set<string>();\n const onStack = new Set<string>();\n const stackPath: string[] = [];\n const missing: string[] = [];\n const toInstall: string[] = [];\n let cycle: string[] | undefined;\n\n const knownIds = new Set<string>([\n ...this.#state.getPlugins().map((plugin) => plugin.meta.profile.key),\n ...this.#catalogEntries().map((entry) => entry.profile.key),\n ]);\n\n const visit = (currentId: string): void => {\n if (cycle) {\n return;\n }\n if (visited.has(currentId)) {\n return;\n }\n if (onStack.has(currentId)) {\n const cycleStart = stackPath.indexOf(currentId);\n cycle = [...stackPath.slice(cycleStart), currentId];\n return;\n }\n onStack.add(currentId);\n stackPath.push(currentId);\n\n if (!knownIds.has(currentId)) {\n missing.push(currentId);\n } else if (!this.#state.getPlugin(currentId)) {\n toInstall.push(currentId);\n }\n\n for (const depId of this.#directDependencies(currentId)) {\n visit(depId);\n if (cycle) {\n break;\n }\n }\n\n onStack.delete(currentId);\n stackPath.pop();\n if (!cycle) {\n visited.add(currentId);\n order.push(currentId);\n }\n };\n\n visit(id);\n return { order, missing, toInstall, cycle };\n }\n\n /**\n * Walks the reverse `dependsOn` edges across registered plugins. With\n * `enabledOnly`, filters the result to currently-enabled ids. Returns\n * dependents in dependents-before-deps order so callers (cascade-disable)\n * can iterate and tear down leaves first.\n */\n #collectDependents(id: string, opts: { transitive: boolean; enabledOnly: boolean }): string[] {\n const direct = this.#state\n .getPlugins()\n .filter((plugin) => plugin.meta.profile.dependsOn?.some((dep) => dep === id))\n .map((plugin) => plugin.meta.profile.key);\n\n if (!opts.transitive) {\n return opts.enabledOnly ? direct.filter((dependentId) => this.#state.isEnabled(dependentId)) : direct;\n }\n\n const result: string[] = [];\n const visited = new Set<string>();\n const visit = (currentId: string): void => {\n if (visited.has(currentId)) {\n return;\n }\n visited.add(currentId);\n const parents = this.#state\n .getPlugins()\n .filter((plugin) => plugin.meta.profile.dependsOn?.some((dep) => dep === currentId))\n .map((plugin) => plugin.meta.profile.key);\n for (const parentId of parents) {\n visit(parentId);\n if (parentId !== id && !result.includes(parentId)) {\n result.push(parentId);\n }\n }\n };\n visit(id);\n\n return opts.enabledOnly ? result.filter((dependentId) => this.#state.isEnabled(dependentId)) : result;\n }\n}\n","//\n// Copyright 2025 DXOS.org\n//\n\n//\n// The manager composes collaborating units behind one public API. Each unit receives the\n// shared substrate — `ManagerState` (`manager-state.ts`): the reactive atoms, the activation\n// status channel, the fiber tracker, and the lifecycle flags — plus the collaborators it\n// drives and its own host configuration. Nothing receives a manager reference or a callback\n// into another unit:\n//\n// 1. The plugin catalog (`plugin-catalog.ts`) — add/remove/enable/disable, lazy plugin\n// resolution, dev-plugin shadowing, and the declared-dependency closure\n// (`getDependencies`/`getDependents`). Collaborators: the scheduler (event replay and\n// plugin deactivation) and the registry catalog.\n//\n// 2. The activation scheduler (`activation-scheduler.ts`) — the lifecycle engine\n// (start / activate / deactivate / reset) and the decision of when each module's\n// `activate` runs. Dependency-mode modules activate in rounds (ordering logic and\n// vocabulary in `activation-graph.ts`), repeated until one activates nothing new;\n// event-mode modules park until their `activatesOn` fires, with inactive dependency\n// providers pulled on demand first. Collaborator: the loader.\n//\n// 3. The module loader (`module-loader.ts`) — the per-module load pipeline. Loads are\n// memoized (id -> Deferred): every activation path converges on `loader.load`, concurrent\n// paths await the same deferred, and contribution is idempotent per module. Because\n// rounds run concurrently (the startup pass and an event fired mid-startup), the loader\n// also waits for in-flight multi providers before a module's activate runs.\n//\n// Module bodies receive the manager as the ambient `Plugin.Service`. That dependency is\n// carried as a typed Effect requirement (`R = Plugin.Service`) through the loader, scheduler,\n// and catalog, and satisfied exactly once here, at the public boundary.\n//\n// Failures are STRUCTURAL, not fatal: missing/duplicate providers and cycles put the owning\n// plugin into an error state (the `failed` atom) and exclude its modules; everything\n// independent proceeds. Per-module failures skip transitive dependents only. The\n// failure -> auto-disable policy is wired here at the composition root, by observing the\n// status channel (the loader publishes module errors; the catalog owns disabling).\n//\n\nimport * as Deferred from 'effect/Deferred';\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport * as Fiber from 'effect/Fiber';\nimport * as PubSub from 'effect/PubSub';\nimport * as Atom from 'effect/reactivity/Atom';\nimport * as Registry from 'effect/reactivity/AtomRegistry';\nimport * as Ref from 'effect/Ref';\nimport * as Semaphore from 'effect/Semaphore';\n\nimport * as AtomEx from '@dxos/effect/AtomEx';\nimport * as EffectEx from '@dxos/effect/EffectEx';\nimport { log } from '@dxos/log';\n\nimport type * as ActivationEvent from '../activation-event.ts';\nimport * as CapabilityManager from '../capability-manager.ts';\nimport * as Plugin from '../plugin.ts';\n// Imported with a `PluginRegistry` alias because the unrelated `@effect/atom-react`\n// `Registry` is already imported above; from outside this file the namespace is\n// re-exported as `Registry` via `./index.ts`.\nimport * as PluginRegistry from '../registry.ts';\nimport { ActivationScheduler } from './activation-scheduler.ts';\nimport { ManagerState } from './manager-state.ts';\nimport {\n type ActivationMessage,\n DEFAULT_ACTIVATION_TIMEOUT,\n DEFAULT_LOAD_TIMEOUT,\n type PluginFailure,\n PluginInitializationError,\n PluginTimeoutError,\n} from './manager-types.ts';\nimport { ModuleLoader } from './module-loader.ts';\nimport { PluginCatalog } from './plugin-catalog.ts';\n\n// Shared with the manager's collaborating units; the canonical public surface stays here.\nexport { PluginInitializationError, PluginTimeoutError } from './manager-types.ts';\nexport type { ActivationMessage, PluginFailure, PluginFailurePhase, PluginFailureReason } from './manager-types.ts';\n\n/**\n * Identifier denoting a Manager.\n */\nexport const ManagerTypeId: unique symbol = Symbol.for('@dxos/app-framework/Manager');\nexport type ManagerTypeId = typeof ManagerTypeId;\n\n/**\n * Loader result that carries optional metadata about how the plugin was sourced.\n *\n * `dev: true` marks a plugin as session-only and triggers shadow-on-id-collision\n * inside the manager: if a plugin with the same id is already registered (a\n * builtin, or a previously-installed plugin from the registry), the dev plugin\n * temporarily takes over that id slot. The original is restored when the dev\n * plugin is removed (or on page reload, since dev plugins aren't persisted).\n */\nexport type LoadedPlugin = {\n plugin: Plugin.Plugin;\n /** True when the plugin came from a dev source. See type doc for semantics. */\n dev?: boolean;\n};\n\nexport type ManagerOptions = {\n pluginLoader: (id: string) => Effect.Effect<LoadedPlugin, Error>;\n plugins?: Plugin.Plugin[];\n enabled?: string[];\n /**\n * Ids of plugins the host pins on: always enabled, never disableable.\n *\n * Defaults to every plugin declaring `system` in `meta.profile.tags`. Hosts pass\n * this when the tag is the wrong authority — a plugin's `dx.config.ts` declares\n * one `system` tag for every host, so without an override the CLI inherits\n * Composer's judgment about what a user may turn off. Ids not present in\n * `plugins` are ignored.\n */\n core?: string[];\n /** Registry to use instead of creating one; `atomIdleTTL` does not apply to it. */\n registry?: Registry.AtomRegistry;\n /**\n * Backend for the plugin registry catalog. When omitted the manager exposes a\n * no-op `pluginRegistry` (empty list, no versions endpoint). Implementations\n * live in app-framework alongside the interface (e.g.\n * `EdgeRegistryPluginProvider`); the host app instantiates one and passes it in.\n */\n pluginRegistryProvider?: PluginRegistry.PluginProvider;\n /**\n * Hook called when a plugin is removed via {@link PluginManager.remove}. Used by the\n * host app to clean up persisted state (e.g. evict offline-cached plugin assets).\n * Failures are logged and swallowed; removal still succeeds even if the hook fails.\n */\n onRemove?: (id: string) => Effect.Effect<void, unknown>;\n /**\n * Maximum time allowed for a lazy plugin's dynamic `import()` to resolve.\n * Plugins that exceed this are flagged on the {@link PluginManager.failed}\n * atom and auto-disabled so a stuck remote host can't stall app boot.\n * Defaults to 30 seconds; pass `Duration.infinity` to disable.\n */\n loadTimeout?: Duration.Input;\n /**\n * Grace period before an atom with no subscribers is removed from the registry this manager creates.\n * Defaults to {@link AtomEx.DEFAULT_IDLE_TTL}; see `AtomEx.makeRegistry`.\n */\n atomIdleTTL?: Duration.Input;\n /**\n * Maximum time allowed for a single module's `activate()` Effect to settle.\n * Modules that exceed this fail with {@link PluginTimeoutError}; the owning\n * plugin is recorded on `failed` and auto-disabled. Defaults to 30 seconds;\n * pass `Duration.infinity` to disable.\n */\n activationTimeout?: Duration.Input;\n /**\n * Completes when the host is idle, gating the Idle wave. Defaults to the real paint/idle wait,\n * which resolves immediately off-browser; `Effect.never` models a browser that has not idled.\n */\n whenIdle?: Effect.Effect<void>;\n};\n\n/**\n * Interface for the Plugin Manager.\n */\nexport interface PluginManager {\n readonly [ManagerTypeId]: ManagerTypeId;\n readonly activation: PubSub.PubSub<ActivationMessage>;\n readonly capabilities: CapabilityManager.CapabilityManager;\n readonly registry: Registry.AtomRegistry;\n /**\n * Cached registry catalog state plus pass-throughs for `listVersions` /\n * `getPlugin`. Always present — the host supplies a `pluginRegistryProvider`\n * via {@link ManagerOptions} for real backends, or it falls back to a no-op\n * implementation that yields an empty catalog.\n */\n readonly pluginRegistry: PluginRegistry.Manager;\n\n readonly plugins: Atom.Atom<readonly Plugin.Plugin[]>;\n readonly core: Atom.Atom<readonly string[]>;\n readonly enabled: Atom.Atom<readonly string[]>;\n readonly modules: Atom.Atom<readonly Plugin.PluginModule[]>;\n readonly active: Atom.Atom<readonly string[]>;\n readonly eventsFired: Atom.Atom<readonly string[]>;\n readonly pendingReset: Atom.Atom<readonly string[]>;\n /**\n * Plugins that failed to load or activate. Subscribers (e.g. the registry\n * UI) can use this to flag unhealthy entries; a plugin id appears here at\n * most once with its most recent failure.\n */\n readonly failed: Atom.Atom<readonly PluginFailure[]>;\n /**\n * Ids of currently-registered plugins that came from a dev source (loaded\n * via {@link LoadedPlugin} with `dev: true`). Subscribers can use this to\n * badge dev-overridden plugins or to derive the id of the active dev plugin\n * for an \"uninstall dev plugin\" affordance.\n */\n readonly devPluginIds: Atom.Atom<readonly string[]>;\n\n getPlugins(): readonly Plugin.Plugin[];\n getCore(): readonly string[];\n getEnabled(): readonly string[];\n getModules(): readonly Plugin.PluginModule[];\n getActive(): readonly string[];\n getEventsFired(): readonly string[];\n getPendingReset(): readonly string[];\n getFailed(): readonly PluginFailure[];\n getDevPluginIds(): readonly string[];\n\n /**\n * Clears the failure record for a plugin so it can be retried. Returns\n * whether a failure record existed and was removed.\n */\n clearFailure(id: string): boolean;\n\n /**\n * Loads a plugin via the plugin loader and registers it without enabling it.\n * Returns the loaded plugin so callers can enable it by its canonical id\n * (which may differ from the locator used to load it, e.g. URL loaders).\n * A plugin whose id is already enabled, such as one persisted from an earlier\n * session, is activated as part of the add.\n */\n add(id: string): Effect.Effect<Plugin.Plugin, Error>;\n\n /**\n * Enables a plugin.\n *\n * Default behavior auto-resolves the plugin's declared `dependsOn` closure:\n * missing entries that exist in the plugin registry catalog are installed via\n * {@link add}, then enabled in dependency-first order. Set `resolveDependencies`\n * to `false` to enable only the named plugin and skip the closure walk\n * entirely — useful when substituting an alternative plugin that satisfies\n * the dependent's capability needs in its own way.\n */\n enable(id: string, opts?: { resolveDependencies?: boolean }): Effect.Effect<boolean, Error>;\n\n /**\n * Removes a plugin from the manager (disables then unregisters).\n *\n * Honors the same cascade option as {@link disable}.\n */\n remove(id: string, opts?: { cascade?: boolean }): Effect.Effect<boolean, Error>;\n\n /**\n * Disables a plugin.\n *\n * By default, cascades to currently-enabled dependents (transitively, leaves\n * first) so disabling a depended-upon plugin never leaves its dependents\n * stranded. Pass `cascade: false` to disable only the named plugin and leave\n * its dependents enabled-but-broken — VS Code-style disable parity for\n * callers that want the escape hatch (e.g. when swapping in an alternative\n * implementation that satisfies the dependents' needs in its own way).\n *\n * Fails with {@link Plugin.PluginDependencyError} (`reason: 'core-dependent'`)\n * when cascading would require disabling a core plugin; UI flows should\n * surface their own confirmation before calling `disable` with the default.\n */\n disable(id: string, opts?: { cascade?: boolean }): Effect.Effect<boolean, Error>;\n\n /**\n * Returns the plugin ids that the given plugin declares as dependencies.\n *\n * Walks `meta.dependsOn` from both registered plugins and the plugin registry\n * catalog so callers can preview the closure for a plugin that isn't yet\n * installed. With `transitive: true` (default), returns the full dependency\n * closure in dependency-first order (deps before dependents). Without it,\n * returns the direct declarations only.\n */\n getDependencies(id: string, opts?: { transitive?: boolean }): readonly string[];\n\n /**\n * Returns the plugin ids that declare the given plugin as a dependency.\n *\n * Walks `meta.dependsOn` over registered plugins. With `transitive: true`\n * (default), returns the full reverse closure. With `enabledOnly: true`,\n * filters to currently-enabled dependents — used by UI flows to preview what\n * a cascading disable would touch.\n */\n getDependents(id: string, opts?: { transitive?: boolean; enabledOnly?: boolean }): readonly string[];\n /**\n * Runs startup: the capability-dependency resolution pass for dependency-mode modules,\n * concurrently with the event-mode activation pass for any module explicitly targeting the\n * Startup event. The event-level Startup `activated` message publishes only after both\n * passes complete. Idempotent — subsequent calls activate whatever registered since.\n * `activate(Startup)` delegates here.\n */\n start(): Effect.Effect<boolean, Error>;\n // TODO(wittjosiah): Improve error typing.\n activate(\n event: ActivationEvent.ActivationEvent | string,\n params?: { before?: string; after?: string },\n ): Effect.Effect<boolean, Error>;\n deactivate(id: string): Effect.Effect<boolean, Error>;\n reset(event: ActivationEvent.ActivationEvent | string): Effect.Effect<boolean, Error>;\n\n /**\n * Shuts down the manager by deactivating all active modules in reverse activation order,\n * clearing all capabilities, and resetting lifecycle bookkeeping.\n * Plugins, core, enabled, and modules remain intact so the manager can be reused.\n */\n shutdown(): Effect.Effect<boolean, Error>;\n}\n\n/**\n * Type guard to check if a value is a PluginManager.\n */\nexport const isManager = (value: unknown): value is PluginManager => {\n return typeof value === 'object' && value !== null && ManagerTypeId in value;\n};\n\n/**\n * Internal implementation of PluginManager.\n */\nclass ManagerImpl implements PluginManager {\n readonly [ManagerTypeId]: ManagerTypeId = ManagerTypeId;\n readonly capabilities: CapabilityManager.CapabilityManager;\n readonly registry: Registry.AtomRegistry;\n readonly pluginRegistry: PluginRegistry.Manager;\n\n private readonly _state: ManagerState;\n private readonly _loader: ModuleLoader;\n private readonly _scheduler: ActivationScheduler;\n private readonly _catalog: PluginCatalog;\n private readonly _shutdownSemaphore = Semaphore.makeUnsafe(1);\n /** The failure-supervision fiber; stopped by `shutdown`, restarted by `_withRuntime`. */\n private _supervisor: Fiber.Fiber<never> | undefined;\n\n constructor({\n pluginLoader,\n plugins = [],\n enabled = [],\n core: coreProp,\n registry,\n pluginRegistryProvider,\n onRemove,\n loadTimeout = DEFAULT_LOAD_TIMEOUT,\n activationTimeout = DEFAULT_ACTIVATION_TIMEOUT,\n atomIdleTTL = AtomEx.DEFAULT_IDLE_TTL,\n whenIdle,\n }: ManagerOptions) {\n // Core plugins default to `meta.tags.includes('system')`, overridden by the host's\n // explicit set. Either way the set is a snapshot of the initial `plugins` array\n // (later `add()` calls do not promote plugins to core), and a host-supplied id\n // that names no registered plugin is dropped rather than pinning a phantom.\n const registered = new Set(plugins.map(({ meta }) => meta.profile.key));\n const core: string[] = coreProp\n ? coreProp.filter((id) => registered.has(id))\n : plugins.filter(({ meta }) => meta.profile.tags?.includes('system')).map(({ meta }) => meta.profile.key);\n this.registry = registry ?? AtomEx.makeRegistry({ idleTTL: atomIdleTTL });\n this.capabilities = CapabilityManager.make({\n registry: this.registry,\n });\n this.pluginRegistry = new PluginRegistry.Manager(pluginRegistryProvider, this.registry);\n\n this._state = new ManagerState(this.registry, { plugins, core, enabled });\n this._loader = new ModuleLoader(this._state, this.capabilities, activationTimeout);\n this._scheduler = new ActivationScheduler(this._state, this.capabilities, this._loader, whenIdle);\n this._catalog = new PluginCatalog(this._state, this._scheduler, this.pluginRegistry, {\n pluginLoader,\n loadTimeout,\n onRemove,\n });\n this._superviseFailures();\n\n // The initialization flag lets event dispatch wait for the constructor-launched\n // core/enabled `enable()` calls to finish registering modules. Lazy plugins make\n // `enable` asynchronous (a dynamic `import()` happens inside it), so without this\n // synchronization an `activate` triggered immediately after `make` could fire on an\n // empty module set. Failures are wrapped in `PluginInitializationError` so awaiters\n // get a tagged error rather than the wide `Error` produced by the underlying chain.\n //\n // Dedupe before mapping to `enable` — `core` and `enabled` may overlap (an\n // app-supplied plugin can be in both); same-id work is coalesced at the leaf\n // (lazy resolution) and module registration dedupes by id, but the dedupe\n // avoids redundant walks. `new Set([...])` preserves first-seen order which\n // matches the natural core-before-enabled precedence. Bounded concurrency:\n // sequential enables serialize ~60 plugin-definition imports (~1.7 s of the\n // boot critical path); unbounded would recreate the import contention plateau.\n const initialIds = [...new Set([...core, ...enabled])];\n void Effect.all(\n initialIds.map((id) => this.enable(id)),\n { concurrency: 8 },\n )\n .pipe(\n Effect.mapError((cause) => new PluginInitializationError({ cause })),\n Effect.tap(() => Deferred.succeed(this._state.initialized, undefined)),\n Effect.tapCause((cause) => Deferred.failCause(this._state.initialized, cause)),\n )\n .pipe(EffectEx.runAndForwardErrors);\n }\n\n get activation(): PubSub.PubSub<ActivationMessage> {\n return this._state.activation;\n }\n\n /**\n * Cross-unit failure policy, wired at the composition root: the loader publishes a module\n * error message for every failed activation; the catalog owns disabling. Idempotent —\n * a supervisor that is already running is kept.\n */\n private _superviseFailures(): void {\n if (this._supervisor !== undefined) {\n return;\n }\n this._supervisor = PubSub.subscribe(this._state.activation).pipe(\n Effect.flatMap((subscription) =>\n PubSub.take(subscription).pipe(\n Effect.tap((message) => Effect.sync(() => this._autoDisableOnModuleError(message))),\n Effect.forever,\n ),\n ),\n Effect.scoped,\n Effect.runFork,\n );\n }\n\n /**\n * Auto-disables the plugin owning a failed module. Error messages without a registered\n * module id (structural failures, lazy plugin loads) are handled by their own paths.\n */\n private _autoDisableOnModuleError(message: ActivationMessage): void {\n if (message.state !== 'error' || message.module === undefined) {\n return;\n }\n const pluginId = this._state.pluginIdOfModule(message.module);\n if (pluginId !== undefined) {\n this._catalog.scheduleAutoDisable(pluginId);\n }\n }\n\n /**\n * Entry wrapper for the unit effects that can run module activations: provides this manager\n * as the ambient `Plugin.Service` (the typed requirement carried by the units) and ensures\n * the failure supervisor is running (shutdown stops it).\n */\n private readonly _withRuntime = <A, E>(effect: Effect.Effect<A, E, Plugin.Service>): Effect.Effect<A, E> => {\n return Effect.suspend(() => {\n this._superviseFailures();\n return Effect.provideService(effect, Plugin.Service, this);\n });\n };\n\n get plugins(): Atom.Atom<readonly Plugin.Plugin[]> {\n return this._state.plugins;\n }\n\n get core(): Atom.Atom<readonly string[]> {\n return this._state.core;\n }\n\n /**\n * Ids of plugins that are currently enabled.\n */\n get enabled(): Atom.Atom<readonly string[]> {\n return this._state.enabled;\n }\n\n /**\n * Modules of plugins which are currently enabled.\n */\n get modules(): Atom.Atom<readonly Plugin.PluginModule[]> {\n return this._state.modules;\n }\n\n /**\n * Ids of modules which are currently active.\n */\n get active(): Atom.Atom<readonly string[]> {\n return this._state.active;\n }\n\n /**\n * Ids of events which have been fired.\n */\n get eventsFired(): Atom.Atom<readonly string[]> {\n return this._state.eventsFired;\n }\n\n /**\n * Ids of modules which are pending reset.\n */\n get pendingReset(): Atom.Atom<readonly string[]> {\n return this._state.pendingReset;\n }\n\n /**\n * Plugins that failed to load or activate.\n */\n get failed(): Atom.Atom<readonly PluginFailure[]> {\n return this._state.failed;\n }\n\n /**\n * Ids of currently-registered plugins that came from a dev source.\n */\n get devPluginIds(): Atom.Atom<readonly string[]> {\n return this._state.devPluginIds;\n }\n\n getPlugins(): readonly Plugin.Plugin[] {\n return this._state.getPlugins();\n }\n\n getCore(): readonly string[] {\n return this._state.read(this._state.core);\n }\n\n getEnabled(): readonly string[] {\n return this._state.read(this._state.enabled);\n }\n\n getModules(): readonly Plugin.PluginModule[] {\n return this._state.getModules();\n }\n\n getActive(): readonly string[] {\n return this._state.getActiveIds();\n }\n\n getEventsFired(): readonly string[] {\n return this._state.read(this._state.eventsFired);\n }\n\n getPendingReset(): readonly string[] {\n return this._state.getPendingReset();\n }\n\n getFailed(): readonly PluginFailure[] {\n return this._state.getFailures();\n }\n\n getDevPluginIds(): readonly string[] {\n return this._state.read(this._state.devPluginIds);\n }\n\n clearFailure(id: string): boolean {\n return this._state.clearFailure(id);\n }\n\n getDependencies(id: string, opts?: { transitive?: boolean }): readonly string[] {\n return this._catalog.getDependencies(id, opts);\n }\n\n getDependents(id: string, opts?: { transitive?: boolean; enabledOnly?: boolean }): readonly string[] {\n return this._catalog.getDependents(id, opts);\n }\n\n add(id: string): Effect.Effect<Plugin.Plugin, Error> {\n return this._catalog.add(id).pipe(\n // An id already in the enabled set (persisted from an earlier session) would otherwise read\n // as enabled while none of its modules is registered, and no toggle short of off-and-on starts it.\n Effect.tap((plugin) =>\n this._state.isEnabled(plugin.meta.profile.key) ? this.enable(plugin.meta.profile.key) : Effect.void,\n ),\n );\n }\n\n enable(id: string, opts?: { resolveDependencies?: boolean }): Effect.Effect<boolean, Error> {\n return this._catalog.enable(id, opts).pipe(this._withRuntime);\n }\n\n remove(id: string, opts?: { cascade?: boolean }): Effect.Effect<boolean, Error> {\n return this._catalog.remove(id, opts).pipe(this._withRuntime);\n }\n\n disable(id: string, opts?: { cascade?: boolean }): Effect.Effect<boolean, Error> {\n // Await the constructor's (concurrent) enable chain: a disable racing bootstrap\n // would miss not-yet-enabled dependents and cascade incorrectly.\n return Deferred.await(this._state.initialized).pipe(Effect.andThen(this._catalog.disable(id, opts)));\n }\n\n //\n // Lifecycle — delegated to the scheduler; `shutdown` is composition-wide and stays here.\n //\n\n start(): Effect.Effect<boolean, Error> {\n return this._scheduler.start().pipe(this._withRuntime);\n }\n\n activate(\n event: ActivationEvent.ActivationEvent | string,\n params?: { before?: string; after?: string },\n ): Effect.Effect<boolean, Error> {\n return this._scheduler.activate(event, params).pipe(this._withRuntime);\n }\n\n deactivate(id: string): Effect.Effect<boolean, Error> {\n return this._scheduler.deactivatePlugin(id);\n }\n\n reset(event: ActivationEvent.ActivationEvent | string): Effect.Effect<boolean, Error> {\n return this._scheduler.resetEvent(event).pipe(this._withRuntime);\n }\n\n shutdown(): Effect.Effect<boolean, Error> {\n return this._shutdownSemaphore.withPermits(1)(\n Effect.gen({ self: this }, function* () {\n yield* Ref.set(this._state.shuttingDown, true);\n log('shutdown');\n\n if (this._supervisor !== undefined) {\n yield* Fiber.interrupt(this._supervisor);\n this._supervisor = undefined;\n }\n yield* this._state.fibers.interruptAll();\n\n const activeIds = [...this._state.getActiveIds()].reverse();\n const allModules = this._state.getModules();\n const modulesToDeactivate = activeIds\n .map((id) => allModules.find((module) => module.id === id))\n .filter((module): module is Plugin.PluginModule => module != null);\n\n for (const module of modulesToDeactivate) {\n yield* this._loader.deactivate(module);\n }\n\n this._state.clearEventsFired();\n this._state.clearAllPendingReset();\n yield* this._loader.clear();\n yield* this._scheduler.clearClaims();\n yield* Ref.set(this._state.started, false);\n this._state.reactivateOnNextPass.clear();\n this._state.structurallyFailed.clear();\n\n log('shutdown complete');\n return true;\n }).pipe(Effect.ensuring(Ref.set(this._state.shuttingDown, false))),\n );\n }\n}\n\n/**\n * Creates a new Plugin Manager instance.\n */\nexport const make = (options: ManagerOptions): PluginManager => new ManagerImpl(options);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chunk-plugin-manager.mjs","names":["__dxlog_file","Capabilities.ReactSurface","Plugin.Service","ActivationEvent.pluginStart","Capability.Service","Capability.CurrentModuleId","Capability.ActivatingModuleIds","CapabilityManager.normalizeActivateResult","CapabilityManager.expandContributions","CapabilityManager.isContribution","__dxlog_file","ActivationEvent.eventKey","ActivationEvent.Startup","ActivationEvents.Idle","ActivationGraph.buildSingletonGraph","ActivationGraph.computeActivationWaves","ActivationGraph.findCyclePath","ActivationEvent.isAllOf","ActivationEvent.getEvents","ActivationEvent.Idle","Capability.ActivatingModuleIds","ActivationGraph.selectRunnableModules","ActivationGraph.buildRoundGraph","ActivationGraph.hasSoftEdges","ActivationGraph.requiredProviderIds","__dxlog_file","ActivationEvent.getEvents","ActivationEvent.eventKey","__dxlog_file","Plugin.PluginDependencyError","ActivationEvent.eventKey","ActivationEvent.Startup","ActivationEvent.pluginStart","Plugin.isLazy","Plugin.resolveLazy","Plugin.LazyPluginError","CapabilityManager.make","PluginRegistry.Manager","Plugin.Service"],"sources":["../../src/core/plugin-manager/activation-graph.ts","../../src/core/plugin-manager/idle.ts","../../src/core/plugin-manager/manager-types.ts","../../src/core/plugin-manager/module-loader.ts","../../src/core/plugin-manager/activation-scheduler.ts","../../src/core/plugin-manager/manager-state.ts","../../src/core/plugin-manager/plugin-catalog.ts","../../src/core/plugin-manager/plugin-manager.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Option from 'effect/Option';\n\nimport * as GraphEdge from '@dxos/graph/GraphEdge';\nimport * as GraphModel from '@dxos/graph/GraphModel';\nimport * as GraphNode from '@dxos/graph/GraphNode';\n\nimport type * as Capability from '../capability.ts';\nimport type * as Plugin from '../plugin.ts';\n\n//\n// Pure ordering logic for the activation scheduler, built on the shared `@dxos/graph` model.\n// Everything here is side-effect free and operates on explicit inputs so the scheduler's\n// decisions can be read — and tested — independently of manager state.\n//\n// This module's vocabulary (kept out of the rest of the manager):\n//\n// - A ROUND is one graph: nodes carry the modules being considered for activation, edges point\n// provider -> consumer and carry the capability identifier that induced them.\n// - Edge KIND distinguishes ordering strength:\n// - `hard`: an unsatisfied singleton require; the consumer must not run before the provider.\n// - `soft`: a multi require; ordering is best-effort so same-round contributions are visible\n// to consumers that read the collection once at startup (multi requires never block).\n// - A WAVE is a batch of modules with no ordering edges among them: waves run one after\n// another, and the modules within a wave run concurrently.\n//\n\nexport type EdgeKind = 'hard' | 'soft';\n\nexport type ActivationNode = GraphNode.Of<Plugin.PluginModule>;\nexport type ActivationEdge = GraphEdge.Of<{ capability: string }>;\nexport type ActivationGraphModel = GraphModel.GraphModel<ActivationNode, ActivationEdge>;\n\nexport type CycleEntry = { module: string; capability: string };\n\nconst makeModel = (modules: readonly Plugin.PluginModule[]): ActivationGraphModel => {\n const model = new GraphModel.GraphModel<ActivationNode, ActivationEdge>();\n modules.forEach((module) => model.addNode({ id: module.id, data: module }));\n return model;\n};\n\n/** Parallel edges (same pair, different capability) need distinct ids. */\nconst edgeId = (kind: EdgeKind, source: string, target: string, capability: string): string =>\n `${kind}|${source}|${capability}|${target}`;\n\nconst addEdge = (\n model: ActivationGraphModel,\n kind: EdgeKind,\n source: string,\n target: string,\n capability: string,\n): void => {\n model.addEdge({ id: edgeId(kind, source, target, capability), type: kind, source, target, data: { capability } });\n};\n\nexport type SelectRunnableInputs = {\n candidates: readonly Plugin.PluginModule[];\n /** Module ids excluded up front (e.g. duplicate singleton providers). */\n excluded: ReadonlySet<string>;\n /** Whether a singleton capability already has a contribution. */\n isSatisfied: (capability: Capability.AnyTag) => boolean;\n /** This round's singleton provider for a capability identifier, if any. */\n providerOf: (identifier: string) => string | undefined;\n /** Already-active module ids (an active provider resolves via the bounded waitFor bridge). */\n activeIds: readonly string[];\n /** Whether ANY registered module (active or not, fired or not) provides this capability. */\n anyRegisteredProvider: (identifier: string) => boolean;\n};\n\nexport type SelectRunnableResult = {\n runnable: Plugin.PluginModule[];\n /** Requires with no possible provider at all — a configuration error for the caller to report. */\n missing: Array<{ module: Plugin.PluginModule; capability: string }>;\n /** Modules left out of this round (including the `missing` ones), with the require that made\n * them wait — a later round reconsiders them once the provider becomes available. */\n waiting: Array<{ module: Plugin.PluginModule; capability: string }>;\n};\n\n/**\n * Selects the candidates that can run this round: a module is runnable when every unsatisfied\n * singleton require is provided by another runnable candidate or an already-active module.\n * Everything else waits for a later round (e.g. providers gated on an event that has not fired\n * yet). Multi requires never block. Requires with no possible provider at all are returned in\n * `missing`.\n *\n * Removing one module can strand its dependents, so removals propagate: dropping a provider\n * re-checks exactly the modules that relied on it within the round, until the selection is\n * stable.\n */\nexport const selectRunnableModules = ({\n candidates,\n excluded,\n isSatisfied,\n providerOf,\n activeIds,\n anyRegisteredProvider,\n}: SelectRunnableInputs): SelectRunnableResult => {\n const selected = new Map(\n candidates.filter((module) => !excluded.has(module.id)).map((module) => [module.id, module]),\n );\n const missing: SelectRunnableResult['missing'] = [];\n const waiting: SelectRunnableResult['waiting'] = [];\n\n // In-round reliance edges: provider id -> the modules (and requires) that count on it. Only\n // these need re-checking when a provider drops out.\n const consumersOf = new Map<string, Array<{ module: Plugin.PluginModule; capability: string }>>();\n const removalQueue: string[] = [];\n const remove = (module: Plugin.PluginModule, capability: string): void => {\n if (!selected.delete(module.id)) {\n return;\n }\n waiting.push({ module, capability });\n removalQueue.push(module.id);\n };\n\n // First pass: drop modules whose provider is outside the round and not active; record\n // in-round reliance edges for everything else.\n for (const module of [...selected.values()]) {\n for (const capability of module.activation.requires) {\n if (capability.arity === 'multi' || isSatisfied(capability)) {\n continue;\n }\n const provider = providerOf(capability.identifier);\n if (provider !== undefined && selected.has(provider)) {\n const consumers = consumersOf.get(provider) ?? [];\n consumers.push({ module, capability: capability.identifier });\n consumersOf.set(provider, consumers);\n continue;\n }\n if (provider !== undefined && activeIds.includes(provider)) {\n // Active provider whose capability was conditionally skipped: the consumer resolves it\n // via the bounded waitFor bridge.\n continue;\n }\n if (provider === undefined && !anyRegisteredProvider(capability.identifier)) {\n missing.push({ module, capability: capability.identifier });\n }\n // A provider exists but is not in play (event not fired, module in a different chain,\n // plugin disabled): wait until a later round unlocks it.\n remove(module, capability.identifier);\n break;\n }\n }\n\n // Propagate: a removed provider strands the modules that relied on it, transitively.\n for (let next = removalQueue.shift(); next !== undefined; next = removalQueue.shift()) {\n for (const consumer of consumersOf.get(next) ?? []) {\n remove(consumer.module, consumer.capability);\n }\n }\n\n return { runnable: [...selected.values()], missing, waiting };\n};\n\n/**\n * Builds a round's ordering graph. Hard edges gate a consumer on its unsatisfied singleton\n * providers within the round; soft edges order a consumer after the round's multi providers.\n */\nexport const buildRoundGraph = (\n modules: readonly Plugin.PluginModule[],\n {\n isSatisfied,\n providerOf,\n }: {\n isSatisfied: (capability: Capability.AnyTag) => boolean;\n providerOf: (identifier: string) => string | undefined;\n },\n): ActivationGraphModel => {\n const model = makeModel(modules);\n const multiProviders = new Map<string, string[]>();\n for (const module of modules) {\n for (const capability of module.activation.provides) {\n if (capability.arity === 'multi') {\n const providers = multiProviders.get(capability.identifier) ?? [];\n providers.push(module.id);\n multiProviders.set(capability.identifier, providers);\n }\n }\n }\n for (const module of modules) {\n for (const capability of module.activation.requires) {\n if (capability.arity === 'multi') {\n for (const provider of multiProviders.get(capability.identifier) ?? []) {\n if (provider !== module.id) {\n addEdge(model, 'soft', provider, module.id, capability.identifier);\n }\n }\n continue;\n }\n if (isSatisfied(capability)) {\n continue;\n }\n const provider = providerOf(capability.identifier);\n if (provider !== undefined && model.findNode(provider) !== undefined) {\n addEdge(model, 'hard', provider, module.id, capability.identifier);\n }\n }\n }\n return model;\n};\n\n/**\n * Builds the singleton require -> provider graph across the given modules regardless of event\n * gating or satisfaction — used to surface capability cycles that span activation events (two\n * modules on different events requiring each other's provides would otherwise pend forever).\n */\nexport const buildSingletonGraph = (modules: readonly Plugin.PluginModule[]): ActivationGraphModel => {\n const model = makeModel(modules);\n const providersByCapability = new Map<string, string[]>();\n for (const module of modules) {\n for (const capability of module.activation.provides) {\n if (capability.arity !== 'single') {\n continue;\n }\n const providers = providersByCapability.get(capability.identifier) ?? [];\n providers.push(module.id);\n providersByCapability.set(capability.identifier, providers);\n }\n }\n for (const module of modules) {\n for (const capability of module.activation.requires) {\n if (capability.arity === 'multi') {\n continue;\n }\n for (const provider of providersByCapability.get(capability.identifier) ?? []) {\n if (provider !== module.id) {\n addEdge(model, 'hard', provider, module.id, capability.identifier);\n }\n }\n }\n }\n return model;\n};\n\nconst edgeOfKind =\n (kinds: readonly EdgeKind[]) =>\n (edge: ActivationEdge): boolean =>\n kinds.some((kind) => kind === edge.type);\n\n/**\n * Topological activation waves over the given edge kinds (modules in the same wave have no edges\n * among them and activate concurrently). Returns `undefined` when the restricted graph is cyclic.\n */\nexport const computeActivationWaves = (\n model: ActivationGraphModel,\n kinds: readonly EdgeKind[],\n): Plugin.PluginModule[][] | undefined =>\n Option.getOrUndefined(\n Option.map(model.topoLevels(edgeOfKind(kinds)), (levels) =>\n levels.map((level) => level.map((id) => model.getNode(id).data)),\n ),\n );\n\n/**\n * Finds one cycle in the graph (restricted to the given edge kinds) for diagnostics: each entry\n * is a module and the capability identifier on its outgoing edge within the cycle.\n */\nexport const findCyclePath = (model: ActivationGraphModel, kinds: readonly EdgeKind[]): CycleEntry[] =>\n model.findCycle(edgeOfKind(kinds)).map((step) => ({ module: step.node, capability: step.edge.data.capability }));\n\n/** Ids of the providers the module must not run before (its incoming hard edges). */\nexport const requiredProviderIds = (model: ActivationGraphModel, moduleId: string): string[] =>\n model.filterEdges({ target: moduleId, type: 'hard' }).map((edge) => edge.source);\n\n/** Whether the graph carries any soft (multi-capability) ordering edges. */\nexport const hasSoftEdges = (model: ActivationGraphModel): boolean => model.edges.some((edge) => edge.type === 'soft');\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\n/**\n * Backstop for the idle wait. An aggressive timeout fires mid-render and floods the main thread\n * ahead of first paint, which is the cost this wait exists to avoid; this only rescues a host\n * that never goes idle at all.\n */\nconst IDLE_TIMEOUT = 15_000;\n\n/**\n * Backstop for the paint wait, for hosts where frames never come — a backgrounded tab does not\n * run `requestAnimationFrame`, and the idle wave must not be lost to that.\n */\nconst PAINT_TIMEOUT = 2_000;\n\n/**\n * Completes after the shell has painted. Two frames: the first callback runs before paint, the\n * second after it. Without this the idle timeout below can expire mid-render-pipeline, flooding\n * the main thread ahead of first paint — precisely the cost the wait exists to avoid.\n */\nconst afterPaint: Effect.Effect<void> = Effect.suspend(() => {\n if (typeof requestAnimationFrame !== 'function') {\n return Effect.void;\n }\n return Effect.callback<void>((resume) => {\n let inner: number | undefined;\n const outer = requestAnimationFrame(() => {\n inner = requestAnimationFrame(() => resume(Effect.void));\n });\n return Effect.sync(() => {\n cancelAnimationFrame(outer);\n inner !== undefined && cancelAnimationFrame(inner);\n });\n }).pipe(\n Effect.timeout(PAINT_TIMEOUT),\n Effect.catch(() => Effect.void),\n );\n});\n\n/**\n * Whether the host has a paint the idle wave should yield to. False under node and workerd, where\n * {@link whenIdle} completes immediately — so forking the wave there buys nothing and only leaves\n * it unfinished when `start()` returns.\n */\nexport const hostYieldsToPaint = (): boolean => typeof requestIdleCallback === 'function';\n\n/**\n * Completes once the host is idle, so work scheduled behind it lands after the shell has painted\n * rather than competing with it.\n */\nexport const whenIdle: Effect.Effect<void> = Effect.suspend(() => {\n if (!hostYieldsToPaint()) {\n return Effect.void;\n }\n return afterPaint.pipe(\n Effect.andThen(\n Effect.callback<void>((resume) => {\n const handle = requestIdleCallback(() => resume(Effect.void), { timeout: IDLE_TIMEOUT });\n return Effect.sync(() => cancelIdleCallback(handle));\n }),\n ),\n );\n});\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Duration from 'effect/Duration';\n\nimport { BaseError } from '@dxos/errors';\n\n//\n// Types and errors shared between the plugin manager's collaborating units (module loader,\n// activation scheduler, catalog). Canonical public access stays on the `PluginManager`\n// namespace, which re-exports everything here.\n//\n\n/**\n * Tagged error for failures during the constructor-launched core/enabled\n * `enable()` chain. Surfaces via the manager's `activate` wait on\n * initialization so a caller blocked on initialization gets a typed\n * failure (with the original error preserved as `cause`) instead of an\n * untyped `Error`.\n */\nexport class PluginInitializationError extends BaseError.extend(\n 'PluginInitializationError',\n 'Plugin manager initialization failed',\n) {}\n\n/**\n * Tagged error raised when a plugin exceeds its configured load or activation\n * timeout. The plugin manager records the failure on the `failed` atom and\n * auto-disables the plugin so that one stuck remote does not stall app boot.\n * `context.id` is the plugin id, `context.phase` is `'load'` or `'activation'`.\n */\nexport class PluginTimeoutError extends BaseError.extend('PluginTimeoutError', 'Plugin operation timed out') {}\n\n/** Phase of the plugin lifecycle in which the failure was observed. */\nexport type PluginFailurePhase = 'load' | 'activation';\n\n/** Why the plugin entered a failed state. */\nexport type PluginFailureReason = 'timeout' | 'error';\n\n/**\n * Record of a plugin that failed to load or activate. Surfaced via the\n * manager's `failed` atom so registry / UI consumers can flag unhealthy\n * plugins (e.g. a remote host that has gone offline) rather than leaving the\n * app in a half-broken state.\n */\nexport type PluginFailure = {\n readonly id: string;\n readonly phase: PluginFailurePhase;\n readonly reason: PluginFailureReason;\n readonly error: Error;\n /** `Date.now()` when the failure was recorded. */\n readonly timestamp: number;\n};\n\n/** Default deadline for resolving a lazy plugin's dynamic import. */\nexport const DEFAULT_LOAD_TIMEOUT = Duration.seconds(30);\n\n/** Default deadline for a single module's `activate()` body. */\nexport const DEFAULT_ACTIVATION_TIMEOUT = Duration.seconds(30);\n\nexport type ActivationMessage = {\n event: string;\n state: 'activating' | 'activated' | 'error';\n /** Module ID when the message pertains to a specific module activation. */\n module?: string;\n error?: Error;\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Cause from 'effect/Cause';\nimport * as Clock from 'effect/Clock';\nimport * as Context from 'effect/Context';\nimport * as Deferred from 'effect/Deferred';\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport * as Exit from 'effect/Exit';\nimport * as Fiber from 'effect/Fiber';\nimport * as PubSub from 'effect/PubSub';\nimport * as Scope from 'effect/Scope';\nimport * as Semaphore from 'effect/Semaphore';\n\nimport * as Performance from '@dxos/effect/Performance';\nimport { log } from '@dxos/log';\n\nimport { Capabilities } from '../../common/index.ts';\nimport * as ActivationEvent from '../activation-event.ts';\nimport * as CapabilityManager from '../capability-manager.ts';\nimport * as Capability from '../capability.ts';\nimport { CapabilityNotFoundError, ProvidesMismatchError } from '../errors.ts';\nimport * as Plugin from '../plugin.ts';\nimport { type ManagerState } from './manager-state.ts';\nimport { type PluginFailurePhase, PluginTimeoutError } from './manager-types.ts';\n\n/**\n * Yields the host's event loop before a module body runs. Effect's scheduler drains its run queue\n * within one macrotask, so a wave of cache-hit module activations otherwise fuses into one\n * multi-second long task that blocks paint and input (measured: 2 s max task, ~4.7 s TBT at boot).\n *\n * Prefers `scheduler.yield()` (input-priority aware); falls back to a MessageChannel hop, which is\n * a real macrotask boundary without `setTimeout`'s clamp. The fallback is `Effect.callback` rather\n * than a hand-built promise so an interrupt closes the ports instead of leaking a channel per\n * yield — this runs between every module activation, so a few hundred times at boot.\n */\nexport const yieldToHost: Effect.Effect<void> = Effect.suspend(() => {\n const scheduler = globalThis.scheduler;\n // Feature-tested, not just presence-checked: Chromium shipped `postTask` before `yield`.\n if (typeof scheduler?.yield === 'function') {\n return Effect.promise(() => scheduler.yield());\n }\n if (typeof MessageChannel === 'undefined') {\n return Effect.void;\n }\n return Effect.callback<void>((resume) => {\n const { port1, port2 } = new MessageChannel();\n const close = () => {\n port1.close();\n port2.close();\n };\n port1.onmessage = () => {\n close();\n resume(Effect.void);\n };\n port2.postMessage(null);\n return Effect.sync(close);\n });\n});\n\n/**\n * Owns the per-module load pipeline and its bookkeeping: memoized loads (id -> Deferred),\n * per-module semaphores, activation scopes, and the contributed-capability index. Every\n * activation path (dependency round, event wave, on-demand pull) converges on {@link load};\n * concurrent paths await the same deferred, and {@link contribute} is idempotent per module.\n *\n * Module bodies run with the manager as the ambient `Plugin.Service`; the loader carries that\n * as a typed requirement (`R = Plugin.Service`) rather than holding a manager reference — the\n * manager satisfies it once at its public boundary.\n */\nconst SLOW_MODULE_WARNING = Duration.seconds(10);\nconst SLOW_MODULE_CHECK_INTERVAL = Duration.seconds(1);\n\ntype InFlightActivation = { moduleId: string; started: number; warned: boolean };\n\nexport class ModuleLoader {\n // One watcher fiber for every in-flight activation rather than a sleeping fiber per module: a boot\n // activates hundreds of modules, and each fiber's fork and timer cost main-thread time.\n readonly #inFlight = new Set<InFlightActivation>();\n #watchingSlow = false;\n readonly #memo = new Map<Plugin.PluginModule['id'], Deferred.Deferred<Capability.Any[], Error>>();\n readonly #semaphores = new Map<Plugin.PluginModule['id'], Semaphore.Semaphore>();\n readonly #scopes = new Map<string, Scope.Closeable>();\n readonly #contributed = new Map<string, Capability.Any[]>();\n readonly #state: ManagerState;\n readonly #capabilities: CapabilityManager.CapabilityManager;\n readonly #activationTimeout: Duration.Input;\n readonly #yieldToHost: Effect.Effect<void>;\n\n constructor(\n state: ManagerState,\n capabilities: CapabilityManager.CapabilityManager,\n activationTimeout: Duration.Input,\n /** Injected so the host yield is explicit at the composition root, and swappable in tests. */\n yieldToHostEffect: Effect.Effect<void> = yieldToHost,\n ) {\n this.#state = state;\n this.#capabilities = capabilities;\n this.#activationTimeout = activationTimeout;\n this.#yieldToHost = yieldToHostEffect;\n }\n\n /** Whether the module's load has started (memoized) — settled or not. */\n isLoading(moduleId: string): boolean {\n return this.#memo.has(moduleId);\n }\n\n /** Whether the module's capabilities have been ingested into the registry. */\n hasContributed(moduleId: string): boolean {\n return this.#contributed.has(moduleId);\n }\n\n /**\n * Loads a module exactly once. `parentEvent` is the activation event that first triggered\n * the load — included in `activating`/`activated` messages so subscribers (e.g. the boot\n * loader's status listener) can associate a module with its triggering event; later paths\n * await the cached deferred without re-publishing.\n */\n load = (module: Plugin.PluginModule, parentEvent: string): Effect.Effect<Capability.Any[], Error, Plugin.Service> =>\n Effect.gen({ self: this }, function* () {\n const semaphore = this.#semaphore(module.id);\n\n // Atomically check-and-set under per-module semaphore to prevent race conditions.\n const deferredToAwait = yield* Effect.gen({ self: this }, function* () {\n const existing = this.#memo.get(module.id);\n if (existing) {\n return existing;\n }\n\n // First caller - create deferred, store it, and start loading in background.\n const deferred = yield* Deferred.make<Capability.Any[], Error>();\n this.#memo.set(module.id, deferred);\n\n const scope = yield* Scope.make();\n\n // Fork the load to run in background, completing the deferred when done.\n const fiber = yield* Effect.forkDetach(\n this.#runActivation(module, parentEvent, scope).pipe(\n Effect.tap((result) => Deferred.succeed(deferred, result)),\n Effect.catchCause((cause) =>\n this.#recordActivationFailure(module, parentEvent, cause).pipe(\n Effect.flatMap((error) => Deferred.fail(deferred, error)),\n ),\n ),\n ),\n );\n yield* this.#state.fibers.trackForked(fiber);\n\n return deferred;\n }).pipe(semaphore.withPermits(1));\n\n // Wait for result outside the semaphore so multiple waiters can proceed concurrently.\n return yield* Deferred.await(deferredToAwait);\n });\n\n /**\n * Awaits an in-flight load without starting one. A module with no memoized load — never\n * started, or deactivated mid-wait (deactivation clears the memo) — counts as settled;\n * joining via {@link load} instead would RESTART such a module (e.g. re-activating a\n * timed-out module of an auto-disabled plugin).\n */\n awaitSettled(moduleId: string): Effect.Effect<void> {\n const deferred = this.#memo.get(moduleId);\n return deferred ? Deferred.await(deferred).pipe(Effect.ignore, Effect.asVoid) : Effect.void;\n }\n\n /**\n * Awaits every in-flight load until none remain, to a fixpoint (a settling load can start\n * new ones). Returns whether anything was pending. Used by streaming startup: forked\n * enable-chain passes load modules outside `start()`'s own passes, and the ready signal\n * must not publish while any of them are mid-load.\n */\n awaitAllSettled(): Effect.Effect<boolean> {\n return Effect.gen({ self: this }, function* () {\n let waited = false;\n for (;;) {\n const pending: Deferred.Deferred<any, Error>[] = [];\n for (const deferred of this.#memo.values()) {\n if (!(yield* Deferred.isDone(deferred))) {\n pending.push(deferred);\n }\n }\n if (pending.length === 0) {\n return waited;\n }\n waited = true;\n yield* Effect.all(\n pending.map((deferred) => Deferred.await(deferred).pipe(Effect.ignore)),\n { concurrency: 'unbounded', discard: true },\n );\n }\n });\n }\n\n /**\n * Ingests a module's expanded capabilities into the registry and marks it active. A module\n * may be reached by more than one activation path; the load is memoized, so contribution is\n * memoized too.\n */\n contribute(module: Plugin.PluginModule, capabilities: Capability.Any[]): Effect.Effect<void, Error> {\n return Effect.gen({ self: this }, function* () {\n if (this.#contributed.has(module.id)) {\n return;\n }\n capabilities.forEach((capability) => {\n this.#capabilities.contribute({ module: module.id, ...capability });\n });\n this.#state.markActive(module.id);\n this.#contributed.set(module.id, capabilities);\n });\n }\n\n /** Removes the module's contributions and closes its scope (running its finalizers). */\n deactivate(module: Plugin.PluginModule): Effect.Effect<boolean, Error> {\n return Effect.gen({ self: this }, function* () {\n const id = module.id;\n log('deactivating', { id });\n this.#memo.delete(id);\n\n const capabilities = this.#contributed.get(id);\n if (capabilities) {\n for (const capability of capabilities) {\n this.#capabilities.remove(capability.interface, capability.implementation);\n }\n this.#contributed.delete(id);\n }\n\n const scope = this.#scopes.get(id);\n if (scope) {\n yield* Scope.close(scope, Exit.void);\n this.#scopes.delete(id);\n }\n\n this.#state.markInactive(id);\n\n log('deactivated', { id });\n return true;\n });\n }\n\n /** Shutdown: drop all memoized loads and close every activation scope. */\n clear(): Effect.Effect<void> {\n return Effect.gen({ self: this }, function* () {\n this.#memo.clear();\n for (const scope of this.#scopes.values()) {\n yield* Scope.close(scope, Exit.void);\n }\n this.#scopes.clear();\n });\n }\n\n /**\n * Builds the Effect context for a module's declared requires: singleton capabilities\n * resolve to their implementation (waiting — bounded by the activation timeout — for\n * concurrent providers), multi capabilities to their live contributions view.\n */\n #resolveRequires(module: Plugin.PluginModule): Effect.Effect<Context.Context<never>, Error> {\n return Effect.gen({ self: this }, function* () {\n const spec = module.activation;\n if (spec.requires.length === 0) {\n return Context.empty();\n }\n\n const services = new Map<string, unknown>();\n for (const capability of spec.requires) {\n if (capability.arity === 'multi') {\n services.set(capability.key, this.#capabilities.contributions(capability));\n continue;\n }\n const [existing] = this.#capabilities.getAll(capability);\n const implementation =\n existing !== undefined\n ? existing\n : yield* this.#capabilities.waitFor(capability).pipe(\n Effect.timeoutOrElse({\n duration: this.#activationTimeout,\n orElse: () =>\n Effect.fail(\n new CapabilityNotFoundError({\n identifier: capability.identifier,\n registered: this.#capabilities.listRegisteredIdentifiers(),\n }),\n ),\n }),\n );\n services.set(capability.key, implementation);\n }\n return Context.makeUnsafe(services);\n });\n }\n\n #semaphore(moduleId: Plugin.PluginModule['id']): Semaphore.Semaphore {\n let semaphore = this.#semaphores.get(moduleId);\n if (!semaphore) {\n semaphore = Semaphore.makeUnsafe(1);\n this.#semaphores.set(moduleId, semaphore);\n }\n return semaphore;\n }\n\n /**\n * The activation pipeline for one module: settle in-flight multi providers, build the\n * requires context, run the module's activate under the activation timeout, validate the\n * result against the declared provides, and expand it to registry entries. Instrumented\n * with a span, a slow-activation warning, and a devtools track entry.\n */\n /**\n * A surface rendering is the demand signal for its own plugin: the feature is now in use, so\n * the contributions other plugins target at it (editor extensions, variants, integrations)\n * should load. Firing here rather than from a blanket post-startup sweep is what keeps an\n * unvisited feature's code off the wire entirely.\n *\n * Forked, not awaited: contributions are read through the reactive capability atoms, so a\n * consumer re-renders when they land, and awaiting here would deadlock a surface behind\n * modules that may themselves resolve surfaces. Re-firing an already-fired event is a no-op\n * in the manager, so no dedup is needed at this call site.\n */\n #fireOwnStartForSurface(\n capabilities: readonly Capability.Any[],\n pluginId: string | undefined,\n ): Effect.Effect<void, never, Plugin.Service> {\n if (!pluginId || !capabilities.some((capability) => capability.interface === Capabilities.ReactSurface)) {\n return Effect.void;\n }\n return Effect.gen(function* () {\n const manager = yield* Plugin.Service;\n yield* manager.activate(ActivationEvent.pluginStart(pluginId)).pipe(\n Effect.catch((error) =>\n Effect.sync(() => log.warn('plugin start event failed', { pluginId, error: String(error) })),\n ),\n Effect.forkDetach,\n );\n });\n }\n\n #runActivation(\n module: Plugin.PluginModule,\n parentEvent: string,\n scope: Scope.Closeable,\n ): Effect.Effect<Capability.Any[], Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n log('loading module', { module: module.id, parentEvent });\n performance.mark(`module:${module.id}:start`);\n // Separate mark: the profiler reads `module:` as a measure, and a measure drops mark detail.\n performance.mark(`module-cause:${module.id}`, { detail: { event: parentEvent } });\n yield* PubSub.publish(this.#state.activation, { event: parentEvent, state: 'activating', module: module.id });\n const pluginId = this.#state.pluginIdOfModule(module.id);\n yield* this.#awaitProvidersInFlight(module);\n const requiresContext = yield* this.#resolveRequires(module);\n // One host yield per module keeps activation tasks under the long-task threshold;\n // counted as wait, not run, by the split below.\n yield* this.#yieldToHost;\n // Wait/run split: `module:<id>` spans the whole pipeline, so scheduling delay (in-flight\n // providers + requires resolution) is indistinguishable from work without these sub-measures.\n performance.mark(`module:${module.id}:run`);\n performance.measure(`module-wait:${module.id}`, `module:${module.id}:start`, `module:${module.id}:run`);\n const [duration, capabilities] = yield* module.activate().pipe(\n Effect.provide(requiresContext),\n Effect.provideService(Capability.Service, this.#capabilities),\n Effect.provideService(Capability.CurrentModuleId, module.id),\n Effect.updateService(Capability.ActivatingModuleIds, (ids) => new Set([...ids, module.id])),\n\n Scope.provide(scope),\n // Cap activation so a single misbehaving module can't hold the\n // event chain open. On timeout the failure is recorded against\n // the plugin and surfaced as `PluginTimeoutError`.\n Effect.timeoutOrElse({\n duration: this.#activationTimeout,\n orElse: () =>\n Effect.fail(\n new PluginTimeoutError({\n context: { id: pluginId ?? module.id, module: module.id, phase: 'activation' as PluginFailurePhase },\n }),\n ),\n }),\n Effect.timed,\n );\n const normalized = CapabilityManager.normalizeActivateResult(capabilities);\n yield* this.#validateProvides(module, normalized);\n\n this.#scopes.set(module.id, scope);\n const elapsed = Duration.toMillis(duration);\n performance.mark(`module:${module.id}:end`);\n performance.measure(`module:${module.id}`, `module:${module.id}:start`, `module:${module.id}:end`);\n performance.measure(`module-run:${module.id}`, `module:${module.id}:run`, `module:${module.id}:end`);\n yield* PubSub.publish(this.#state.activation, { event: parentEvent, state: 'activated', module: module.id });\n\n log('loaded module', {\n module: module.id,\n parentEvent,\n elapsed,\n failed: false,\n });\n const expanded = CapabilityManager.expandContributions(normalized);\n yield* this.#fireOwnStartForSurface(expanded, pluginId);\n return expanded;\n }).pipe(\n Effect.tapCause(() => Scope.close(scope, Exit.void)),\n Effect.withSpan('ModuleLoader.load', { attributes: { 'dx.module.id': module.id } }),\n (activation) =>\n Effect.flatMap(this.#watchSlow(module.id), (settled) => activation.pipe(Effect.ensuring(settled))),\n Performance.addTrackEntry({\n name: module.id,\n devtools: {\n dataType: 'track-entry',\n track: 'Module Activation',\n trackGroup: 'Composer',\n color: 'primary',\n },\n }),\n );\n }\n\n /**\n * Waits for providers of this module's multi requires whose load has already started in a\n * concurrent round, and ingests their contributions before this module's activate runs.\n * Round-internal ordering only covers providers inside one round — a provider mid-load in a\n * concurrent round (the startup dependency pass while an event-triggered pull runs) is\n * dropped from the pulled round's candidates entirely, so without this a consumer that reads\n * the collection once at startup (e.g. the process manager's `Capabilities.LayerSpec`\n * collection) races the provider's contribution. Bounded by the activation timeout so a\n * multi-capability require cycle (legal — multi requires never block) degrades to the old\n * behaviour instead of deadlocking.\n */\n #awaitProvidersInFlight(module: Plugin.PluginModule): Effect.Effect<void> {\n return Effect.gen({ self: this }, function* () {\n const multiIdentifiers = new Set(\n module.activation.requires\n .filter((capability) => capability.arity === 'multi')\n .map((capability) => capability.identifier),\n );\n if (multiIdentifiers.size === 0) {\n return;\n }\n const inflight = this.#state\n .getModules()\n .filter(\n (provider) =>\n provider.id !== module.id &&\n !this.#contributed.has(provider.id) &&\n this.#memo.has(provider.id) &&\n provider.activation.provides.some((provided) => multiIdentifiers.has(provided.identifier)),\n );\n if (inflight.length === 0) {\n return;\n }\n log('waiting for in-flight multi providers', { module: module.id, providers: inflight.map((m) => m.id) });\n yield* Effect.forEach(\n inflight,\n (provider) =>\n Effect.gen({ self: this }, function* () {\n const deferred = this.#memo.get(provider.id);\n if (deferred === undefined) {\n return;\n }\n const capabilities = yield* Deferred.await(deferred);\n // Idempotent (memoized per module): the provider's own round contributes the same\n // entries as a no-op when it gets there.\n yield* this.contribute(provider, capabilities);\n }).pipe(\n // A provider that failed to activate resolves to nothing here; its failure is\n // recorded and surfaced by its own load fiber.\n Effect.ignore,\n ),\n { concurrency: 'unbounded', discard: true },\n ).pipe(\n Effect.timeout(this.#activationTimeout),\n Effect.catch(() =>\n Effect.sync(() =>\n log.warn('proceeding without in-flight multi providers', {\n module: module.id,\n providers: inflight.map((m) => m.id),\n }),\n ),\n ),\n );\n });\n }\n\n /**\n * Runtime provides validation (the authoritative check; the type-level one is best-effort).\n * Validated on the raw items so an empty provideAll still counts as covering its capability.\n * Undeclared contributions fail (they would bypass dependency ordering); missing ones only\n * warn — a provider may legitimately decide at runtime not to contribute (consumers then\n * surface a bounded CapabilityNotFoundError instead of silently proceeding).\n */\n #validateProvides(\n module: Plugin.PluginModule,\n normalized: Array<Capability.Any | Capability.AnyContribution>,\n ): Effect.Effect<void, ProvidesMismatchError> {\n const declared = new Set(module.activation.provides.map((capability) => capability.identifier));\n const returned = new Set(\n normalized.map((item) =>\n CapabilityManager.isContribution(item) ? item.capability.identifier : item.interface.identifier,\n ),\n );\n const missing = [...declared].filter((identifier) => !returned.has(identifier));\n const undeclared = [...returned].filter((identifier) => !declared.has(identifier));\n if (undeclared.length > 0) {\n return Effect.fail(new ProvidesMismatchError({ module: module.id, missing, undeclared }));\n }\n if (missing.length > 0) {\n log.warn('module did not contribute all declared capabilities', { module: module.id, missing });\n }\n return Effect.void;\n }\n\n /**\n * Failure bookkeeping for a module whose activation failed or died: logs the cause, records\n * the failure against the owning plugin, and publishes an error activation message —\n * symmetric with the 'activating'/'activated' messages so boot UIs observe a failed module,\n * not just a silent stall (the manager's auto-disable policy also watches these messages).\n * Returns the normalized error for the caller to fail the memoized deferred with.\n */\n #recordActivationFailure(\n module: Plugin.PluginModule,\n parentEvent: string,\n cause: Cause.Cause<Error>,\n ): Effect.Effect<Error> {\n return Effect.gen({ self: this }, function* () {\n const error = Cause.squash(cause);\n const errorMessage = error instanceof Error ? error.message : String(error);\n const missingCapability = error instanceof CapabilityNotFoundError ? error.context.identifier : undefined;\n log.error('module failed to activate', {\n module: module.id,\n parentEvent,\n missingCapability,\n registeredCapabilities: this.#capabilities.listRegisteredIdentifiers(),\n error: errorMessage,\n stack: error instanceof Error ? error.stack : undefined,\n isDefect: !Cause.hasFails(cause),\n });\n const normalizedError = error instanceof Error ? error : new Error(String(error));\n const pluginId = this.#state.pluginIdOfModule(module.id);\n if (pluginId !== undefined) {\n this.#state.recordFailure(pluginId, 'activation', normalizedError);\n }\n yield* PubSub.publish(this.#state.activation, {\n event: parentEvent,\n state: 'error',\n module: module.id,\n error: normalizedError,\n });\n return normalizedError;\n });\n }\n\n /** Registers an in-flight activation for the slow-module warning; the returned effect deregisters it. */\n #watchSlow(moduleId: string): Effect.Effect<Effect.Effect<void>> {\n return Effect.gen({ self: this }, function* () {\n const activation: InFlightActivation = { moduleId, started: yield* Clock.currentTimeMillis, warned: false };\n this.#inFlight.add(activation);\n if (!this.#watchingSlow) {\n this.#watchingSlow = true;\n yield* this.#state.fibers.trackForked(yield* Effect.forkDetach(this.#slowWatcher()));\n }\n return Effect.sync(() => void this.#inFlight.delete(activation));\n });\n }\n\n #slowWatcher(): Effect.Effect<void> {\n return Effect.gen({ self: this }, function* () {\n for (;;) {\n yield* Effect.sleep(SLOW_MODULE_CHECK_INTERVAL);\n if (this.#inFlight.size === 0) {\n return;\n }\n const now = yield* Clock.currentTimeMillis;\n for (const activation of this.#inFlight) {\n if (!activation.warned && now - activation.started >= Duration.toMillis(SLOW_MODULE_WARNING)) {\n activation.warned = true;\n log.warn('module is taking a long time to activate', { module: activation.moduleId });\n }\n }\n }\n }).pipe(Effect.ensuring(Effect.sync(() => (this.#watchingSlow = false))));\n }\n}\n\n/**\n * Runs an effect concurrently with another effect.\n * If the first effect completes, the second effect is interrupted.\n */\n// TODO(dmaretskyi): Effect.race > Effect.asVoid\nexport const together =\n <R1>(togetherEffect: Effect.Effect<void, never, R1>) =>\n <A, E, R2>(effect: Effect.Effect<A, E, R2>): Effect.Effect<A, E, R1 | R2> =>\n Effect.gen(function* () {\n const togetherFiber = yield* Effect.forkChild(togetherEffect);\n const result = yield* effect;\n yield* Fiber.interrupt(togetherFiber);\n return result;\n });\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Array from 'effect/Array';\nimport * as Deferred from 'effect/Deferred';\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport * as Fiber from 'effect/Fiber';\nimport * as PubSub from 'effect/PubSub';\nimport * as Ref from 'effect/Ref';\n\nimport * as Performance from '@dxos/effect/Performance';\nimport { log } from '@dxos/log';\n\nimport { ActivationEvents } from '../../common/index.ts';\nimport * as ActivationEvent from '../activation-event.ts';\nimport type * as CapabilityManager from '../capability-manager.ts';\nimport * as Capability from '../capability.ts';\nimport { DependencyCycleError, DuplicateProviderError, MissingProviderError } from '../errors.ts';\nimport type * as Plugin from '../plugin.ts';\nimport * as ActivationGraph from './activation-graph.ts';\nimport { hostYieldsToPaint, whenIdle } from './idle.ts';\nimport { type ManagerState } from './manager-state.ts';\nimport { type ModuleLoader, together } from './module-loader.ts';\n\n/**\n * The activation lifecycle engine: owns {@link start} / {@link activate} /\n * {@link deactivatePlugin} / {@link resetEvent} and decides when each module's `activate`\n * runs. Every module names a wave via `activatesOn` (defaulting to Idle), and two paths\n * drive them:\n *\n * - {@link runDependencyPass}: rounds over the capability graph (vocabulary and ordering logic\n * in `activation-graph.ts`), repeated until nothing new is runnable — each round's\n * contributions (or a concurrent event wave's) can unlock modules that were waiting. A fired\n * event stays fired, so a module whose wave has passed stays eligible in later rounds.\n * - Event dispatch: a module parks until its `activatesOn` fires, then runs as an event wave;\n * providers of its requires are pulled on demand first, scoped to waves that have fired.\n *\n * Structural problems (cycles, duplicate or missing singleton providers) put the offending\n * plugins into an error state and exclude their modules; everything independent proceeds.\n */\nexport class ActivationScheduler {\n /** Per-wave activation concurrency cap — see the note at the `#executeWaves` call site. */\n static readonly WAVE_CONCURRENCY = 16;\n\n /** Events currently mid-activation (an `allOf` gate counts them as already fired). */\n readonly #activatingEvents = Effect.runSync(Ref.make<string[]>([]));\n /** Modules currently claimed by an event wave (excluded from re-matching). */\n readonly #activatingModules = Effect.runSync(Ref.make<string[]>([]));\n readonly #state: ManagerState;\n readonly #capabilities: CapabilityManager.CapabilityManager;\n readonly #loader: ModuleLoader;\n readonly #whenIdle: Effect.Effect<void>;\n /** False when the host supplied its own idle gate, which makes its completion the host's business. */\n readonly #ownsIdleGate: boolean;\n\n constructor(\n state: ManagerState,\n capabilities: CapabilityManager.CapabilityManager,\n loader: ModuleLoader,\n whenIdleEffect: Effect.Effect<void> = whenIdle,\n ) {\n this.#state = state;\n this.#capabilities = capabilities;\n this.#loader = loader;\n this.#whenIdle = whenIdleEffect;\n this.#ownsIdleGate = whenIdleEffect === whenIdle;\n }\n\n /**\n * Runs startup: the capability-dependency resolution pass for dependency-mode modules,\n * concurrently with the event dispatch for any module explicitly targeting the Startup\n * event. The event-level Startup `activated` message publishes only after both passes\n * complete. Idempotent — subsequent calls activate whatever registered since.\n *\n * Streaming: activation does NOT wait for the constructor's full enable chain. `started`\n * flips immediately and a pass runs over whatever has registered; each still-in-flight\n * `enable()` runs its own incremental pass on completion (see `PluginCatalog`), so early\n * definitions (e.g. the client) begin activating while later ones are still importing.\n * The ready signal below still waits for the complete set.\n */\n start(): Effect.Effect<boolean, Error, Plugin.Service> {\n return Effect.withFiber<boolean, Error, Plugin.Service>((fiber) =>\n this.#start(fiber).pipe(Effect.ensuring(this.#state.fibers.untrack(fiber))),\n );\n }\n\n #start(fiber: Fiber.Fiber<unknown, unknown>): Effect.Effect<boolean, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n if (yield* this.#state.isShuttingDown()) {\n log('skipping start during shutdown');\n return false;\n }\n\n // Tracked for the whole call: the startup wave runs in the early streaming pass as well as\n // the complete one, so shutdown must be able to interrupt either.\n yield* this.#state.fibers.track(fiber);\n\n // With streaming, activation work is spread across this call's passes AND the enable\n // chain's incremental passes — the return value reports whether anything activated.\n const activeBefore = this.#state.getActiveIds().length;\n\n yield* Ref.set(this.#state.started, true);\n // Early pass over already-registered modules. Failures here are re-evaluated by the\n // complete pass below, so they log rather than fail start.\n yield* this.runDependencyPass().pipe(\n Effect.catch((error) => Effect.sync(() => log.warn('streaming startup pass failed', { error: String(error) }))),\n );\n\n // The complete pass and the Startup event wait for the enable chain: the ready signal\n // must reflect the full registry (see the note in `activate`).\n yield* Deferred.await(this.#state.initialized);\n\n const key = ActivationEvent.eventKey(ActivationEvent.Startup);\n\n // A capability cycle spanning event boundaries would leave both chains pending\n // forever. Surface the lock (error state on the involved plugins) and continue —\n // the cycle members simply never activate; everything else proceeds.\n yield* this.#reportGlobalCycle();\n\n // The startup wave and the dependency pass are the same thing: the pass already admits every\n // module whose wave is firing, so dispatching the event alongside it would claim the same\n // modules twice. An undeclared `activatesOn` normalizes to Idle, so what runs here is the\n // modules that asked for Startup plus the baseline providers they pull.\n this.#state.clearPendingReset(key);\n // Graph-level failures (missing provider, duplicate provider, cycle) fail the start call;\n // publish them so boot UIs surface the root cause instead of a silent hang behind their\n // own watchdog.\n const ranAny = yield* this.runDependencyPass().pipe(\n Effect.tapError((error) =>\n Effect.gen({ self: this }, function* () {\n log.error('dependency activation failed', { error: String(error) });\n yield* PubSub.publish(this.#state.activation, { event: key, state: 'error', error });\n }),\n ),\n );\n\n // The enable chain forked its incremental passes, so loads may still be in flight outside\n // the passes above. Ready must reflect a settled world — alternate between awaiting\n // in-flight loads and mop-up passes until neither does any work.\n for (;;) {\n const settledAny = yield* this.#loader.awaitAllSettled();\n const ranAny = yield* this.runDependencyPass().pipe(\n Effect.catch((error) =>\n Effect.sync(() => {\n log.warn('startup mop-up pass failed', { error: String(error) });\n return false;\n }),\n ),\n );\n if (!settledAny && !ranAny) {\n break;\n }\n }\n\n // The event-level Startup `activated` message (no `module` field) is the app-ready\n // signal (see useApp); it must not publish before the startup wave finishes.\n this.#state.markEventFired(key);\n yield* PubSub.publish(this.#state.activation, { event: key, state: 'activated' });\n // Releases the events that were dispatched while this wave ran (see `activate`).\n yield* Deferred.succeed(this.#state.startupComplete, undefined);\n\n // The idle wave belongs to the manager rather than to each host: it is an app-framework\n // event, and a host that owned the wait would re-implement it (and could forget to).\n // In a browser it is forked so `start` returns at ready and the contributions gated on it\n // land after first paint instead of competing with it; tracked, because the wave sits behind\n // a wait of up to 15s and an untracked daemon outlives `shutdown()` — dispatching Idle into a\n // manager that has already reset re-activates modules after teardown. A headless host has no\n // paint to lose the race to and completes `whenIdle` immediately, so forking there would only\n // let `start()` return before the wave ran.\n // Inlining is only safe for the gate this module owns, whose headless branch completes\n // immediately. A host that passes its own gate decides when (or whether) idle arrives —\n // `Effect.never` is a legitimate \"do not run the idle wave\" — and awaiting that inline would\n // hang `start()` rather than defer a wave.\n if (hostYieldsToPaint() || !this.#ownsIdleGate) {\n yield* this.#state.fibers.trackForked(yield* this.#activateWhenIdle().pipe(Effect.forkDetach));\n } else {\n yield* this.#activateWhenIdle();\n }\n\n return this.#state.getActiveIds().length > activeBefore || ranAny;\n });\n }\n\n /**\n * Fires the idle wave once the host goes idle. Failures are logged rather than propagated:\n * the wave carries registration contributions, so one broken plugin must not take down an\n * app that is already interactive.\n */\n #activateWhenIdle(): Effect.Effect<void, never, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n yield* this.#whenIdle;\n yield* this.activate(ActivationEvents.Idle).pipe(\n Effect.catch((error) => Effect.sync(() => log.warn('idle activation failed', { error: String(error) }))),\n );\n });\n }\n\n /**\n * Runs an activation event end to end. Startup delegates to {@link start}; anything else\n * waits for the manager's initialization, then dispatches the event.\n */\n activate(\n event: ActivationEvent.ActivationEvent | string,\n params?: { before?: string; after?: string },\n ): Effect.Effect<boolean, Error, Plugin.Service> {\n const key = typeof event === 'string' ? event : ActivationEvent.eventKey(event);\n const startupKey = ActivationEvent.eventKey(ActivationEvent.Startup);\n return Effect.gen({ self: this }, function* () {\n // Startup is not a plain event: it triggers the dependency pass alongside the event\n // dispatch. Delegating keeps useApp/harness/cli call sites unchanged.\n if (key === startupKey) {\n return yield* this.start();\n }\n\n if (yield* this.#state.isShuttingDown()) {\n log('skipping activation during shutdown', { key, ...params });\n return false;\n }\n\n // Startup provides the baseline capabilities, so a module activating on an event dispatched\n // mid-startup could otherwise find a require unsatisfied purely by timing. Waiting also keeps\n // the wave out of startup's settle check, which would hold `ready` behind unrelated work.\n if ((yield* Ref.get(this.#state.started)) && !this.#state.eventFired(startupKey)) {\n log('deferring activation until startup completes', { key, ...params });\n yield* Deferred.await(this.#state.startupComplete);\n }\n\n // Re-dispatching a fired event is already a no-op — an active module is never re-selected —\n // but the instrumentation below is not free (two marks, a devtools track entry, a forked\n // warning timer), and demand events are fired from reactive paths that re-evaluate freely.\n // Bail before paying for a dispatch that has nothing to activate. The module scan is still\n // required: modules register after the fact under streaming start, so a fired event can\n // have newly-eligible modules. A fired event implies the wait below already completed once,\n // so the scan is safe this early.\n if (this.#state.eventFired(key)) {\n const activatingEvents = yield* Ref.get(this.#activatingEvents);\n const activatingModules = yield* Ref.get(this.#activatingModules);\n if (this.#getModulesForActivation(key, activatingEvents, activatingModules).length === 0) {\n log('no modules to activate', { key, ...params });\n return false;\n }\n }\n\n // Dispatch-latency split: `requested` → `initialized` is registration wait; `initialized`\n // → the wave's `event:` measure is provider-join wait (in-flight round-1 loads).\n performance.mark(`milestone:dispatch:${key}:requested`);\n\n // Wait for the constructor's core/enabled `enable()` chain — including\n // any async dynamic imports for lazy plugins — to finish registering\n // modules. Without this, dispatching to an empty module set is the\n // observable symptom of the race.\n yield* Deferred.await(this.#state.initialized);\n performance.mark(`milestone:dispatch:${key}:initialized`);\n\n return yield* Effect.withFiber<boolean, Error, Plugin.Service>((fiber) =>\n this.#activateEvent(key, params, fiber).pipe(\n together(\n Effect.sleep(Duration.seconds(15)).pipe(\n Effect.andThen(Effect.sync(() => log.warn('event activation is taking a long time', { event: key }))),\n ),\n ),\n Performance.addTrackEntry({\n name: key,\n devtools: {\n dataType: 'track-entry',\n track: 'Event Activation',\n trackGroup: 'Composer',\n color: 'primary',\n },\n }),\n ),\n );\n });\n }\n\n /**\n * Deactivates all of a plugin's modules. Active modules elsewhere that require a singleton\n * capability provided by this plugin are deactivated first (reverse activation order) and\n * marked for reactivation when a provider returns.\n */\n deactivatePlugin(id: string): Effect.Effect<boolean, Error> {\n return Effect.gen({ self: this }, function* () {\n const plugin = this.#state.getPlugin(id);\n if (!plugin) {\n return false;\n }\n\n const modules = plugin.modules;\n\n const dependents = this.#collectCapabilityDependents(modules);\n for (const dependent of dependents) {\n yield* this.#loader.deactivate(dependent);\n this.#state.reactivateOnNextPass.add(dependent.id);\n }\n\n const results = yield* Effect.all(\n modules.map((module) => this.#loader.deactivate(module)),\n { concurrency: 'unbounded' },\n );\n return results.every((result) => result);\n });\n }\n\n /**\n * Re-activates the modules that were activated by the event.\n */\n resetEvent(event: ActivationEvent.ActivationEvent | string): Effect.Effect<boolean, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n const key = typeof event === 'string' ? event : ActivationEvent.eventKey(event);\n log('reset', { key });\n const modules = this.#state.getActiveModulesByEvent(key);\n const results = yield* Effect.all(\n modules.map((module) => this.#loader.deactivate(module)),\n { concurrency: 'unbounded' },\n );\n\n if (results.every((result) => result)) {\n return yield* this.activate(key);\n } else {\n return false;\n }\n });\n }\n\n /** Shutdown support: forget in-flight event/module claims. */\n clearClaims(): Effect.Effect<void> {\n return Effect.all([Ref.set(this.#activatingEvents, []), Ref.set(this.#activatingModules, [])]).pipe(Effect.asVoid);\n }\n\n /**\n * Runs one activation event: matches parked event-mode modules (an `allOf` module joins once\n * all its events have fired), pulls their inactive dependency providers on demand, activates\n * them, then re-runs the dependency pass so contributions made here can unlock modules that\n * were waiting.\n */\n #activateEvent(\n key: string,\n params: { before?: string; after?: string } | undefined,\n fiber: Fiber.Fiber<unknown, unknown>,\n opts?: { suppressEventMessage?: boolean },\n ): Effect.Effect<boolean, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n yield* this.#state.fibers.track(fiber);\n log('activating', { key, ...params });\n yield* Ref.update(this.#activatingEvents, (activating) => Array.append(activating, key));\n this.#state.clearPendingReset(key);\n\n const activatingEvents = yield* Ref.get(this.#activatingEvents);\n const activatingModules = yield* Ref.get(this.#activatingModules);\n const modules = this.#getModulesForActivation(key, activatingEvents, activatingModules);\n if (modules.length === 0) {\n log('no modules to activate', { key });\n this.#state.markEventFired(key);\n return false;\n }\n\n // Modules resolve their requires on demand: inactive providers of unsatisfied singleton\n // requires are activated first (transitively).\n yield* this.#pullDependencyProviders(modules, key);\n const activated = yield* this.#activateModulesForEvent(key, modules, opts);\n\n // Follow-up pass: contributions made by this event may unlock modules that were waiting\n // on them. Cheap no-op when nothing became runnable.\n if (yield* this.#state.isStarted()) {\n yield* this.runDependencyPass({});\n }\n\n return activated;\n }).pipe(\n Effect.ensuring(\n Effect.all([\n this.#state.fibers.untrack(fiber),\n Ref.update(this.#activatingEvents, (activating) => Array.filter(activating, (event) => event !== key)),\n ]),\n ),\n );\n }\n\n /**\n * Activates inactive modules in dependency order of the capability graph, in rounds,\n * repeated until a round activates nothing new. Candidates are dependency-mode modules plus\n * event-mode modules whose `activatesOn` events have already fired; modules whose singleton\n * requires cannot be satisfied by this pass WAIT — they are reconsidered by the next round\n * (each round of contributions, and each event wave, can unlock them). With\n * `candidateModules`, the first round is scoped to those modules (plus any marked for\n * reactivation); follow-up rounds consider the full pool unless `scopedToCandidates` keeps\n * them scoped — demand pulls and event waves must not become drain workers for the whole\n * startup pool (that serializes event dispatch behind unrelated startup work).\n *\n * Structural problems — duplicate singleton providers within a round, capability cycles,\n * or a singleton requirement no registered module of any mode could ever provide — put\n * the offending plugins into an error state (the `failed` atom, plus an error activation\n * message) and the pass continues with everything else. Individual module activation\n * failures are recorded per plugin (via the loader) and skip that module's transitive\n * dependents without aborting independent modules.\n */\n runDependencyPass(options?: {\n candidateModules?: Plugin.PluginModule[];\n scopedToCandidates?: boolean;\n }): Effect.Effect<boolean, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n let scoped = options?.candidateModules;\n let ranAny = false;\n let allSucceeded = true;\n // Contributions made by one round (or concurrently by event waves) can make modules that\n // were waiting runnable, so keep running rounds until one activates nothing. Each round\n // activates at least one module or ends the loop, so this terminates.\n for (;;) {\n const round = yield* this.#runRound(scoped);\n if (round === undefined) {\n break;\n }\n ranAny = true;\n allSucceeded = allSucceeded && round;\n // Follow-up rounds consider everything that might have been unlocked — unless scoped:\n // a demand pull draining the full pool would block its event wave on unrelated work.\n scoped = options?.scopedToCandidates ? options?.candidateModules : undefined;\n }\n\n // A round filters out anything a concurrent round started loading (awaiting it inside the\n // round could deadlock), so the loop can end while those loads are still settling. Every\n // caller reads the registry straight after and relies on \"pass resolved => candidates\n // contributed\", so join them here. Bounded: each load settles under the activation timeout.\n const candidates = options?.candidateModules;\n if (candidates !== undefined) {\n const settling = (yield* this.#notActivatingHere(candidates)).filter((module) =>\n this.#loader.isLoading(module.id),\n );\n if (settling.length > 0) {\n yield* Effect.all(\n settling.map((module) => this.#loader.awaitSettled(module.id)),\n { concurrency: 'unbounded', discard: true },\n );\n }\n }\n return ranAny && allSucceeded;\n });\n }\n\n /**\n * Detects capability cycles across the FULL module set, regardless of event gating.\n * Two modules on different activation events that require each other's provides would\n * otherwise wait forever (neither chain can start); this surfaces the lock at startup:\n * the members are put into an error state and excluded — they simply never activate,\n * and everything else proceeds.\n */\n #reportGlobalCycle(): Effect.Effect<void> {\n return Effect.gen({ self: this }, function* () {\n const graph = ActivationGraph.buildSingletonGraph(this.#state.getModules());\n if (ActivationGraph.computeActivationWaves(graph, ['hard']) !== undefined) {\n return;\n }\n const path = ActivationGraph.findCyclePath(graph, ['hard']);\n yield* this.#reportStructuralError(\n path.map((entry) => entry.module),\n new DependencyCycleError({ path }),\n );\n path.forEach((entry) => this.#state.structurallyFailed.add(entry.module));\n });\n }\n\n /**\n * Collects active modules (outside the given set) whose declared requires include a\n * singleton capability provided by the given modules, transitively. Returned in reverse\n * activation order, which is reverse topological order (safe deactivation order).\n */\n #collectCapabilityDependents(modules: readonly Plugin.PluginModule[]): Plugin.PluginModule[] {\n const active = this.#state.getActiveIds();\n const allModules = this.#state.getModules();\n const ownIds = new Set(modules.map((module) => module.id));\n const providedIds = new Set<string>();\n const collectProvides = (module: Plugin.PluginModule) => {\n for (const capability of module.activation.provides) {\n if (capability.arity === 'single') {\n providedIds.add(capability.identifier);\n }\n }\n };\n modules.filter((module) => active.includes(module.id)).forEach(collectProvides);\n\n const dependents = new Map<string, Plugin.PluginModule>();\n let changed = providedIds.size > 0;\n while (changed) {\n changed = false;\n for (const module of allModules) {\n if (ownIds.has(module.id) || dependents.has(module.id) || !active.includes(module.id)) {\n continue;\n }\n if (module.activation.requires.some((capability) => providedIds.has(capability.identifier))) {\n dependents.set(module.id, module);\n collectProvides(module);\n changed = true;\n }\n }\n }\n\n const order = this.#state.getActiveIds();\n return [...dependents.values()].sort((a, b) => order.indexOf(b.id) - order.indexOf(a.id));\n }\n\n #activateModulesForEvent(\n key: string,\n modules: Plugin.PluginModule[],\n opts?: { suppressEventMessage?: boolean },\n ): Effect.Effect<boolean, Error, Plugin.Service> {\n const activatingModuleIds = modules.map((module) => module.id);\n return Effect.gen({ self: this }, function* () {\n yield* Ref.update(this.#activatingModules, (activating) => Array.appendAll(activating, activatingModuleIds));\n\n log('activation wave', { event: key, modules: activatingModuleIds });\n performance.mark(`event:${key}:start`);\n yield* PubSub.publish(this.#state.activation, { event: key, state: 'activating' });\n\n // Same-event provider/consumer pairs are topologically ordered with per-module\n // contribution via the capability-graph machinery. Scoped: the post-wave pass in\n // `#activateEvent` handles unlocking, so the wave never drains the startup pool.\n yield* this.runDependencyPass({ candidateModules: modules, scopedToCandidates: true });\n\n // A matched module may be mid-load via a concurrent wave (the round filters it as\n // `isLoading` to avoid in-round deadlocks). Await those loads before reporting the event\n // activated — demand pulls rely on \"activate resolved ⇒ matched modules contributed\"\n // (a lookup retry that runs earlier misses the handlers and fails a one-shot invocation).\n // Bounded: every load settles its deferred under the activation timeout.\n const inFlight = (yield* this.#notActivatingHere(modules)).filter((module) => this.#loader.isLoading(module.id));\n if (inFlight.length > 0) {\n yield* Effect.all(\n inFlight.map((module) => this.#loader.awaitSettled(module.id)),\n { concurrency: 'unbounded', discard: true },\n );\n }\n this.#state.markEventFired(key);\n\n performance.mark(`event:${key}:end`);\n performance.measure(`event:${key}`, `event:${key}:start`, `event:${key}:end`);\n // `start()` suppresses the event-level message for Startup and publishes it itself\n // once the concurrent dependency pass has also completed (the useApp ready gate).\n if (!opts?.suppressEventMessage) {\n yield* PubSub.publish(this.#state.activation, { event: key, state: 'activated' });\n }\n log('activated', { key });\n\n return true;\n }).pipe(\n Effect.ensuring(\n Ref.update(this.#activatingModules, (activating) =>\n Array.filter(activating, (module) => !activatingModuleIds.includes(module)),\n ),\n ),\n );\n }\n\n #getModulesForActivation(\n key: string,\n activatingEvents: string[],\n activatingModules: string[],\n ): Plugin.PluginModule[] {\n return this.#state.getInactiveModulesByEvent(key).filter((module) => {\n const spec = module.activation;\n const allOf = ActivationEvent.isAllOf(spec.activatesOn);\n if (!allOf) {\n return true;\n }\n\n // Check to see if all of the events in the `allOf` have been fired.\n // An event can be considered \"fired\" if it is in the `eventsFired` list or if it is currently being activated.\n const events = ActivationEvent.getEvents(spec.activatesOn).filter(\n (event) => ActivationEvent.eventKey(event) !== key,\n );\n return (\n events.every(\n (event) =>\n this.#state.eventFired(ActivationEvent.eventKey(event)) ||\n activatingEvents.includes(ActivationEvent.eventKey(event)),\n ) && !activatingModules.includes(module.id)\n );\n });\n }\n\n /**\n * Records a structural dependency-graph error against a plugin and publishes it on the\n * activation stream (so boot UIs surface it) without aborting the pass.\n */\n #reportStructuralError(moduleIds: string[], error: Error): Effect.Effect<void> {\n return Effect.gen({ self: this }, function* () {\n log.error('dependency graph error', { error: String(error), modules: moduleIds });\n const plugins = new Set<string>();\n for (const moduleId of moduleIds) {\n const pluginId = this.#state.pluginIdOfModule(moduleId);\n if (pluginId !== undefined) {\n plugins.add(pluginId);\n }\n }\n plugins.forEach((pluginId) => this.#state.recordFailure(pluginId, 'activation', error));\n yield* PubSub.publish(this.#state.activation, {\n event: ActivationEvent.eventKey(ActivationEvent.Startup),\n state: 'error',\n error,\n });\n });\n }\n\n /**\n * Whether a module's wave has fired: every event for an `all-of` declaration, any one for a\n * plain or `one-of` declaration. A fired event stays fired, so this stays true for the rest of\n * the session once the module's wave has passed.\n *\n * `activating` is the wave currently being dispatched, counted as fired: an event is marked\n * fired only once its modules have settled, so without this the wave's own modules would be\n * excluded from the very round activating them.\n */\n #waveFired(module: Plugin.PluginModule, activating?: string): boolean {\n const { activatesOn } = module.activation;\n const events = ActivationEvent.getEvents(activatesOn).map(ActivationEvent.eventKey);\n const fired = (event: string) => event === activating || this.#state.eventFired(event);\n return ActivationEvent.isAllOf(activatesOn) ? events.every(fired) : events.some(fired);\n }\n\n /**\n * Whether a module can activate now: its wave has already fired, or it declared Startup. The\n * catalog uses this to pick which of a newly enabled plugin's modules join an incremental pass;\n * the rest wait for their event.\n *\n * Deliberately NOT `#isBaselineWave`, which also admits Idle. Candidates handed to\n * `runDependencyPass` are EXPLICIT candidates and bypass the `#waveFired` gate in `#runRound`, so\n * admitting idle-default modules here would activate them eagerly during boot for any plugin\n * whose `enable()` lands after `started` flips — the dominant path in Composer, where lazy plugin\n * stubs enable over seconds while Startup dispatches milliseconds after mount. That would make\n * deferral depend on an enable/start race and defeat the idle default entirely. Idle stays in the\n * baseline for PROVIDER PULLS only (see {@link ActivationScheduler.#isBaselineWave}).\n */\n isEligible(module: Plugin.PluginModule): boolean {\n return this.#waveFired(module) || this.#declaresStartup(module);\n }\n\n /** Whether the module explicitly names the Startup wave. */\n #declaresStartup(module: Plugin.PluginModule): boolean {\n const startup = ActivationEvent.eventKey(ActivationEvent.Startup);\n return ActivationEvent.getEvents(module.activation.activatesOn).map(ActivationEvent.eventKey).includes(startup);\n }\n\n /**\n * Whether a module sits in the baseline wave — `Startup u Idle`. A module there is pullable as a\n * provider by any wave, whether or not its own wave has run; explicitly gated providers stay\n * wave-scoped, which is what keeps two mutually-exclusive providers of one capability from both\n * being candidates.\n *\n * Idle is in the baseline because it is what omitting `activatesOn` normalizes to: scoping\n * un-annotated modules to their own wave would make every un-annotated provider invisible to the\n * startup pass, so `ClientPlugin`'s `Client` would not initialize until idle. Modules declaring\n * `Startup` explicitly lose nothing — their wave fires first, so `#waveFired` covers them after.\n */\n #isBaselineWave(module: Plugin.PluginModule): boolean {\n const baseline = [ActivationEvent.Startup, ActivationEvent.Idle].map(ActivationEvent.eventKey);\n return ActivationEvent.getEvents(module.activation.activatesOn)\n .map(ActivationEvent.eventKey)\n .some((event) => baseline.includes(event));\n }\n\n /**\n * Drops the modules whose `activate` bodies this fiber is running inside. A body that fires an\n * activation event is a caller of the wave, so awaiting its own load is a circular wait that\n * ends only at the activation timeout — recorded as a `PluginTimeoutError` and read by the\n * failure supervisor as a broken plugin, which then disables it. Their contributions are simply\n * not visible to this wave; the body contributes them when it returns.\n */\n #notActivatingHere(modules: Plugin.PluginModule[]): Effect.Effect<Plugin.PluginModule[]> {\n return Effect.gen(function* () {\n const activating = yield* Capability.ActivatingModuleIds;\n if (activating.size === 0) {\n return modules;\n }\n return modules.filter((module) => !activating.has(module.id));\n });\n }\n\n /**\n * One topological activation round. Returns `undefined` when nothing is runnable.\n */\n #runRound(\n candidateModules: Plugin.PluginModule[] | undefined,\n ): Effect.Effect<boolean | undefined, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n const key = ActivationEvent.eventKey(ActivationEvent.Startup);\n const active = this.#state.getActiveIds();\n const allModules = this.#state.getModules();\n\n // During the streaming bootstrap the provider's plugin definition may simply not have\n // registered yet — the module waits and the post-initialization pass re-evaluates;\n // a missing provider is structural only once the registry is complete.\n const registryComplete = yield* Deferred.isDone(this.#state.initialized);\n\n const reactivations = allModules.filter((module) => this.#state.reactivateOnNextPass.has(module.id));\n // Explicitly passed candidates are trusted to be triggered (an event wave passes its\n // matched modules before the event is marked fired); pooled candidates must have their\n // events already fired.\n const explicit = new Set((candidateModules ?? []).map((module) => module.id));\n const pool = candidateModules ? [...candidateModules, ...reactivations] : allModules;\n // Explicit candidates are a snapshot taken when the wave started, so a plugin disabled\n // mid-wave (auto-disable after a module failure is the common case) leaves de-registered\n // modules in it; re-loading one would restart the very activation that just failed.\n const registered = new Set(allModules.map((module) => module.id));\n const seen = new Set<string>();\n const candidates = pool.filter((module) => {\n if (\n !registered.has(module.id) ||\n active.includes(module.id) ||\n seen.has(module.id) ||\n this.#state.structurallyFailed.has(module.id) ||\n // Already loading via another path (memoized): awaiting it here could deadlock —\n // e.g. a cascade triggered by an event wave that an in-flight module itself fired.\n this.#loader.isLoading(module.id)\n ) {\n return false;\n }\n // A multi require is a collection, so \"satisfied\" is only meaningful once every plugin\n // definition has registered — a consumer admitted during the streaming window snapshots\n // whatever happens to have contributed so far (the process manager's one-shot\n // `Capabilities.LayerSpec` read is how this surfaced). Which providers are still to come\n // is unknowable mid-registration, so these wait for the complete pass wholesale; this is\n // the ordering they had before streaming.\n if (!registryComplete && module.activation.requires.some((capability) => capability.arity === 'multi')) {\n return false;\n }\n if (!explicit.has(module.id) && !this.#waveFired(module, key)) {\n return false;\n }\n seen.add(module.id);\n return true;\n });\n if (candidates.length === 0) {\n return undefined;\n }\n\n // Singleton provider index across candidates and already-active typed modules.\n // The duplicate check spans only modules in play, so mutually-exclusive event-gated\n // alternatives (only one has fired) do not trip it. Duplicates put both providers into\n // an error state and exclude them; their dependents wait.\n const providerIndex = new Map<string, string>();\n const structurallyExcluded = new Set<string>();\n const activeTypedModules = allModules.filter((module) => active.includes(module.id));\n for (const module of [...activeTypedModules, ...candidates]) {\n for (const capability of module.activation.provides) {\n if (capability.arity !== 'single') {\n continue;\n }\n const existing = providerIndex.get(capability.identifier);\n if (existing !== undefined && existing !== module.id) {\n const error = new DuplicateProviderError({\n capability: capability.identifier,\n providers: [existing, module.id],\n });\n yield* this.#reportStructuralError([existing, module.id], error);\n structurallyExcluded.add(existing);\n structurallyExcluded.add(module.id);\n this.#state.structurallyFailed.add(existing);\n this.#state.structurallyFailed.add(module.id);\n providerIndex.delete(capability.identifier);\n continue;\n }\n providerIndex.set(capability.identifier, module.id);\n }\n }\n\n // Does ANY registered module (active or not, fired or not) provide this?\n const anyRegisteredProvider = (identifier: string): boolean =>\n allModules.some((module) => module.activation.provides.some((provided) => provided.identifier === identifier));\n\n // Pure selection: everything that waits here is reconsidered by a later round; requires\n // with no possible provider at all are a configuration error recorded against the\n // requiring plugin.\n const { runnable, missing, waiting } = ActivationGraph.selectRunnableModules({\n candidates,\n excluded: structurallyExcluded,\n isSatisfied: (capability) => this.#capabilities.getAll(capability).length > 0,\n providerOf: (identifier) => providerIndex.get(identifier),\n activeIds: [...active],\n anyRegisteredProvider,\n });\n for (const waits of waiting) {\n log('module waiting on capability', { module: waits.module.id, capability: waits.capability });\n }\n for (const miss of missing) {\n if (!registryComplete) {\n log('module waiting on unregistered provider', { module: miss.module.id, capability: miss.capability });\n continue;\n }\n yield* this.#reportStructuralError(\n [miss.module.id],\n new MissingProviderError({\n capability: miss.capability,\n requiredBy: [miss.module.id],\n registered: this.#capabilities.listRegisteredIdentifiers(),\n }),\n );\n this.#state.structurallyFailed.add(miss.module.id);\n }\n if (runnable.length === 0) {\n return undefined;\n }\n runnable.forEach((module) => this.#state.reactivateOnNextPass.delete(module.id));\n\n const graph = ActivationGraph.buildRoundGraph(runnable, {\n isSatisfied: (capability) => this.#capabilities.getAll(capability).length > 0,\n providerOf: (identifier) => providerIndex.get(identifier),\n });\n\n const ordered = yield* this.#orderRoundBreakingCycles(graph);\n if (ordered === undefined) {\n return undefined;\n }\n const { waves, cycleFailed } = ordered;\n log('dependency activation waves', {\n waves: waves.map((wave) => wave.map((module) => module.id)),\n });\n\n return yield* this.#executeWaves(waves, graph, cycleFailed, key);\n });\n }\n\n /**\n * Orders a round's graph into activation waves (see `activation-graph.ts` for the terms),\n * repeatedly removing required-edge cycles (recorded as an error state on the involved\n * plugins; their dependents skip via the failed set) until the remaining graph is acyclic.\n * Best-effort ordering edges are then layered on top: if they cycle, the round falls back to\n * required-edge order wholesale. Returns `undefined` when nothing survives cycle removal.\n */\n #orderRoundBreakingCycles(\n graph: ActivationGraph.ActivationGraphModel,\n ): Effect.Effect<{ waves: Plugin.PluginModule[][]; cycleFailed: Set<string> } | undefined, Error> {\n return Effect.gen({ self: this }, function* () {\n const cycleFailed = new Set<string>();\n let hardWaves = ActivationGraph.computeActivationWaves(graph, ['hard']);\n while (hardWaves === undefined) {\n const path = ActivationGraph.findCyclePath(graph, ['hard']);\n yield* this.#reportStructuralError(\n path.map((entry) => entry.module),\n new DependencyCycleError({ path }),\n );\n const members = path.map((entry) => entry.module);\n members.forEach((member) => {\n cycleFailed.add(member);\n this.#state.structurallyFailed.add(member);\n });\n graph.removeNodes(members);\n if (graph.nodes.length === 0) {\n return undefined;\n }\n hardWaves = ActivationGraph.computeActivationWaves(graph, ['hard']);\n }\n\n const combinedWaves = ActivationGraph.computeActivationWaves(graph, ['hard', 'soft']);\n if (combinedWaves === undefined && ActivationGraph.hasSoftEdges(graph)) {\n log('multi-capability soft ordering dropped (cycle)', { modules: graph.nodes.map((node) => node.id) });\n }\n return { waves: combinedWaves ?? hardWaves, cycleFailed };\n });\n }\n\n /**\n * Activates a round wave by wave (modules within a wave run concurrently). A module whose\n * required provider failed is skipped and marked failed so its own dependents skip too;\n * independent modules proceed. Cycle members arrive pre-failed so their dependents skip as\n * well. Returns whether every module in the round activated.\n */\n #executeWaves(\n waves: Plugin.PluginModule[][],\n graph: ActivationGraph.ActivationGraphModel,\n preFailed: Set<string>,\n key: string,\n ): Effect.Effect<boolean, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n const failed = new Set<string>(preFailed);\n const providersOf = (moduleId: string): string[] => ActivationGraph.requiredProviderIds(graph, moduleId);\n // Singleton providers gate dependents (in this round or a later pass), so under the\n // concurrency cap they claim the first slots instead of queuing behind leaf modules.\n const singletonProvides = (module: Plugin.PluginModule): number =>\n module.activation.provides.filter((capability) => capability.arity === 'single').length;\n let allSucceeded = true;\n for (const wave of waves) {\n const ordered = [...wave].sort((a, b) => singletonProvides(b) - singletonProvides(a));\n yield* Effect.all(\n ordered.map((module) =>\n Effect.gen({ self: this }, function* () {\n if (providersOf(module.id).some((provider) => failed.has(provider))) {\n log.warn('skipping module: provider failed', { module: module.id });\n failed.add(module.id);\n allSucceeded = false;\n return;\n }\n const result = yield* this.#activateModule(module, key).pipe(Effect.result);\n if (result._tag === 'Failure') {\n failed.add(module.id);\n allSucceeded = false;\n }\n }),\n ),\n // Bounded: a 350-wide unbounded fan-out oversubscribes import/parse and stretches\n // every module's wall clock (the measured contention plateau); small waves and\n // tests (which gate concurrent modules on each other) stay fully concurrent.\n { concurrency: ActivationScheduler.WAVE_CONCURRENCY },\n );\n }\n return allSucceeded;\n });\n }\n\n /**\n * Loads and contributes a single dependency-mode module. Contribution happens as the module\n * completes (not batched per wave), so singleton gating is exactly wave ordering.\n */\n #activateModule(module: Plugin.PluginModule, parentEvent: string): Effect.Effect<void, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n if (this.#state.getActiveIds().includes(module.id)) {\n return;\n }\n const capabilities = yield* this.#loader.load(module, parentEvent);\n yield* this.#loader.contribute(module, capabilities);\n });\n }\n\n /**\n * Activates the inactive dependency-mode providers (transitively) of the given modules'\n * unsatisfied singleton requires, plus any inactive dependency-mode providers of their\n * multi requires. Used before running event-mode modules so their requires resolve on\n * demand.\n *\n * Multi requires never gate (they resolve to whatever is currently contributed), but a\n * pulled provider that takes a one-shot snapshot of a multi capability (e.g. the process\n * manager's `Capabilities.LayerSpec` collection) needs its fellow multi providers activated\n * in the *same* scoped round so the round's ordering can land them first — otherwise a\n * narrow pull (this provider alone) skips that ordering entirely and the snapshot can be\n * taken before sibling providers have contributed.\n */\n #pullDependencyProviders(\n modules: Plugin.PluginModule[],\n activating?: string,\n ): Effect.Effect<void, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n const active = this.#state.getActiveIds();\n const allModules = this.#state.getModules();\n const providerIndex = new Map<string, Plugin.PluginModule>();\n const multiProviderIndex = new Map<string, Plugin.PluginModule[]>();\n for (const module of allModules) {\n // Wave-scoped, with the baseline wave always in scope: an explicitly gated provider is\n // pullable only once its own wave has fired, so two providers of the same singleton\n // capability gated on mutually exclusive events are never both candidates.\n if ((!this.#waveFired(module, activating) && !this.#isBaselineWave(module)) || active.includes(module.id)) {\n continue;\n }\n for (const capability of module.activation.provides) {\n if (capability.arity === 'single') {\n if (!providerIndex.has(capability.identifier)) {\n providerIndex.set(capability.identifier, module);\n }\n } else {\n const providers = multiProviderIndex.get(capability.identifier) ?? [];\n providers.push(module);\n multiProviderIndex.set(capability.identifier, providers);\n }\n }\n }\n if (providerIndex.size === 0 && multiProviderIndex.size === 0) {\n return;\n }\n\n const needed = new Map<string, Plugin.PluginModule>();\n const visit = (requires: readonly Capability.AnyTag[]) => {\n for (const capability of requires) {\n if (capability.arity === 'multi') {\n for (const provider of multiProviderIndex.get(capability.identifier) ?? []) {\n if (!needed.has(provider.id)) {\n needed.set(provider.id, provider);\n visit(provider.activation.requires);\n }\n }\n continue;\n }\n if (this.#capabilities.getAll(capability).length > 0) {\n continue;\n }\n const provider = providerIndex.get(capability.identifier);\n if (provider && !needed.has(provider.id)) {\n needed.set(provider.id, provider);\n visit(provider.activation.requires);\n }\n }\n };\n for (const module of modules) {\n visit(module.activation.requires);\n }\n\n if (needed.size > 0) {\n log('pulling dependency providers', { modules: [...needed.keys()] });\n // Providers already mid-load (e.g. via the concurrent startup pass) are joined, not\n // re-drained — the scoped round below filters them as `isLoading` and would otherwise\n // return before their capabilities land.\n const inFlight = (yield* this.#notActivatingHere([...needed.values()])).filter((module) =>\n this.#loader.isLoading(module.id),\n );\n if (inFlight.length > 0) {\n yield* Effect.all(\n inFlight.map((module) => this.#loader.awaitSettled(module.id)),\n { concurrency: 'unbounded', discard: true },\n );\n }\n yield* this.runDependencyPass({ candidateModules: [...needed.values()], scopedToCandidates: true });\n }\n });\n }\n}\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Deferred from 'effect/Deferred';\nimport * as Effect from 'effect/Effect';\nimport * as Fiber from 'effect/Fiber';\nimport * as PubSub from 'effect/PubSub';\nimport * as Atom from 'effect/reactivity/Atom';\nimport type * as Registry from 'effect/reactivity/AtomRegistry';\nimport * as Ref from 'effect/Ref';\n\nimport { log } from '@dxos/log';\n\nimport * as ActivationEvent from '../activation-event.ts';\nimport type * as Plugin from '../plugin.ts';\nimport {\n type ActivationMessage,\n type PluginFailure,\n type PluginFailurePhase,\n type PluginFailureReason,\n type PluginInitializationError,\n PluginTimeoutError,\n} from './manager-types.ts';\n\n/**\n * The plugin manager's shared substrate, owned by no single unit: the observable state, the\n * activation status channel, the fiber tracker, and the lifecycle flags the manager and its\n * collaborating units (catalog, scheduler, loader) coordinate through. One object with named\n * operations instead of per-unit getter and setter callbacks: this IS shared mutable state, and\n * giving it a single home makes the sharing visible and its invariants enforceable.\n *\n * The atoms are the manager's public reactive surface (exposed via the `PluginManager`\n * interface); everything else is internal bookkeeping.\n */\nexport class ManagerState {\n /** All registered plugins (enabled or not). */\n readonly plugins: Atom.Writable<Plugin.Plugin[]>;\n /** Ids of system plugins (snapshot of the initial set; never disabled). */\n readonly core: Atom.Writable<string[]>;\n /** Ids of enabled plugins. */\n readonly enabled: Atom.Writable<string[]>;\n /** Modules of enabled plugins. */\n readonly modules: Atom.Writable<Plugin.PluginModule[]>;\n /** Ids of modules whose activate has completed and contributed. */\n readonly active: Atom.Writable<string[]>;\n /** Activation events that have fired. */\n readonly eventsFired: Atom.Writable<string[]>;\n /** Events whose modules changed after the event fired — replayed on the next enable. */\n readonly pendingReset: Atom.Writable<string[]>;\n /** Plugins that failed to load or activate (latest failure per id). */\n readonly failed: Atom.Writable<PluginFailure[]>;\n /** Ids of currently-registered dev-sourced plugins. */\n readonly devPluginIds: Atom.Writable<string[]>;\n\n /** Status channel: `activating`/`activated`/`error` messages per event and module. */\n readonly activation = Effect.runSync(PubSub.unbounded<ActivationMessage>());\n /** Fibers forked by the units, so shutdown can interrupt in-flight work. */\n readonly fibers = new FiberTracker();\n /**\n * Completed when the constructor's core/enabled `enable()` chain has registered all\n * modules; event dispatch awaits it so lazy plugin imports can't race activation.\n */\n readonly initialized = Effect.runSync(Deferred.make<void, PluginInitializationError>());\n /** Whether `start()` has run — gates incremental activation on later enables. */\n readonly started = Effect.runSync(Ref.make(false));\n /**\n * Completed when the Startup wave has finished; events dispatched mid-startup await it so their\n * modules can rely on every startup capability. Reset by {@link clearEventsFired}.\n */\n startupComplete = Effect.runSync(Deferred.make<void>());\n /** Set for the duration of `shutdown()` — new starts/activations are skipped meanwhile. */\n readonly shuttingDown = Effect.runSync(Ref.make(false));\n /**\n * Modules deactivated because a singleton capability they require lost its provider\n * (provider plugin disabled). Re-included as candidates in the next dependency pass.\n */\n readonly reactivateOnNextPass = new Set<string>();\n /**\n * Modules in a structural error state (cycle member, duplicate provider, impossible\n * require): excluded from activation rounds until a plugin-set change re-evaluates them.\n */\n readonly structurallyFailed = new Set<string>();\n\n readonly #registry: Registry.AtomRegistry;\n\n constructor(\n registry: Registry.AtomRegistry,\n initial: { plugins: readonly Plugin.Plugin[]; core: readonly string[]; enabled: readonly string[] },\n ) {\n this.#registry = registry;\n this.plugins = Atom.make<Plugin.Plugin[]>([...initial.plugins]).pipe(Atom.keepAlive);\n this.core = Atom.make<string[]>([...initial.core]).pipe(Atom.keepAlive);\n this.enabled = Atom.make<string[]>([...initial.enabled]).pipe(Atom.keepAlive);\n this.modules = Atom.make<Plugin.PluginModule[]>([]).pipe(Atom.keepAlive);\n this.active = Atom.make<string[]>([]).pipe(Atom.keepAlive);\n this.eventsFired = Atom.make<string[]>([]).pipe(Atom.keepAlive);\n this.pendingReset = Atom.make<string[]>([]).pipe(Atom.keepAlive);\n this.failed = Atom.make<PluginFailure[]>([]).pipe(Atom.keepAlive);\n this.devPluginIds = Atom.make<string[]>([]).pipe(Atom.keepAlive);\n }\n\n /** Generic read of any atom through the manager's registry. */\n read<T>(atom: Atom.Atom<T>): T {\n return this.#registry.get(atom);\n }\n\n #update<T>(atom: Atom.Writable<T>, fn: (value: T) => T): void {\n this.#registry.set(atom, fn(this.#registry.get(atom)));\n }\n\n //\n // Plugins.\n //\n\n getPlugins(): readonly Plugin.Plugin[] {\n return this.read(this.plugins);\n }\n\n getPlugin(id: string): Plugin.Plugin | undefined {\n return this.getPlugins().find((plugin) => plugin.meta.profile.key === id);\n }\n\n registerPlugin(plugin: Plugin.Plugin): void {\n log('add plugin', { id: plugin.meta.profile.key });\n // TODO(wittjosiah): Find a way to add a warning for duplicate plugins that doesn't cause log spam.\n this.#update(this.plugins, (plugins) => (plugins.includes(plugin) ? plugins : [...plugins, plugin]));\n }\n\n /** Swaps the plugin registered under the id (lazy resolution, dev shadowing). */\n replacePlugin(id: string, plugin: Plugin.Plugin): void {\n this.#update(this.plugins, (plugins) => plugins.map((p) => (p.meta.profile.key === id ? plugin : p)));\n }\n\n unregisterPlugin(id: string): void {\n log('remove plugin', { id });\n this.#update(this.plugins, (plugins) => plugins.filter((plugin) => plugin.meta.profile.key !== id));\n }\n\n isCore(id: string): boolean {\n return this.read(this.core).includes(id);\n }\n\n isEnabled(id: string): boolean {\n return this.read(this.enabled).includes(id);\n }\n\n markEnabled(id: string): void {\n this.#update(this.enabled, (enabled) => (enabled.includes(id) ? enabled : [...enabled, id]));\n }\n\n markDisabled(id: string): void {\n this.#update(this.enabled, (enabled) => enabled.filter((item) => item !== id));\n }\n\n markDevPlugin(id: string): void {\n this.#update(this.devPluginIds, (ids) => (ids.includes(id) ? ids : [...ids, id]));\n }\n\n unmarkDevPlugin(id: string): void {\n this.#update(this.devPluginIds, (ids) => ids.filter((existing) => existing !== id));\n }\n\n //\n // Modules.\n //\n\n getModules(): readonly Plugin.PluginModule[] {\n return this.read(this.modules);\n }\n\n addModule(module: Plugin.PluginModule): void {\n log('add module', { id: module.id });\n // TODO(wittjosiah): Find a way to add a warning for duplicate modules that doesn't cause log spam.\n // Dedup by id, not reference: re-resolving a lazy plugin yields fresh module objects for\n // the same ids, and double-registration would double-activate.\n this.#update(this.modules, (modules) =>\n modules.some((existing) => existing.id === module.id) ? modules : [...modules, module],\n );\n }\n\n removeModule(id: string): void {\n log('remove module', { id });\n this.#update(this.modules, (modules) => modules.filter((module) => module.id !== id));\n }\n\n pluginIdOfModule(moduleId: string): string | undefined {\n return this.getPlugins().find((plugin) => plugin.modules.some((module) => module.id === moduleId))?.meta.profile\n .key;\n }\n\n getActiveIds(): readonly string[] {\n return this.read(this.active);\n }\n\n isActive(moduleId: string): boolean {\n return this.getActiveIds().includes(moduleId);\n }\n\n markActive(moduleId: string): void {\n this.#update(this.active, (ids) => [...ids, moduleId]);\n }\n\n markInactive(moduleId: string): void {\n this.#update(this.active, (ids) => ids.filter((id) => id !== moduleId));\n }\n\n getActiveModules(): Plugin.PluginModule[] {\n const active = this.getActiveIds();\n return this.getModules().filter((module) => active.includes(module.id));\n }\n\n getInactiveModules(): Plugin.PluginModule[] {\n const active = this.getActiveIds();\n return this.getModules().filter((module) => !active.includes(module.id));\n }\n\n getActiveModulesByEvent(key: string): Plugin.PluginModule[] {\n return this.getActiveModules().filter((module) =>\n ActivationEvent.getEvents(module.activation.activatesOn).map(ActivationEvent.eventKey).includes(key),\n );\n }\n\n getInactiveModulesByEvent(key: string): Plugin.PluginModule[] {\n return this.getInactiveModules().filter((module) =>\n ActivationEvent.getEvents(module.activation.activatesOn).map(ActivationEvent.eventKey).includes(key),\n );\n }\n\n //\n // Activation events.\n //\n\n eventFired(key: string): boolean {\n return this.read(this.eventsFired).includes(key);\n }\n\n markEventFired(key: string): void {\n if (!this.eventFired(key)) {\n this.#update(this.eventsFired, (events) => [...events, key]);\n }\n }\n\n clearEventsFired(): void {\n this.#update(this.eventsFired, () => []);\n this.startupComplete = Effect.runSync(Deferred.make<void>());\n }\n\n isStarted(): Effect.Effect<boolean> {\n return Ref.get(this.started);\n }\n\n isShuttingDown(): Effect.Effect<boolean> {\n return Ref.get(this.shuttingDown);\n }\n\n //\n // Pending reset: events that already fired but whose module set changed (a plugin was\n // enabled after the fact) — replayed so the new modules activate.\n //\n\n getPendingReset(): readonly string[] {\n return this.read(this.pendingReset);\n }\n\n markPendingResetFor(module: Plugin.PluginModule): void {\n const activationEvents = ActivationEvent.getEvents(module.activation.activatesOn)\n .map(ActivationEvent.eventKey)\n .filter((key) => this.eventFired(key));\n\n const pendingReset = [...new Set(activationEvents)].filter((event) => !this.getPendingReset().includes(event));\n if (pendingReset.length > 0) {\n log('pending reset', { events: pendingReset });\n this.#update(this.pendingReset, (current) => [...current, ...pendingReset]);\n }\n }\n\n clearPendingReset(key: string): void {\n if (this.getPendingReset().includes(key)) {\n this.#update(this.pendingReset, (pending) => pending.filter((event) => event !== key));\n }\n }\n\n clearAllPendingReset(): void {\n this.#update(this.pendingReset, () => []);\n }\n\n //\n // Failures.\n //\n\n getFailures(): readonly PluginFailure[] {\n return this.read(this.failed);\n }\n\n /**\n * Records a failure for a plugin. Latest failure wins so the registry UI always sees the\n * most recent reason. Walks the `cause` chain when checking for timeouts: lazy-load\n * timeouts arrive wrapped in `LazyPluginError` (the timeout is the cause), but the\n * operator-visible reason should still be `'timeout'`.\n */\n recordFailure(id: string, phase: PluginFailurePhase, error: Error): void {\n const reason: PluginFailureReason = isTimeoutCause(error) ? 'timeout' : 'error';\n const failure: PluginFailure = { id, phase, reason, error, timestamp: Date.now() };\n // `LazyPluginError`'s own message says only that resolution failed; the import's rejection is\n // the cause, and without it a load failure is undiagnosable from the console alone.\n const cause = error.cause instanceof Error ? error.cause.message : undefined;\n log.warn('plugin failed to activate', { id, phase, reason, error: error.message, cause });\n this.#update(this.failed, (current) => [...current.filter((entry) => entry.id !== id), failure]);\n }\n\n clearFailure(id: string): boolean {\n if (!this.getFailures().some((failure) => failure.id === id)) {\n return false;\n }\n this.#update(this.failed, (current) => current.filter((failure) => failure.id !== id));\n return true;\n }\n}\n\n/**\n * Tracks fibers forked by the manager's units so shutdown can interrupt in-flight work.\n */\nexport class FiberTracker {\n readonly #fibers = new Set<Fiber.Fiber<unknown, unknown>>();\n\n track(fiber: Fiber.Fiber<unknown, unknown>): Effect.Effect<void> {\n return Effect.sync(() => void this.#fibers.add(fiber));\n }\n\n untrack(fiber: Fiber.Fiber<unknown, unknown>): Effect.Effect<void> {\n return Effect.sync(() => void this.#fibers.delete(fiber));\n }\n\n /** Fire-and-forget: fork the effect and track the fiber until it settles. */\n fork(effect: Effect.Effect<unknown>): void {\n this.#trackUntilSettled(Effect.runFork(effect));\n }\n\n /**\n * Registers a fiber forked inside an Effect, untracking it when it settles. The counterpart to\n * {@link fork} for effects that need the ambient context (`Plugin.Service`), which `runFork`\n * cannot supply.\n */\n trackForked(fiber: Fiber.Fiber<unknown, unknown>): Effect.Effect<void> {\n return Effect.sync(() => this.#trackUntilSettled(fiber));\n }\n\n interruptAll(): Effect.Effect<void> {\n return Effect.gen({ self: this }, function* () {\n const fibers = [...this.#fibers];\n this.#fibers.clear();\n yield* Effect.forEach(fibers, (fiber) => Fiber.interrupt(fiber), { concurrency: 'unbounded', discard: true });\n });\n }\n\n // An exit observer rather than a forked `Fiber.await`: this runs per module activation, and each\n // fork costs a scheduler hop (a clamped `setTimeout` in the browser).\n #trackUntilSettled(fiber: Fiber.Fiber<unknown, unknown>): void {\n this.#fibers.add(fiber);\n fiber.addObserver(() => this.#fibers.delete(fiber));\n }\n}\n\n/**\n * True when `error` (or anything along its `cause` chain) is a {@link PluginTimeoutError}.\n * Lazy-load timeouts wrap the timeout inside `LazyPluginError`, so a shallow check on the\n * outer error misses them. Bounded depth so a circular chain can't loop forever.\n */\nconst isTimeoutCause = (error: unknown, depth = 0): boolean => {\n if (depth > 5 || !(error instanceof Error)) {\n return false;\n }\n if (PluginTimeoutError.is(error)) {\n return true;\n }\n return isTimeoutCause((error as Error & { cause?: unknown }).cause, depth + 1);\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Deferred from 'effect/Deferred';\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport * as PubSub from 'effect/PubSub';\nimport * as Semaphore from 'effect/Semaphore';\n\nimport { log } from '@dxos/log';\n\nimport * as ActivationEvent from '../activation-event.ts';\nimport * as Plugin from '../plugin.ts';\nimport type * as PluginRegistry from '../registry.ts';\nimport { type ActivationScheduler } from './activation-scheduler.ts';\nimport { type ManagerState } from './manager-state.ts';\nimport { type PluginFailurePhase, PluginTimeoutError } from './manager-types.ts';\n\n/** Host configuration passed through from `ManagerOptions`. */\nexport type PluginCatalogOptions = {\n pluginLoader: (id: string) => Effect.Effect<{ plugin: Plugin.Plugin; dev?: boolean }, Error>;\n loadTimeout: Duration.Input;\n onRemove?: (id: string) => Effect.Effect<void, unknown>;\n};\n\n/**\n * The plugin catalog: add / enable / disable / remove, lazy plugin resolution, dev-plugin\n * shadowing, and the declared-dependency closure (`getDependencies` / `getDependents`).\n * Enabling resolves declared dependencies (installing registry-catalog-only entries), enables\n * in dependency-first order, and — after startup — runs an incremental activation pass for the\n * newly enabled modules. Disabling tears down dependents first, delegating plugin-level\n * deactivation to the scheduler.\n */\nexport class PluginCatalog {\n /** Coalesces concurrent lazy-plugin resolutions per plugin id. */\n readonly #resolving = new Map<string, Deferred.Deferred<Plugin.Plugin, Plugin.LazyPluginError>>();\n /** Serializes enable/disable per plugin id — see {@link PluginCatalog.#lifecycle}. */\n readonly #lifecycles = new Map<string, Semaphore.Semaphore>();\n /** Dev-sourced plugin ids, with the shadowed original (if any) for restoration on remove. */\n readonly #devPlugins = new Map<string, { shadow?: { plugin: Plugin.Plugin; wasEnabled: boolean } }>();\n readonly #state: ManagerState;\n readonly #scheduler: ActivationScheduler;\n readonly #pluginRegistry: PluginRegistry.Manager;\n readonly #options: PluginCatalogOptions;\n\n constructor(\n state: ManagerState,\n scheduler: ActivationScheduler,\n pluginRegistry: PluginRegistry.Manager,\n options: PluginCatalogOptions,\n ) {\n this.#state = state;\n this.#scheduler = scheduler;\n this.#pluginRegistry = pluginRegistry;\n this.#options = options;\n }\n\n /**\n * Fire-and-forget disable of a failed plugin. Forked because a failure can\n * happen mid-activation chain — yielding a `disable` inline would deadlock\n * on the shared semaphores. Core plugins are skipped (the host opted into\n * them being non-removable; the failure record is enough signal).\n */\n scheduleAutoDisable(id: string): void {\n if (import.meta.env.DEV && import.meta.env.MODE !== 'test') {\n // Transient HMR failures must not persist; skip auto-disable in dev server.\n return;\n }\n if (!this.#state.isCore(id) && this.#state.isEnabled(id)) {\n this.#state.fibers.fork(\n this.disable(id).pipe(\n Effect.tap(() => Effect.sync(() => log.error('plugin auto-disabled', { id }))),\n Effect.tapError((error) => Effect.sync(() => log.warn('auto-disable failed', { id, error }))),\n Effect.ignore,\n ),\n );\n }\n }\n\n /**\n * The per-plugin enable/disable lock.\n *\n * `#disableOne` flips the `enabled` atom before it tears anything down, so without this an\n * `enable` reacting to that atom re-registers the plugin's modules and the in-flight disable\n * then de-registers them again — the plugin ends up enabled with no modules. Auto-disable\n * forks precisely so taking this lock cannot deadlock an activation chain.\n */\n #lifecycle(id: string): Semaphore.Semaphore {\n let semaphore = this.#lifecycles.get(id);\n if (!semaphore) {\n semaphore = Semaphore.makeUnsafe(1);\n this.#lifecycles.set(id, semaphore);\n }\n return semaphore;\n }\n\n /** Whether the id is currently dev-sourced. */\n isDev(id: string): boolean {\n return this.#devPlugins.has(id);\n }\n\n /**\n * Marks `id` as dev-sourced. If the plugin displaced an existing one, pass\n * the shadow snapshot so `remove` can restore it. Repeat calls (e.g. a dev\n * plugin reload) preserve the original shadow target — restoration always\n * unwinds back to the real underlying plugin, never an intermediate dev build.\n */\n #markDev(id: string, shadow?: { plugin: Plugin.Plugin; wasEnabled: boolean }): void {\n if (this.#devPlugins.has(id)) {\n return;\n }\n this.#devPlugins.set(id, { shadow });\n this.#state.markDevPlugin(id);\n }\n\n /** Drops the dev-plugin entry and returns its shadow data (if any) for restoration. */\n #unmarkDev(id: string): { plugin: Plugin.Plugin; wasEnabled: boolean } | undefined {\n const entry = this.#devPlugins.get(id);\n this.#devPlugins.delete(id);\n this.#state.unmarkDevPlugin(id);\n return entry?.shadow;\n }\n\n //\n // Plugin catalog — dependency closure, add / enable / remove / disable, dev plugins.\n //\n\n getDependencies(id: string, opts?: { transitive?: boolean }): readonly string[] {\n const transitive = opts?.transitive !== false;\n if (!transitive) {\n return this.#directDependencies(id);\n }\n const walk = this.#computeDependencyClosure(id);\n // Drop the target itself; callers asked for its dependencies, not the\n // closure including the root.\n return walk.order.filter((depId) => depId !== id);\n }\n\n getDependents(id: string, opts?: { transitive?: boolean; enabledOnly?: boolean }): readonly string[] {\n return this.#collectDependents(id, {\n transitive: opts?.transitive !== false,\n enabledOnly: opts?.enabledOnly === true,\n });\n }\n\n /**\n * Adds a plugin to the manager via the plugin loader.\n * The plugin is registered but not enabled; call `enable` separately to activate it.\n * @param id The id of the plugin.\n */\n add(id: string): Effect.Effect<Plugin.Plugin, Error> {\n return Effect.gen({ self: this }, function* () {\n log('add plugin', { id });\n const { plugin, dev = false } = yield* this.#options.pluginLoader(id);\n const pluginId = plugin.meta.profile.key;\n const existing = this.#state.getPlugin(pluginId);\n\n if (dev && existing && existing !== plugin) {\n // Shadow path: a plugin with this id is already registered (a builtin,\n // a registry install, or a previous dev load). Disable it, stash it,\n // and swap the dev plugin into the same id slot. The dialog will call\n // `enable(pluginId)` next, which activates the dev plugin's modules.\n // Marking as dev is a no-op when the id is already tracked, so a dev-plugin\n // reload (after editing source) keeps the *original* shadow target —\n // removal restores the real underlying plugin, not an intermediate build.\n const wasEnabled = this.#state.isEnabled(pluginId);\n if (wasEnabled) {\n yield* this.disable(pluginId);\n }\n this.#markDev(pluginId, { plugin: existing, wasEnabled });\n this.#state.replacePlugin(pluginId, plugin);\n } else {\n this.#state.registerPlugin(plugin);\n if (dev) {\n this.#markDev(pluginId);\n }\n }\n\n return plugin;\n });\n }\n\n /**\n * Enables a plugin.\n * @param id The id of the plugin.\n * @param opts See {@link PluginManager.enable}.\n */\n enable(id: string, opts?: { resolveDependencies?: boolean }): Effect.Effect<boolean, Error, Plugin.Service> {\n const resolveDependencies = opts?.resolveDependencies !== false;\n return Effect.gen({ self: this }, function* () {\n log('enable plugin', { id, resolveDependencies });\n\n if (!resolveDependencies) {\n return yield* this.#enableOne(id);\n }\n\n // If the root id is unknown to both the registered set and the catalog,\n // fall back to the silent `_enableOne` path (which returns `false`).\n // This preserves the prior contract for persisted `enabled` entries\n // whose plugins are no longer bundled, instead of recording a confusing\n // \"missing self-dependency\" failure.\n if (!this.#state.getPlugin(id) && !this.#getCatalogEntry(id)) {\n return yield* this.#enableOne(id);\n }\n\n // Compute the transitive closure across registered plugins and catalog\n // entries. Missing or cyclic entries are recorded as failures and the\n // target plugin is left disabled.\n const walk = this.#computeDependencyClosure(id);\n if (walk.cycle) {\n this.#state.recordFailure(\n id,\n 'load',\n new Plugin.PluginDependencyError({ context: { id, reason: 'cycle', path: walk.cycle } }),\n );\n return false;\n }\n if (walk.missing.length > 0) {\n this.#state.recordFailure(\n id,\n 'load',\n new Plugin.PluginDependencyError({ context: { id, reason: 'missing', missing: walk.missing } }),\n );\n return false;\n }\n\n // Install any catalog-only entries before enabling them. `add` may also\n // discover further declared deps once the plugin's real meta is loaded;\n // we re-walk after each install to absorb those.\n let queue = walk.toInstall.slice();\n const installed = new Set<string>();\n for (let next = queue.shift(); next !== undefined; next = queue.shift()) {\n if (installed.has(next) || this.#state.getPlugin(next)) {\n continue;\n }\n const installResult = yield* this.add(next).pipe(Effect.result);\n if (installResult._tag === 'Failure') {\n this.#state.recordFailure(\n id,\n 'load',\n new Plugin.PluginDependencyError({\n context: { id, reason: 'install-failed', dependency: next },\n cause: installResult.failure,\n }),\n );\n return false;\n }\n installed.add(next);\n const rewalk = this.#computeDependencyClosure(id);\n if (rewalk.cycle) {\n this.#state.recordFailure(\n id,\n 'load',\n new Plugin.PluginDependencyError({ context: { id, reason: 'cycle', path: rewalk.cycle } }),\n );\n return false;\n }\n if (rewalk.missing.length > 0) {\n this.#state.recordFailure(\n id,\n 'load',\n new Plugin.PluginDependencyError({ context: { id, reason: 'missing', missing: rewalk.missing } }),\n );\n return false;\n }\n queue = rewalk.toInstall.filter((depId) => !installed.has(depId));\n }\n\n // Enable in dependency-first order. `_enableOne` is idempotent on the\n // enabled atom so previously-enabled deps short-circuit.\n const order = this.#computeDependencyClosure(id).order;\n let succeeded = false;\n for (const depId of order) {\n const ok = yield* this.#enableOne(depId);\n if (depId === id) {\n succeeded = ok;\n }\n }\n return succeeded;\n });\n }\n\n /**\n * Enables a single plugin without consulting its declared dependencies.\n * Used by {@link PluginCatalog.enable} as the leaf step after closure resolution, and\n * directly when callers pass `{ resolveDependencies: false }`.\n *\n * The underlying operations (module registration and pending-reset marking,\n * `activate`) are all idempotent, so this method is safe to call multiple\n * times for the same id. The constructor's bootstrap path relies on this:\n * the persisted `enabled` ids are written into `_enabledAtom` up front, so\n * the very first `enable(id)` for those plugins sees `alreadyEnabled`-style\n * state but still needs to perform the module registration and activation.\n */\n #enableOne(id: string): Effect.Effect<boolean, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n const stub = this.#state.getPlugin(id);\n if (!stub) {\n return false;\n }\n\n // Clear any prior failure record so a retry starts from a clean slate.\n // The failure stays on the atom only if this attempt also fails. Structural\n // exclusions are re-evaluated too: a newly enabled plugin may resolve them.\n this.#state.clearFailure(id);\n this.#state.structurallyFailed.clear();\n\n const plugin = yield* this.#resolveLazy(stub);\n\n this.#state.markEnabled(id);\n\n plugin.modules.forEach((module) => {\n this.#state.addModule(module);\n this.#state.markPendingResetFor(module);\n });\n\n log('pending reset', { events: [...this.#state.getPendingReset()] });\n // Replay events that already fired so the newly registered modules activate. Startup is\n // excluded: `activate` delegates it to `start()`, which would re-run the full unscoped\n // passes, re-publish the event-level `activated` message that gates app-ready, and fork a\n // second idle daemon — once per enable. The scoped pass below covers this plugin's\n // baseline-wave modules, which is all the replay was reaching for.\n const startupKey = ActivationEvent.eventKey(ActivationEvent.Startup);\n const replay = this.#state.getPendingReset().filter((event) => event !== startupKey);\n this.#state.clearPendingReset(startupKey);\n yield* Effect.all(\n replay.map((event) => this.#scheduler.activate(event)),\n { concurrency: 'unbounded' },\n );\n\n // After startup, a newly enabled module whose wave has already passed activates\n // incrementally against the already-contributed capability set. Failures are scoped to\n // this plugin. Modules still waiting on an unfired event are excluded — they activate\n // when it fires, and the pending-reset dispatch above replays the ones that already did.\n if (yield* this.#state.isStarted()) {\n const pass = this.#scheduler\n .runDependencyPass({\n candidateModules: plugin.modules.filter((module) => this.#scheduler.isEligible(module)),\n })\n .pipe(\n Effect.result,\n Effect.map((result) => {\n if (result._tag === 'Failure') {\n this.#state.recordFailure(id, 'activation', result.failure);\n }\n }),\n );\n // Streaming bootstrap: fork so `enable` (and thus `initialized`, which event dispatch\n // awaits) completes on REGISTRATION — awaiting here would serialize the entire startup\n // fan-out into the enable chain. `start()` waits for loads to settle before ready.\n if (yield* Deferred.isDone(this.#state.initialized)) {\n yield* pass;\n // A plugin enabled after boot missed every host fire of its own start event, and the\n // pending-reset replay above only covers events that fired — so fire it here, or the\n // plugin's start-gated modules would never activate.\n yield* this.#scheduler\n .activate(ActivationEvent.pluginStart(id))\n .pipe(Effect.catch((error) => Effect.sync(() => this.#state.recordFailure(id, 'activation', error))));\n } else {\n // Tracked so `shutdown()` interrupts an incremental pass still running from the\n // bootstrap enable chain.\n yield* this.#state.fibers.trackForked(yield* pass.pipe(Effect.forkDetach));\n }\n }\n\n return true;\n }).pipe(this.#lifecycle(id).withPermits(1));\n }\n\n /**\n * Resolves a lazy plugin stub (returned by {@link Plugin.lazy}) to its\n * loaded form and swaps it into `_pluginsAtom`. Returns the input unchanged\n * when the plugin is already resolved, so callers can `yield*` this\n * unconditionally. The lazy stub carries `meta` synchronously but its\n * `modules` list is empty until the loader resolves; the swap ensures\n * subsequent enable/disable operations see the resolved plugin.\n *\n * Concurrent calls for the same id are coalesced:\n * the first caller starts the resolution, every subsequent caller awaits\n * the same `Deferred`. On failure we publish a `lazy:<id>` error message\n * and skip the atom swap so the failure is observable to the activation\n * subscriber and a retry can be attempted.\n */\n #resolveLazy(plugin: Plugin.Plugin): Effect.Effect<Plugin.Plugin, Plugin.LazyPluginError> {\n return Effect.gen({ self: this }, function* () {\n if (!Plugin.isLazy(plugin)) {\n return plugin;\n }\n const id = plugin.meta.profile.key;\n\n const existing = this.#resolving.get(id);\n if (existing) {\n return yield* Deferred.await(existing);\n }\n const deferred = yield* Deferred.make<Plugin.Plugin, Plugin.LazyPluginError>();\n this.#resolving.set(id, deferred);\n\n return yield* Effect.gen({ self: this }, function* () {\n log('resolving lazy plugin', { id });\n yield* PubSub.publish(this.#state.activation, { event: '', state: 'activating', module: `lazy:${id}` });\n // The plugin-definition chunk import is startup work that predates any module\n // activation; measured so the profiler can attribute it per plugin.\n performance.mark(`plugin-load:${id}:start`);\n const resolvedPlugin = yield* Plugin.resolveLazy(plugin).pipe(\n // Cap how long a remote import can hang. Without this the host can\n // sit on a pending dynamic `import()` indefinitely if the plugin's\n // server is unreachable, which stalls every caller awaiting\n // `enable(id)` and (transitively) the manager's initialization.\n Effect.timeoutOrElse({\n duration: this.#options.loadTimeout,\n orElse: () =>\n Effect.fail(\n new Plugin.LazyPluginError({\n context: { id, reason: 'load-failed' },\n cause: new PluginTimeoutError({ context: { id, phase: 'load' as PluginFailurePhase } }),\n }),\n ),\n }),\n );\n performance.mark(`plugin-load:${id}:end`);\n performance.measure(`plugin-load:${id}`, `plugin-load:${id}:start`, `plugin-load:${id}:end`);\n this.#state.replacePlugin(id, resolvedPlugin);\n yield* PubSub.publish(this.#state.activation, { event: '', state: 'activated', module: `lazy:${id}` });\n return resolvedPlugin;\n }).pipe(\n Effect.tapError((error) =>\n Effect.gen({ self: this }, function* () {\n yield* PubSub.publish(this.#state.activation, { event: '', state: 'error', module: `lazy:${id}`, error });\n this.#state.recordFailure(id, 'load', error);\n this.scheduleAutoDisable(id);\n }),\n ),\n Effect.tap((value) => Deferred.succeed(deferred, value)),\n Effect.tapCause((cause) => Deferred.failCause(deferred, cause)),\n Effect.ensuring(Effect.sync(() => this.#resolving.delete(id))),\n );\n });\n }\n\n /**\n * Removes a plugin from the manager.\n * @param id The id of the plugin.\n * @param opts See {@link PluginManager.remove}.\n */\n remove(id: string, opts?: { cascade?: boolean }): Effect.Effect<boolean, Error, Plugin.Service> {\n return Effect.gen({ self: this }, function* () {\n log('remove plugin', { id });\n const wasDev = this.#devPlugins.has(id);\n const disabled = yield* this.disable(id, opts);\n if (!disabled) {\n return false;\n }\n\n this.#state.unregisterPlugin(id);\n if (this.#options.onRemove) {\n this.#state.fibers.fork(\n this.#options.onRemove(id).pipe(\n Effect.tapError((error) => Effect.sync(() => log.warn('plugin remove hook failed', { id, error }))),\n Effect.ignore,\n ),\n );\n }\n\n // If a dev plugin was shadowing an existing plugin, reinstate the\n // original now that the dev plugin is gone. Re-enable only if the\n // original was enabled at shadow time — preserving the user's intent\n // for plugins they had explicitly disabled before iterating on a dev\n // build.\n if (wasDev) {\n const shadow = this.#unmarkDev(id);\n if (shadow) {\n this.#state.registerPlugin(shadow.plugin);\n if (shadow.wasEnabled) {\n yield* this.enable(id);\n }\n }\n }\n return true;\n });\n }\n\n /**\n * Disables a plugin.\n * @param id The id of the plugin.\n * @param opts See {@link PluginManager.disable}.\n */\n disable(id: string, { cascade = true }: { cascade?: boolean } = {}): Effect.Effect<boolean, Error> {\n return Effect.gen({ self: this }, function* () {\n log('disable plugin', { id, cascade });\n if (this.#state.isCore(id)) {\n return false;\n }\n\n const plugin = this.#state.getPlugin(id);\n if (!plugin) {\n return false;\n }\n\n if (cascade) {\n const enabledDependents = this.#collectDependents(id, { transitive: true, enabledOnly: true });\n if (enabledDependents.length > 0) {\n const coreDependent = enabledDependents.find((dependentId) => this.#state.isCore(dependentId));\n if (coreDependent) {\n return yield* Effect.fail(\n new Plugin.PluginDependencyError({\n context: { id, reason: 'core-dependent', coreDependent },\n }),\n );\n }\n // Disable transitive dependents first (leaves before root). The\n // walk returns them in dependents-before-deps order — exactly what\n // we want for teardown.\n for (const dependentId of enabledDependents) {\n yield* this.#disableOne(dependentId);\n }\n }\n }\n\n yield* this.#disableOne(id);\n return true;\n });\n }\n\n /**\n * Disables a single plugin without consulting its dependents. Used by\n * {@link PluginCatalog.disable} after the dependents pass has run (or been skipped via\n * `cascade: false`).\n */\n #disableOne(id: string): Effect.Effect<boolean, Error> {\n return Effect.gen({ self: this }, function* () {\n if (this.#state.isCore(id)) {\n return false;\n }\n const plugin = this.#state.getPlugin(id);\n if (!plugin) {\n return false;\n }\n const enabledIndex = this.#state.read(this.#state.enabled).findIndex((enabled) => enabled === id);\n if (enabledIndex !== -1) {\n this.#state.markDisabled(id);\n yield* this.#scheduler.deactivatePlugin(id);\n plugin.modules.forEach((module) => {\n this.#state.removeModule(module.id);\n });\n }\n return true;\n }).pipe(this.#lifecycle(id).withPermits(1));\n }\n\n /** Entries of the cached registry catalog. */\n #catalogEntries(): readonly Plugin.Meta[] {\n return this.#state.read(this.#pluginRegistry.plugins).entries;\n }\n\n /** Looks up an id in the cached registry catalog, returning the entry or `undefined`. */\n #getCatalogEntry(id: string): Plugin.Meta | undefined {\n return this.#catalogEntries().find((entry) => entry.profile.key === id);\n }\n\n /**\n * Returns the direct `dependsOn` declarations for an id, drawing from the\n * registered plugin's meta when available and falling back to the registry\n * catalog entry. Unknown ids return an empty list (callers detect \"missing\"\n * separately).\n */\n #directDependencies(id: string): string[] {\n const plugin = this.#state.getPlugin(id);\n if (plugin) {\n return [...(plugin.meta.profile.dependsOn ?? [])];\n }\n const catalog = this.#getCatalogEntry(id);\n return catalog?.profile.dependsOn ? [...catalog.profile.dependsOn] : [];\n }\n\n /**\n * Computes the transitive dependency closure for an id.\n *\n * Walks {@link #directDependencies} (registered plugins ∪ catalog entries).\n * Returns:\n * - `order`: closure including the root in dependency-first topological order.\n * - `missing`: ids in the closure that are neither registered nor in the catalog.\n * - `toInstall`: ids in the closure that are in the catalog but not yet registered.\n * - `cycle`: when a cycle is detected, the cycle path; otherwise `undefined`.\n */\n #computeDependencyClosure(id: string): {\n order: string[];\n missing: string[];\n toInstall: string[];\n cycle?: string[];\n } {\n const order: string[] = [];\n const visited = new Set<string>();\n const onStack = new Set<string>();\n const stackPath: string[] = [];\n const missing: string[] = [];\n const toInstall: string[] = [];\n let cycle: string[] | undefined;\n\n const knownIds = new Set<string>([\n ...this.#state.getPlugins().map((plugin) => plugin.meta.profile.key),\n ...this.#catalogEntries().map((entry) => entry.profile.key),\n ]);\n\n const visit = (currentId: string): void => {\n if (cycle) {\n return;\n }\n if (visited.has(currentId)) {\n return;\n }\n if (onStack.has(currentId)) {\n const cycleStart = stackPath.indexOf(currentId);\n cycle = [...stackPath.slice(cycleStart), currentId];\n return;\n }\n onStack.add(currentId);\n stackPath.push(currentId);\n\n if (!knownIds.has(currentId)) {\n missing.push(currentId);\n } else if (!this.#state.getPlugin(currentId)) {\n toInstall.push(currentId);\n }\n\n for (const depId of this.#directDependencies(currentId)) {\n visit(depId);\n if (cycle) {\n break;\n }\n }\n\n onStack.delete(currentId);\n stackPath.pop();\n if (!cycle) {\n visited.add(currentId);\n order.push(currentId);\n }\n };\n\n visit(id);\n return { order, missing, toInstall, cycle };\n }\n\n /**\n * Walks the reverse `dependsOn` edges across registered plugins. With\n * `enabledOnly`, filters the result to currently-enabled ids. Returns\n * dependents in dependents-before-deps order so callers (cascade-disable)\n * can iterate and tear down leaves first.\n */\n #collectDependents(id: string, opts: { transitive: boolean; enabledOnly: boolean }): string[] {\n const direct = this.#state\n .getPlugins()\n .filter((plugin) => plugin.meta.profile.dependsOn?.some((dep) => dep === id))\n .map((plugin) => plugin.meta.profile.key);\n\n if (!opts.transitive) {\n return opts.enabledOnly ? direct.filter((dependentId) => this.#state.isEnabled(dependentId)) : direct;\n }\n\n const result: string[] = [];\n const visited = new Set<string>();\n const visit = (currentId: string): void => {\n if (visited.has(currentId)) {\n return;\n }\n visited.add(currentId);\n const parents = this.#state\n .getPlugins()\n .filter((plugin) => plugin.meta.profile.dependsOn?.some((dep) => dep === currentId))\n .map((plugin) => plugin.meta.profile.key);\n for (const parentId of parents) {\n visit(parentId);\n if (parentId !== id && !result.includes(parentId)) {\n result.push(parentId);\n }\n }\n };\n visit(id);\n\n return opts.enabledOnly ? result.filter((dependentId) => this.#state.isEnabled(dependentId)) : result;\n }\n}\n","//\n// Copyright 2025 DXOS.org\n//\n\n//\n// The manager composes collaborating units behind one public API. Each unit receives the\n// shared substrate — `ManagerState` (`manager-state.ts`): the reactive atoms, the activation\n// status channel, the fiber tracker, and the lifecycle flags — plus the collaborators it\n// drives and its own host configuration. Nothing receives a manager reference or a callback\n// into another unit:\n//\n// 1. The plugin catalog (`plugin-catalog.ts`) — add/remove/enable/disable, lazy plugin\n// resolution, dev-plugin shadowing, and the declared-dependency closure\n// (`getDependencies`/`getDependents`). Collaborators: the scheduler (event replay and\n// plugin deactivation) and the registry catalog.\n//\n// 2. The activation scheduler (`activation-scheduler.ts`) — the lifecycle engine\n// (start / activate / deactivate / reset) and the decision of when each module's\n// `activate` runs. Dependency-mode modules activate in rounds (ordering logic and\n// vocabulary in `activation-graph.ts`), repeated until one activates nothing new;\n// event-mode modules park until their `activatesOn` fires, with inactive dependency\n// providers pulled on demand first. Collaborator: the loader.\n//\n// 3. The module loader (`module-loader.ts`) — the per-module load pipeline. Loads are\n// memoized (id -> Deferred): every activation path converges on `loader.load`, concurrent\n// paths await the same deferred, and contribution is idempotent per module. Because\n// rounds run concurrently (the startup pass and an event fired mid-startup), the loader\n// also waits for in-flight multi providers before a module's activate runs.\n//\n// Module bodies receive the manager as the ambient `Plugin.Service`. That dependency is\n// carried as a typed Effect requirement (`R = Plugin.Service`) through the loader, scheduler,\n// and catalog, and satisfied exactly once here, at the public boundary.\n//\n// Failures are STRUCTURAL, not fatal: missing/duplicate providers and cycles put the owning\n// plugin into an error state (the `failed` atom) and exclude its modules; everything\n// independent proceeds. Per-module failures skip transitive dependents only. The\n// failure -> auto-disable policy is wired here at the composition root, by observing the\n// status channel (the loader publishes module errors; the catalog owns disabling).\n//\n\nimport * as Deferred from 'effect/Deferred';\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport * as Fiber from 'effect/Fiber';\nimport * as PubSub from 'effect/PubSub';\nimport * as Atom from 'effect/reactivity/Atom';\nimport * as Registry from 'effect/reactivity/AtomRegistry';\nimport * as Ref from 'effect/Ref';\nimport * as Semaphore from 'effect/Semaphore';\n\nimport * as AtomEx from '@dxos/effect/AtomEx';\nimport * as EffectEx from '@dxos/effect/EffectEx';\nimport { log } from '@dxos/log';\n\nimport type * as ActivationEvent from '../activation-event.ts';\nimport * as CapabilityManager from '../capability-manager.ts';\nimport * as Plugin from '../plugin.ts';\n// Imported with a `PluginRegistry` alias because the unrelated `@effect/atom-react`\n// `Registry` is already imported above; from outside this file the namespace is\n// re-exported as `Registry` via `./index.ts`.\nimport * as PluginRegistry from '../registry.ts';\nimport { ActivationScheduler } from './activation-scheduler.ts';\nimport { ManagerState } from './manager-state.ts';\nimport {\n type ActivationMessage,\n DEFAULT_ACTIVATION_TIMEOUT,\n DEFAULT_LOAD_TIMEOUT,\n type PluginFailure,\n PluginInitializationError,\n PluginTimeoutError,\n} from './manager-types.ts';\nimport { ModuleLoader } from './module-loader.ts';\nimport { PluginCatalog } from './plugin-catalog.ts';\n\n// Shared with the manager's collaborating units; the canonical public surface stays here.\nexport { PluginInitializationError, PluginTimeoutError } from './manager-types.ts';\nexport type { ActivationMessage, PluginFailure, PluginFailurePhase, PluginFailureReason } from './manager-types.ts';\n\n/**\n * Identifier denoting a Manager.\n */\nexport const ManagerTypeId: unique symbol = Symbol.for('@dxos/app-framework/Manager');\nexport type ManagerTypeId = typeof ManagerTypeId;\n\n/**\n * Loader result that carries optional metadata about how the plugin was sourced.\n *\n * `dev: true` marks a plugin as session-only and triggers shadow-on-id-collision\n * inside the manager: if a plugin with the same id is already registered (a\n * builtin, or a previously-installed plugin from the registry), the dev plugin\n * temporarily takes over that id slot. The original is restored when the dev\n * plugin is removed (or on page reload, since dev plugins aren't persisted).\n */\nexport type LoadedPlugin = {\n plugin: Plugin.Plugin;\n /** True when the plugin came from a dev source. See type doc for semantics. */\n dev?: boolean;\n};\n\nexport type ManagerOptions = {\n pluginLoader: (id: string) => Effect.Effect<LoadedPlugin, Error>;\n plugins?: Plugin.Plugin[];\n enabled?: string[];\n /**\n * Ids of plugins the host pins on: always enabled, never disableable.\n *\n * Defaults to every plugin declaring `system` in `meta.profile.tags`. Hosts pass\n * this when the tag is the wrong authority — a plugin's `dx.config.ts` declares\n * one `system` tag for every host, so without an override the CLI inherits\n * Composer's judgment about what a user may turn off. Ids not present in\n * `plugins` are ignored.\n */\n core?: string[];\n /** Registry to use instead of creating one; `atomIdleTTL` does not apply to it. */\n registry?: Registry.AtomRegistry;\n /**\n * Backend for the plugin registry catalog. When omitted the manager exposes a\n * no-op `pluginRegistry` (empty list, no versions endpoint). Implementations\n * live in app-framework alongside the interface (e.g.\n * `EdgeRegistryPluginProvider`); the host app instantiates one and passes it in.\n */\n pluginRegistryProvider?: PluginRegistry.PluginProvider;\n /**\n * Hook called when a plugin is removed via {@link PluginManager.remove}. Used by the\n * host app to clean up persisted state (e.g. evict offline-cached plugin assets).\n * Failures are logged and swallowed; removal still succeeds even if the hook fails.\n */\n onRemove?: (id: string) => Effect.Effect<void, unknown>;\n /**\n * Maximum time allowed for a lazy plugin's dynamic `import()` to resolve.\n * Plugins that exceed this are flagged on the {@link PluginManager.failed}\n * atom and auto-disabled so a stuck remote host can't stall app boot.\n * Defaults to 30 seconds; pass `Duration.infinity` to disable.\n */\n loadTimeout?: Duration.Input;\n /**\n * Grace period before an atom with no subscribers is removed from the registry this manager creates.\n * Defaults to {@link AtomEx.DEFAULT_IDLE_TTL}; see `AtomEx.makeRegistry`.\n */\n atomIdleTTL?: Duration.Input;\n /**\n * Maximum time allowed for a single module's `activate()` Effect to settle.\n * Modules that exceed this fail with {@link PluginTimeoutError}; the owning\n * plugin is recorded on `failed` and auto-disabled. Defaults to 30 seconds;\n * pass `Duration.infinity` to disable.\n */\n activationTimeout?: Duration.Input;\n /**\n * Completes when the host is idle, gating the Idle wave. Defaults to the real paint/idle wait,\n * which resolves immediately off-browser; `Effect.never` models a browser that has not idled.\n */\n whenIdle?: Effect.Effect<void>;\n};\n\n/**\n * Interface for the Plugin Manager.\n */\nexport interface PluginManager {\n readonly [ManagerTypeId]: ManagerTypeId;\n readonly activation: PubSub.PubSub<ActivationMessage>;\n readonly capabilities: CapabilityManager.CapabilityManager;\n readonly registry: Registry.AtomRegistry;\n /**\n * Cached registry catalog state plus pass-throughs for `listVersions` /\n * `getPlugin`. Always present — the host supplies a `pluginRegistryProvider`\n * via {@link ManagerOptions} for real backends, or it falls back to a no-op\n * implementation that yields an empty catalog.\n */\n readonly pluginRegistry: PluginRegistry.Manager;\n\n readonly plugins: Atom.Atom<readonly Plugin.Plugin[]>;\n readonly core: Atom.Atom<readonly string[]>;\n readonly enabled: Atom.Atom<readonly string[]>;\n readonly modules: Atom.Atom<readonly Plugin.PluginModule[]>;\n readonly active: Atom.Atom<readonly string[]>;\n readonly eventsFired: Atom.Atom<readonly string[]>;\n readonly pendingReset: Atom.Atom<readonly string[]>;\n /**\n * Plugins that failed to load or activate. Subscribers (e.g. the registry\n * UI) can use this to flag unhealthy entries; a plugin id appears here at\n * most once with its most recent failure.\n */\n readonly failed: Atom.Atom<readonly PluginFailure[]>;\n /**\n * Ids of currently-registered plugins that came from a dev source (loaded\n * via {@link LoadedPlugin} with `dev: true`). Subscribers can use this to\n * badge dev-overridden plugins or to derive the id of the active dev plugin\n * for an \"uninstall dev plugin\" affordance.\n */\n readonly devPluginIds: Atom.Atom<readonly string[]>;\n\n getPlugins(): readonly Plugin.Plugin[];\n getCore(): readonly string[];\n getEnabled(): readonly string[];\n getModules(): readonly Plugin.PluginModule[];\n getActive(): readonly string[];\n getEventsFired(): readonly string[];\n getPendingReset(): readonly string[];\n getFailed(): readonly PluginFailure[];\n getDevPluginIds(): readonly string[];\n\n /**\n * Clears the failure record for a plugin so it can be retried. Returns\n * whether a failure record existed and was removed.\n */\n clearFailure(id: string): boolean;\n\n /**\n * Loads a plugin via the plugin loader and registers it without enabling it.\n * Returns the loaded plugin so callers can enable it by its canonical id\n * (which may differ from the locator used to load it, e.g. URL loaders).\n * A plugin whose id is already enabled, such as one persisted from an earlier\n * session, is activated as part of the add.\n */\n add(id: string): Effect.Effect<Plugin.Plugin, Error>;\n\n /**\n * Enables a plugin.\n *\n * Default behavior auto-resolves the plugin's declared `dependsOn` closure:\n * missing entries that exist in the plugin registry catalog are installed via\n * {@link add}, then enabled in dependency-first order. Set `resolveDependencies`\n * to `false` to enable only the named plugin and skip the closure walk\n * entirely — useful when substituting an alternative plugin that satisfies\n * the dependent's capability needs in its own way.\n */\n enable(id: string, opts?: { resolveDependencies?: boolean }): Effect.Effect<boolean, Error>;\n\n /**\n * Removes a plugin from the manager (disables then unregisters).\n *\n * Honors the same cascade option as {@link disable}.\n */\n remove(id: string, opts?: { cascade?: boolean }): Effect.Effect<boolean, Error>;\n\n /**\n * Disables a plugin.\n *\n * By default, cascades to currently-enabled dependents (transitively, leaves\n * first) so disabling a depended-upon plugin never leaves its dependents\n * stranded. Pass `cascade: false` to disable only the named plugin and leave\n * its dependents enabled-but-broken — VS Code-style disable parity for\n * callers that want the escape hatch (e.g. when swapping in an alternative\n * implementation that satisfies the dependents' needs in its own way).\n *\n * Fails with {@link Plugin.PluginDependencyError} (`reason: 'core-dependent'`)\n * when cascading would require disabling a core plugin; UI flows should\n * surface their own confirmation before calling `disable` with the default.\n */\n disable(id: string, opts?: { cascade?: boolean }): Effect.Effect<boolean, Error>;\n\n /**\n * Returns the plugin ids that the given plugin declares as dependencies.\n *\n * Walks `meta.dependsOn` from both registered plugins and the plugin registry\n * catalog so callers can preview the closure for a plugin that isn't yet\n * installed. With `transitive: true` (default), returns the full dependency\n * closure in dependency-first order (deps before dependents). Without it,\n * returns the direct declarations only.\n */\n getDependencies(id: string, opts?: { transitive?: boolean }): readonly string[];\n\n /**\n * Returns the plugin ids that declare the given plugin as a dependency.\n *\n * Walks `meta.dependsOn` over registered plugins. With `transitive: true`\n * (default), returns the full reverse closure. With `enabledOnly: true`,\n * filters to currently-enabled dependents — used by UI flows to preview what\n * a cascading disable would touch.\n */\n getDependents(id: string, opts?: { transitive?: boolean; enabledOnly?: boolean }): readonly string[];\n /**\n * Runs startup: the capability-dependency resolution pass for dependency-mode modules,\n * concurrently with the event-mode activation pass for any module explicitly targeting the\n * Startup event. The event-level Startup `activated` message publishes only after both\n * passes complete. Idempotent — subsequent calls activate whatever registered since.\n * `activate(Startup)` delegates here.\n */\n start(): Effect.Effect<boolean, Error>;\n // TODO(wittjosiah): Improve error typing.\n activate(\n event: ActivationEvent.ActivationEvent | string,\n params?: { before?: string; after?: string },\n ): Effect.Effect<boolean, Error>;\n deactivate(id: string): Effect.Effect<boolean, Error>;\n reset(event: ActivationEvent.ActivationEvent | string): Effect.Effect<boolean, Error>;\n\n /**\n * Shuts down the manager by deactivating all active modules in reverse activation order,\n * clearing all capabilities, and resetting lifecycle bookkeeping.\n * Plugins, core, enabled, and modules remain intact so the manager can be reused.\n */\n shutdown(): Effect.Effect<boolean, Error>;\n}\n\n/**\n * Type guard to check if a value is a PluginManager.\n */\nexport const isManager = (value: unknown): value is PluginManager => {\n return typeof value === 'object' && value !== null && ManagerTypeId in value;\n};\n\n/**\n * Internal implementation of PluginManager.\n */\nclass ManagerImpl implements PluginManager {\n readonly [ManagerTypeId]: ManagerTypeId = ManagerTypeId;\n readonly capabilities: CapabilityManager.CapabilityManager;\n readonly registry: Registry.AtomRegistry;\n readonly pluginRegistry: PluginRegistry.Manager;\n\n private readonly _state: ManagerState;\n private readonly _loader: ModuleLoader;\n private readonly _scheduler: ActivationScheduler;\n private readonly _catalog: PluginCatalog;\n private readonly _shutdownSemaphore = Semaphore.makeUnsafe(1);\n /** The failure-supervision fiber; stopped by `shutdown`, restarted by `_withRuntime`. */\n private _supervisor: Fiber.Fiber<never> | undefined;\n\n constructor({\n pluginLoader,\n plugins = [],\n enabled = [],\n core: coreProp,\n registry,\n pluginRegistryProvider,\n onRemove,\n loadTimeout = DEFAULT_LOAD_TIMEOUT,\n activationTimeout = DEFAULT_ACTIVATION_TIMEOUT,\n atomIdleTTL = AtomEx.DEFAULT_IDLE_TTL,\n whenIdle,\n }: ManagerOptions) {\n // Core plugins default to `meta.tags.includes('system')`, overridden by the host's\n // explicit set. Either way the set is a snapshot of the initial `plugins` array\n // (later `add()` calls do not promote plugins to core), and a host-supplied id\n // that names no registered plugin is dropped rather than pinning a phantom.\n const registered = new Set(plugins.map(({ meta }) => meta.profile.key));\n const core: string[] = coreProp\n ? coreProp.filter((id) => registered.has(id))\n : plugins.filter(({ meta }) => meta.profile.tags?.includes('system')).map(({ meta }) => meta.profile.key);\n this.registry = registry ?? AtomEx.makeRegistry({ idleTTL: atomIdleTTL });\n this.capabilities = CapabilityManager.make({\n registry: this.registry,\n });\n this.pluginRegistry = new PluginRegistry.Manager(pluginRegistryProvider, this.registry);\n\n this._state = new ManagerState(this.registry, { plugins, core, enabled });\n this._loader = new ModuleLoader(this._state, this.capabilities, activationTimeout);\n this._scheduler = new ActivationScheduler(this._state, this.capabilities, this._loader, whenIdle);\n this._catalog = new PluginCatalog(this._state, this._scheduler, this.pluginRegistry, {\n pluginLoader,\n loadTimeout,\n onRemove,\n });\n this._superviseFailures();\n\n // The initialization flag lets event dispatch wait for the constructor-launched\n // core/enabled `enable()` calls to finish registering modules. Lazy plugins make\n // `enable` asynchronous (a dynamic `import()` happens inside it), so without this\n // synchronization an `activate` triggered immediately after `make` could fire on an\n // empty module set. Failures are wrapped in `PluginInitializationError` so awaiters\n // get a tagged error rather than the wide `Error` produced by the underlying chain.\n //\n // Dedupe before mapping to `enable` — `core` and `enabled` may overlap (an\n // app-supplied plugin can be in both); same-id work is coalesced at the leaf\n // (lazy resolution) and module registration dedupes by id, but the dedupe\n // avoids redundant walks. `new Set([...])` preserves first-seen order which\n // matches the natural core-before-enabled precedence. Bounded concurrency:\n // sequential enables serialize ~60 plugin-definition imports (~1.7 s of the\n // boot critical path); unbounded would recreate the import contention plateau.\n const initialIds = [...new Set([...core, ...enabled])];\n void Effect.all(\n initialIds.map((id) => this.enable(id)),\n { concurrency: 8 },\n )\n .pipe(\n Effect.mapError((cause) => new PluginInitializationError({ cause })),\n Effect.tap(() => Deferred.succeed(this._state.initialized, undefined)),\n Effect.tapCause((cause) => Deferred.failCause(this._state.initialized, cause)),\n )\n .pipe(EffectEx.runAndForwardErrors);\n }\n\n get activation(): PubSub.PubSub<ActivationMessage> {\n return this._state.activation;\n }\n\n /**\n * Cross-unit failure policy, wired at the composition root: the loader publishes a module\n * error message for every failed activation; the catalog owns disabling. Idempotent —\n * a supervisor that is already running is kept.\n */\n private _superviseFailures(): void {\n if (this._supervisor !== undefined) {\n return;\n }\n this._supervisor = PubSub.subscribe(this._state.activation).pipe(\n Effect.flatMap((subscription) =>\n PubSub.take(subscription).pipe(\n Effect.tap((message) => Effect.sync(() => this._autoDisableOnModuleError(message))),\n // A yield per message is a clamped 4ms browser timer; `take` already suspends when the queue is empty.\n Effect.forever({ disableYield: true }),\n ),\n ),\n Effect.scoped,\n Effect.runFork,\n );\n }\n\n /**\n * Auto-disables the plugin owning a failed module. Error messages without a registered\n * module id (structural failures, lazy plugin loads) are handled by their own paths.\n */\n private _autoDisableOnModuleError(message: ActivationMessage): void {\n if (message.state !== 'error' || message.module === undefined) {\n return;\n }\n const pluginId = this._state.pluginIdOfModule(message.module);\n if (pluginId !== undefined) {\n this._catalog.scheduleAutoDisable(pluginId);\n }\n }\n\n /**\n * Entry wrapper for the unit effects that can run module activations: provides this manager\n * as the ambient `Plugin.Service` (the typed requirement carried by the units) and ensures\n * the failure supervisor is running (shutdown stops it).\n */\n private readonly _withRuntime = <A, E>(effect: Effect.Effect<A, E, Plugin.Service>): Effect.Effect<A, E> => {\n return Effect.suspend(() => {\n this._superviseFailures();\n return Effect.provideService(effect, Plugin.Service, this);\n });\n };\n\n get plugins(): Atom.Atom<readonly Plugin.Plugin[]> {\n return this._state.plugins;\n }\n\n get core(): Atom.Atom<readonly string[]> {\n return this._state.core;\n }\n\n /**\n * Ids of plugins that are currently enabled.\n */\n get enabled(): Atom.Atom<readonly string[]> {\n return this._state.enabled;\n }\n\n /**\n * Modules of plugins which are currently enabled.\n */\n get modules(): Atom.Atom<readonly Plugin.PluginModule[]> {\n return this._state.modules;\n }\n\n /**\n * Ids of modules which are currently active.\n */\n get active(): Atom.Atom<readonly string[]> {\n return this._state.active;\n }\n\n /**\n * Ids of events which have been fired.\n */\n get eventsFired(): Atom.Atom<readonly string[]> {\n return this._state.eventsFired;\n }\n\n /**\n * Ids of modules which are pending reset.\n */\n get pendingReset(): Atom.Atom<readonly string[]> {\n return this._state.pendingReset;\n }\n\n /**\n * Plugins that failed to load or activate.\n */\n get failed(): Atom.Atom<readonly PluginFailure[]> {\n return this._state.failed;\n }\n\n /**\n * Ids of currently-registered plugins that came from a dev source.\n */\n get devPluginIds(): Atom.Atom<readonly string[]> {\n return this._state.devPluginIds;\n }\n\n getPlugins(): readonly Plugin.Plugin[] {\n return this._state.getPlugins();\n }\n\n getCore(): readonly string[] {\n return this._state.read(this._state.core);\n }\n\n getEnabled(): readonly string[] {\n return this._state.read(this._state.enabled);\n }\n\n getModules(): readonly Plugin.PluginModule[] {\n return this._state.getModules();\n }\n\n getActive(): readonly string[] {\n return this._state.getActiveIds();\n }\n\n getEventsFired(): readonly string[] {\n return this._state.read(this._state.eventsFired);\n }\n\n getPendingReset(): readonly string[] {\n return this._state.getPendingReset();\n }\n\n getFailed(): readonly PluginFailure[] {\n return this._state.getFailures();\n }\n\n getDevPluginIds(): readonly string[] {\n return this._state.read(this._state.devPluginIds);\n }\n\n clearFailure(id: string): boolean {\n return this._state.clearFailure(id);\n }\n\n getDependencies(id: string, opts?: { transitive?: boolean }): readonly string[] {\n return this._catalog.getDependencies(id, opts);\n }\n\n getDependents(id: string, opts?: { transitive?: boolean; enabledOnly?: boolean }): readonly string[] {\n return this._catalog.getDependents(id, opts);\n }\n\n add(id: string): Effect.Effect<Plugin.Plugin, Error> {\n return this._catalog.add(id).pipe(\n // An id already in the enabled set (persisted from an earlier session) would otherwise read\n // as enabled while none of its modules is registered, and no toggle short of off-and-on starts it.\n Effect.tap((plugin) =>\n this._state.isEnabled(plugin.meta.profile.key) ? this.enable(plugin.meta.profile.key) : Effect.void,\n ),\n );\n }\n\n enable(id: string, opts?: { resolveDependencies?: boolean }): Effect.Effect<boolean, Error> {\n return this._catalog.enable(id, opts).pipe(this._withRuntime);\n }\n\n remove(id: string, opts?: { cascade?: boolean }): Effect.Effect<boolean, Error> {\n return this._catalog.remove(id, opts).pipe(this._withRuntime);\n }\n\n disable(id: string, opts?: { cascade?: boolean }): Effect.Effect<boolean, Error> {\n // Await the constructor's (concurrent) enable chain: a disable racing bootstrap\n // would miss not-yet-enabled dependents and cascade incorrectly.\n return Deferred.await(this._state.initialized).pipe(Effect.andThen(this._catalog.disable(id, opts)));\n }\n\n //\n // Lifecycle — delegated to the scheduler; `shutdown` is composition-wide and stays here.\n //\n\n start(): Effect.Effect<boolean, Error> {\n return this._scheduler.start().pipe(this._withRuntime);\n }\n\n activate(\n event: ActivationEvent.ActivationEvent | string,\n params?: { before?: string; after?: string },\n ): Effect.Effect<boolean, Error> {\n return this._scheduler.activate(event, params).pipe(this._withRuntime);\n }\n\n deactivate(id: string): Effect.Effect<boolean, Error> {\n return this._scheduler.deactivatePlugin(id);\n }\n\n reset(event: ActivationEvent.ActivationEvent | string): Effect.Effect<boolean, Error> {\n return this._scheduler.resetEvent(event).pipe(this._withRuntime);\n }\n\n shutdown(): Effect.Effect<boolean, Error> {\n return this._shutdownSemaphore.withPermits(1)(\n Effect.gen({ self: this }, function* () {\n yield* Ref.set(this._state.shuttingDown, true);\n log('shutdown');\n\n if (this._supervisor !== undefined) {\n yield* Fiber.interrupt(this._supervisor);\n this._supervisor = undefined;\n }\n yield* this._state.fibers.interruptAll();\n\n const activeIds = [...this._state.getActiveIds()].reverse();\n const allModules = this._state.getModules();\n const modulesToDeactivate = activeIds\n .map((id) => allModules.find((module) => module.id === id))\n .filter((module): module is Plugin.PluginModule => module != null);\n\n for (const module of modulesToDeactivate) {\n yield* this._loader.deactivate(module);\n }\n\n this._state.clearEventsFired();\n this._state.clearAllPendingReset();\n yield* this._loader.clear();\n yield* this._scheduler.clearClaims();\n yield* Ref.set(this._state.started, false);\n this._state.reactivateOnNextPass.clear();\n this._state.structurallyFailed.clear();\n\n log('shutdown complete');\n return true;\n }).pipe(Effect.ensuring(Ref.set(this._state.shuttingDown, false))),\n );\n }\n}\n\n/**\n * Creates a new Plugin Manager instance.\n */\nexport const make = (options: ManagerOptions): PluginManager => new ManagerImpl(options);\n"],"mappings":"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"}
|