Skip to content

health: TUI-direct 릴레이 채널을 tmux-capture 축으로 스톨 판정해 3일 29,533건 오탐 + 30분마다 스톨 멘션 + doctor 상시 degraded #5712

Description

@itismyfield

증상

TUI 직결(TUI-direct) 릴레이 채널에서 health 스톨 감시가 계속 오탐을 낸다. 2026-09-01~09-05 dcserver 로그 3일치 기준:

신호 건수 위치
health::transcript_binding_stall (#5188 … frozen_with_live_turn) 22,112 snapshot.rs:697transcript_binding_stall.rs:219
health::stall_liveness (shadow_verdict=control_plane_desync existing_decision=force_cleanup) 7,292 recovery.rs:2130stall_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건의 운영 정리만 포함한다.

수정 방향

  1. delivery owner가 TUI direct relay(rollout/hook frontier)인 채널은 tmux-capture liveness 축에서 제외하거나, hook/rollout frontier 전진을 liveness 근거로 공급한다.
  2. 로그 문구 forced cleanupsuspected stall paged (no cleanup)로 교정한다. 실제로 cleanup을 하지 않으므로 현재 문구는 진단을 오도한다.
  3. stall_liveness·transcript_binding_stall 모두 상태 전이 시에만 WARN 1회 ((session, bound_path) 키로 dedupe).
  4. relay_recovery의 TUI-direct 채널 skip은 WARN → DEBUG.

완료 정의

  • claude-adk-cc, codex-adk-cdx 채널에서 정상 유휴 상태일 때 stall_liveness·transcript_binding_stall 발화 0건 (24시간 로그 대조)
  • doctor가 두 채널 때문에 degraded로 떨어지지 않음
  • 진짜 스톨(tmux-capture 채널에서 inflight 10분 이상 + 출력 없음)은 여전히 감지됨. 반대방향 테스트 추가
  • 2026-08-30, 09-02 stale inflight row 2건 운영 정리 (1회). 재발 방지는 #5464로 위임하고 본 이슈에서 구조 변경하지 않음
  • 로그 문구·레벨 교정 반영

관련

기준: main 59c50750f2, 로그 ~/.adk/release/logs/dcserver.stdout.log{,.1,.2} 2026-09-01~05. 좌표는 설계 착수 시 재확인.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent:project-agentdeskAuto-assign follow-up work to project-agentdeskbugSomething isn't workingpriority:P1P1: high

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions