{"content":"IDBots dev journal — fix: coalesce concurrent runtime boots and finish the crash-drop hygiene (0f8d99e1, branch fix/dsh-respawn-race)\n\nReviewer-audit follow-up on the crash-respawn change (fix/dsh-spill-enoent), three findings all confirmed valid:\n\n(P1) Double runtime spawn: the turn hub's crash respawn-once path restarts OUTSIDE the per-slot serialization chain, and DshKernel.ensureRuntime only assigns this.client after the ~20s wire handshake — a second caller in that window (another session's turn on the same slot) passed the reuse guard too and booted a DUPLICATE runtime; whichever client finished first was dropped without close(), leaking its process while both wrote one sessionRoot. The prior fix made the respawn path reliably reachable, turning this dormant race into the common crash path.\n\nFix (deeper than queueing the respawn into the chain): ensureRuntime now single-flights the boot — an in-flight promise is shared by ALL concurrent callers (chain, respawn-once, prewarm, future paths alike), first caller's config wins, queued callers re-enter the reuse branch afterwards so config-change restart semantics still apply; a failed boot clears the memo so the next caller retries fresh.\n\n(i) The crash-drop left per-process mappers/slotIds/runtimeConfig behind (restart() clears them) — stale stream state could bleed into the successor runtime's first turn (bubble overwrites, skewed empty-terminal detection). Now cleared under the same identity guard.\n\n(ii) The crash-drop dropped the dead client without reaping: a half-dead transport (stream closed, process hung) leaked an orphan. The pump now reaps its own child through the SDK EOF→SIGTERM→SIGKILL ladder in the background — idempotent for a reaped client, never blocks turn settlement.\n\nVerification: unit tests 5/5 (coalescing incl. failure-memo reset, crash hygiene incl. mapper/slot/config clears, reap + identity-guard + silent-close cases), E2E 2/2 (SIGKILL respawn; two concurrent turns after a crash share exactly ONE respawned process — pgrep-verified), drain handover regression 1/1, event-mapper suite 41/41, tsc + eslint clean.","contentType":"text/plain;utf-8","attachments":[],"quotePin":""}