virtual-insanity
← 리포트 목록

needs_evidence 반복 반려 상위 3개 원인별 방지안 (guardian #42016 분류 대조 + 미국 IG·HY OAS 직접 파싱 지시문 초안)

2026-10-18 claude [needs_evidence, completion-gate, guardian, cowork, analyst-macro, us-ig-oas, credit, prevention]

needs_evidence 반복 반려 상위 3개 원인별 방지안

조회: 2026-10-18 18:37~18:45 KST, sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db (읽기 전용). 코드·DB·크론·설정 수정 없음. 같은 날 앞서 만든 261018_claude_needs_evidence_prevention.md(언더스코어 표기, 18:23)와 별개 문서다. 이 문서는 (a) guardian #42016 result_note 전문 대조, (b) 원인을 body/에이전트 제출/인프라로 구분, (c) 미국 IG·HY OAS 직접 파싱 지시문 초안을 추가했다.

1. [권고]

→ 1순위 (크레딧 우선): 미국 IG·HY OAS 태스크는 #40913, #41923, #42021을 같은 지시문으로 다시 발행하지 않는다. 6절의 초안(실행 전에 파일 경로와 줄 번호를 먼저 확정하는 지시문)으로 1회만 새로 발행한다. 이유: 9건(analyst-macro 5, analyst-pm 4)이 needs_evidence로 남았고 analyst-macro 3건(#42017, #42019, #42021)은 failed까지 갔다. 수치 자체(IG 0.84, HY 3.25)는 파일에서 바로 나오는데 근거 표기만 막힌다. 기대효과: 이 유형 신규 반려 0건, 해리의 크레딧 입력 확보. → 2순위: 반려 집계·방지안 같은 메타 태스크의 재발행을 끊는다(원인 2). 현재 38건(74.5%)이 메타 태스크다. 최신 집계 문서 1개를 정본으로 두고 건수만 갱신하게 하면 신규 needs_evidence가 일 3~8건 줄어들 것으로 추정한다(추정치이며, 실측 기준은 9절 검증 쿼리). → 3순위: 검증 줄 exit code 표기(원인 1, 20건)는 오케스트레이터 body 문구의 "'exit code 0' 또는 '통과'" 허용부터 정리한다(코드 변경이라 codex 위임, 8절).

2. [현황] guardian 분류 vs 직접 집계

guardian #42016(완료 2026-10-18 17:01) result_note는 sqlite3 -readonly ... > /tmp/g42016.txt로 읽었다. 크기 717자, 3줄. 게이트가 저장 시 줄인 형태라 본문에 표가 없고 "51행을 얻었다"까지만 남아 있다. 표 원문은 guardian이 만든 memory/needs_evidence_51_breakdown_20261018.md에 있고, 이를 기준으로 대조했다.

직접 집계(SELECT id,claimed_by,title,result_note FROM bus_commands WHERE status='needs_evidence' → 51행, result_note의 "차단 사유:" 구간 라벨 기준, 한 건 1라벨):

차단 사유 직접 집계 guardian 문서 에이전트 분포(직접 집계)
exit code 누락/형식오류 (missing 12 + invalid 8) 20 20 guardian 17, cowork 2, ron 1
라벨 없는 일반 "결과 확인 보류/검증 근거 없음" 18 18 guardian 15, cowork 3
missing_result_or_verification 11 11 analyst-macro 5, analyst-pm 4, guardian 1, cowork 1
verification_command_unverifiable 1 1 cowork 1
execution_artifact_path_not_found 1 1 guardian 1
합계 51 51 guardian 34, cowork 7, analyst-macro 5, analyst-pm 4, ron 1

대조 결과: 사유별 건수 6개 칸이 모두 일치한다. 에이전트별 합계도 일치한다(guardian 34, cowork 7, analyst-macro 5, analyst-pm 4, ron 1). 차이가 나는 곳 한 군데: 제목 유형 중 "반려 분류·집계·방지안 메타"가 guardian 문서 36건(guardian 29 + cowork 7), 직접 집계 38건(guardian 31 + cowork 7)이다. 제목 키워드 정규식(needs_evidence|반려|방지안|분류|집계)이 guardian의 수작업 분류보다 guardian 2건을 더 넓게 잡은 차이다. 어느 쪽이든 70% 이상이 메타 태스크라는 결론은 같다. 참고: 같은 SQL의 failed는 5건(#42015, #42017, #42019, #42021, #42022). guardian 문서의 "failed 5건"은 #42009~42012 계열이라 현재 DB의 failed 5건과 다르다(guardian 조회 이후 id가 바뀜). 이 문서는 현재 DB 기준을 쓴다.

미국 IG·HY OAS 제목 9건(title LIKE '%OAS%' → 9행)은 모두 analyst-macro 또는 analyst-pm이다. 이 중 needs_evidence는 6건, 나머지 3건(#42017, #42019, #42021)은 failed다. 요청서에 적힌 #40913, #41923은 현재 DB에서 select ... where id in (40913,41923) → 0행이다(삭제 또는 보존 기간 밖). #42021 body만 남아 있고, 그 본문이 "#42019, #41923 재시도에서 반려된 문제를 고치려고 파일 기반으로 다시 쓴 것"이라고 밝히고 있다.

3. 상위 3개 원인과 소속 판정

판정 기준 세 갈래: 지시문(body) 문제 / 수신 에이전트의 완료 제출 문제 / 인프라 지연. 인프라는 llm_infra_failure 라벨로 판별하는데, needs_evidence 51건의 "차단 사유:" 구간에는 이 라벨이 0건이다(result_note 안에 "llm_infra"가 나오는 14건은 전부 guardian 집계 보고가 "0건"이라고 쓴 문장이다). 따라서 3개 모두 인프라 지연이 아니다.

원인 1. 검증 줄 exit code 누락/형식오류 — 20건 (39%)

  • 구분: 에이전트 제출 문제가 주, body 문구가 보조 원인.
  • 근거(제출): 게이트는 검증 줄에 숫자 0 exit code를 요구한다. config/agent_completion_submission_standard.md 4절 표에 invalid_verification_exit_code는 "검증 명령의 exit code가 0이 아님"이라고 정의돼 있다. 맨 grep이 일치 0건에서 exit 1을 내 반려된 사례(ron #40193/#40199)가 이미 같은 표에 있다. 이번 8건(invalid)도 같은 유형이다.
  • 근거(body): scripts/orchestrator.py 1104, 1131, 1137, 1795행이 "검증 문장 끝에 반드시 'exit code 0' 또는 '통과'를 적는다"로 가르친다. completion_required_evidence_gaps(scripts/shared/public_result_formatter.py 3134행~)의 macro-timeseries 예외 정규식 _MACRO_TIMESERIES_VERIFICATION_VALUE_RE(2503행)는 exit code 0 또는 통과를 받는다. 반면 missing_verification_exit_code 게이트(agent_queue_worker.py 4172행의 재시도 안내 검증 결과의 exit code, public_result_formatter.py 3295행 패치 주석)는 검증 결과의 exit code 숫자를 따로 요구한다. 게이트별로 "통과"를 인정하는 범위가 달라서, body가 "또는 통과"를 허용하는 것이 12건 누락의 원인이라고 추정한다(게이트별 판정 분기까지는 이번에 코드를 끝까지 추적하지 않았다 — 확정은 codex 점검 항목).

원인 2. 라벨 없는 일반 "결과 확인 보류/검증 근거 없음" — 18건 (35%)

  • 구분: 에이전트 제출 문제 + 지시문 문제(순환 발행).
  • 근거: 18건 전부 "반려 사유를 집계하라"는 메타 태스크(guardian 15, cowork 3)다. 저장 note는 게이트가 교체한 문구("결과물과 검증 근거가 없음. 차단 사유: 검증 근거 없음, 결과 확인 보류")인데, 그 원본 요약에 집계 결과를 쓰다 "검증 근거 없음" 같은 차단 구절을 그대로 인용한 흔적이 있다. is_empty_evidence_placeholder_text(public_result_formatter.py 2663행)가 "확인 보류" 단독 문장을 빈 근거로 보고, agent_queue_worker.py _completion_hard_block_phrase_reasons(466행)의 하드블록 구절 검사가 결론·근거에 인용된 차단 구절까지 잡는다. 제목에 건수만 바꾼 집계 태스크(예: #41992 50건, #42016 51건)가 계속 새로 발행돼 자기 반려를 다시 집계하는 순환이 생긴다.

원인 3. missing_result_or_verification (미국 IG·HY OAS 판독) — 11건 (22%)

  • 구분: 에이전트 제출 문제(근거 경로 표기)와 지시문 문제가 함께 있음. 인프라 지연 아님.
  • 근거: analyst-macro 5, analyst-pm 4, guardian 1, cowork 1. #42021의 result_note는 source_log_path_not_found:BAMLC0A0CM.json:707-708 "date": "2026-10-14", "value": 0.84 / BAMLH0A0HYM2.json: 이다. 줄 번호와 값 자체는 맞다(실제 파일 707~708행이 같은 값, 6절에서 직접 확인). 막힌 이유는 파일명만 적고 실존 전체 경로를 적지 않은 것이다. #42019는 verification_command_unverifiable(재현 가능한 명령 없음), #42017은 "확인 못함" 하드블록 구절이다. 즉 이 유형은 분석 부재가 아니라 근거 표기 3가지(경로, 검증 명령, 금지 구절)에서 번갈아 막힌다.
  • body 문제: #42021 body는 4블록 라벨을 안내하고 "검증값 문장 끝에 'exit code 0' 또는 '통과'"를 적으라고 한다. 계산 결과 수치를 어디에 어떻게 적으라는 예시 줄이 없고, 근거 경로를 memory/macro-timeseries/<파일>.json:<줄> 형식으로 쓰라는 지정도 없다. 수집기 이름으로 market_indicator_tracker.py를 적게 했는데, 해당 JSON을 쓰는 스크립트는 scripts/pipeline/macro_series_collector.py다(그 파일 3행 docstring: "46개 FRED 시리즈를 수집해 memory/macro-timeseries/{SERIES_ID}.json 으로 저장"). 게이트의 macro-timeseries 예외(_completion_has_macro_timeseries_collector_evidence, 2649행)는 JSON 경로, scripts/pipeline/*.py 경로, exit code 0|통과 세 가지가 모두 있고 실존할 때만 통과시킨다.

4. 원인별 방지안 (문서·운영 규칙, 코드 변경 없음)

방지안 1 — exit code (원인 1)

  1. 에이전트 완료보고 규칙: 검증 줄 형식을 검증: <명령> → <결과 수치>, exit code 0으로 고정한다. 숫자 0을 반드시 쓴다. "통과"는 덧붙이는 말이지 대체가 아니다.
  2. 부재·불일치를 확인하는 검증은 맨 grep 대신 config/agent_completion_submission_standard.md 4절에 있는 부정형(! grep -rlq ...; echo "exit code $?")을 쓴다(일치 0건일 때 grep이 exit 1을 내 반려되는 문제 회피).
  3. guardian·cowork에 읽기 전용 점검이 많으니, 점검 명령 마지막에 python3 -c "print('exit code 0')"처럼 값을 가장하지 않는다. 실제 명령의 $?를 쓴다(위조 검증은 R29 계열 게이트가 별도로 막는다).

방지안 2 — 메타 집계 순환 (원인 2)

  1. 정본 1개 지정: memory/needs_evidence_51_breakdown_20261018.md(guardian)와 이 문서를 정본으로 한다. 이후 집계 요청은 "정본의 건수만 갱신" 한 줄 과제로 한다.
  2. 결론·검증 줄에 "결과 확인 보류", "검증 근거 없음" 같은 게이트 차단 구절을 인용하지 않는다. 표나 별도 파일 안에서만 쓰고, 결론에는 "51건을 5개 사유로 분류했다"처럼 풀어 쓴다.
  3. 같은 주제 집계 과제가 24시간 안에 이미 있으면 새로 발행하지 않는다(오케스트레이터 규칙, 구현은 8절 codex 항목).

방지안 3 — 미국 IG·HY OAS (원인 3)

  1. 근거 경로는 항상 /Users/ron/.hermes/workspace/memory/macro-timeseries/BAMLC0A0CM.json:707-708 형식의 전체 경로 + 줄 번호 + 원문 1줄로 쓴다. 파일명만 쓰면 source_log_path_not_found가 난다.
  2. 검증은 하나의 python3 명령이 수치를 출력하고 끝에 exit code 0을 붙이게 한다(6절 명령).
  3. 수집기는 scripts/pipeline/macro_series_collector.py로 쓴다(JSON을 실제로 만드는 스크립트).
  4. 결과물은 ~/knowledge-agent/400-reports/에 YYMMDD_hermes_us-ig-hy-oas.md 1개로 저장하게 하고, 그 경로를 근거파일에 쓴다(실존해야 게이트의 저장 위치 요건을 채운다).
  5. 3회 재시도 후에도 failed면 같은 지시문 재발행 금지. 오케스트레이터가 body 문구를 바꾸지 않고 재발행하는 경우를 막는 장치는 8절에서 codex에 맡긴다.

5. 인프라 지연 여부

  • needs_evidence 51건 중 llm_infra_failure 차단 사유: 0건.
  • failed 5건 중 인프라 의심은 #42015(guardian, 일요일 09시 주간 크레딧 요약 크론 점검) 한 건뿐이고, 같은 note에 verification_command_unverifiable도 있어 단독 원인으로 단정하지 않는다.

6. 미국 IG·HY OAS 지시문 초안 (새로 1회 발행용, 파일 직접 파싱)

실측(조회 2026-10-18 18:40 KST, 두 JSON 모두 last_updated 2026-10-16, 마지막 관측일 2026-10-14, 175개 관측): - IG(BAMLC0A0CM): 0.84 (2026-10-14), 5영업일 전(10-07) 0.82 → +2bp, 20영업일 전(09-16) 0.78 → +6bp, 구간 최저 0.73·최고 0.94, 구간 내 백분위 85%. - HY(BAMLH0A0HYM2): 3.25 (2026-10-14), 5영업일 전 3.09 → +16bp, 20영업일 전 2.70 → +55bp, 구간 최저 2.60·최고 3.46, 구간 내 백분위 97%. - 해석 초안: HY가 구간 상단(97%)으로 밀리는 동안 IG는 +2bp로 거의 제자리다. 격차(HY-IG)는 5영업일 사이 2.27에서 2.41로 벌어졌다(+14bp). 신용 악화가 저등급에 몰려 있다는 뜻이다. IG 쪽 크레딧 포지션 판단은 방향이 아니라 HY 확산 여부를 보는 쪽이 맞다. (이 수치는 지시문의 예시이며, 에이전트가 실행 시 다시 계산해 쓰게 한다.)

지시문 초안:

대상: /Users/ron/.hermes/workspace/memory/macro-timeseries/BAMLC0A0CM.json(미국 IG OAS)과 같은 폴더의 BAMLH0A0HYM2.json(미국 HY OAS). 두 파일은 scripts/pipeline/macro_series_collector.py가 저장한 것이다. 외부 원천을 호출하지 말고 이 파일만 직접 파싱한다. 이전 지시문(#40913, #41923, #42021)과 달리 근거 표기 형식을 아래에 고정했다.
실행:
(1) 아래 명령을 그대로 1회 실행해 출력을 얻는다.
python3 -c "import json;[print(s,d[-1],d[-6],d[-21],round((d[-1]['value']-d[-6]['value'])*100),round((d[-1]['value']-d[-21]['value'])*100)) for s in ['BAMLC0A0CM','BAMLH0A0HYM2'] for d in [json.load(open('/Users/ron/.hermes/workspace/memory/macro-timeseries/'+s+'.json'))['data']]]"
(2) 출력으로 최신 관측일·값, 5영업일(bp)·20영업일(bp) 변화, IG-HY 격차를 정리하고 '그래서 무엇이 달라졌는지'를 2~3문장으로 쓴다.
(3) 결과를 ~/knowledge-agent/400-reports/YYMMDD_hermes_us-ig-hy-oas.md 에 저장한다.
완료 검증: result_note를 아래 4줄로 쓴다.
결론: 미국 IG·HY OAS를 파일에서 직접 읽어 최신값·변화폭·격차를 계산하고 판단을 저장했다. (완료형)
근거: 읽은 파일 /Users/ron/.hermes/workspace/memory/macro-timeseries/BAMLC0A0CM.json 과 BAMLH0A0HYM2.json의 전체 경로, 수집기 scripts/pipeline/macro_series_collector.py, 조회 시각 YYYY-MM-DD HH:MM KST.
검증: 위 (1) 명령과 출력 수치(IG 최신값, HY 최신값, 5영업일 변화 bp) → exit code 0
근거파일: /Users/ron/.hermes/workspace/memory/macro-timeseries/BAMLC0A0CM.json:707-708 "date": "2026-10-14", "value": 0.84 (HY 파일은 별도 줄: BAMLH0A0HYM2.json의 마지막 관측 줄), 저장한 보고서 경로:줄번호 "원문 1줄".
금지: 파일명만 적기, '확인 못함', '결과 확인 보류', '검증 근거 없음' 문구 사용.

게이트 통과 근거: 이 초안은 _MACRO_TIMESERIES_RESULT_JSON_RE(2497행 memory/macro-timeseries/....json), _PIPELINE_COLLECTOR_RESULT_PATH_RE(2500행 scripts/pipeline/....py), _MACRO_TIMESERIES_VERIFICATION_VALUE_RE(2503행 exit code 0|통과) 세 정규식과 일치하도록 썼다. 세 경로가 실존하면 completion_required_evidence_gaps가 3192행에서 return []로 통과시킨다.

7. [리스크]

  • 게이트가 agent_queue_worker.py, public_result_formatter.py, server.py 세 곳에 있어 한 곳만 고치면 판정이 갈린다. server.py는 재시작에 해리 승인이 필요하다.
  • 저장된 result_note가 게이트 교체 문구라 원본 제출의 다른 결함은 일부 미확인이다(guardian 문서도 같은 한계를 적음).
  • 지시문 초안의 5영업일·20영업일 인덱스(d[-6], d[-21])는 휴일이 낀 주에 달력일과 어긋날 수 있다. 영업일 기준이라는 점을 보고서에 적게 했다.
  • 데이터가 10-14일까지다. 10-15일 이후 값은 파일에 없으므로 "최신"이라고 쓸 때 관측일을 반드시 같이 적게 해야 한다.

8. codex 위임 항목 (이 작업에서는 수정하지 않음)

  1. scripts/orchestrator.py 1104, 1131, 1137, 1795행 상용구 — "'exit code 0' 또는 '통과'"를 "exit code 0 (숫자 필수)"로 교체. 같이 볼 곳: scripts/shared/agent_task_quality.py의 허용 토큰, 테스트 scripts/tests/test_orchestrator_task_quality.py.
  2. scripts/orchestrator.py create_task()(2310행) — 제목에 needs_evidence/반려/집계가 있는 태스크가 24시간 안에 이미 있으면 신규 발행 대신 정본 문서 경로 안내로 대체. 동일 지표(OAS)로 3회 이상 failed·needs_evidence가 났으면 body가 달라지지 않은 재발행은 차단.
  3. scripts/agent_queue_worker.py 하드블록 구절 검사와 scripts/shared/public_result_formatter.py 사본 — 표·백틱·인용 안의 차단 구절은 제외하고 결론·검증 줄에서 직접 쓴 경우만 차단(반대 테스트로 진짜 빈 보고는 계속 차단).
  4. source_log_path_not_found 판정(agent_queue_worker.py 1275행, public_result_formatter.py 3850행) — 파일명만 인용했고 memory/macro-timeseries/ 안에 유일하게 일치하는 파일이 있으면 반려 메시지에 후보 전체 경로를 같이 안내.

9. [검증방법]

  • 신규 반려 추이: sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT claimed_by,count(*) FROM bus_commands WHERE status='needs_evidence' AND updated_at>='2026-10-19' GROUP BY 1" → 기대 0~2행.
  • OAS 새 태스크: 완료 시 SELECT status FROM bus_commands WHERE title LIKE '%OAS%' ORDER BY id DESC LIMIT 1 → 기대 done. 두 번째에도 needs_evidence면 body 재발행을 멈추고 사람이 원인을 본다(롤백 조건).
  • exit code 계열: 적용 후 ... AND result_note LIKE '%exit_code%' → 기대 0건.