needs_evidence 반려 69건 상위 원인별 방지안 제안서
needs_evidence 반려 69건 상위 원인별 방지안 제안서
작성: Cowork(다듬) / 조회 2026-10-23 11:34~12:00 KST / 코드·DB·크론 수정 없음(조회·재현 실행만)
[권고]
1순위: 실행 중인 워커·서버·오케스트레이터를 재기동해 이미 고쳐 둔 코드를 실제로 올린다(해리 승인 후, 재기동 명령은 해리/ron이 실행). - 왜: 프로세스 시작 시각이 파일 수정 시각보다 앞선다. agent_queue_worker.py는 guardian PID 3974(9/29 02:16)·cowork PID 9235(9/29 01:27)·analyst-macro PID 9385(9/29 01:27), server.py는 PID 15335(9/28 09:17), orchestrator.py --loop는 PID 46446(9/27 07:55) 시작인데, 파일 수정은 agent_queue_worker.py 10/19 15:06, server.py 10/19 15:06, public_result_formatter.py 10/13 19:32, orchestrator.py 10/19 21:01이다. 워커 코드에 reload/execv 호출은 grep 0건이다. 오케스트레이터 로그의 NEEDS_EVIDENCE_REISSUE_LOOP_BLOCKED는 0건이다(ron_orchestrator.log 등 3개 파일 grep -c 모두 0). - 기대효과: 반려 원문 69건을 현재 파일 코드로 재판정하면(워커 게이트 + server 저장 게이트) 25건(36.2%)이 통과로 바뀐다. 44건(63.8%)은 재기동만으로 안 풀리므로 2·3순위가 필요하다.
2순위: "반려 집계·분류 태스크가 자기 분석 대상 문구 때문에 다시 반려되는 고리"를 끊는다(codex 구현 후보 + 표준 문서 보강). - 왜: 69건 중 56건(81.2%)이 제목에 needs_evidence/반려/failed/실패 원인/원인 분류가 있는 분석류 태스크다(guardian 48, cowork 8). 이 56건 중 "라벨 없는 결과 확인 보류" 25건 전부가 분석류다. 분석 보고서가 "결과 확인 보류", "검증 근거 없음" 같은 문구를 서술하다가 하드블록 정규식에 걸려 반려되고, 그 반려가 다음 집계 대상(62→63→65→68→69건)이 되는 자기참조 구조다. - 기대효과: 이 25건 중 현재 코드로도 18건이 계속 막힌다(server 저장 게이트 재현). 예외 기준을 고치면 18건 해소, 그리고 분석류 신규 유입(id>42103, 10/18 이후 15건 전부 guardian) 억제.
3순위: exit code 표기 경직 + 에이전트 미준수 20건 대응(정규식 완화 후보 + guardian 프롬프트 반영 확인). - 왜: missing_verification_exit_code 20건 중 8건은 "exit code는 0입니다"처럼 조사가 끼어 정규식이 못 읽었다. 8건은 검증 줄에 리터럴이 있는데도 나중 단계에서 반려됐다(워커 압축 경로, 10/19 패치 대상). 2건은 exit code 표기가 아예 없다. - 기대효과: 조사형 8건(40%) 즉시 해소, 리터럴 보유 8건은 1순위 재기동으로 해소 예상.
[현황]
1. 직접 집계 (sqlite3 -readonly, 2026-10-23 11:34 KST)
- 합계 69건. claimed_by: guardian 51(73.9%), cowork 8, analyst-macro 5, analyst-pm 4, ron 1. 기간 9/28~10/23. 25개 날짜에 걸쳐 하루 1~5건씩 유입(10/1은 0건).
- 사유 라벨은 result_note의 "차단 사유:" 구간 기준(상호배타 분류):
- 라벨 없는 일반 보류(결과 확인 보류/검증 근거 없음/결과물과 검증 근거가 없음) 25건 (guardian 22, cowork 3)
- missing_verification_exit_code 포함 20건 (guardian 19, cowork 1)
- missing_result_or_verification 13건 (analyst-macro 5, analyst-pm 4, guardian 3, cowork 1)
- invalid_verification_exit_code 8건 (guardian 5, cowork 2, ron 1)
- verification_command_unverifiable 3건 (cowork 1, guardian 2)
- 합 25+20+13+8+3=69 일치.
- 요청서에 적힌 라벨 건수(result_note 전체 문자열 기준 / 차단 사유 구간 기준): missing_execution_value 1/0, missing_source 2/0(둘 다 missing_source_log_path 문자열 안), missing_verification_value 0/0, missing_original_verification 1/0, execution_artifact_path_not_found 4/3. 이 5개는 상위 3개가 아니다. 서술 속에 단어만 나온 건(#42332 등)이 섞여 있다.
- 중복 허용(한 건에 라벨 여러 개) 구간 기준: missing_verification_exit_code 20, missing_result_or_verification 13, invalid_verification_exit_code 8, missing_verification_command 6, completion_result_note_forces_rework 4, verification_command_unverifiable 3, missing_execution_artifact 3, execution_artifact_path_not_found 3.
2. guardian 09:55 집계(CMD#42432, memory/needs_evidence_breakdown_20261023.json, queried_at 09:55:27)와 대조
- 일치: total 69, by_agent(51/8/5/4/1), 문자열 전체 기준 label_counts(missing_verification_exit_code 22, missing_result_or_verification 14, missing_verification_command 6, execution_artifact_path_not_found 4, missing_execution_artifact 3, missing_source_log_path 2, missing_next_action_section 1, missing_original_verification 1, missing_execution_value 1, llm_infra_failure 17)는 내 전체문자열 집계와 전부 같다.
- 불일치 1: guardian blocking_reason_counts는 missing_verification_exit_code 17, missing_verification_command 3인데 내 차단 사유 구간 집계는 20과 6이다. 차이 3건은 #41323, #42062, #42314다. 이 3건은 차단 사유가 "execution_artifact_path_not_found:경로, missing_verification_command, missing_verification_exit_code" 형태라 guardian 파싱이 놓쳤다.
- 불일치 2: guardian label_counts의 llm_infra_failure 17은 반려 사유가 아니다. 17건 모두 본문에서 "llm_infra_failure 0건"처럼 서술만 한 것이고 차단 사유 구간에는 0건이다. guardian 자신의 infra_ids도 []이다. 결론(인프라 지연형 0건)은 맞지만 숫자 17은 그대로 인용하면 오해를 부른다.
- 불일치 3: guardian label_counts의 "needs_evidence 46", "(라벨없음) 2", "needs_evidence_breakdown_ 2", "needs_evidence_ 2"는 라벨이 아니라 파일명·헤더 문자열을 라벨로 센 파싱 부산물이다.
- 불일치 4: guardian 완료 노트(DB result_note, 459자)는 "근거파일: 와 :3 ..."에서 끊겨 경로가 비어 있다. 같은 노트의 근거파일 줄이 공란이어서 이 노트 자체를 근거로 재인용하기 어렵다.
3. 상위 3개 사유별 원인 구분
사유 A. 라벨 없는 일반 보류 25건 (guardian 22, cowork 3) — 규칙 공백(주) + 코드 미반영(일부)
- 태스크 유형: 전부 "needs_evidence N건 반려 사유·에이전트별 집계/분류" 계열 분석류. 유형 대표 제목 예: #42412 "needs_evidence 68건 에이전트·반려사유별 분포 집계".
- 메커니즘: 분석 보고서가 분석 대상 문구를 서술 → server.py _COMPLETION_STORAGE_HARD_BLOCK_PATTERNS(687행)가 원문에서 "결과 확인 보류", "검증 근거 없음"을 잡음. 구제용 _completion_has_meta_investigation_report는 구체 근거 앵커가 2개 이상 있어야 하는데 #41902, #42165, #42171, #42310은 False로 재현됐다.
- 재현: 원문 6건(41902, 42165, 42171, 42264, 42310, 42412)을 server._completion_storage_block_reasons로 재판정 → 5건 여전히 차단(4건은 결과 확인 보류 등 하드블록, #42264는 exit code 누락), 1건(#42412)만 통과. 25건 전체는 18건 차단 유지, 7건 통과.
- 기존 규칙: config/agent_completion_submission_standard.md 121행 "결과 확인 보류를 다시 결과로 제출하지 않는다" 1줄뿐이다. 분석 대상 라벨을 어떻게 쓰라는 규칙은 표준·정책 어디에도 없다(표준 grep "메타" 매치는 조사 서술 문맥뿐, 작성 지침 0건). → 규칙 자체의 공백.
- 재발행 고리: 같은 계열 guardian needs_evidence 제목 44건의 연속 본문 유사도는 최대 0.42, 평균 0.30, 0.9 이상 0쌍(43쌍). orchestrator.py _is_needs_evidence_reissue_loop_tripped(4330행)는 유사도 0.9 이상일 때만 막으므로, 재기동해도 이 계열은 막지 못한다. → 게이트 기준의 공백.
사유 B. missing_verification_exit_code 20건 (guardian 19, cowork 1) — 규칙은 있으나 안 지켜진 건 + 정규식 경직 + 미반영 패치
- 20건을 원문(에이전트 큐 로그에서 69/69 복원)으로 재분류:
- 검증 줄에 리터럴 "exit code N"이 있는데 반려 8건(#40346, 40633, 40842, 41431, 42062, 42083, 42307, 42332): 워커의 4블록 압축 경로가 검증 줄을 잘라 서버 게이트가 재반려한 유형. 10/19 15:06 패치(_has_labeled_four_block_note_passing_gate, agent_queue_worker.py 4551행)가 대상인데 워커 프로세스가 패치 이전이라 반영 전이다. 현재 파일 코드로 재판정하면 3건(40346, 42062, 42332) 통과.
- 조사형 "exit code는 0입니다" 8건(#40854, 41274, 41498, 41640, 41897, 42264, 42293, 42314): 정규식 _CODEX_VERIFICATION_EXIT_CODE_RE(agent_queue_worker.py 7120행)와 _STORAGE_EXIT_CODE_RE(server.py 733행)가 "exit code" 뒤에 조사가 오면 숫자를 못 잡는다. 표준 187행이 리터럴 "exit code 0"을 요구하고 있으니 규칙은 있고 에이전트가 안 지킨 것이지만, 정규식이 경직돼 자연스러운 서술까지 막는 점은 코드 공백이다.
- exit code가 검증 줄 밖에만 있는 2건(#40902, 41323), 표기 전무 2건(#40276, 40994): 에이전트 미준수.
- 기존 규칙: 표준 187~194행(리터럴 exit code 0 요구), 245행(invalid_verification_exit_code 표). guardian 프롬프트는 agent_queue_worker.py 8134~8143행에 exit code 0 안내를 10/14에 넣었으나 같은 이유로 실행 중 워커에는 없다.
사유 C. missing_result_or_verification 13건 (analyst-macro 5, analyst-pm 4, guardian 3, cowork 1) — 이미 코드로 해소된 것으로 보이는 유형
- analyst 9건은 전부 "미국 IG/HY OAS 파일 기반 판독" 태스크(#40408, 40518, 40874, 40960, 41035, 41067, 41769, 41780, 41900). 4블록 라벨 4개는 모두 있었다.
- 재현: 원문 4건(40408, 41067, 41769, 41900)을 현재 코드로 재판정 → server 저장 게이트 [] , 워커 증거 게이트 [] 로 모두 통과. 13건 전체로는 11건 통과, 2건(guardian 분석류) 차단 유지.
- 10/17 #41900 이후 analyst-macro·analyst-pm의 신규 반려는 0건이다(id>41900 조회 0행). 당시 어느 게이트가 막았는지(워커/서버)는 이번에 확정하지 못했다(미확인). 현재 파일 코드는 통과시킨다는 점만 확인했다.
- 판단: 규칙은 있었고(표준 §9-2·§9-3) 코드가 이후 보정돼 현재 재현되지 않는다. 남은 문제는 반려 상태로 남은 9건이 정리되지 않는 것뿐이다.
4. 전체 재판정 결과 (현재 파일 코드 기준, 원문 69/69 복원)
- 워커+서버 양쪽 통과 25건 / 서버 저장 게이트만 차단 42건 / 워커 게이트만 차단 2건 → 재기동만으로 25건(36.2%) 해소 예상, 44건은 코드·지침 보강 필요.
- 한계: 이 재판정은 두 게이트 함수를 원문에 직접 호출한 결과이고, 워커 전체 파이프라인(압축·재라우팅 포함) 실행은 아니다.
[리스크]
- 재기동 리스크: agent_queue_worker.py 5개 워커 + server.py(대시보드 3344) + orchestrator 재기동은 진행 중 태스크(현재 cowork #42437 claimed)를 끊는다. 해리 승인과 idle 시점 확인이 필요하다. 이 문서 작성자는 재기동을 실행하지 않았다.
- 하드블록 정규식 완화는 가짜 완료 통과 위험이 있다. 예외는 "구체 근거 앵커 2개 이상 + 검증 줄에 실행 명령과 exit code 0" 조건을 유지해야 한다.
- 단일 장애점: 같은 정규식 계열이 agent_queue_worker.py 로컬 사본, server.py 사본, shared/public_result_formatter.py 세 곳에 중복돼 있어 한 곳만 고치면 다시 갈라진다(앞서 R24 기록).
- 구조적 위험: 반려 건이 needs_evidence에서 나갈 경로가 없어(orchestrator _cleanup_old_commands는 done/cancelled/failed만 아카이브) 69건이 계속 쌓이고, 집계 태스크가 그 건수를 다시 제목에 넣어 재발행된다.
- 미확인: 사유 C의 당시 차단 주체, 사유 B 중 압축 경로 8건이 실제로 10/19 패치로 해소되는지(재기동 후 실측 필요).
[검증방법]
KPI(재기동·보강 후 72시간): 1. 신규 needs_evidence 유입: 기준선 id>42103 구간 15건(전부 guardian) → 5건 이하. 명령: sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT count(*) FROM bus_commands WHERE status='needs_evidence' AND id>(재기동 시점 최대 id)" 기대값 5 이하. 2. 오케스트레이터 게이트 가동 확인: ps -o lstart= -p (orchestrator PID) 시작 시각이 stat -f '%Sm' scripts/orchestrator.py 시각보다 늦어야 한다. 3. 재현 테스트: 분석류 원문 6건(41902, 42165, 42171, 42264, 42310, 42412)과 조사형 exit code 원문 8건을 server._completion_storage_block_reasons로 재판정 → 14건 중 12건 이상 [] 기대. 미달이면 예외 기준 재검토. 4. 합계 정합: 사유별 합 = 전체 건수(현재 69)를 매번 SQL로 대조. 롤백 조건: 가짜 완료(경로·명령 허구)가 done으로 저장되는 사례가 1건이라도 나오면 예외를 즉시 되돌린다. 재기동 후 워커가 기동 실패하면 이전 plist로 복구한다.
코드 수정 후보 (직접 작성하지 않음, codex 위임용)
- scripts/server.py
_completion_storage_block_reasons(854행),_COMPLETION_STORAGE_HARD_BLOCK_PATTERNS(687행): 분석류 원문 예외 기준. - scripts/shared/public_result_formatter.py
completion_result_note_forces_rework(3602행),strip_quoted_citations(3588행): "라벨 열거" 문맥 면제. - scripts/agent_queue_worker.py
_CODEX_VERIFICATION_EXIT_CODE_RE(7120행),_codex_has_verification_result_field(7219행),_completion_required_evidence_gaps(1966행): 조사형 exit code 허용. - scripts/server.py
_STORAGE_EXIT_CODE_RE(733행): 같은 완화. - scripts/orchestrator.py
_is_needs_evidence_reissue_loop_tripped(4330행),REISSUE_LOOP_SIMILARITY(4090행 부근): 본문 유사도 대신 제목 계열 + 직전 반려 건수 기준 보강. - config/agent_completion_submission_standard.md §3-1(121행 부근): 분석 대상 라벨은 따옴표 없이 snake_case 코드명으로만 쓰고 한국어 하드블록 문구를 서술에 옮기지 않는다는 1줄과 "exit code 0" 리터럴 예시 보강.