Skip to content

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”

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.

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.

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-catalog
connections → provider-sdk
extension-runtime → tool-catalog, plugin-sdk
builtin-tools → tool-catalog, plugin-sdk
tool-runtime → tool-catalog, context, connections, extension-runtime, policy-processor
scheme-runtime → tool-catalog, context
agent-calls → tool-catalog, context
session-runtime → tool-runtime, scheme-runtime, agent-calls, context,
connections, extension-runtime
runtime → session-runtime and lower subsystems for binding adapters
runtime-server → runtime, protocol
provider-auth → provider-sdk
provider-openai-compat→ provider-sdk, context
provider-openrouter → provider-openai-compat, provider-auth
provider-chatgpt → provider-openai-compat, provider-auth
provider-grok → provider-openai-compat, provider-auth, provider-web/wire
provider-nous → provider-openai-compat, provider-auth, provider-web/wire
provider-mcp → provider-sdk, provider-auth
provider-web → provider-sdk
server/composition → hypervisor, yjs-server, runtime-server, builtin-tools,
selected driver providers and extension plugins
  1. 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.
  2. Concrete providers are imported only by product composition and their own test assemblies.
  3. Catalog accepts registrations; it does not import builtin-tools, providers, or loaders.
  4. context reads model and catalog metadata; it does not import agent-calls or session-runtime.
  5. Deep imports, type-only reverse dependencies, cycles, and importing an upper-layer /testing or testkit from a lower package are forbidden.
  6. Independent publication/versioning is not a goal. All packages ship in one distribution.
  7. Driver providers are not loaded through plugin manifests or the plugin loader.
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.

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.

These stay in place, not moved, until a later extraction PR:

  • One-process shipped topology (HarnessDaemon from packages/harness-server).
  • Public exports of harness-server, harness-sdk, plugin-sdk, and plexus-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-sdk technical name (it means extension-plugin SDK).
  • PEW connection/actor as the execution mechanism.
  • Plugin drivers[] parse-and-project path, which remains unsupported.