Exit code 4. That was Spike.Meter’s verdict on the first real matrix run against the gate we’d written into the phase-1 spec for a Windows shell decorator: two physical pixels of error for 99.9% of sampled frames during a drag, no sustained lag past one refresh interval. Two separate passes had signed off on that number, a design review of the original ticket and then the phase-1 slicing document that turned the review into a testable spec. It read as rigorous. It was also arithmetically impossible for any implementation to pass.
What the spike was measuring
We’re building a small overlay window, Spike.Tracker in the spike, that has to sit flush above another process’s window and follow it in real time as it’s dragged around the desktop, the way an existing Windows window-tabbing utility already does. The design review had flagged a real constraint on the mechanism. SetWinEventHook on another process is normally delivered out-of-context, queued through the registering thread’s message loop, with no guarantee about which composited frame the callback lands in. We built the first spike to find out whether that mattered in practice.
Three pieces:
Spike.Targetis a plain popup window with four 16x16 fiducial markers baked into its corners.Spike.Trackeris the WinEvent-hook decorator under test.Spike.Meterruns DXGI Desktop Duplication on the same monitor and scans every composited frame for those markers, computing error and lag from pixels. It never asksGetWindowRect, which only tells you what the window thinks its position is. The meter tells you what actually got drawn.
Spike.Tracker ships four strategies: A chases the WinEvent hook, B rides an owned window that needs nothing per frame, D polls every 250ms, and the spec’s default pick was A.
A week of tuning the wrong thing
We spent the better part of a week assuming the gate was reachable and that a failing run meant a bug. Runs against strategy A came back consistently short of 99.9% inside 2px, so we did what you do when a number looks close. We tuned. We tried different z-order modes (after-target versus keep versus topmost), tighter coalescing in the hook callback, and stripped every allocation out of the render path so GC would never fire mid-drag. Each change moved the histogram a little. None of them touched the tail. We burned real spike time chasing a number that had nothing to do with the tracker’s code.
The flag that flipped the question
The --inject-delay flag is what broke the assumption. It applies every placement N nominal refresh intervals late on command, a known deliberate lag, so you can confirm the meter detects lag instead of reporting favorable noise. We ran it at --inject-delay 0, no injected lag at all, on top of the already-optimized strategy A. It still failed the pixel gate under --synthetic drag at real drag speeds. That’s where the question changed from “why is the tracker slow” to “what is this gate actually demanding.”
The arithmetic is short. Positional error on a moving target is velocity times lag. A hand-driven drag isn’t a fixed speed. The spike’s own drag mode drives the real cursor through SendInput with a hand-like wobble, and normal fast drags land somewhere around 500 to 1800 pixels per second. At 60Hz, one refresh interval is 16.7ms. A single frame of lag, the same frame the WinEvent hook’s out-of-context delivery already costs before any of our code runs, works out to 8 to 30 pixels of positional error at those speeds.
The gate asked for under 2 pixels, 99.9% of the time, during exactly the condition that produces 8 to 30. No z-order mode, no allocation-free render path, no amount of hook coalescing closes that gap, because the gap lies outside the implementation. The gate treated pixel error and frame lag as the same measurement.
What replaced it
The new gate measures the thing that is actually true or false about the mechanism: lag counted in frames, and the variance of that lag, with no translation into pixels. A decorator that’s reliably one frame behind, every time, at any drag speed, reads to a human eye as attached, because the offset is constant and the brain folds a fixed lag into the object. A decorator that’s sometimes zero frames behind and sometimes three, with the same average lag, reads as broken, because the change in offset is what your eye tracks.
Spike.Meter already had the raw material in frames.csv and its per-segment lag fields. The fix was to stop collapsing that into one pixel-error number and report the distribution and its spread instead.
Before an acceptance gate gets a third sign-off, work the arithmetic from the speeds and timings involved and see whether a correct implementation could pass it at all.