Server module ownership and allowed package graph
Source:
harness/docs/decisions/server-module-ownership.md
Status: Current living ADR. The package split is planned; the shipped topology remains one process.
Server module ownership and allowed package graph
Section titled “Server module ownership and allowed package graph”Decision
Section titled “Decision”Target packages, allowed npm imports, and state owners for the harness-server
split. Scope @inhuman.tools/ is omitted in tables; npm names use the scope.
Independent publication and versioning are not a goal. All packages ship in one
distribution.
Driver providers are not loaded through plugin manifests or the plugin loader.
Extension plugins are not a source of new drivers. Product nouns:
../canon/grain.md. Driver roster:
../runtime/drivers.md.
Shipped topology is one process. Accepted process names for the planned split — hypervisor, Yjs-server, runtime-server — do not claim three processes today.
Target packages
Section titled “Target packages”Foundation: plexus-expectations (existing), harness-model, harness-protocol
(/document, /rpc, /supervision), harness-sdk, harness-diagnostics,
harness-provider-sdk, plugin-sdk (existing; extension-plugin SDK),
harness-server (composition/facade), harness-hypervisor, harness-yjs-server,
harness-runtime-server.
Runtime bottom-up: harness-tool-catalog, harness-context, harness-connections,
harness-extension-runtime, harness-builtin-tools, harness-tool-runtime,
harness-scheme-runtime, harness-agent-calls, harness-session-runtime,
harness-runtime.
Driver providers: harness-provider-openai-compat, harness-provider-auth,
harness-provider-openrouter, harness-provider-nous, harness-provider-grok,
harness-provider-chatgpt, harness-provider-mcp, harness-provider-web.
Allowed import graph
Section titled “Allowed import graph”Arrow is npm import, not message flow. Prefix harness- omitted.
model, PEW, diagnostics, and third-party libraries omitted for readability.
provider-web/wire is a narrow shared wire-adapter export, not a dependency on
every web vendor registration. policy-processor is an existing workspace
package consumed by tool-runtime.
context → tool-catalogconnections → provider-sdkextension-runtime → tool-catalog, plugin-sdkbuiltin-tools → tool-catalog, plugin-sdktool-runtime → tool-catalog, context, connections, extension-runtime, policy-processorscheme-runtime → tool-catalog, contextagent-calls → tool-catalog, contextsession-runtime → tool-runtime, scheme-runtime, agent-calls, context, connections, extension-runtimeruntime → session-runtime and lower subsystems for binding adaptersruntime-server → runtime, protocol
provider-auth → provider-sdkprovider-openai-compat→ provider-sdk, contextprovider-openrouter → provider-openai-compat, provider-authprovider-chatgpt → provider-openai-compat, provider-authprovider-grok → provider-openai-compat, provider-auth, provider-web/wireprovider-nous → provider-openai-compat, provider-auth, provider-web/wireprovider-mcp → provider-sdk, provider-authprovider-web → provider-sdk
server/composition → hypervisor, yjs-server, runtime-server, builtin-tools, selected driver providers and extension pluginsGraph laws
Section titled “Graph laws”- Runtime, provider, and extension packages import public model/PEW/contract exports, not server/SDK barrels. A lower package does not depend on upper composition even for types.
- Concrete providers are imported only by product composition and their own test assemblies.
- Catalog accepts registrations; it does not import builtin-tools, providers, or loaders.
contextreads model and catalog metadata; it does not import agent-calls or session-runtime.- Deep imports, type-only reverse dependencies, cycles, and importing an
upper-layer
/testingor testkit from a lower package are forbidden. - Independent publication/versioning is not a goal. All packages ship in one distribution.
- Driver providers are not loaded through plugin manifests or the plugin loader.
State ownership
Section titled “State ownership”| State / decision | Owner |
|---|---|
| Process topology, root ownership, runtime generation, replacement | Hypervisor + OS-backed lifetime locks held by the corresponding processes |
| Server epoch, active private connection, rejection of stale frames | Yjs-server; the allowed execution owner is set by supervision |
| Public rooms, subscriptions, occupancy facts | Yjs-server |
| Document images, inventory, revisions, exact-prefix durable receipts | Yjs-server, the sole image writer |
| Domain initialization, config/secrets, session eligibility, recovery | Runtime; document publication through the document service |
| Turn/job execution | Session/tool/Scheme actors with a single execution owner |
| Call acceptance, leases, callbacks | Agent-calls actors; durable proof comes from the document service |
| Catalog projections | Catalog instances + registered contribution actors |
| Provider auth/refresh/account | Live provider connections; the durable secret store belongs to runtime |
| Extension state | Extension runtime: session log on the session document; project/global backend through an adapter; private state in memory |
| Model context | Context projections; writing a compaction result belongs to the executing actor |
Synchronous getLoaded never reads disk or network. There is no second image
writer in runtime.
Rationale
Section titled “Rationale”A lower package that imports an upper barrel for types still creates a compile-time dependency and glues composition into the leaf. A catalog that imports builtins cannot be assembled as an empty roster. Concrete providers imported from generic runtime freeze vendor branches in the core. Plugin manifests that load drivers mix two mechanisms and break the product law that plugins do not introduce drivers.
The full design lives in
working-proposals/server-modules-2026-09-24/.
This ADR is the living graph law.
What stays in place
Section titled “What stays in place”These stay in place, not moved, until a later extraction PR:
- One-process shipped topology (
HarnessDaemonfrompackages/harness-server). - Public exports of
harness-server,harness-sdk,plugin-sdk, andplexus-expectations. - Driver IDs
nous,chatgpt,grok,openrouter, and the rest of the registered roster; connection IDs; PEW kinds; sync tags; document image format. @inhuman.tools/plugin-sdktechnical name (it means extension-plugin SDK).- PEW connection/actor as the execution mechanism.
- Plugin
drivers[]parse-and-project path, which remains unsupported.