Cordis
Five rules of the baseplate
Cordis is the vendored plugin framework. dsh has no kernel to patch; extend it by mounting a plugin beside the others.
- 1
A plugin is one brick
A brick may be a function or a Service subclass. It has a name, apply(ctx), and sometimes an inject list.
A plugin implements Service. Function plugins export inject + apply(ctx); class plugins call super(ctx, name) in the constructor and register immediately.
- 2
Context is the shared shelf
A teacher puts the brain on the shelf; everyone else takes ctx.llm without importing that teacher.
Context is the service repository. Stable keys include ctx.tools, ctx.llm, and ctx.sessions. Depend on service names, not implementations.
- 3
inject waits for friends
Say ‘I need the tool cabinet,’ and the baseplate waits until it appears before activating you. No manual queue required.
Load order is expressed through service requirements, not manual boot sequencing.
- 4
Events are ways to call out
Broadcast, pass a note, work together, or take turns—four dispatch contracts.
emit / waterfall / parallel / serial. Waterfall is around-middleware: listeners receive (...args, next).
- 5
Every registration is reversible
Remove the brick and everything it placed on the shelf or listened to disappears.
Registrations use ctx.effect() or ctx.on() and unwind on fiber disposal. There is no privileged kernel to patch.
Four dispatch modes
| Mode | Await? | Order | Return | Plain-language version |
|---|---|---|---|---|
| emit | No | Observe in registration order | None | Broadcast: listeners may observe but cannot veto. |
| waterfall | No (but wraps) | Onion, outside in | Yes | Call next() to pass the paper inward; otherwise you take control. |
| parallel | Yes | Run together | None | The whole class works at once, such as flushing the journal to disk. |
| serial | Yes | One after another | Yes | Take turns speaking, with no next(). turn-stopping uses this mode. |
A waterfall is an onion
Skip next() and you take control. agent/pre-step, agent/request, llm/stream, and tools/* all use this onion.
A locker is not a water tap
scope · locker
One locker per person keeps coats on the right hook. It is not a fence.
dsh-scope partitions registration layers by agent. Use agent.ctx to scope a registration to one agent.
isolate · its own tap
This classroom's tap is separate from the lobby's. It may have another same-named service.
isolate(name, label) gives a child Context another same-named service. Agent presets use it to change outfits.