* perf(relay): stop ACK boundary scans at first pending boundary
* test(relay): pin PTY source boundary cleanup and guard ascending sends
The early-`break` in advanceCredit is only correct while sentBoundaries is
inserted in ascending sentEndSu order. Turn that implicit invariant into a
throw at the sole live write site (commitPtySourceSend), and assert the
post-state directly instead of inferring it from an iteration budget:
- assert the surviving boundary set after the 1,023-ACK benchmark
- cover the jump-ahead cumulative ACK that must delete many boundaries in
one pass (the case an over-eager `break` would get wrong)
- cover the settleReservedPtySourceAck -> advanceCredit entry point
- drop an arithmetically-implied assertion and CI benchmark log noise
* perf(relay): reclaim ACK boundaries with a monotone cursor
The early-break Set scan still rebuilt a Set iterator per ACK, so V8 walked
delete tombstones and the drain stayed superlinear; the visit-count test could
not see it because it stubbed sentBoundaries with a generator over a private
Set. Replace the Set with an ascending boundary list plus a monotone cursor,
assert the real structure, and add a benchmark over the shipped code.
* test(relay): enforce ascending sent-boundary inserts in the collection
Move the ascending-order precondition into PtySourceSentBoundaries.add so
both insert sites are covered, and assert per-ACK span reclamation in the drain.
* test(relay): collapse ledger test record accessors into getDeliveryRecord
Rebase onto #17490 left two structurally identical internals accessors
(getCursorRecord, getBoundaryRecord); one typed accessor covers both.
* perf(relay): index PTY source-credit send spans
* perf(relay): maintain PTY source-credit retention totals
* test(relay): pin PTY send-cursor rebase across ACK reclaim
Cover the Math.max clamp branch in reclaimCreditedSpans where reclaim
removes spans at or past the send cursor, and widen the seeded fuzz case
to 20 spans per seed so the cursor actually traverses spans; assert the
cursor never overshoots the span containing sentEndSu.
* refactor(relay): drop dead retained-total helpers and pin retention counters
The incremental PtySourceCreditRetention counters replaced the recompute-from-records
helpers; delete the now-unreferenced exports and recompute the totals from the live
records inside the ledger tests so the counters have an independent oracle.
* test(relay): bound send-span reads instead of pinning the read pattern
Address review feedback on the send-span cursor coverage:
- replace the exact indexed-read pin and the tautological naive-visit
assertion with a linear bound that still fails on the old Array.find path
- drop the per-run bench console.log
- assert retention totals immediately after rotate(), the only path that
removes and re-adds a record in one call
Also count the replacement delivery in retention as it enters the delivery
map so the "in deliveries <=> counted" invariant never has a hole.
* fix(daemon): bound the whole boot-recovery sequence with one budget (STA-5732)
* fix(daemon): keep socket probes inside recovery budget
* fix(daemon): size the recovery budget against the real post-kill tail
The 24s budget reserved only 9s for everything after the deadline, leaving
27s of the startup PTY gate's fail-open cap unused — and every unused second
is one where a daemon that would have drained gets killed with its live PTYs
instead. Reserve each post-deadline stage's actual hard cap (kill 10.5s, fork
10s, lease 5s) and spend the rest: 24s -> 32s of adopt window.
* fix(daemon): keep the last-resort endpoint rescue outside the recovery budget
The rescue probe in the launcher's outer catch was clamped to the recovery
budget's remainder, but it runs *after* that budget by construction — past
prepareDaemonReplacement, killStaleDaemon, the fork and the adoption lease.
The remainder is therefore essentially always negative, so Math.max(1, ...)
handed a live socket a 1ms connect window. On the loaded machine this path
exists for the probe loses to its own timer, the launcher rethrows, and a
recoverable degraded adoption becomes total daemon loss for the whole run —
the outcome the comment above it exists to prevent. Restore the 1s default
and pin the window with a test that drives the launcher to that catch with
the budget already spent.
Also make the deliberate narrowing legible instead of implicit:
- daemon-recovery-budget.ts: TRANSIENT_WEDGE_DRAIN_MS documented 20s as the
grace #8697 sized, but #8697's merged second commit (840d3277d1) widened
it to 11 retries ~= 60s. Record that 20s is the drain estimate and that the
budget deliberately sits under #8697's shipped grace.
- daemon-init-wedged-daemon-grace.test.ts: pin the trade directly — a wedge
draining after the budget is replaced and loses its live sessions.
- Rewrite 'preserves a daemon that stays wedged until the LAST allowed grace
retry' onto the simulated clock. It never mocked Date.now, so its 12 probes
elapsed ~0ms and asserted a retry grace the wall clock can no longer
deliver; it now pins the last drain the budget still adopts.
* fix(daemon): name the socket probe default and correct the grace-retry rationale
Answers the review round on the budget accounting: the outer-catch endpoint
rescue is deliberately outside it, and the preflight clamp no longer duplicates
probeDaemonSocket's default as a bare literal.