Skip to content

How pairs are compared

Petar Liovic edited this page Sep 9, 2026 · 1 revision

When two rings count as related, and how that pair becomes a graph edge. This is the current rule (0.6.6). Cosine is not the gate.

What is compared

Each variable is 50 bits, one per recent paint frame: 1 if it wrote in that frame, else 0.

For two rings A and B:

  • d_A, d_B — how many 1s each has (density)
  • k — how many frames are 1 in both (overlap)

Same-frame overlap is “they moved together.” Shift the rings by one tick and you get “one moved, then the other.”

Hit rule

If the 1s were placed at random, the chance of overlap k is hypergeometric:

$$ P(K = k) = \frac{ \binom{d_B}{k},\binom{50 - d_B}{d_A - k} }{ \binom{50}{d_A} } $$

The rarity cut asks: would chance do this often? Current default is a ~1% tail.

Rarity is not enough when both rings are busy. Two dense traces can share a few frames by accident and still look rare. So there is a second cut: the quieter timeline must mostly land on the other one:

$$ k \ge \left\lceil 0.65 \cdot \min(d_A, d_B) \right\rceil $$

Both must pass. The stored threshold is max(rare k, 65% floor).

65% is a default, not a p-value. 50% is too weak on click/effect clumps. 80%+ is “almost a clone” and misses real coupling. If it is wrong, we change the constant. We do not put a cosine cutoff back on the gate.

Cosine

Cosine similarity is the same overlap, scaled by how busy each ring is. If it is printed at all, it is a display number. It is not “% overlapped” and it does not decide the alert.

The old 0.88 line was the decision. That is gone.

Same source vs a chain

Two names can overlap because one drives the other (A → effect → B), or because both are children of the same click.

The graph is what separates those. An event node with two targets is a shared source. An effect edge is a chain. Roles (local / context / store) only change the wording of the suggestion: merge two locals, or stop copying Context.

Ranking

Once edges exist, the report prefers sources that sit upstream of the most updates. That is “look here first,” not a unique root cause and not a claim that we diagonalize the graph.

Filters

  • Streams: a variable that is 1 in most of the window (animation-style) is not used as causal evidence.
  • Old event nodes are dropped after the interaction window (seconds, not the whole session).
  • A slow async gap can look like two unrelated updates.

What a hit means

A hit means: in this window, these two timelines were unusually aligned. It does not mean the values are the same, or that the code is wrong. Intentional sync is a reason to ignore the line or add // @basis-ignore.

Clone this wiki locally