From 32803ef97e47dfb1068a852a79d488ffdfbadcdd Mon Sep 17 00:00:00 2001 From: bowenliang123 Date: Mon, 17 Aug 2026 01:10:33 +0800 Subject: [PATCH] refactor(host): register the projection unit directly, drop the double injection The module-level inject: ['sessionProjections'] already gates apply and auto-restarts when the registry provider is replaced; wrapping the same registration in ctx.inject(...) created a redundant dependent fiber (cordis-api/registry.md documents ctx.inject as shorthand for ctx.plugin({ inject, apply })). Registering in apply keeps one gate. --- src/host/index.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/host/index.ts b/src/host/index.ts index 2bd8b57..0815e37 100644 --- a/src/host/index.ts +++ b/src/host/index.ts @@ -10,9 +10,11 @@ * * Required service: the session-projection registry (the framework drives * the unit over `session/event` and persists its state via the projection - * cache). Registration conditions on the registry being composed - * (`ctx.inject(['sessionProjections'], …)`, the official pattern — an absent - * registry leaves the plugin inert, which is safe). + * cache). The module-level `inject` is the one gate: Cordis keeps this + * plugin PENDING until the registry exists, re-runs it when a provider is + * replaced, and an absent registry leaves the plugin inert (safe). The + * registration itself is an effect whose disposer rides the calling fiber — + * an unloaded plugin's key disappears from drives and snapshots. */ import type { Context } from '@deepseek-ai/cordis' @@ -24,9 +26,7 @@ export const name = 'dsh-context' export const inject = ['sessionProjections'] export function apply(ctx: Context): void { - ctx.inject(['sessionProjections'], (projectionCtx) => { - projectionCtx.sessionProjections.register(contextTimelineDefinition) - }) + ctx.sessionProjections.register(contextTimelineDefinition) } // ---- public type surface (stable for downstream consumers) -------------------