Two telemetry handlers in Sources/TerminalController.swift block the calling socket thread with DispatchQueue.main.sync: surface.report_tty and surface.ports_kick. Both fire from shell-prompt hooks, so this sits on a hot path and directly contradicts the socket threading policy in CLAUDE.md (telemetry parses and dedupes off-main, minimal mutation via main.async only when needed).
Real-world effect: a busy main thread (window churn, split drags) can stall telemetry delivery and back-pressure the socket, and the sync hop itself is a typing-latency risk on every prompt.
Fix: parse and validate off-main, coalesce, then schedule the minimal model mutation with main.async, same shape as the other telemetry commands already use.
From the 2026-07-09 nuclear review (10 module reviewers + Codex cross-model pass, disprove-first). Line refs are against the reductive-audit branch (PR #81).
Two telemetry handlers in
Sources/TerminalController.swiftblock the calling socket thread withDispatchQueue.main.sync:surface.report_ttyandsurface.ports_kick. Both fire from shell-prompt hooks, so this sits on a hot path and directly contradicts the socket threading policy in CLAUDE.md (telemetry parses and dedupes off-main, minimal mutation viamain.asynconly when needed).Real-world effect: a busy main thread (window churn, split drags) can stall telemetry delivery and back-pressure the socket, and the sync hop itself is a typing-latency risk on every prompt.
Fix: parse and validate off-main, coalesce, then schedule the minimal model mutation with
main.async, same shape as the other telemetry commands already use.From the 2026-07-09 nuclear review (10 module reviewers + Codex cross-model pass, disprove-first). Line refs are against the
reductive-auditbranch (PR #81).