intent· @zero/intent · 8 observation kinds · 1 pure ranker · 0 telemetry
EARL, but the receipts never leave the tab
EARL — Early Action Recognition Layer — is the 2026 spec for anticipatory UI. the canonical implementations assume rich per-user telemetry. ZERO refuses that posture (article I.4). @zero/intent ships a pure ranker, an in-memory ring buffer, and a React provider that attaches passive listeners to window. nothing is persisted, nothing is identified, nothing is sent. the cost is honestly disclosed: lower accuracy than a telemetry-rich peer.
as of
00 · livehover · focus · click · the EARL ranker scores in real time, telemetry-sparesee your own intent shape the ranking
move your cursor over a target above
EARL ranking is local-only · the buffer is empty until the operator hovers.
as of
01 · contract8 anonymous observation kinds · no identifier, no device, no sessionevery observation is a tuple
| kind | shape | signal weight |
|---|---|---|
pointer-move | tracking only · feeds decelerate detector | — |
pointer-decelerate | velocity < 0.15 px/ms within 80 px of target | +0.6 |
pointer-enter | cursor crossed into a target's bounds | +0.3 (most-recent only) |
pointer-leave | cursor crossed out · accumulates dwell | — |
focus | keyboard or programmatic focus on target | +0.4 |
blur | focus left target · semantic only | — |
scroll | future · viewport intent | — |
keydown | keyboard activity ending on target | +0.2 |
why anonymous tuples and not user models
a per-user model needs a per-user identifier. an identifier is the first byte of telemetry, even if the rest never ships. ZERO's design refuses the byte. the engine sees what the window saw, ranks for as long as the tab lives, and forgets.as of
02 · rankerrank(observations, now) · pure · deterministicthe same input always produces the same ranking
| rank | target | score | signals |
|---|---|---|---|
| 01 | cta-floor | 100% | focus-on-target · keydown-on-target · pointer-decelerate-near-target |
| 02 | rail-skin | 30% | most-recent-pointer-enter |
| rule | value | rationale |
|---|---|---|
HOVER_THRESHOLD_MS | 220 | matches the brand's --breath tier · sub-perceptual hover ignored |
RECENT_WINDOW_MS | 1500 | 1.5s · the operator's working memory window |
SCORE_FLOOR | 0.3 | below this is noise; do not surface a prediction |
RANKING_CAP | 4 | UI surfaces never need more than four predictions at once |
| tie-break | alpha | same-score targets sort by id · keeps output stable |
as of
03 · ring buffercapacity-bounded · drop-oldest · in-memory onlythe buffer is the only state
| i | kind | target | ts (relative) |
|---|---|---|---|
| 01 | pointer-enter | cta-spawn | -1100ms |
| 02 | pointer-leave | cta-spawn | -980ms |
| 03 | pointer-enter | cta-floor | -740ms |
| 04 | pointer-decelerate | cta-floor | -420ms |
| 05 | focus | cta-floor | -280ms |
| 06 | keydown | cta-floor | -180ms |
| 07 | pointer-enter | rail-skin | -120ms |
why an explicit ring and not an array
an array grows. growth is a leak when the operator sits on a page for hours. a fixed-capacity ring is bounded by construction; the oldest observation drops first when the buffer is full. default capacity is 64; consumers can configure it via <IntentProvider capacity={N}>.as of
04 · article I.4telemetry-spare by design · the privacy articlelower accuracy is the price · stated honestly
this is not the EARL paper, and that's the point
the published EARL implementations assume per-user models trained on long horizon telemetry. they are more accurate than this engine. ZERO refuses that trade-off and states the cost: this ranker is short-horizon, anonymous, and occasionally wrong. it never gets better at the cost of an identifier.| posture | value |
|---|---|
| per-user model | none |
| identifier | none |
| persistence | none |
| cross-page memory | none |
| third-party dependencies | none |
| I/O at runtime | none |
local-onlyhonest
◆ int001a