virtual-insanity
← 리포트 목록

needs_evidence 45건·failed 7건 반려 사유별 재발 방지안 (상위 3개 원인)

2026-10-17 claude [needs_evidence, completion-gate, bus_commands, prevention, prompt-template, codex-delegation]

needs_evidence 45건 + failed 7건 재발 방지안 (읽기 전용 조회 2026-10-17 06:50 KST)

범위: /Users/ron/.hermes/data/ops_multiagent.db bus_commands에서 status가 needs_evidence 또는 failed인 행. 지시문은 failed 6건이라 했으나 라이브 DB는 7건이다(#41868, #41869, #41872, #41873, #41874, #41876, #41878). 새 집계는 하지 않고 result_note의 "차단 사유:/누락·차단:" 라벨을 직접 읽어 상위 3개 원인만 확인했다. 코드는 수정하지 않았다.

[권고]

1순위 — 원인 A: 검증 줄의 exit code·명령·산출물 (25건, 48%) - 무엇을: 4블록 규칙 중 "검증은 한 줄 안에 명령·결과 수치·exit code, 부재 확인은 부정형 명령"을 guardian에만 있는 상태에서 cowork·analyst-macro·analyst-pm·ron 프롬프트로 확장하고, 자동 보강 문구를 값 자리 표기로 바꾼다. - 왜: guardian 블록(scripts/agent_registry.py 311행~)에만 그 규칙이 있고 cowork(272행~)·analyst-macro(394행~)·analyst-pm(485행~)·ron(182행~)에는 공통 4줄 형식뿐이다. 반려 25건 중 비 guardian이 7건(cowork 4, analyst-macro 2, ron 1). - 기대효과: 7일 내 A 신규 반려 일 1건 미만(현재 25건/약 18일). - 실례: - #40276 (guardian): 결과가 "수행한 일과 현재 상태를 완료형 한 문장으로 적는다"라는 자동 보강 안내문을 그대로 복사한 상태. 차단 사유 missing_verification_exit_code. - #40346 (guardian): PID 표 파일은 만들었으나 검증 줄에 exit code 숫자가 없음. 차단 사유 missing_verification_exit_code. - #40297 (ron): 지정 스크립트가 exit 1로 멈춘 것을 정직하게 보고했는데 "exit code 1"이라 invalid_verification_exit_code로 반려. 규정 공백(실패를 보고하는 경우). - 변형: #41869·#41876 (cowork, failed)는 /Users/ron/.hermes/workspace/jobs.json, .../standard.md 같은 상대경로를 workspace 아래로 풀어 execution_artifact_path_not_found. - 바꿀 문구(프롬프트 4개 + 태스크 body 자동 보강 공통): 1. 현재 "검증: <실행한 검증 명령> → <실제 결과값>, exit code <숫자>"를 유지하되 아래 3줄을 추가한다. - "검증은 한 줄 안에 명령, 결과 수치, 마지막에 exit code 0을 모두 쓴다. 'exit code는 0'처럼 조사를 끼우지 않는다." - "없음을 확인하는 검증은 ! grep -rlq '<패턴>' <경로>; echo \"exit code $?\" → 일치 0개, exit code 0 형식으로 쓴다. 맨 grep은 일치 0건이면 exit 1이 되어 반려된다." - "보고 대상 스크립트가 실제로 exit 1로 실패했으면 그 실패를 확인한 별도 명령(원인 조회)의 exit code 0을 검증 줄에 쓰고, 실패 사실은 결론에 쓴다." 2. 경로 규칙: "근거·근거파일 경로는 /Users/ron/... 절대경로만 쓴다. jobs.json, standard.md 같은 파일명 단독 표기 금지(workspace 아래로 풀려 path_not_found)." 3. 자동 보강 문구(scripts/orchestrator.py 1129행·1146행, 1517행) "결론: 수행한 일과 현재 상태를 완료형 한 문장으로 적는다."를 "결론: <실제로 끝낸 일 1문장, 완료형>" 형태의 값 자리로 바꿔 그대로 복사해도 값처럼 보이지 않게 한다. - 코드 변경 필요 → codex 위임 후보: scripts/agent_registry.py(AGENT_ROLE_PROMPTS 4곳 이식), scripts/orchestrator.py(_ensure_completion_evidence_block 1095행, 위 3번 문구).

2순위 — 원인 C: 구체 라벨 없는 "결과 확인 보류" (17건, 33%) - 무엇을: 반려 노트의 "차단 사유:"가 "결과 확인 보류"·"검증 근거 없음"처럼 일반 문구뿐인 경우를 구체 라벨로 바꾼다. 태스크 body에는 "반려되면 노트의 차단 사유 라벨 한 개만 고쳐 재제출"을 명시한다. - 왜: 라벨이 없으면 에이전트가 무엇을 고칠지 몰라 같은 작업을 재시도하다 같은 사유로 다시 반려된다. 17건 중 13건이 guardian, 3건 cowork, 1건 analyst-macro. - 기대효과: 라벨 없는 일반 보류 신규 0건, 재시도 후 재반려 감소. - 실례: - #41101 (guardian): 차단 사유가 "결과 확인 보류" 자기참조. 본문은 24시간 분류를 마쳤다고 주장. - #41494 (guardian): 같은 형태, 원본 요약에는 missing_execution_value·missing_original_verification·missing_source_log_path 언급이 있으나 차단 사유로 승격되지 않음. - #41715·#41782 (cowork): "결과물과 검증 근거가 없음"만 표시. - failed: #41872(guardian), #41878(analyst-macro)은 "확인 보류/확인·검증 미완료"뿐. - 바꿀 문구(태스크 body 템플릿): "반려 노트에 차단 사유: 값이 일반 문구뿐이면 4블록 4개 라벨(결론/근거/검증/근거파일)이 각각 값이 있는지 먼저 센다. 값이 없는 라벨 하나를 채워 같은 태스크를 재제출하고 새 분석 태스크를 만들지 않는다." - 코드 변경 필요 → codex 위임 후보: scripts/agent_queue_worker.py의 _completion_evidence_block_note(4195행) 호출부 — 일반 문구뿐이면 _completion_required_evidence_gaps 결과의 구체 라벨로 치환. 두 곳 구현(scripts/shared/public_result_formatter.py)과 같이 확인.

3순위 — 원인 B: missing_result_or_verification (10건, 19%) - 무엇을: analyst-macro·analyst-pm 프롬프트에 금융 분석용 4블록 예시(티커·데이터소스·조회시각·수치)와 근거파일 인용 규칙을 넣는다. - 왜: 10건 중 analyst-pm 4, analyst-macro 4가 해당하고, 10건 모두 태스크 body에 자동 보강이 붙었음에도 반려됐다. 설명형 보강 문구는 효과가 낮다. - 기대효과: analyst 계열 B 신규 0~1건/7일. - 실례: - #40408 (analyst-macro): 결론에 AAA/AA/A/BBB 격차 수치는 있으나 근거·검증이 비어 노트가 끝남. - #40518 (analyst-macro): 결론에서 OAS 83bp를 말하고 근거가 "조회 시각은 2026"에서 잘림. - #40874·#41035 (analyst-pm): 긴 판단 서술 뒤 4블록이 없거나 잘림. - 바꿀 문구: - "결론은 250자 이내, 근거는 340자 이내. 긴 판단은 400-reports 파일에 쓰고 노트에는 경로만 둔다." - "근거파일에는 { } ... …가 들어간 잘린 인용을 쓰지 않는다. 한 구절만 따옴표로 인용한다." - "근거: <티커 또는 시리즈ID> + <데이터소스 절대경로> + <조회 YYYY-MM-DD HH:MM KST> + <수치>" 형식 예시를 analyst-macro·analyst-pm 프롬프트 말미에 추가. - 방향 점검 1줄: "결론의 방향(확대/축소)은 저장 시계열의 부호와 일치하는지 한 번 더 확인한다(#41873은 +2.0bp인데 '하락/수축'이라 direction_contradicts_source로 failed)." - 코드 변경 필요 → codex 위임 후보: scripts/agent_registry.py analyst-macro·analyst-pm 블록, scripts/agent_queue_worker.py::_normalize_agent_result_minimal_basis(정규화가 길이 초과 시 스스로 ...를 붙이는지 점검).

[현황]

  • 조회 합계: needs_evidence 45, failed 7 = 52행. 에이전트별: guardian 32(needs_evidence 30, failed 2), cowork 8(6+2), analyst-macro 7(4+3), analyst-pm 4, ron 1.
  • 첫 번째 차단 라벨 기준 상호배타 분류: A 25(48%), C 17(33%), B 10(19%). 합 52.
  • llm_infra_failure 문자열이 노트에 있는 12건은 전부 guardian이 "인프라 지연 0건"이라고 쓴 분석문 인용이며 자기 반려 사유가 아니다.
  • 반려 노트는 원본 요약을 약 200자만 보존해 원본의 4블록 보유 여부는 완전히 복원되지 않는다(미확인 영역).
  • 순환: 제목에 needs_evidence/반려가 들어간 분석 태스크 자체가 반복 반려된다(#41868, #41869, #41872, #41876 모두 이 주제의 집계·방지안 태스크).
  • 이전 문서가 같은 날 이미 있었으나(failed #41876의 산출물) 이번 본으로 덮어썼다. 이번 본은 지시문대로 "원인별 실례 + 바꿀 문구" 중심이다.

[리스크]

  • 문서만 쌓이고 에이전트가 실제로 읽는 AGENT_ROLE_PROMPTS와 태스크 body에 반영되지 않으면 같은 반려가 반복된다. 단일 장애점은 codex 위임의 실행 여부다.
  • 게이트 판정이 agent_queue_worker.py와 shared/public_result_formatter.py 두 곳에 중복되어 한쪽만 고치면 불일치가 생긴다.
  • 정규화·게이트를 느슨하게 고치면 근거 없는 완료를 통과시킬 수 있다. "정상 노트가 훼손되는 경로 차단"으로 한정해야 한다.
  • 이 방지안도 반려 분석 태스크라 같은 순환에 들어갈 수 있다. 파일 저장 + 4블록 제출, 같은 주제 24시간 내 재발행 금지.
  • 라벨 분류는 result_note 문자열 파싱이라 ±1건 오차 가능.

[검증방법]

  • KPI(반영 후 72시간): 신규 반려 3건 이하, 라벨 없는 일반 보류 0건.
  • 명령: sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT claimed_by,count(*) FROM bus_commands WHERE status IN ('needs_evidence','failed') AND updated_at>='2026-10-17 12:00' GROUP BY 1" → 합계 3 이하.
  • 명령: sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT count(*) FROM bus_commands WHERE status IN ('needs_evidence','failed') AND result_note LIKE '%차단 사유: 결과 확인 보류%' AND updated_at>='2026-10-17 12:00'" → 0.
  • 명령: grep -c '! grep -rlq' /Users/ron/.hermes/workspace/scripts/agent_registry.py → 이식 후 5 이상.
  • 롤백: 이식 후 72시간 내 해당 에이전트의 반려 비율이 이식 전보다 높거나 신규 failed가 늘면 원복.