Skip to content

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.

js
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:

ConcernWhatWhere
Structureassets, connections, types, regionssystem-core (SystemGraph + TypeRegistry)
State spacethe parameters a type can bear (features)system-core — a first-class trait on the type
Behaviourhow state evolves (generators, influence, events)system-sim — a declarative Dynamics spec
Inputswhat comes in from outside: an asset type's inputs (its ports), and input streamssystem-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/unproject adapters 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:

js
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:

js
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.

js
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) ​

js
{
  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.