Overview
wity-system is a headless spatial/topological network computation library — propagation, reachability, and scenario analysis built on wity-graph primitives. It is a Level 2 domain library in the Wity ecosystem (same level as wity-workbook, wity-ideation, wity-rkf).
Core model
SystemGraph is the top-level domain object. It wraps a GraphAbstract internally — one graph; consumers never touch it directly. Assets are typed nodes, connections are typed edges — the system's structure — and all computation over them is driven by behavioral traits declared in the type registry.
Beside its structure a system can hold aspects: further models of the same system, in the same graph — the order process of a shop. The kind of model an aspect is, its formalism, is declared as data. See Aspects and formalisms.
import { GraphAbstract } from '@wity/graph-headless';
import { SystemGraph } from 'wity-system';
const sys = new SystemGraph({ GraphAbstract });The constructor requires GraphAbstract to be injected — wity-system never hard-imports graph-headless, keeping the build isomorphic and the dependency inverted.
Architecture
Level 1 @wity/graph-headless — DAG, typed nodes/edges, traversal, serialization,
propagation, reachability, shortest path, all paths
↑
Level 2 system-core — assets, connections, regions, type registry with
(wity-system) behavioral traits + feature/parameter schemas
(the state space), cascade/impact analysis,
playback sequences, scenario state,
optional spatial projection; the mechanism of
aspects (further models of a system, in its graph)
system-formalisms — the formalisms an aspect can be made in, each
declared as data (process)
system-sim — temporal simulation runtime over system-core:
declarative dynamics (generators / influence /
events as data), the tick loop, history buffers
↑
Level 3 (application widget) — water networks, telecom infra, military planning,
drone operations, digital twins, etc.Monorepo structure
wity-system/
packages/
system-core/ ← SystemGraph, TypeRegistry, propagation, serializer
system-formalisms/ ← the formalisms of aspects, declared as data; describe()
system-sim/ ← SimulationRuntime, FeatureStore, SimClock, InfluenceEngine
system-ui-compute/ ← computeScene, computeAspectScene, signal strip views (zero-DOM)
system-ui/ ← <signal-strip> (draws what system-ui-compute returns)
docs/ ← VitePress documentation (this site)system-core is the structural authoring layer — you define topology, types, and relationships. system-sim is the temporal dynamics layer — you overlay features, generators, and influence rules onto an authored graph.
Structure, state, and behaviour
The two levels split a system into three separable concerns — a carve borrowed from engineering/formal ontology (structure / behaviour / function), which keeps each concern independently authorable and composable:
| Concern | What | Where |
|---|---|---|
| Structure | assets, connections, types, regions | system-core (SystemGraph + TypeRegistry) |
| State space | the parameters a type can bear (features) | system-core — a first-class trait on the type |
| Behaviour | how state evolves (generators, influence, events) | system-sim — a declarative Dynamics spec |
| Inputs | what comes in from outside: an asset type's inputs (its ports), and input streams | system-core holds them; system-sim plays them and runs what they do (Inputs) |
Because behaviour is separated from the state space, one system can bear many independent dynamics (normal, peak, failure), each referencing the same structure. Behaviour is authored/serialized as data (see Declarative dynamics), not shipped as code.
What each level owns
Level 1 (graph-headless) provides the DAG substrate: typed nodes, typed edges, BFS traversal (propagate, reachable), Dijkstra (shortestPath), DFS enumeration (allPaths), and <wity-knowledge> serialization.
Level 2 (system-core) adds domain semantics on top:
- TypeRegistry — behavioral traits (role, canFail, carriesFlow, costField) that algorithms consume automatically
- Cascade & impact — domain-level propagation that reads traits to detect sources, filter flow edges, and determine failure behavior
- Regions — polygon spatial annotations with point-in-polygon containment queries
- Playback — ordered step sequences for presentation, with selector resolution
- Scenarios — named snapshots (graph + viewport + regions) with save, load, diff, delete
- Spatial projection — pluggable
project/unprojectadapters with per-type coordinate field support
Level 2 (system-sim) adds temporal dynamics:
- FeatureStore — columnar Float64Array storage for per-asset parameter values at varying emission frequencies
- SimClock — simulation clock with speed control and drift compensation
- InfluenceEngine — topologically-ordered propagation of state changes along connections
- HistoryBuffer — opt-in ring-buffer time-series per feature
- Event conditions — user-defined predicates over asset state, with cooldown
Level 3 (application) brings domain-specific types, rendering, and interaction. The L2 packages provide the computational layer; L3 decides how to present it.
Trait-enriched algorithms
When types are registered, algorithms auto-read their behavioral traits:
sys.registerAssetType('plant', { role: 'source', canFail: true });
sys.registerConnectionType('feeds', { carriesFlow: true, costField: 'length' });
// cascade auto-detects sources (role: 'source') and flow edges (carriesFlow: true)
sys.cascade(['V1']);
// shortestPath auto-reads costField from connection type
sys.shortestPath('WTP', 'H1');Explicit options always override trait-derived defaults:
sys.shortestPath('WTP', 'H1', { cost: () => 1 });When no types are registered, algorithms fall back to graph-headless defaults (all edges, uniform cost).
Documents are <wity-knowledge> graphs
wity-system has no serialization format of its own. A system document is a knowledge graph — assets are typed nodes, connections are typed edges, metadata (type registry, scenarios, viewport) are structural nodes with a $sys prefix. The canonical stored form is a <wity-knowledge> document, the same representation used by wity-graph, wity-rkf, and wity-workbook.
import * as graph from '@wity/graph-headless';
import { setGraphProvider, serialize, parse } from 'wity-system';
setGraphProvider(graph);
const xml = serialize(sys.snapshot()); // → <wity-knowledge> XML
const snapshot = parse(xml); // → SystemGraph-compatible snapshot
sys.restore(snapshot);snapshot() and restore() operate on plain objects. serialize() and parse() handle the <wity-knowledge> round-trip via graph-headless's codec.
Snapshot format (v1)
{
version: 1,
graph: { nodes, edges },
scenarios: { name: { graph, viewport, regions } },
spatial: { coordFields } | null,
types: { assetTypes: {...}, connectionTypes: {...} } | null,
viewport: { center, zoom, bounds },
regions: { uid: { label, polygon, meta } } | null,
playback: [{ type, ...fields }] | null,
// each of these only when the system has it
canvas, meta, run, view, dynamics,
aspects: { nodes, edges }, // its aspects, as they are in the graph (see Aspects and formalisms)
}Round-trips through snapshot() → JSON → restore(). All fields except version and graph are optional — omitted or null fields restore to empty defaults.
