증상 (2026-08-13 실기, Luke 보고)
- 거짓 실패: 라디오 DJ가 "지금은 조건에 맞는 음악을 재생하지 못했어요."라고 말했는데 실제로는 음악이 (뒤늦게) 재생되고 있었음.
- 침묵 실패: 유튜브 임베드가 "동영상을 재생할 수 없습니다"를 띄웠는데(임베드 차단 추정) 나이아는 실패 사실을 인지하지 못함.
원인 분석
A. 성공→실패 오보 (타임아웃 레이스)
- 셸
BgmPlayer.tsx watchdog PLAYBACK_TIMEOUT_MS = 12_000 — 12초 안에 playing 관측 없으면 status=timeout 마크.
- naia-agent
activity-radio-dj-bgm.ts observationTimeoutMs = 15_000 — 15초 안에 playbackId 일치 + status=playing + track 관측 실패 시 ok:false.
- 유튜브 임베드 콜드 로드는 12~15초를 넘는 경우가 실재. 타임아웃 판정 후 진짜
onStateChange playing이 도착하면 음악은 재생되지만, 에이전트는 이미 실패 발화를 마쳤고 정정 발화 경로가 없음 (컨트롤러는 music_only 상태로 전이만 함).
B. 실패→침묵 (onError 유실 + 이벤트 부재)
onError는 iframe bridge handshake({event:"listening"})가 성립해야만 postMessage로 도착. WebView2에서 src 교체 후 handshake 유실은 알려진 문제(sendYtCmd 주석).
- 임베드 차단(오류 101/150)은 initialDelivery 이전에 죽는 경우 onError 자체가 안 옴 → status가 requested/loading에 고착 → watchdog
timeout(진단 마크만).
emitAiInterferenceEvent에 music_error/music_timeout 액션이 없음 — music_changed/music_ended뿐. 직접 스킬 호출 경로(LLM tool call)에서는 play receipt만 보고 끝나므로 에이전트가 실패를 학습할 채널이 0.
수정 방향(제안)
error/timeout 관측 시 emitAiInterferenceEvent(music_error) 발행 — 에이전트가 실패·복구를 능동 인지.
- 타임아웃 후 뒤늦은
playing 관측 시 music_recovered(또는 music_changed 재발행) — 거짓 실패 발화를 정정할 능동 큐 제공. 에이전트 컨트롤러(music_only 상태)는 이 큐에서 재생 확인 멘트로 정정.
- 데드라인 재검토: 에이전트 관측 15s가 셸 watchdog 12s보다 길어 셸 timeout 마크를 그대로 실패로 읽는 구조 — 셸의 timeout은 진단 마크(주석에도 '증거 아님' 명시)인데 에이전트는 하드 실패로 해석(
BGM ${state.status}). timeout은 관측 계속으로 완화 검토.
- handshake 유실 내성: onError 대체 신호(임베드 로드 후 N초 내 initialDelivery 미도착 = 오류 추정) 검토.
교차 저장소
- naia-agent:
src/main/adapters/activity-radio-dj-bgm.ts (172행 timeout을 하드 실패로 해석), personal-radio-dj-controller.ts:383 (실패 발화 후 정정 경로 없음)
- naia-shell:
packages/shell/src/components/BgmPlayer.tsx, src/lib/bgm-playback.ts
🤖 Written with AI assistance. If anything looks off, please ping @luke-n-alpha or open a discussion.
증상 (2026-08-13 실기, Luke 보고)
원인 분석
A. 성공→실패 오보 (타임아웃 레이스)
BgmPlayer.tsxwatchdogPLAYBACK_TIMEOUT_MS = 12_000— 12초 안에playing관측 없으면 status=timeout마크.activity-radio-dj-bgm.tsobservationTimeoutMs = 15_000— 15초 안에playbackId 일치 + status=playing + track관측 실패 시ok:false.onStateChange playing이 도착하면 음악은 재생되지만, 에이전트는 이미 실패 발화를 마쳤고 정정 발화 경로가 없음 (컨트롤러는 music_only 상태로 전이만 함).B. 실패→침묵 (onError 유실 + 이벤트 부재)
onError는 iframe bridge handshake({event:"listening"})가 성립해야만 postMessage로 도착. WebView2에서 src 교체 후 handshake 유실은 알려진 문제(sendYtCmd 주석).timeout(진단 마크만).emitAiInterferenceEvent에music_error/music_timeout액션이 없음 —music_changed/music_ended뿐. 직접 스킬 호출 경로(LLM tool call)에서는 play receipt만 보고 끝나므로 에이전트가 실패를 학습할 채널이 0.수정 방향(제안)
error/timeout관측 시emitAiInterferenceEvent(music_error)발행 — 에이전트가 실패·복구를 능동 인지.playing관측 시music_recovered(또는 music_changed 재발행) — 거짓 실패 발화를 정정할 능동 큐 제공. 에이전트 컨트롤러(music_only 상태)는 이 큐에서 재생 확인 멘트로 정정.BGM ${state.status}). timeout은 관측 계속으로 완화 검토.교차 저장소
src/main/adapters/activity-radio-dj-bgm.ts(172행 timeout을 하드 실패로 해석),personal-radio-dj-controller.ts:383(실패 발화 후 정정 경로 없음)packages/shell/src/components/BgmPlayer.tsx,src/lib/bgm-playback.ts🤖 Written with AI assistance. If anything looks off, please ping @luke-n-alpha or open a discussion.