-
Notifications
You must be signed in to change notification settings - Fork 3
Measuring State Correlation
Every state variable is treated as a vector in {0, 1}⁵⁰. Each dimension represents a single browser paint frame (Tick).
The dot product counts the number of frames where both variables updated together:
In our binary system, this is just a count of simultaneous pulses.
To separate structural relationships from raw update frequency, we use Cosine Similarity. Without normalization, a high-frequency animation and a low-frequency toggle could look "synced" just because they overlapped once.
Where
| Score | What it means |
|---|---|
| 1.0 | Identity: Updates are perfectly synchronized across the window. |
| 0.0 | Orthogonal: No updates happened in the same frames. |
Basis considers two variables behaviorally redundant (what we call diagnostic "linear dependence") if their similarity exceeds 0.88.
- Geometric Meaning: This corresponds to an angle of roughly 28° in the 50-dimensional space.
- Why 0.88? This was found through empirical testing on production codebases, including Excalidraw. It turned out to be the best balance between filtering browser scheduling jitter and still catching real structural synchronization.
The engine performs Discrete Cross-Correlation by sampling similarity across three temporal planes (
To keep this under a millisecond, we use Amortized Modulo math. Instead of doing expensive division inside the hot loop, we pre-normalize the circular offset once:
// O(1) Setup: Normalize the circular shift outside the loop
const baseOffset = ((headB - headA + offset) % L + L) % L;
for (let i = 0; i < L; i++) {
let iB = i + baseOffset;
if (iB >= L) iB -= L; // O(n) Execution: Single predictable branch
// ... dot product math
}This keeps the inner loop linearized. The CPU can do branch prediction efficiently, and the math stays correct even for negative temporal offsets.
In v0.5.0, the engine goes beyond a flat list of signals and performs a Subspace Audit. We model the state space as a composition of local signals (
The architectural ideal is a Direct Sum where the intersection is zero:
-
Rule A (Context Mirroring): If a Local Basis vector (
$U$ ) is found within the span of a Global Subspace ($W$ ), it gets flagged as a Shadow State. You're storing a local copy of something that already exists in context. -
Rule B (Duplicate State): If two Local Basis vectors (
$U_i, U_j$ ) overlap, they are managing the same logical dimension. One of them shouldn't exist.
Vector analysis finds correlation. v0.6 adds Graph Theory to find causality. The engine builds a Directed Adjacency Matrix
-
Nodes (
$V$ ): State Variables, Effects, and Implicit Events. -
Edges (
$E$ ): Causal links where$u \to v$ means "u triggered v".
Sometimes
Z → {A, B}
This lets the engine distinguish between a Dependency Chain (
In a complex app you can get dozens of alerts. To solve this "Alert Fatigue" problem, Basis calculates Eigenvector Centrality on the causal graph to find the "Prime Mover" (Root Cause).
We solve for the principal eigenvector
Exact diagonalization is
The key idea: a node's influence isn't just about how many nodes it triggers, but about how important those triggered nodes are.
-
Leaf Node: Influence
$\approx 0$ . -
Chain Link: Influence
$\approx$ Local Impact. -
Prime Mover: Influence
$\approx$ Sum of the entire cascade.
- Linear Dependence: Simultaneous updates that reveal redundant state.
- Prime Movers: The specific hook or event driving the largest volume of downstream updates.
- Global Event Fragmentation: A single user interaction forcing updates across unrelated files/contexts.
- Volatility Guard: Variables pulsing in >50% of the window are classified as Streams (~) and filtered from causal alerts.
-
Asynchronous Gaps: Logic chains with delays
$> 10s$ (e.g., slow API responses) are treated as independent signals. The engine can't hold the graph open that long without risking memory leaks.