removeSiriShortcut answers from inside the completion handler of +[NSUserActivity deleteSavedUserActivitiesWithPersistentIdentifiers:completionHandler:], on both sides of the hand-off:
// CraftApp.swift
NSUserActivity.deleteSavedUserActivities(withPersistentIdentifiers: [action]) {
self.resolveCallback(callbackId, result: ["removed": true, "action": action])
}bridge_mobile_siri.zig does the same through an ios_async ticket. Nothing else ever settles the call: no timeout, no fallback, no cancellation.
On CI that completion sometimes never fires. The Zig slice fixture (packages/ios/fixtures/zig-slice) waits for it as i=38, and it did not arrive within 900 seconds on:
In both logs removeSiriShortcut i=97 is dispatched and then nothing follows. Every other id in the fixture arrived. The runner image was the same as for the main run 35094828558, where the reply did arrive, so this is intermittent rather than tied to one runner image. The completion comes from a system daemon; on a freshly booted simulator it sometimes does not answer.
Why this is a product bug, not only a flaky fixture
The page's promise has no way to settle if the framework does not call back. That is #197's failure again, a location promise that never settled when Core Location stayed silent, with a different framework staying silent. _invoke's 30-second JavaScript timeout would eventually reject on the contract path. The native reply slot stays held, though, and a page that uses a longer timeout, or none, waits for ever.
What a fix looks like
Give the native call its own deadline, as getCurrentPosition now has: if the completion has not fired within N seconds, settle with a typed error (TIMEOUT, or NATIVE_CALL_FAILED with a message naming the framework), release the slot, and ignore a completion that arrives late. bridge_mobile_location.zig's schedulePositionTimeout is the pattern already in the tree.
The fixture's i=38 assertion should then accept only the real answer, and fail with "the deletion completion never fired" when the timeout fires instead. That keeps it an assertion about the argument-free block path, and a missing completion becomes a named failure rather than a 900-second stall.
Found while fixing the mobile E2E launch on a cold simulator.