needs_evidence 12건 + failed 3건 반려 사유 분류와 재발 방지안
needs_evidence 12건 + failed 3건 반려 사유 분류와 재발 방지안 (2026-10-05 조회)
[권고]
→ 1순위: "검증:" 줄의 exit code 계열(missing/invalid_verification_exit_code 7건 + verification_command_unverifiable 3건 = 10/15, 67%)을 막는다. 두 갈래다.
(가) 태스크 본문 템플릿 수정(orchestrator 자동 보강 문구): 검증 줄 형식을 "검증: <명령 전체, 실존 경로 포함> → <결과값>, exit code 0" 한 줄로 못박는다. 수정 파일: scripts/shared/agent_task_quality.py (자동 보강 문구 생성부 975~1048행, 현재 "검증: exit code 0; 통과"처럼 값만 안내해 명령이 빠짐). 기대효과: verification_command_unverifiable 3건 → 0건.
(나) 게이트 오탐 수정(codex 위임): 반려 사유를 분류하는 보고서는 본문에 "missing_verification_exit_code 4건"처럼 라벨 이름을 쓴다. 이 글자가 exit code 정규식에 걸려 "exit_code 4"로 읽힌다(재현은 아래 [현황] 참고). 수정 대상: scripts/server.py _STORAGE_EXIT_CODE_RE(733행)와 이를 쓰는 _completion_storage_required_result_gaps(823행 부근), scripts/agent_queue_worker.py _CODEX_VERIFICATION_EXIT_CODE_RE(7031행)와 _codex_has_verification_result_field(7126행). 정규식 앞에 단어 경계((?<![A-Za-z_]))를 두고, 판정은 "검증:" 줄 안의 exit code만 보도록 한다. 기대효과: 분류형 보고 오탐 2건(#40854, #40869) → 0건.
→ 2순위: analyst-pm/analyst-macro의 missing_result_or_verification 3건(#40408, #40518, #40874)과 라벨 없는 "결과 확인 보류" 1건(#40825)을 막는다. 판단형 보고는 결과물 경로가 없어 _completion_report_has_result_and_verification(scripts/agent_queue_worker.py 2146행)에서 결과물/검증 쌍을 못 찾는다. 처방은 에이전트 프롬프트: scripts/agent_registry.py AGENT_ROLE_PROMPTS의 analyst-pm, analyst-macro 항목에 "판단 결론 뒤에 입력 파일 경로와 파싱 명령을 '근거파일:'에 쓰고, '검증:'에 python3 -c ... 또는 grep -c 명령과 exit code 0을 같은 줄에 쓴다"를 추가한다. 기대효과: analyst 계열 반려 4건(27%) → 0건.
[현황]
조회: sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT id,status,claimed_by,title,result_note FROM bus_commands WHERE status IN ('needs_evidence','failed')" → 15행 (needs_evidence 12, failed 3). 조회 2026-10-05 KST.
건별 분류 (건당 대표 라벨 1개, 한 건에 라벨이 여러 개면 비고에 표기):
| id | 담당 | 상태 | 반려 라벨 | 계열 |
|---|---|---|---|---|
| 40276 | guardian | needs_evidence | missing_verification_exit_code | 검증값 |
| 40297 | ron | needs_evidence | invalid_verification_exit_code | 검증값 |
| 40346 | guardian | needs_evidence | missing_verification_exit_code | 검증값 |
| 40408 | analyst-macro | needs_evidence | missing_result_or_verification | 실행값+출처 |
| 40518 | analyst-macro | needs_evidence | missing_result_or_verification | 실행값+출처 |
| 40633 | guardian | needs_evidence | missing_verification_exit_code | 검증값 |
| 40691 | cowork | needs_evidence | verification_command_unverifiable | 검증값 |
| 40825 | guardian | needs_evidence | 라벨 없음("결과 확인 보류") | 미상 |
| 40842 | guardian | needs_evidence | missing_execution_artifact + missing_verification_command + missing_verification_exit_code | 검증값(+출처) |
| 40854 | guardian | needs_evidence | missing_verification_exit_code | 검증값 |
| 40869 | guardian | needs_evidence | invalid_verification_exit_code | 검증값 |
| 40874 | analyst-pm | needs_evidence | missing_result_or_verification | 실행값+출처 |
| 40871 | analyst-pm | failed | verification_command_unverifiable + direction_contradicts_source:BAMLH0A0HYM2 | 검증값 |
| 40876 | guardian | failed | verification_command_unverifiable + source_log_path_not_found:/Users/ron/.hermes/logs/agent.log.1 | 검증값+경로 |
| 40877 | guardian | failed | llm_infra_failure(429/timeout/empty) + verification_command_unverifiable + missing_execution_artifact | 인프라(혼합) |
에이전트별 건수:
| 에이전트 | needs_evidence | failed | 합계 | 주요 라벨 |
|---|---|---|---|---|
| guardian | 7 | 2 | 9 | missing_verification_exit_code 4(+40842), invalid 1, unverifiable 1, 경로 없음 1, infra 1, 라벨 없음 1 |
| analyst-pm | 1 | 1 | 2 | missing_result_or_verification 1, unverifiable 1 |
| analyst-macro | 2 | 0 | 2 | missing_result_or_verification 2 |
| ron | 1 | 0 | 1 | invalid_verification_exit_code 1 |
| cowork | 1 | 0 | 1 | verification_command_unverifiable 1 |
| 합계 | 12 | 3 | 15 |
계열별: 검증값 계열 10건(exit code 7 + 명령 재현 불가 3), 실행값+출처 계열 3건, 인프라 혼합 1건(#40877, 다른 라벨 2개 동반이라 주원인은 4블록 미비), 라벨 없음 1건. missing_source 단독·missing_execution_value 단독·missing_verification_value 단독은 0건이다(게이트가 exit code/명령 단위의 세부 라벨로 반환하기 때문).
실측 사실 (직접 실행):
1. 게이트 오탐 재현: guardian 로그(agent-queue-guardian.log 187408행, 187582행)에서 #40854/#40869 원본 보고를 꺼내 server.py의 _STORAGE_EXIT_CODE_RE로 훑었다. #40854 본문에서 첫 매치가 "exit_code: 4"(원문 "missing_verification_exit_code: 4건"의 일부), #40869 본문에서 첫 매치가 "exit_code 4"로 나왔다. 두 정규식 모두 단어 경계가 없어 라벨 이름 안의 "exit_code"를 잡는다. _codex_has_verification_result_field에 #40854 원본을 넣으면 (False, 'invalid_verification_exit_code')가 나왔다. 반려 분류 보고는 구조상 이 라벨을 인용하므로 게이트를 통과하기 어렵다.
2. DB 저장 노트 손실: 반려된 12건의 result_note는 382~385자 고정 템플릿이고, "원본 요약"이 260자 부근에서 잘려 "근거:"에서 끝난다(예: #40408, #40518). 그래서 DB만으로는 에이전트가 처음 낸 원문 검증 줄을 확인할 수 없다. #40408, #40518, #40874, #40825의 근본 원인은 원문 미보존으로 미확인이다.
3. llm_infra_failure 문구가 실제 차단 사유로 적힌 건은 #40877 1건뿐이고, 그 건도 verification_command_unverifiable와 missing_execution_artifact가 함께 있다.
4. #40876의 인용 경로 /Users/ron/.hermes/logs/agent.log.1 은 source_log_path_not_found로 판정됐다(게이트 문구 그대로).
게이트 근거 위치 (읽은 파일):
- scripts/shared/public_result_formatter.py:3087 def completion_required_evidence_gaps — 검증 명령 갭은 3154행에서 completion_verification_command_gap(2879행)을 먼저 호출해 verification_command_unverifiable을 반환한다.
- config/agent_completion_submission_standard.md:234 "## 4. 반려 판정 기준 요약", 245행에 invalid_verification_exit_code 설명이 이미 있으나 "라벨 이름 속 exit_code 오탐"은 기록돼 있지 않다.
[리스크]
- 오탐 구조: 분류·감사 태스크가 같은 게이트에 걸리는 자기참조 구조라 guardian이 같은 유형의 태스크를 연속 반려당한다(#40825 → #40842 → #40854 → #40869, 4연속). 에이전트 규율을 아무리 높여도 라벨명을 본문에 쓰는 한 해소되지 않을 수 있다. 근거: 위 실측 1.
- 정규식 수정 시 반대 위험: exit code 판정을 "검증:" 줄로 좁히면 기존에 통과하던 "검증 결과:" 줄이나 근거 줄의 exit code를 놓칠 수 있다. server.py와 agent_queue_worker.py, public_result_formatter.py에 같은 정규식이 사본으로 존재해 한 곳만 고치면 드리프트가 생긴다.
- 저장 노트 260자 절단: 원문이 DB에 안 남아 반려 원인 감사가 로그 파일(agent-queue-guardian.log) 의존이다. 로그가 로테이션되면 재현 불가.
- analyst 건은 원문 미확인이라 2순위 처방의 정확도가 낮다. 1순위(오탐) 수정 후에도 analyst 반려가 남는지 먼저 본다.
[검증방법]
- KPI: 같은 7일 창에서 needs_evidence+failed 중 검증값 계열 건수 10건 → 2건 이하, guardian 분류형 태스크 연속 반려 4연속 → 0.
- 검증 명령: sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT claimed_by,count(*) FROM bus_commands WHERE status IN ('needs_evidence','failed') AND created_at>='<적용 시각>' GROUP BY 1" → guardian 건수 감소 확인.
- 단위 확인(codex 수정 후): #40854 원본 문구를
_codex_has_verification_result_field에 넣어 (True, '')가 나오고, 진짜 "exit code 1" 문구는 여전히 (False, 'invalid_verification_exit_code')인지 확인한다. - 롤백 조건: 수정 후 exit code 1 보고가 통과 처리되는 케이스가 1건이라도 나오면 정규식 변경을 되돌린다.
완료 보고 4블록
결론: bus_commands의 needs_evidence 12건과 failed 3건을 조회해 반려 라벨별·에이전트별로 분류하고, 상위 2개 사유(검증 exit code 계열 10건, analyst 결과·검증 쌍 누락 4건)의 방지안과 수정 대상 파일·함수를 이 문서에 작성했다. 코드는 수정하지 않았다. 근거: sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT ... FROM bus_commands WHERE status IN ('needs_evidence','failed')" → 15행(needs_evidence 12, failed 3), 조회 2026-10-05 KST. 오탐 재현은 /Users/ron/.hermes/logs/agent-queue-guardian.log 187408행·187582행. 검증: 표의 에이전트별 합계 9+2+2+1+1=15가 조회 행 수 15와 일치함을 python3 집계로 확인했다. exit code 0, 통과. 근거파일: /Users/ron/knowledge-agent/400-reports/261005_cowork_needs_evidence_15건_분류와_방지안.md (아래 행 번호는 저장 후 grep -n으로 확인한 값을 최종 보고에 인용)