Telemetry
Each frame the UI polls a telemetry snapshot from the simulation. The shape of that snapshot is a contract shared between Rust (which produces it) and TypeScript (which consumes it), and it is locked by a Vitest test.
The snapshot contract
The TypeScript type is the source of truth for the shape:
export interface TelemetrySnapshot {
activeSignals: number
firedThisFrame: number
releasedSignalsThisFrame: number
signalVelocityMean: number
corticalResponseIndex: number
onsetResponse: number
sustainedActivation: number
focusDrift: number
regionActivity: Record<RegionKey, number>
rolling: {
oneSec: RollingWindow
threeSec: RollingWindow
fifteenSec: RollingWindow
}
}
export interface RollingWindow {
activeSignalsAvg: number
firedNeurons: number
releasedSignals: number
signalVelocityMean: number
regionActivity: Record<RegionKey, number>
}
The Rust telemetry_snapshot() serializes a matching structure with
serde-wasm-bindgen, so the JavaScript side receives a plain object that
satisfies TelemetrySnapshot:
getTelemetrySnapshot(): TelemetrySnapshot {
return this.world.telemetry_snapshot() as TelemetrySnapshot
}
src/__tests__/telemetry-contract.test.ts asserts the snapshot shape. If the
Rust serialization and the TypeScript type drift apart, pnpm test fails. Keep
both in sync when adding a field.
Fields
Instantaneous (this frame):
| Field | Meaning |
|---|---|
activeSignals | Currently live signals. |
firedThisFrame | Neurons that fired this frame. |
releasedSignalsThisFrame | Signals released this frame. |
signalVelocityMean | Mean travel speed of live signals. |
regionActivity | Per-region activity counts. |
Derived response metrics:
| Field | Meaning |
|---|---|
corticalResponseIndex | Headline "responsiveness" score. |
onsetResponse | Sharpness of response right after a stimulus. |
sustainedActivation | Activity held over time. |
focusDrift | How much the dominant region wanders. |
Rolling windows
Three rolling windows: oneSec, threeSec, fifteenSec: accumulate averages
over their respective time spans. Each RollingWindow carries an average active
signal count, fired-neuron and released-signal counts, mean velocity, and
per-region activity. The UI uses these to draw the activity-window bars.
Active load and the response index
The response index is built partly from "active load": how full the pool is relative to the live cap:
let active_load =
(self.pool.active_count() as f32
/ self.settings.current_max_signals.max(1) as f32) * 100.0;
Because this normalizes against current_max_signals (default 16_000), the
load percentage moves as you change the max-signals setting. The UI's activity
bars normalize against the configured cap as well, so they read as a fraction of
capacity rather than an absolute count.