증상
TUI 직결(TUI-direct) 릴레이 채널에서 health 스톨 감시가 계속 오탐을 낸다. 2026-09-01~09-05 dcserver 로그 3일치 기준:
| 신호 |
건수 |
위치 |
health::transcript_binding_stall (#5188 … frozen_with_live_turn) |
22,112 |
snapshot.rs:697 → transcript_binding_stall.rs:219 |
health::stall_liveness (shadow_verdict=control_plane_desync existing_decision=force_cleanup) |
7,292 |
recovery.rs:2130 → stall_liveness.rs:618 |
health::recovery::stall_alert (alert queued) |
129 |
stall_alert.rs:108 |
discord::relay_recovery auto-heal skipped (durable_reattach_circuit_open / durable_reattach_stale_identity) |
7,756 |
relay_auto_heal.rs:746, relay_recovery.rs:941 |
전체의 99.9%가 두 채널이다: claude-adk-cc (1479671298497183835), codex-adk-cdx (1479671301387059200). 27시간·9시간 연속 같은 판정이 이어졌다.
사용자 영향:
- 30분마다 운영 채널에 "스톨 의심" 멘션이 온다 (
stall_alert 125건 큐잉).
doctor가 항상 degraded로 뜬다. 진짜 스톨이 생겨도 구분이 안 된다.
relay_recovery가 30초마다 reattach_watcher를 시도하고 skip한다 (순수 노이즈. TUI-direct 세션에 tmux-capture redrive를 하지 않는 것 자체는 정답이다).
원인
TUI-direct 채널은 tmux pane을 캡처해서 Discord로 옮기는 경로가 아니라 rollout/hook frontier로 배달한다. 그래서 tmux-capture 축의 last_relay_offset이 영원히 0이고, 감시기는 unread_bytes = pane 전체로 계산한다. 스톨 판정 조건(watchdog_decisions.rs:81-115)이 attached && desynced && inflight_present && !terminal_committed && inflight_age ≥ 600 && liveness 근거 없음인데, TUI-direct 채널은 liveness 근거를 tmux 축에 절대 공급하지 못하므로 구조적으로 항상 참이 된다.
recovery.rs:2115-2150은 정리 없이 페이지만 하므로(#4460) 판정이 매 30초 반복된다. transcript_binding_stall은 스냅샷 빌드마다(≈4회/31초) 중복 발화한다 (relay_attached && tmux_alive && idle ≥ 300s && inflight_present, :95-118).
오탐이 아닌 잔여 결함 1건
두 채널의 Discord inflight row가 inflight_started_at=2026-08-30 15:11:48, 2026-09-02 16:54:13, terminal_delivery_committed=false인 채로 며칠째 남아 있다. 이것이 transcript_binding_stall(inflight_present 단독 조건, transcript_binding_stall.rs:117)과 stall_liveness를 동시에 먹인다. TUI-direct 세션의 inflight를 정착시키는 주체가 없다.
이 결함의 구조적 재발 방지는 #5464 (T5, inflight 권위 폐지)의 범위다. 본 이슈는 T5와 충돌하지 않도록 판정 구조를 바꾸지 않고, 남은 row 2건의 운영 정리만 포함한다.
수정 방향
- delivery owner가 TUI direct relay(rollout/hook frontier)인 채널은 tmux-capture liveness 축에서 제외하거나, hook/rollout frontier 전진을 liveness 근거로 공급한다.
- 로그 문구
forced cleanup → suspected stall paged (no cleanup)로 교정한다. 실제로 cleanup을 하지 않으므로 현재 문구는 진단을 오도한다.
stall_liveness·transcript_binding_stall 모두 상태 전이 시에만 WARN 1회 ((session, bound_path) 키로 dedupe).
relay_recovery의 TUI-direct 채널 skip은 WARN → DEBUG.
완료 정의
관련
기준: main 59c50750f2, 로그 ~/.adk/release/logs/dcserver.stdout.log{,.1,.2} 2026-09-01~05. 좌표는 설계 착수 시 재확인.
증상
TUI 직결(TUI-direct) 릴레이 채널에서 health 스톨 감시가 계속 오탐을 낸다. 2026-09-01~09-05 dcserver 로그 3일치 기준:
health::transcript_binding_stall(#5188 … frozen_with_live_turn)snapshot.rs:697→transcript_binding_stall.rs:219health::stall_liveness(shadow_verdict=control_plane_desync existing_decision=force_cleanup)recovery.rs:2130→stall_liveness.rs:618health::recovery::stall_alert(alert queued)stall_alert.rs:108discord::relay_recoveryauto-heal skipped(durable_reattach_circuit_open/durable_reattach_stale_identity)relay_auto_heal.rs:746,relay_recovery.rs:941전체의 99.9%가 두 채널이다:
claude-adk-cc(1479671298497183835),codex-adk-cdx(1479671301387059200). 27시간·9시간 연속 같은 판정이 이어졌다.사용자 영향:
stall_alert125건 큐잉).doctor가 항상 degraded로 뜬다. 진짜 스톨이 생겨도 구분이 안 된다.relay_recovery가 30초마다reattach_watcher를 시도하고 skip한다 (순수 노이즈. TUI-direct 세션에 tmux-capture redrive를 하지 않는 것 자체는 정답이다).원인
TUI-direct 채널은 tmux pane을 캡처해서 Discord로 옮기는 경로가 아니라 rollout/hook frontier로 배달한다. 그래서 tmux-capture 축의
last_relay_offset이 영원히 0이고, 감시기는unread_bytes = pane 전체로 계산한다. 스톨 판정 조건(watchdog_decisions.rs:81-115)이attached && desynced && inflight_present && !terminal_committed && inflight_age ≥ 600 && liveness 근거 없음인데, TUI-direct 채널은 liveness 근거를 tmux 축에 절대 공급하지 못하므로 구조적으로 항상 참이 된다.recovery.rs:2115-2150은 정리 없이 페이지만 하므로(#4460) 판정이 매 30초 반복된다.transcript_binding_stall은 스냅샷 빌드마다(≈4회/31초) 중복 발화한다 (relay_attached && tmux_alive && idle ≥ 300s && inflight_present,:95-118).오탐이 아닌 잔여 결함 1건
두 채널의 Discord inflight row가
inflight_started_at=2026-08-30 15:11:48,2026-09-02 16:54:13,terminal_delivery_committed=false인 채로 며칠째 남아 있다. 이것이transcript_binding_stall(inflight_present단독 조건,transcript_binding_stall.rs:117)과stall_liveness를 동시에 먹인다. TUI-direct 세션의 inflight를 정착시키는 주체가 없다.이 결함의 구조적 재발 방지는 #5464 (T5, inflight 권위 폐지)의 범위다. 본 이슈는 T5와 충돌하지 않도록 판정 구조를 바꾸지 않고, 남은 row 2건의 운영 정리만 포함한다.
수정 방향
forced cleanup→suspected stall paged (no cleanup)로 교정한다. 실제로 cleanup을 하지 않으므로 현재 문구는 진단을 오도한다.stall_liveness·transcript_binding_stall모두 상태 전이 시에만 WARN 1회 ((session, bound_path)키로 dedupe).relay_recovery의 TUI-direct 채널 skip은 WARN → DEBUG.완료 정의
claude-adk-cc,codex-adk-cdx채널에서 정상 유휴 상태일 때stall_liveness·transcript_binding_stall발화 0건 (24시간 로그 대조)doctor가 두 채널 때문에 degraded로 떨어지지 않음관련
recovery.rs스톨 판정이 정리 없이 페이지만 하는 배경transcript_binding_stall도입 이슈기준: main
59c50750f2, 로그~/.adk/release/logs/dcserver.stdout.log{,.1,.2}2026-09-01~05. 좌표는 설계 착수 시 재확인.