$dshubuser@dshub:~/plugins$
  • Plugins
  • Submit
  • Blog
Composition and HMR: Import New Code, Dispose the Old Fiber, Then Activate
2026/08/28

Composition and HMR: Import New Code, Dispose the Old Fiber, Then Activate

Understand stable ids, configuration groups, and Cordis HMR’s unload-reload cycle, including how to diagnose plugins stuck in PENDING.

The real HMR flow: save the file → import the replacement module → unload the old plugin and reverse its effects → register the replacement → activate it once dependencies are ready.

If HMR means only “import the file again”, the most important step is missing: the old instance must first lose its runtime side effects.

01 / Configuration entries are comparable runtime nodes

Cordis HMR comparing configuration rows by id and selecting only changed plugin nodes

Give entries stable identities:

- id: logger
  name: '@deepseek-ai/cordis-plugin-logger-console'
- id: timer
  name: '@deepseek-ai/cordis-plugin-timer'
- id: hmr
  name: '@deepseek-ai/cordis-plugin-hmr'
  config:
    root: ['.']
- id: hello
  name: './hello.ts'

id lets Loader distinguish retained, unloaded, and reconfigured rows after cordis.yml changes. Without it, a row can receive a new identity on every read and look like “remove, then add”.

group loads and unloads nested entries as one unit, while isolate gives a group independent service instances.

This HMR example also depends on the timer service and Node loader internals. It is server-side Node HMR, not the browser-side client-plugin HMR path.

02 / HMR imports the replacement before unloading the old instance

Cordis HMR cycle from file save through old Fiber disposal to new plugin activation

@deepseek-ai/cordis-plugin-hmr watches file changes:

  1. After a save, HMR classifies the change as configuration, plugin code, or an external file.
  2. For a plugin-code change, HMR imports the replacement module first.
  3. The old runtime is unloaded and all effects are reversed.
  4. The replacement module is then registered and apply runs.
  5. If its services are not ready, the new Fiber remains PENDING instead of half-starting.

External or framework files are not single-plugin reload units; those changes make Loader exit so the host can restart.

Editing hello.ts can therefore stop the old output and produce the new one; editing the configuration lets Loader update rows by id.

03 / Why HMR can appear to do nothing

Separate two cases:

  • A misspelled path or package name is a resolution problem. Check name and logs first.
  • A missing provider is a valid PENDING state. The plugin produces no output and does not throw.

Inspect pending Fibers through the registry:

import { FiberState } from '@deepseek-ai/cordis'

for (const runtime of ctx.registry.values()) {
  for (const fiber of runtime.fibers) {
    if (fiber.state === FiberState.PENDING) {
      console.log(fiber.name + ' is PENDING')
    }
  }
}

04 / HMR’s safety boundary

HMR can reliably reverse resources that are registered as effects. Cordis manages event listeners, service registrations, and child plugins; custom timers, connections, and watchers must return disposers from ctx.effect().

If a resource escapes the Fiber, repeated saves can leave duplicate listeners or stale connections. “HMR-safe” first means clear ownership, and only then a watcher that detects the file.

05 / Why DSH puts HMR in the base composition

The dsh-base configuration includes timer and HMR plugins. Profiles add model, tool, session, and Agent capabilities on top. Editing a plugin can reuse the same unload-reload semantics instead of requiring a refresh implementation per capability.

The headless and web overlays disable server HMR. Browser-side client-plugin HMR is a separate path, so its behavior cannot be inferred from this Node watcher.

Where to go next

  • cordis.yml: Configuration as Composition
  • Lifecycle and effects
  • Cordis Inside DeepSeek Harness

Sources: composition and HMR tutorial, HMR plugin, and dsh-base composition.

All Posts

Author

avatar for DSH Research
DSH Research

Categories

  • Agent Infrastructure
01 / Configuration entries are comparable runtime nodes02 / HMR imports the replacement before unloading the old instance03 / Why HMR can appear to do nothing04 / HMR’s safety boundary05 / Why DSH puts HMR in the base compositionWhere to go next

More Posts

Cordis Inside DeepSeek Harness: Making Everything a Plugin
Agent Infrastructure

Cordis Inside DeepSeek Harness: Making Everything a Plugin

Trace dsh-base, Context services, event domains, and the tool pipeline to see how Cordis organizes a replaceable Agent runtime.

avatar for DSH Research
DSH Research
2026/08/29
Cordis: Turning a Running Application into a Reversible Plugin Tree
Agent Infrastructure

Cordis: Turning a Running Application into a Reversible Plugin Tree

Follow cordis.yml, Loader, and Context to see how Cordis composes, replaces, and safely tears down runtime capabilities in DeepSeek Harness.

avatar for DSH Research
DSH Research
2026/08/18
waterfall: Intercept, Wrap, and Short-Circuit with next()
Agent Infrastructure

waterfall: Intercept, Wrap, and Short-Circuit with next()

Follow a Cordis waterfall chain to see listeners delegate downstream, wrap results, or short-circuit when they own the decision.

avatar for DSH Research
DSH Research
2026/08/26

Newsletter

Join the community

Subscribe to our newsletter for the latest news and updates

[dshub] [zsh]$ dshub ls$ dshub submit$ dshub blog
-- NORMAL -- ✓ 2026 dshub