Type Registry
TypeRegistry is the open-ended type schema for asset and connection types. Each type declares behavioral traits that L2 algorithms consume, plus an open meta field for arbitrary domain data that wity-system never reads.
Registration
import { SystemGraph, TypeRegistry } from 'wity-system';
// Option A: register through SystemGraph
sys.registerAssetType('plant', {
label: 'Water Treatment Plant',
role: 'source',
canFail: true,
coordFields: ['lat', 'lon'],
meta: { icon: 'plant.svg', minCapacity: 1000 },
});
sys.registerConnectionType('feeds', {
label: 'Feed Pipe',
directionality: 'directed',
carriesFlow: true,
defaultCost: 1,
costField: 'length',
meta: { material: 'PVC', color: '#0ea5e9' },
});
// Option B: pre-build a registry and pass to constructor
const types = new TypeRegistry();
types.registerAssetType('router', { ... });
types.registerConnectionType('fiber', { ... });
const sys = new SystemGraph({ GraphAbstract, types });Asset type traits
| Trait | Type | Default | Used by |
|---|---|---|---|
label | string | type name | Display |
description | string | '' | Display |
role | 'source' | 'sink' | 'relay' | 'relay' | cascade — auto-detects 'source' nodes |
canFail | boolean | true | cascade — which assets can be disabled |
cascadeOnFailure | boolean | true | cascade — does failure sever downstream |
coordFields | string[] | null | null | reproject — per-type coordinate field names |
features | object | (omitted) | system-sim — parameter/disposition schema (state space) |
meta | object | {} | L3 only — open bag |
Role semantics
source— origin of flow.cascade()auto-detects sources by role whensourceUidsis not explicitly provided.sink— terminal consumer. Currently informational; algorithms don't treat sinks specially.relay— intermediate node (default). Passes flow through.
Feature schema (the state space)
An asset type may declare features — the parameter/disposition schema describing the state variables assets of that type can bear. It is a first-class trait, not meta: it defines the system's state space, is read by the temporal runtime (system-sim), and serializes with the system.
sys.registerAssetType('router', {
role: 'relay',
features: {
cpu: { range: [0, 100], unit: '%', frequency: 5000, defaultValue: 0 },
throughput: { range: [0, 40], unit: 'Gbps', frequency: 1000, defaultValue: 0 },
},
});
sys.getFeatureSchema('router'); // → the features object, or null if the type declares none| Feature field | Type | Description |
|---|---|---|
range | [min, max] | Clamp bounds for the value |
unit | string | Display unit |
frequency | number | Emission interval in ms (temporal runtime) |
defaultValue | number | Initial value |
features is optional and omitted entirely when not declared — types without it serialize exactly as before. This is the state space only; how those features evolve over time (generators, influence, events) is a separate concern — see system-sim → Declarative dynamics. One state space can be driven by many independent dynamics.
Inputs (the type's input ports)
An asset type may declare inputs: the ways the outside acts on an asset of the type — { inputName: { label?, description?, payload?: { key: 'text' | 'number' | 'boolean' } } }. Checked when the type is registered (inputsProblems; PAYLOAD_KINDS), stored with it only when declared, read with getInputs(name). See Inputs.
Connection type traits
| Trait | Type | Default | Used by |
|---|---|---|---|
label | string | type name | Display |
description | string | '' | Display |
directionality | 'directed' | 'bidirectional' | 'directed' | Algorithm direction handling |
carriesFlow | boolean | true | cascade, impact, propagate, reachable — edge type filtering |
defaultCost | number | 1 | shortestPath, allPaths — fallback cost |
costField | string | null | null | shortestPath, allPaths — reads cost from edge.data[costField] |
meta | object | {} | L3 only — open bag |
Flow semantics
When types are registered, propagate, cascade, impact, and reachable automatically filter to edges whose connection type has carriesFlow: true. Non-flow edges (monitoring links, documentation references) are excluded from traversal by default.
Cost semantics
shortestPath and allPaths auto-build a cost function from the registry:
- If the edge's connection type defines a
costFieldand the edge's data contains that field, useedge.data[costField] - Otherwise use
defaultCostfrom the connection type definition - If no connection type is registered for the edge type, cost is
1
The meta field
Open bag on every type definition — wity-system stores it, never reads it. L3 consumers use it for domain-specific rendering and behavior data:
// Cisco network
meta: { snmpOid: '1.3.6.1.2.1', category: 'layer3', icon: 'router.svg' }
// Military planning
meta: { milSymbol: 'SFGPUCI', echelon: 'company', color: '#0000ff' }
// Water infrastructure
meta: { material: 'PVC', maxPressure: 150, unit: 'psi', vendor: 'Grundfos' }The same convention applies to region meta and asset data — L2 carries the data, L3 interprets it.
Trait queries
TypeRegistry provides query methods used internally by SystemGraph to enrich algorithm options:
sys.types.getSourceTypes(); // → ['plant'] — asset types with role: 'source'
sys.types.getSinkTypes(); // → ['house'] — asset types with role: 'sink'
sys.types.getFlowTypes(); // → ['feeds'] — connection types with carriesFlow: true
sys.types.getFailableTypes(); // → ['plant', 'valve'] — asset types with canFail: true
sys.types.buildCostFn(); // → (edge) => number — reads costField/defaultCost per typeSerialization
TypeRegistry serializes to a plain object and hydrates from one:
const data = sys.types.serialise();
// → { assetTypes: { plant: {...}, ... }, connectionTypes: { feeds: {...}, ... } }
const types = new TypeRegistry();
types.hydrate(data);Types are included in SystemGraph snapshots automatically. When a system document is serialized to <wity-knowledge>, the type registry becomes a system-types node in the knowledge graph.
CRUD
sys.registerAssetType('valve', { ... });
sys.getAssetType('valve'); // → { label, role, canFail, ... }
sys.getAssetTypes(); // → Map of all asset types
sys.types.hasAssetType('valve'); // → true
sys.types.removeAssetType('valve'); // → true
sys.registerConnectionType('monitor', { carriesFlow: false });
sys.getConnectionType('monitor');
sys.getConnectionTypes();
sys.types.hasConnectionType('monitor');
sys.types.removeConnectionType('monitor');Re-registering a type with the same name replaces the previous definition.
