Appearance
system.registry
system.registry is the logical mount claim table owned by the system runtime. It maps canonical mount names (chat.conversation, system.agents.memory) to the local mount + provider runtime ID + wire root that actually serve them. Director treats it as the primary source of the displayed catalog.
Ops Director consumes
registry.list (read)
DirectorRuntimeAdapter.listRegistryBindings (src/services/DirectorRuntimeAdapter.ts:234-287):
ts
const result = await RequestReply.execute(
context,
'system.registry',
'registry.list',
{},
{ timeoutMs: 5000, targetRoot: root },
) as {
ok?: boolean,
claims?: Array<{ logicalMount?: string; providers?: RegistryProviderEntry[] }>,
};
if (result?.ok !== true || !Array.isArray(result.claims)) {
throw new Error('system.registry registry.list returned an invalid response');
}Director then walks each claim, normalizes its providers, and emits a BindingRuleEntry:
ts
{
match: <logicalMount>, // canonical mount, e.g. 'chat.conversation'
ops?: string[], // optional op subset declared in metadata
forward: <provider.localMount>, // local mount the provider actually serves
provider: <runtimeId>, // who serves it
runtimeId,
localMount,
packageName?: string,
runtimeWireRoot?: string,
componentType?: string,
description?: string,
source?: string,
hasChildren?: boolean,
}Unlike system.runtimes, the registry call throws on bad responses instead of returning empty. That surfaces misconfigured registries explicitly rather than masking them as "nothing mounted".
Combined with system.runtimes
loadCatalogWithRuntimes runs registry.list and runtimes.registered in parallel (Promise.all, line 359-362), then buildCatalogFromBindings merges them. Each binding becomes a CatalogEntry; runtime inventory entries enrich type, purpose, and hasChildren when the runtime advertised them.
If the canonical catalog is empty, loadCatalogWithRuntimes returns { source: 'empty-registry', fallbackUsed: false } rather than synthesizing entries from runtime heartbeats alone — Director honestly shows an empty tree when the registry is empty.
Resolution semantics
resolveCanonicalTarget (src/services/DirectorRuntimeAdapter.ts:185-198) is how Director turns an operator-typed canonical mount into the actual (mount, targetRoot) pair to invoke. The chain:
- Read all bindings.
resolveBoundTarget(canonicalMount, bindings, runtimes)finds a binding rule whosematchequals the canonical mount.- Returns
{ mount: <localMount>, targetRoot: <runtimeWireRoot or root> }. - If no binding matches, throw
Mount is not registered in system.registry: <canonicalMount>.
This is what makes the Detail tab's $introspect work even when the canonical mount differs from the local mount on the runtime.
Operator note
The registry is the contract. Two failure modes:
- Registry empty. No runtime called
runtimes.registeron its claims. Check the runtime's startup log. - Registry has entries but tree is empty. The runtime is dead but the registry still has stale claims. Check
system.runtimes runtimes.registered— if the runtime ID isn't there, the registry is stale and a freshhost.control runtimes.reconcileshould clean it up.
See also
Source:
projects/matrix-3/packages/director/src/services/DirectorRuntimeAdapter.ts:185-525(resolution + catalog construction).