Commit 8b1e50b
test(deflake): deterministic BookRegistry write-seams + ~57 wall-clock-wait conversions (#1331)
* [swarm_ad0b4c65] swarm scaffold: wall-clock-wait elimination plan + manifest
Architect triage of the ~675-wait-token population: collapses to 12 new
XCTest-gated Task-join seams across 16 contracts in 3 waves. Correctness
over volume — no bounded wait replaced by an unbounded await.
**Scope:** swarm scaffolding only (plan + manifest); per-module contracts,
implementer diffs, and integration land in subsequent commits on this branch.
**Not done:** the 16 per-module contract bodies + any code — pending user GO.
* [swarm_ad0b4c65] wave-1 infra contracts: S1/S2 registry, S3 network, S4/S11 download
**Scope:** the 3 critical-path wave-1 seam contracts only (prod-only, no test
files). Wave-2/3 contracts authored after wave-1 seams land (so they cite real
signatures).
**Not done:** wave-2/3 module contracts + all call-site conversions.
* [swarm_ad0b4c65] wave-1 infra seams: S1/S2 registry, S3 network, S4/S11 download
Adds deterministic, XCTest-gated Task-join / barrier-drain seams so Wave-2 test
conversions can await fire-and-forget async work instead of wall-clock polling.
BUILD SUCCEEDED on the Palace target (iPhone 16 Pro sim).
- S1 BookRegistryStore._awaitPendingWritesForTesting — trailing-barrier drain
(concurrent-queue .barrier ⇒ always drains; no handle await).
- S2 TPPBookRegistry._awaitPendingWritesForTesting — forwards to S1 + one main hop;
skips the intrinsic switch-back debounce.
- S3 TPPNetworkExecutor/Responder._awaitInFlightForTesting — grow-until-stable
join over the completion Tasks fired off the URLSession delegate queue;
terminal synchronous completion + watchdog deliberately not retained.
- S4 MyBooksDownloadCenter._awaitDownloadDispatchForTesting — grow-until-stable
join over all 14 fire-and-forget Task spawns (retention gated by XCTest).
- S11 DownloadProgressPublisher throttle interval made injectable (prod default
0.5s unchanged; RELEASE byte-identical).
All retention arrays populated ONLY under _isRunningUnderXCTest; RELEASE spawns
identical work and never reads/populates them. Every seam is BOUNDED — a barrier
that always drains or a retained Task that completes; no bare never-resuming
await, no added sleep/poll/Date/Timer; NSLock never held across a suspension.
**Scope:** wave-1 production seams only (6 files); no test files change here.
**Not done:** wave-2/3 module contracts + the ~550-620 call-site conversions
that consume these seams; those land in subsequent commits after per-contract
CI verification.
* [swarm_ad0b4c65] wave-2 conversion playbook (seam catalog + bounded-await rule + bucket protocol)
**Scope:** the shared wave-2 playbook only.
**Not done:** the 12 module conversions.
* [swarm_ad0b4c65] wave-2: land validated S1/S2 conversions; drop S3/S4/S11 (no/broken consumers)
Wave-2 fanned 12 module agents over the full PalaceTests suite to convert
wall-clock/deadline-poll waits to the wave-1 seams. Honest outcome: the
"~675 sites" premise was a mismeasure — most waits are already-converted (prior
#1319 sweep) or legitimate KEEP (bounded by a direct synchronous injected-mock
callback, the correct pattern). Real net-new conversions concentrate in the
registry seams.
LANDED (verified green — 161 tests, 0 failures on iPhone 16 Pro sim):
- S1 BookRegistryStore._awaitPendingWritesForTesting + S2 TPPBookRegistry (kept
from the wave-1 commit) — ~51 real consumers across Book + BookRegistry.
- Converted: Book (BookRegistryStoreTests, BookRegistrySyncTests),
BookRegistry (7 files), BookStateManagement (BookCellModelStateTests) — all
wait(for:)/waitForExpectations on registry fire-and-forget writes → the S1/S2
barrier-drain seams; async-context DispatchGroup waits use `await fulfillment`.
- Accounts (AccountsManagerTests, AccountsManagerStateMachineWiringTests) —
6 conversions using EXISTING primitives (drainMainQueue / awaitCondition),
no production seam; deleted a global().asyncAfter settle-pad + a Thread.sleep poll.
DROPPED (this commit reverts the wave-1 seams that didn't earn their place):
- S3 TPPNetworkExecutor/Responder._awaitInFlightForTesting — 1 consumer, and that
conversion FAILED (testSessionInvalidationCallsPendingCompletionsWithCancelError:
seam join returned without the cancellation completion). Marginal + broken → out.
- S4 MyBooksDownloadCenter + S11 DownloadProgressPublisher — 0 consumers
(MyBooks tests use synchronous mocks per "never hit real singletons"). Unused
test-only production surface is a blast-radius liability → out.
The 8 other modules correctly produced 0 conversions (already-done / legit KEEP /
UNMAPPED-needs-unbuilt-seam). UNMAPPED clusters flagged for a possible targeted
Wave 3: HoldsViewModel debounce (15), OfflineQueueService (12), AudiobookLoader
(5), BookmarkManager.waitForBarrier (~20), SignInLogic main-hops (46, mostly
drainMainQueueAsync-able). Full per-module transcripts under transcripts/.
**Scope:** S1/S2 registry seams + ~57 verified test-only conversions; drop
S3/S4/S11.
**Not done:** Wave-3 targeted seams (Holds/OfflineQueue) — deferred, pending a
decision they're worth the production surface. The remaining raw wait-token count
is intentional (legitimate KEEP), not a silent cap.
---------
Co-authored-by: t <t@t.io>1 parent 8c346c3 commit 8b1e50b
35 files changed
Lines changed: 3758 additions & 529 deletions
File tree
- .forgeos/swarms/swarm_ad0b4c65
- contracts
- transcripts
- PalaceTests
- Accounts
- BookRegistry
- BookStateManagement
- Book
- Palace/Book/Models
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
Lines changed: 80 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
Lines changed: 55 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
0 commit comments