needs_evidence 76건 반복 반려 방지안 (문서 수준, 코드 수정 없음)
needs_evidence 76건 반복 반려 방지안
0. 한눈에 (결론)
- 76건 중 guardian 56건(73.7%)이다. 그런데 76건의 77.6%(59건)는 제목이 "반려·집계·방지안"인 메타 태스크다. 즉 "반려를 집계하라"는 태스크가 또 반려되고, 그 반려를 다시 집계하는 순환이다(guardian 50건, cowork 9건).
- 라벨은 3묶음이다. (1) 검증 줄 exit code·명령 문제 34건(44.7%), (2) 영문 코드가 없는 일반 보류 문구만 남은 28건(36.8%), (3) missing_result_or_verification 14건(18.4%).
- 해리 관심사: 미국 IG 크레딧 태스크 10건이 전부 (3)번 묶음이다(analyst-macro 6, analyst-pm 4). 주간 크레딧 크론 점검은 needs_evidence 1건(#41323) + failed 2건(#42717, #42718). Sell Axe가 주제인 반려는 0건이다.
1. 재집계 결과 (직접 실행)
조회 2026-10-26 08:51 KST ~ 09:0x KST, 모두 sqlite3 -readonly 또는 mode=ro.
1-1. 에이전트별 (needs_evidence 76건)
| 에이전트 | 건수 | 비율 |
|---|---|---|
| guardian | 56 | 73.7% |
| cowork | 9 | 11.8% |
| analyst-macro | 6 | 7.9% |
| analyst-pm | 4 | 5.3% |
| ron | 1 | 1.3% |
| 합계 | 76 | 100% |
| failed: 조회 시작 때 3건(#42717 guardian, #42718 guardian, #42720 ron). 작성 도중 이 태스크 자체(#42722, cowork)가 08:57에 failed로 바뀌어 마지막 조회는 4건이다. guardian #42715(07:31)가 쓴 failed 4건과 숫자는 같지만 구성은 다르다(그 4건의 ID는 미확인). |
1-2. 반려 묶음별 (건당 1묶음, 합계 76)
| 묶음 | 건수 | guardian | cowork | analyst-macro | analyst-pm | ron |
|---|---|---|---|---|---|---|
| A. exit code·검증명령 (missing/invalid_verification_exit_code, missing_verification_command, verification_command_unverifiable) | 34 | 28 | 5 | 0 | 0 | 1 |
| B. 영문 코드 없음 (결과 확인 보류 / 검증 근거 없음 / 결과물과 검증 근거가 없음 문구만) | 28 | 25 | 3 | 0 | 0 | 0 |
| C. missing_result_or_verification (completion_result_note_forces_rework 동반 포함) | 14 | 3 | 1 | 6 | 4 | 0 |
| 합계 | 76 | 56 | 9 | 6 | 4 | 1 |
라벨 출현 횟수(한 건에 여러 개): 결과 확인 보류 30, missing_verification_exit_code 21, 검증 근거 없음 17, missing_result_or_verification 14, 결과물과 검증 근거가 없음 14, invalid_verification_exit_code 10, missing_verification_command 7, completion_result_note_forces_rework 5, missing_execution_artifact 4, verification_command_unverifiable 3, execution_artifact_path_not_found 3. 요청서가 예시로 든 missing_source, missing_verification_value, missing_source_log_path는 차단 사유에 0건이다(result_note 본문에는 guardian 집계 문장이 언급할 뿐). llm_infra_failure도 차단 사유 0건이다(본문 언급 19건은 전부 "0건"이라고 적은 집계 문장).
1-3. 상위 2개 에이전트 / 상위 2개 영문 라벨
- 에이전트: guardian 56, cowork 9.
- 영문 라벨(출현 기준): missing_verification_exit_code 21(guardian 20, cowork 1), missing_result_or_verification 14(analyst-macro 6, analyst-pm 4, guardian 3, cowork 1). "결과 확인 보류"(30)는 게이트가 붙이는 공통 머리글이라 원인 라벨로 세지 않는다.
1-4. 해리 관심사 관련 (우선 표시)
| CMD | 에이전트 | 상태 | 주제 | 반려 사유 |
|---|---|---|---|---|
| 40408 | analyst-macro | needs_evidence | 미국 IG 등급별 OAS 격차 | missing_result_or_verification |
| 40518 | analyst-macro | needs_evidence | 미국 IG 회사채 OAS 추이 (주간 크레딧 입력용) | missing_result_or_verification |
| 40874 | analyst-pm | needs_evidence | 미국 HY-IG OAS 격차 | missing_result_or_verification |
| 40960 | analyst-pm | needs_evidence | IG·HY 스프레드 포지션 판단 | missing_result_or_verification |
| 41035 | analyst-pm | needs_evidence | IG·HY 스프레드 종합 판단 | missing_result_or_verification |
| 41067 | analyst-pm | needs_evidence | 미국 IG 스프레드 현황 (BAMLC0A0CM) | missing_result_or_verification |
| 41769 | analyst-macro | needs_evidence | IG·HY OAS 5영업일 변화 | missing_result_or_verification |
| 41780 | analyst-macro | needs_evidence | IG·HY OAS 최신값 | missing_result_or_verification |
| 41900 | analyst-macro | needs_evidence | IG·HY OAS 5영업일 변화 | missing_result_or_verification |
| 42671 | analyst-macro | needs_evidence | 미국 IG OAS 최신값 (10/25) | forces_rework + missing_result_or_verification |
| 41323 | guardian | needs_evidence | 주간 크레딧 일요일 크론 5c45c26045be 사전 점검 | execution_artifact_path_not_found (jobs.json 경로 오기) |
| 42717 | guardian | failed | 주간 크레딧 W44 스레드 게이트 점검 | verification_command_unverifiable + execution_artifact_path_not_found |
| 42718 | guardian | failed | 주간 크레딧 10/25 실행·W44 등록 확인 | verification_command_path_not_found + execution_artifact_path_not_found |
| Sell Axe: 제목·본문 기준 직접 반려 0건. #41628 본문에 "Sell Axe 관련 반려가 있으면 표시" 문구만 있다. | ||||
| 참고(해리 관심사 밖): 지식사랑방 인사이트 #40633, #40691, #40994 (needs_evidence), #42720 (ron, failed, missing_next_action_section). |
실물 확인: analyst 10건의 반려 로그(workspace/logs/completion_evidence_blocked.jsonl)에서 #40518, #41769, #41900, #42671의 note_preview를 열었다. 네 건 모두 "결론:/근거:" 라벨과 실제 수치(예: #41900 IG 84bp, HY 325bp, 격차 241bp)를 담고 있다. 결과가 틀려서가 아니라 게이트가 검증 줄을 못 찾아서 막힌 것이다. 미리보기가 240자에서 잘려 "검증:" 줄이 있었는지는 이 로그만으로 확인되지 않는다(미확인).
2. 기존 규정과 어긋나는 곳 (상위 2 에이전트 x 상위 2 라벨)
대조 문서: config/agent_completion_submission_standard.md(이하 표준서), config/completion_evidence_policy.md(이하 정책서), 게이트 코드 scripts/agent_queue_worker.py(읽기만 함).
2-1. guardian x missing_verification_exit_code (20건) / invalid (6건)
- 표준서 §9-3-1 guardian 예시(570~589행)는 검증 줄 예로 "→ exit 1, cron_ok=True, worker_ok=False"를 보여준다. 그런데 같은 표준서 §4(245행)와 게이트
_codex_has_verification_result_field(agent_queue_worker.py 7220~7249행: "if int(exit_match.group("code")) != 0: return False, "invalid_verification_exit_code"")는 exit code가 0이 아니면 반려한다. 예시를 그대로 따라 쓰면 반려되는 구조다. 표준서 안의 모순이다. - 오케스트레이터가 모든 태스크 본문에 붙이는 안내문(orchestrator.py
_ensure_completion_evidence_block, 1095행~)은 "검증 문장 끝에 반드시 'exit code 0' 또는 '통과'"라고 한다. 그런데 게이트의 숫자 exit code 판정(7243행missing_verification_exit_code)은 "통과"만으로는 만족되지 않는다("N passed" 화살표 형식만 예외). 안내문이 약속하는 것과 게이트 요구가 다르다. - 표준서 177행은 게이트 함수 위치를 "6593~6621행"이라고 적었으나 지금은 7220행 부근이다. 줄 번호가 낡아 에이전트가 인용하면 근거 경로 검증에 걸린다.
- 표준서 TL;DR 2번("검증 값 안의 수치/exit code가 그 줄 안에서 바로 읽히는가")은 맞다. 그러나 guardian 템플릿 §9-3-1에는 이 요건이 "exit code 0 리터럴 필수"로 명시돼 있지 않다. 필수 조항은 analyst-fundamental 전용(표준서 653행)에만 있다. guardian이 같은 게이트에 걸리는데 규정에는 적용 대상으로 쓰여 있지 않다.
2-2. guardian x 영문 코드 없는 보류 문구 (25건) / cowork (3건)
- 정책서와 표준서는 "라벨별 대응"을 전제로 하는데, 28건은 라벨 자체가 result_note에 남지 않는다. 게이트 요약(agent_queue_worker.py 4196행
_completion_evidence_block_note)이 "결론: 결과 확인 보류 / 근거: ... 차단 사유 / 원본 요약" 형태로 쓰면서 원본 요약을 앞부분만 남긴다. 그래서 어떤 줄이 빠졌는지 사후에 알 수 없다. 규정의 "라벨별 방지"가 데이터로는 검증 불가능하다. - 반려 대상 태스크 59건(77.6%)이 메타 집계다. 정책서(457행 부근 "이 문제를 고쳐서 재작성하라는 메타 태스크조차 ...")가 이미 이 위험을 적었지만 "같은 주제 집계 태스크의 재발행 제한" 규칙은 표준서 §10(재발행 시 구분 기준) 외에 없다. 실제로 guardian의 집계 태스크는 71, 73, 76건으로 숫자만 바꿔 연달아 발행됐다(#42640, #42680, #42715).
- guardian이 done으로 통과한 #42715 자체가 근거파일 줄에 경로가 비어 있다(":3 "## status=needs_evidence 합계 76건""). 같은 부류 보고가 어떤 날은 done, 어떤 날은 needs_evidence라 에이전트가 기준을 학습할 수 없다. 이 점은 표준서가 아니라 게이트 일관성 문제다(코드 항목으로 분리).
- 표준서 §10-3은 guardian이 "코드 브레이커 밖"이라고 인정한다. 즉 반복 반려가 쌓여도 자동 중단이 없다. 24건이 10-14 패치(안내문 한 줄 추가) 이후에도 늘었다는 10-24 제안서(
memory/261024_cowork_guardian_needs_evidence_prevention_proposal.md)의 지적이 그대로 유효하다.
2-3. analyst-macro/analyst-pm x missing_result_or_verification (10건, 해리 관심사)
- 표준서 §9-4 신설 조항 5(805~850행)는 macro-timeseries JSON 직접 파싱 태스크의 4블록 예시를 이미 갖고 있다. 그런데 오케스트레이터 본문은 이 조항을 가리키지 않고, 매번 "근거에는 JSON 경로 2개와 market_indicator_tracker.py를 적어라"는 새 문장을 즉흥으로 쓴다(#41900, #42671 본문 확인). 규정은 있는데 태스크 본문이 연결하지 않는다.
- 표준서 §9-4 조항 1의 "검증에 exit code 0 리터럴 필수"는 analyst-fundamental 전용이라 analyst-macro/pm은 적용 대상이 아니라고 돼 있다(653~654행). 그러나 본문 안내문은 "exit code 0 또는 통과"를 요구하고, 게이트(agent_queue_worker.py 4748행 부근
missing_result_or_verification일괄 부여)는 사유를 한 가지로 뭉뚱그린다. 어느 줄이 부족한지 에이전트가 모른다. -
42671은
completion_result_note_forces_rework가 동반됐다. 보고 원문에 "조회 ... KST" 같은 정상 문장이 있었는데도 하드블록 패턴에 걸렸을 가능성이 있다. 반려 note가 잘려 있어 어떤 패턴인지는 미확인이다.
2-4. cowork x missing_*exit_code (invalid 3, missing 1)
cowork 9건 전부가 "반려 집계·방지안" 태스크다. 표준서 §9-5·§9-6이 cowork 완료 제출 규율을 이미 정했는데, 이번 건들은 코드 변경이 없는 문서 작업이라 검증 줄에 "grep -n ... → 건수" 형태 대신 서술만 적는 경향이 반복된다. 정책서 v31절(비코딩 완료보고 규칙)이 해법이지만 태스크 본문에 연결되지 않는다.
3. 방지안 (문서 수준)
3-1. 오케스트레이터 body 템플릿 개선안
현재 자동 보강 문구(orchestrator.py _ensure_completion_evidence_block)는 4줄 설명형이라, 에이전트가 "exit code 0; 통과"를 그대로 베끼기 쉽다. 아래로 교체하도록 codex에 위임한다.
[읽기 전용 점검·집계 태스크용]
완료 검증: result_note 를 아래 4줄로 쓴다. 라벨은 줄 맨 앞, 콜론은 반각이다.
결론: <무엇을 조회/집계/작성했는지 완료형 한 문장>
근거: source_log_path: <실존 절대경로> / 조회 <YYYY-MM-DD HH:MM> KST / 반환 <N>행
검증: verification_command: <실행한 명령 전체> → exit code 0, <핵심 수치>
근거파일: <실존 절대경로>:<줄번호> "<그 줄 원문 일부 1줄>"
규칙:
1) exit code 는 명령이 실제로 반환한 숫자를 쓴다. "통과"만 쓰지 않는다.
2) 0건이 정상인 확인은 `! grep -q ... ; echo "exit code $?"` 형식으로 exit code 0을 만든다.
3) 근거에 쓴 경로는 제출 직전에 ls 또는 search_files로 열어 본 경로만 쓴다. 스크립트는 /tmp 가 아니라 workspace/scripts/ 아래에 저장해 실행한다.
4) 게이트 문구(결과 확인 보류, missing_* 라벨 이름)를 본문에 그대로 인용하지 않는다. CMD 번호로 가리킨다.
5) 코드는 수정하지 않았다면 그 사실을 결론에 한 번만 쓴다.
[분석 태스크(analyst-macro/pm)용 추가 3줄]
데이터 파일 경로: memory/macro-timeseries/<시리즈>.json (표준서 §9-4 조항 5 형식을 따른다)
검증: python3 -c "import json;d=json.load(open('<경로>'));print(d['data'][-1],d['last_updated'])" → 실제 stdout, exit code 0
근거파일: <JSON 경로>:<줄번호> "date": "YYYY-MM-DD", "value": <값>
[재발행 태스크용]
직전 시도 #<N>이 <유형>으로 반려됐다. 이번에 바꿀 한 가지: <예: 검증 줄에 exit code 0 숫자 추가>. 직전 note 의 어느 줄이 부족했는지 먼저 sqlite3 -readonly 로 읽고 시작한다.
[발행 제한 규칙 (문서)]
- 제목에 "needs_evidence", "반려", "집계", "방지안"이 들어가는 태스크는 직전 24시간 안에 같은 주제가 done이면 발행하지 않고 기존 산출물을 인용한다. 이미 있는 것: workspace/memory/needs_evidence_breakdown_20261026.md, memory/261024_cowork_guardian_needs_evidence_prevention_proposal.md.
- 숫자만 바꾼 재집계(71→73→76건)는 금지. 건수 변화가 10건 미만이면 신규 집계를 만들지 않는다.
3-2. 에이전트별 보완 지침
guardian (56건, 73.7%)
- 검증 줄에는 점검 명령과 함께 "exit code <숫자>"를 쓰되, 점검 대상이 비정상이어도 명령 자체의 exit code는 0인 형태(예: 출력 판독 명령)로 쓴다. 대상 상태가 비정상이면 결론에 쓴다. 표준서 §9-3-1의 "→ exit 1" 예시는 따르지 않는다.
- 크론·설정 경로는 이름으로 짐작하지 않는다. 정답: 크론 장부는 /Users/ron/.hermes/cron/jobs.json(workspace/jobs.json 아님, #41323 오기), 주간 크레딧 게이트는 /Users/ron/.hermes/scripts/research-sales-engine/weekly_credit_thread_gate.py(workspace/scripts/research-sales-engine/... 아님, #42717 오기), 스레드 맵은 /Users/ron/knowledge-agent/400-reports/hermes-research-sales-engine/data/week_thread_map.json. 세 경로 모두 오늘 find로 존재를 확인했다.
- 임시 스크립트(/tmp/g_check1.py 등)는 다음 실행에서 사라져 검증 명령이 재현되지 않는다(#42718 verification_command_path_not_found). 점검용 스크립트는 workspace/scripts/ 아래에 저장한다.
- 집계 태스크는 새 파일을 만들기 전에 memory/needs_evidence_breakdown_*.md 최신본을 읽고 차이만 보고한다.
cowork (9건, 11.8%)
- 문서 작성 태스크의 검증 줄은 grep -n "^결론:\|^근거:\|^검증:\|^근거파일:" <방지안 파일> 결과(4건)와 exit code 0을 쓴다(정책서 v31절 (a)).
- 근거 줄에는 대조한 규정의 파일명+줄번호+원문 인용을 쓴다. "정책을 검토했다"는 서술만으로는 부족하다.
- 코드 파일 수정이 필요한 항목은 직접 고친 것처럼 쓰지 않고 "수정 대상 파일·함수" 목록으로만 쓴다(표준서 §9-5).
analyst-macro / analyst-pm (10건, 해리 관심사)
- 결론의 수치(예: IG 84bp, 5영업일 +2bp)는 이미 맞게 쓰고 있다. 막히는 곳은 검증 줄이다. JSON을 파싱한 명령 전체와 그 stdout, 그리고 "exit code 0"을 같은 줄에 쓴다.
- 근거파일에는 JSON 경로와 "date": "...", "value": ... 원문 줄을 쓴다(표준서 §9-4 조항 5). 파이썬 표현식(d['data'][-1])을 쓰지 않는다.
- 데이터 기준일이 오늘보다 뒤처지면(#42671: 최신 관측 10-21, 조회 10-25) 결론에 그 차이를 한 줄로 쓴다.
ron (1건) / #42720 failed
- 지식사랑방 인사이트 생성은 다음 행동: 섹션이 필수(missing_next_action_section). 완료 보고 마지막에 "다음 행동: 추가 조치 없음" 한 줄이라도 쓴다.
3-3. 표준서·정책서 문서 정정 대상 (이번에는 고치지 않고 목록만)
| 문서 | 위치 | 정정 내용 |
|---|---|---|
| agent_completion_submission_standard.md | §9-3-1 (570~589행) | guardian 예시의 "exit 1" 제거, "점검 명령 exit code는 0, 대상 상태는 결론에" 로 교체 |
| 같은 문서 | 177행 | 게이트 함수 위치 "6593~6621행" → 현재 7220행 부근으로 갱신 |
| 같은 문서 | §9-3-1 | guardian도 검증 줄 "exit code 0 리터럴 필수"임을 명시(현재는 fundamental 전용 653행에만) |
| 같은 문서 | §9-4 조항 5 | 오케스트레이터 본문에서 이 조항을 인용하도록 연결 문구 추가 |
| completion_evidence_policy.md | 신규 절 | 메타 집계 태스크 재발행 제한(24시간, 변화 10건 미만 금지) |
4. 코드 변경이 필요한 항목 (직접 고치지 않음, codex 위임 대상)
scripts/orchestrator.py_ensure_completion_evidence_block(1095행~): 대체 문구에서 "또는 '통과'" 제거, 3-1 템플릿으로 교체, 에이전트별(analyst/guardian/cowork) 분기.scripts/orchestrator.pycreate_task(2310행): 제목 키워드(needs_evidence/반려/집계/방지안) 태스크의 24시간 내 중복 발행 차단.scripts/agent_queue_worker.py_completion_evidence_block_note(4196행): result_note에 차단 사유 코드와 원문 SHA·로그 경로를 보존(28건이 라벨 없이 남는 문제).scripts/agent_queue_worker.py_handle_guardian(8085행): 반환 직전에 4라벨과 숫자 exit code를 검사해 빠지면 blocked로 돌림(10-24 제안서 1순위와 동일).scripts/agent_queue_worker.py4748행 부근missing_result_or_verification일괄 부여: 검증 줄 없음/결과 줄 없음을 구분하는 세부 사유로 분리.scripts/agent_queue_worker.py_completion_result_note_forces_rework(486행): #42671에서 어떤 패턴이 걸렸는지 로그에 패턴 이름 기록.scripts/agent_queue_worker.py_log_completion_evidence_block: note_preview 240자 제한을 늘리거나 원문 전체를 jsonl에 보관(현재는 검증 줄 유무를 사후 확인 불가).
5. 리스크
- 단일 원인이 아니다. 문서만 고치면 A묶음(34건)은 줄어들 가능성이 높지만, B묶음(28건)은 원인이 데이터로 남지 않아 효과를 측정할 수 없다. 코드 항목 3·7이 먼저여야 한다.
- 10-14 안내문 패치 이후에도 guardian 반려가 줄지 않았다는 10-24 제안서의 수치(일평균 1.75건→2.4건)가 있다. 문구 보강은 모델이 무시하면 효과가 없다. 템플릿 교체만으로 해결된다고 보지 않는다.
- 메타 집계 순환은 자기 증식한다. 이 방지안 태스크(#42722)와 guardian 집계(#42715)도 같은 부류다. 발행 제한이 없으면 이 문서 이후에도 "77건 집계"가 발행될 수 있다.
- 이 태스크(#42722) 자신이 작성 도중 failed로 바뀐 경위(08:57)는 미확인이다. 이 문서가 완료 보고로 다시 제출돼 게이트를 통과하는지가 이 방지안의 첫 실측이 된다.
6. 검증방법
- 지표: guardian의 최근 7일 needs_evidence 신규 건수. 현재 기준선은 10-14~10-23 사이 24건(10-24 제안서 실측, 일 2.4건)이다. 목표는 7일 합계 5건 이하(일 1건 미만).
- 명령:
sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT claimed_by,COUNT(*) FROM bus_commands WHERE status='needs_evidence' AND created_at>=datetime('now','-7 days','localtime') GROUP BY 1" - 해리 관심사 지표: analyst-macro/pm의 IG OAS 태스크 needs_evidence 신규 0건, 주간 크레딧 점검(5c45c26045be) 태스크의 execution_artifact_path_not_found 0건.
- 기대값: B묶음(코드 없는 보류) 신규는 코드 항목 3 반영 후 0건(모든 반려에 코드 표기).
- 롤백/재검토 조건: 템플릿 교체 후 7일 내 A묶음이 줄지 않으면 문서 접근은 실패로 보고 코드 항목 4(
_handle_guardian사후 보강)를 우선 진행한다.