Skip to content

fix: wait out a quarantined ScreenCaptureKit gate and explain the refusal - #63

Merged
iamnbutler merged 1 commit into
mainfrom
fix/sck-quarantine
Oct 17, 2026
Merged

iamnbutler merged 1 commit into
mainfrom
fix/sck-quarantine

Conversation

@iamnbutler

Copy link
Copy Markdown
Contributor

Addresses #16.

What changes (new peekaboo-sck-quarantine.patch, last in the stack):

  • Clearer refusal. A new capture now waits up to 2 s for an abandoned ScreenCaptureKit call to return before refusing. The grace period doesn't count against the call's own budget. The refusal now says the quarantine is temporary, is usually caused by another busy capture on the Mac, and clears by itself. It asks the caller to wait a few seconds and retry. A timed-out wait for another process's capture gets the same wording.
  • No fallback, on purpose. Peekaboo's "CGWindowList" engine captures through the private SCShareableContent.fetchWindowForWindowID lookup or /usr/sbin/screencapture -l. screencapture itself uses ScreenCaptureKit, and CGWindowListCreateImage is obsoleted. Any fallback would therefore start ScreenCaptureKit beside the abandoned call, which upstream rules out ("Private SCK fallback never crosses an abandoned operation"). The patch README has a paragraph saying so, so nobody adds a fallback later.
  • Fewer quarantines to begin with. The private window lookup gets 3 s instead of 1 s. Its 1 s budget is what timed out and quarantined the gate in the Explain and recover from a quarantined ScreenCaptureKit gate #16 run.
  • Apps inventory budget grows from 1 s to 2.5 s (healthy runs took 0.95 s), and its timeout message now suggests retrying. Upstream deliberately refuses an inventory that misses its deadline rather than returning it partial (the test "overall deadline refuses an inventory that cannot finish observation"), so this keeps that behavior instead of degrading.
  • Inspect failure path. After a failed inspect, its availability read gives apps 3.5 s instead of 2.5 s, to fit the new budget.
  • Gate lock stays per-user, in $TMPDIR. Keying it to the host app would let separate apps overlap ScreenCaptureKit calls again, which is what it prevents.

Time per call: the worst case for a window capture is the 2 s grace period, plus the 3 s lookup timeout, plus a 2 s grace period on the next ScreenCaptureKit call before it refuses: about 7 s. That's within inspect's 20 s observation budget, the client's 25 s bridge request timeout and the 30 s MCP timeout, so none of those needed raising.

Tests (foreground, process-group wrapper, temporary coordination root):

  • New ScreenCaptureKitQuarantineGraceTests (3 tests). Together with ScreenCaptureKitOperationCoordinatorTests and ScreenCaptureKitTimeoutRaceTests, 11 tests pass.
  • ApplicationInventoryTimeoutTests: 25 pass. One test advanced its fake clock by a fixed 2 s; it now advances past the default budget.
  • npm run check and the native build pass.

Live check: pending (screen locked).

…usal (#16)

A capture now waits up to 2 s for an abandoned ScreenCaptureKit call to
return before refusing, and the refusal says the quarantine is temporary
and asks the caller to retry. The private window lookup gets 3 s instead
of 1 s, and the application inventory 2.5 s instead of 1 s.

There is no fallback around a quarantine: every remaining capture path
also uses ScreenCaptureKit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant