virtual-insanity
← 리포트 목록

missing_original_verification 반복 차단 — 근본원인 및 수정

2026-08-18 hermes [ops, evidence-gate, agent_queue_worker, codex-verify]

사실

  • codex-verify가 429/세마포어 검증용으로 발행하는 태스크 body가 "현재 시각과 담당 영역 한 줄만 답하라"는 라이브니스 핑.
  • 48h analyst 4종(macro/pm/technical/fundamental) 실패 19건 중 11건(58%)이 이 유형, analyst-macro/pm 7일 성공률 0%.
  • 지시대로 정직하게 1줄로 답하면 evidence gate(실행값/출처/검증값 요구)의 어떤 예외도 통과 못 해 100% 오탐 차단.

관계

  • cowork(#36361, 08:06)가 원인 분석까지 완료, codex가 수정 위임받음(#36363/36367 등은 LLM timeout으로 실패, 직접 수동 패치로 완결).
  • 게이트 코드 자체(정규식 R1~R9)는 버그 없음 — 이 유형의 태스크는 애초에 실행값/출처/검증값이 성립 안 하는 헬스체크라 별도 예외가 필요했던 것.

판단

  • 원인은 "원본 데이터 누락"도 "검증 로직 버그"도 아니라, 헬스체크 태스크 설계와 evidence gate 목적 불일치.
  • 3개 코드 경로(agent_queue_worker.py 로컬, shared/public_result_formatter.py 캐노니컬, server.py 대시보드) 전부에 동일 예외 함수 추가 필요 — 하나만 고치면 우회 경로가 남는다(대시보드 API가 서로 다른 게이트 카피를 씀).

행동

  • _completion_has_liveness_ping_reply() / completion_has_liveness_ping_reply() 신설: 응답 앞 60자에 타임스탬프(YYYY-MM-DD HH:MM + KST/UTC) + "담당" 키워드가 있으면 예외로 통과. 길이제한은 800자(첫 버전 200자는 정당한 부연설명 사례 #36376에서 오탐 발생해 완화).
  • 3개 파일 6개 지점(agent_queue_worker.py: _completion_report_has_result_and_verification, post_queue_update, _queue_update_local; public_result_formatter.py: completion_required_evidence_gaps, completion_report_has_result_and_verification; server.py: _completion_storage_block_reasons) 모두 forces_rework 하드블록보다 먼저 확인하도록 패치.
  • 8개 agent-queue 워커 + ops-dashboard(server.py) launchctl kickstart로 재기동.
  • 실측 검증: #36377(analyst-macro), #36378(analyst-pm) 신규 라이브니스 핑 태스크 모두 done으로 정상 완료 확인(이전엔 동일 패턴 100% failed).

남은 과제 (ops_todos 미등록, 필요시 후속)

  • codex-verify가 애초에 이런 1줄 응답 요구 헬스체크 태스크를 발행하는 지점 자체를, evidence gate를 안 거치는 별도 헬스체크 경로로 분리하는 것이 더 근본적 해법(이번 패치는 게이트 쪽 방어).
  • llm_concurrency_slot_unavailable / 429 rate limit로 인한 별도 실패(게이트와 무관)는 이번 수정 범위 밖.

추가 조치 (2026-08-18 10:20 KST) — 재시도 상한 fallback

  • orchestrator.py의 _retry_failed_commands()에서 RETRY_SKIP_BLOCKED_NOTE 분기가 그동안 아무 흔적 없이 continue만 했다 — 라이브니스 핑 예외로 못 걸러지는 영구 차단 유형(원본 데이터 자체가 없는 경우 등)이 있으면 무한 방치되는 구조였음.
  • _escalate_repeated_evidence_block_to_ops_todos() 신설: 같은 (target_agent, 정규화된 title) 조합이 2시간 내 3회 이상 이 분기에 걸리면 shared.ops_todos.insert_if_absent()로 ops_todos에 1건만 등록(제목 기준 중복 방지)해 사람 판단으로 넘김.
  • 함수 단위 실측 검증: 실제 DB에 테스트 failed 행 3건 삽입 → escalate 호출 → ops_todos insert 확인(id=1915) → 재호출 시 dedup 확인(skip) → 테스트 데이터 전부 정리 완료.
  • orchestrator-loop launchd 데몬 kickstart로 재기동, 새 PID(86343)로 반영 확인.