needs_evidence 59건 반려사유 분류 기반 재발 방지안 (기존 규정 대조 후 공백만)
needs_evidence 59건 재발 방지안
작성: Cowork(다듬) / 조회 2026-10-21 05:34~05:50 KST / 코드·DB·크론 수정 없음(제안서)
0. 먼저 알아야 할 사실 (이전 제안서와 달라진 점)
- guardian #42233(2026-10-21 04:25 done)의 result_note는 DB에 747자만 저장돼 있고, 결론 줄이
DB는 ...에서, 근거 줄이select ... from ...에서 잘려 있다. 분류표 본문은 DB에 없다(미확인). 그래서 이 문서는 59건을 직접 다시 집계했다. - 직접 집계 합계는 59행이고 guardian 41 / cowork 8 / analyst-macro 5 / analyst-pm 4 / ron 1 = 59로 #42233의 에이전트별 수와 일치한다.
- 2026-10-19에 이미
orchestrator.py에 재발행 루프 차단 게이트가 들어갔다(_is_needs_evidence_reissue_loop_tripped, 4330행, 호출 2549행, 파일 수정 10-19 21:01). 그런데 이 게이트가 막지 못한 증거가 있다(아래 [현황] 3번).
[권고]
→ 1순위 (codex 후보, 코드 변경): 재발행 루프 게이트의 "같은 제목 계열" 판정을 느슨하게 만든다. 이유: 게이트는 숫자·괄호·접두어를 지운 앞 60자가 같아야 한 계열로 센다(_reissue_family_key, 4300행대). 그런데 반려집계 태스크 44건은 제목 문구가 거의 매번 달라 계열 42개로 갈라진다(같은 계열 2건인 묶음이 2개뿐). 게이트 적용 이후(10-19 21:01~) 발행된 반려집계 태스크 6건(#42165·#42167·#42171·#42219·#42231·#42233)이 하나도 안 걸렸다. 기대효과: 같은 에이전트(guardian)가 "needs_evidence + 분류/집계" 키워드를 가진 태스크를 72시간 안에 3건 넘게 받지 못하게 해, 이후 신규 반려 유입을 최근 3주 기준 월 약 44건 → 약 9건 이하(첫 3건만 통과, 80% 감소)로 줄인다.
→ 2순위 (codex 후보, 코드 변경): 분석형 완료보고(analyst-macro/pm) 반려 9건의 오탐 여부를 실제 원문으로 확정한다. 이유: 이 9건 전부 missing_result_or_verification 한 가지로 반려됐는데, 해당 판정(_completion_report_has_result_and_verification, agent_queue_worker.py 2193행·421행)은 본문에 "결과물/산출물/파일/artifact/output" 단어와 "검증/통과/passed" 단어가 둘 다 있어야 통과시키는 단어 검색이다. #41769·#41780·#41900의 원문 앞부분(logs/completion_evidence_blocked.jsonl 19467·19472·19538행)에는 결론·근거 라벨이 있지만 240자에서 잘려 뒷부분은 확인하지 못했다(미확인). 기대효과: 분석 태스크 지시문과 본문 템플릿에 단어 한 줄을 넣어 해결되는지, 게이트 정규식을 고쳐야 하는지 가르면 analyst 반려 월 9건 → 0건 목표.
→ 3순위 (운영 규칙, 코드 변경 없음): 이미 규정된 내용은 재작성하지 않는다. 남은 공백은 아래 [규정 대조] 표의 "공백" 3줄뿐이다.
[현황]
1. 반려사유별 집계 (59건, 건당 대표 사유 1개로 배정, 우선순위: 구체 경로·코드 > 껍데기 문구)
| 순위 | 반려 사유 | 건수 | 비율 | 에이전트 | 대표 CMD |
|---|---|---|---|---|---|
| 1 | missing_result_or_verification | 12 | 20.3% | analyst-macro 5, analyst-pm 4, guardian 2, cowork 1 | 40408, 40518, 40874 |
| 2 | 결과 확인 보류 단독(껍데기) | 11 | 18.6% | guardian 8, cowork 3 | 40825, 41101, 41151 |
| 2 | 검증 근거 없음/결과물과 검증 근거가 없음(껍데기) | 11 | 18.6% | guardian 11 | 41233, 41316, 41387 |
| 4 | missing_verification_exit_code | 10 | 16.9% | guardian 10 | 40276, 40346, 40633 |
| 5 | invalid_verification_exit_code | 8 | 13.6% | guardian 5, cowork 2, ron 1 | 40297, 40869, 41295 |
| 6 | missing_execution_artifact | 3 | 5.1% | guardian 2, cowork 1 | 40842, 41431, 42083 |
| 7 | verification_command_unverifiable | 2 | 3.4% | cowork 1, guardian 1 | 40691, 42111 |
| 7 | execution_artifact_path_not_found | 2 | 3.4% | guardian 2 | 41323, 42062 |
| 합계 | 59 | 100% |
집계 방법: result_note의 차단 사유: 필드를 파싱(/tmp/ne_agg.py, /tmp/prim.py). 두 껍데기 문구형(22건, 37.3%)은 차단 사유:에 구체 코드가 없어 원인을 이 필드로는 알 수 없다. 원인은 jsonl 행의 reasons(예: 42171은 ["검증 근거 없음","결과 확인 보류"])로만 추정된다.
2. 상위 3개 원인과 해당 에이전트 (확정)
- 반려집계 메타태스크의 자기증식 — 확정. guardian 36건 + cowork 8건 = 44건(74.6%)이 제목에 "needs_evidence"나 "반려"가 들어간 분류·집계·방지안 태스크다. 즉 반려를 분류하는 태스크가 또 반려돼 반려 건수를 늘리고, 그 숫자(54→55→…→59건)로 다음 분류 태스크가 발행된다. 직전 연속 체인: #42219(58건) → #42231(failed) → #42233(done) → #42235(이 태스크). 담당: guardian(주), cowork.
- 검증 줄의 exit code 누락·형식 오류 — 확정. missing_verification_exit_code 10건 + invalid_verification_exit_code 8건 = 18건(30.5%). guardian 15, cowork 2, ron 1. 이 규칙은 이미 문서화돼 있다(아래 규정 대조). 지금 남은 원인은 "규정 없음"이 아니라 "제출 규율"이다. 증거: 59건 중 result_note에
exit code 0/통과가 있는 건은 1건뿐이고, 그것도 반려 사유 설명 속에서가 아니라 원본 요약 중 인용이다. - 분석형 완료보고의 missing_result_or_verification — 건수 확정(9건, analyst-macro 5 + analyst-pm 4), 원인은 가설. 9건이 전부 BAMLC0A0CM/BAMLH0A0HYM2 JSON 기반 IG/HY OAS 분석이고 요일·모델 무관하게 같은 사유다(9월 29일~10월 17일). 단어 검색형 판정과의 불일치 가능성이 높으나 원문 전체를 확인하지 못해 확정하지 않는다.
3. 이미 배포된 차단 게이트가 효과가 없었다는 증거
- 반려 집계 태스크 중
created_at >= 2026-10-19 21:01(orchestrator.py 수정 시각) 이후 발행된 것: 7건(#42165, #42167, #42171, #42219, #42231, #42233, #42235). 이 중 guardian 6건이 연속 발행됐고 게이트가 막은 흔적이 없다. logs/ron_orchestrator.log·orchestrator_rescue.log에서NEEDS_EVIDENCE_REISSUE_LOOP_BLOCKED검색 결과 0건. 유일한 매치는logs/agent-queue-codex.log의 codex 작업 보고(CMD#42125) 문장뿐이다.- 실행 중인 오케스트레이터 프로세스(PID 46446)는 2026-09-27 07:55에 시작했다(경과 23일). 게이트 코드가 들어간 파일 수정(10-19 21:01)은 프로세스 시작보다 늦다. 이 프로세스가 새 코드를 다시 읽었는지는 확인하지 못했다(
importlib.reload/os.execv검색 결과 0건). 즉 "코드는 있으나 실제 실행 프로세스에 반영되지 않았을 가능성"이 열려 있다. 이 가능성은 해리 승인 후 codex가 확인해야 한다(재시작은 승인 필요). - 관련: #42125·#42127(failed), #42130(cancelled)이 이전 게이트 구현 시도였고 현재 DB에서 해당 id는 조회되지 않는다(
select count(*) ... id in (42125,42127,42130)→ 0). 이전 기록과 현재 DB가 일치하지 않는다.
4. 기타 확인 사실
- body에
[자동 보강: 완료보고 4블록 설명형 라벨 보충]이 붙어 있는 건: 59건 중 55건. 보강 문구(orchestrator.py1129행 "결론: 수행한 일과 현재 상태를 완료형 한 문장으로 적는다.")는 라벨 설명문이고 예시값이 아니다. result_note에 이 설명문이 그대로 복사된 건은 1건(#40276)이다. - result_note가
...로 절단된 건: 6건. 길이 360~486자로 저장돼 있어 원문 전체를 DB에서 복원할 수 없다. - 59건 중 최근 24시간(2026-10-20 05:34 이후) 신규 4건(#42165, #42167, #42171, #42219, 전부 guardian 집계류 — 조회
created_at>='2026-10-20 05:34'반환 4행), 나머지 55건은 9월 28일~10월 19일에 쌓였다(가장 오래된 #40276, 가장 최근 #42219).
[규정 대조] 이미 규정된 것 vs 비어 있는 것
| 항목 | 이미 규정된 위치 | 판정 |
|---|---|---|
| 완료보고 4블록(결론/근거/검증/근거파일) 라벨과 순서 | config/agent_completion_submission_standard.md §3, AGENTS.md "대행 태스크 완료보고 검증 근거 정책" | 규정됨 |
| guardian 점검용 4블록 예시 | standard.md §9-3-1(570행) | 규정됨 |
| analyst-* 4블록 예시, macro-timeseries JSON 직접 파싱 | standard.md §9-3-2(590행), §9-4 신설 조항 3·5(685행·805행) | 규정됨 |
| exit code 0 리터럴 요건 | standard.md §9-4 신설 조항 1(653행). completion_evidence_policy.md v13(약 1796행)에 "있어도 0이 아니면 invalid_verification_exit_code" | 규정됨 (단 적용 에이전트가 codex·analyst-fundamental로 한정돼 있다고 문서가 명시한 줄이 있음, 현재 guardian·cowork 반려가 18건) |
| 재발행 시 인프라실패 vs 근거미비 구분 | standard.md §10(1038행) | 규정됨 |
| 반려집계 메타태스크 자기증식 차단 정책 | 261019_claude_needs_evidence_reissue_loop_policy.md(400-reports) |
설계안 있음, 코드 반영됨(10-19), 실효성 미확인 |
| 이미 반영된 수정 사전확인, 상시 실행 코드 반영 확인 | policy.md v33(4291행)·v35(4509행)·v36(4601행) | 규정됨 |
공백 A: 지시문이 요구해도 guardian/cowork 보고가 따르지 않는 문제 (재확인: guardian·cowork 반려 49건 중 body가 exit code/통과를 요구한 건 39건(79.6%), ls -l/실존 확인을 요구한 건 28건(57.1%) — 템플릿 요구는 이미 있음) |
템플릿 부재가 아니라 준수 실패. 부족한 것은 "제출 직전 자가 점검을 강제하는 장치" | 비어 있음(성격 정정) |
| 공백 B: 같은 목적의 반려 분류가 이미 최근 7일 안에 400-reports에 있으면 신규 분류 태스크 대신 기존 파일 갱신으로 처리한다는 규칙 | 미발견. 400-reports에 needs_evidence 포함 파일 23개 존재(10-01~10-20) |
비어 있음 |
| 공백 C: guardian의 반려 분류 보고 DB 저장 길이(747자 절단)로 인해 분류표 본문이 DB에서 사라지는 문제의 보존 위치 규정 | 미발견. guardian #42233은 분류표 파일 경로를 result_note에 남기지 않았거나 절단돼 확인 불가 | 비어 있음 |
[권고 상세 — 공백 A·B·C만]
공백 A (정정: 템플릿 추가가 아니라 준수 장치): 지시문에는 이미 exit code·ls -l 요구가 들어 있었다(위 39건/28건). 그래도 반려된 이유는 보고가 길어져 result_note 저장 길이(실측 최대 486자, 6건은 ...로 절단)에 걸리거나 검증 줄이 빠지기 때문이다. 같은 요구를 한 줄 더 붙여도 효과가 없다. 대신 ① 분류표 본문은 400-reports 파일에 두고 result_note에는 4블록 각 1~2줄만 남기며(#42233은 'exit code 0'을 결론 줄에 끼워 넣어 done이 된 반면 같은 형식의 #42219는 껍데기 문구로 반려돼, 어느 쪽이 통과 조건인지 일관되지 않다 — 원인 미확인), ② 저장 직전에 4라벨과 exit code 숫자 존재를 확인하는 검사를 guardian 크론 점검 지시문 상단 체크리스트로 둔다. 코드 변경이 필요한 부분은 하단 후보 3의 "완료 제출 전 라벨 사전검사"로 한정한다.
공백 B (사전 중복 확인): 반려 분류·방지안 태스크를 새로 발행하기 전에 최근 7일 안의 400-reports/*needs_evidence*가 있으면 새 태스크를 만들지 않고 해당 파일을 이어서 쓰게 한다. 지금까지 23개 파일이 생겼는데도 매번 새 태스크가 발행됐다. 이 판단은 규칙화하기 쉽다(파일 존재 확인 한 번). 구현은 create_task()에서 제목에 needs_evidence+(분류|집계|방지) 키워드이고 최근 7일 안에 같은 키워드 보고서가 있으면 드롭하는 분기 → codex 후보 ②(1순위 게이트와 같은 함수 영역).
공백 C (결과 보존): 위 공백 A ③으로 같이 해결된다. 추가 코드 불필요.
codex에 넘길 후보 (구현 전 해리 승인 필요, 코드는 건드리지 않았다)
| # | 수정 대상 | 함수 | 변경 요지 | 검증 명령 | 기대값 | 롤백 |
|---|---|---|---|---|---|---|
| 1 | scripts/orchestrator.py | _reissue_family_key(4300행대), _is_needs_evidence_reissue_loop_tripped(4330행) |
제목에 needs_evidence와 (분류|집계|방지) 키워드가 같이 있으면 숫자·문구와 무관하게 같은 계열로 본다. 임계 3 유지 | python3 -m pytest tests -k reissue_loop -q(테스트 파일이 없으면 신규), 실제 제목 6건(#42165~#42235)을 입력해 3번째부터 True인지 확인 |
6건 중 4번째 이후 True, exit code 0 | ORCH_REISSUE_LOOP_THRESHOLD=0 |
| 2 | scripts/orchestrator.py (프로세스 반영 확인) | — | PID 46446이 10-19 수정본을 로드했는지 확인. 미반영이면 해리 승인 후 재시작 | ps -o lstart -p <PID>와 grep -c NEEDS_EVIDENCE_REISSUE_LOOP_BLOCKED logs/ron_orchestrator.log |
재시작 후 신규 반려집계 태스크 발행 시 BLOCKED 로그 ≥1 | 재시작 전 plist 백업 |
| 3 | scripts/agent_queue_worker.py (대상 함수 미특정: 완료 제출 직전 경로를 codex가 실측 확인) | — | 저장 직전 result_note가 4라벨과 exit code <숫자>를 갖췄는지 사전검사하고, 부족하면 작업을 다시 열어 보완 요청(done 저장 전). 절단 길이도 4블록 보존 기준으로 확인 |
라벨 누락 샘플(#41233, #42062 note) 입력 시 사전검사가 False, 정상 샘플(#42171 형식+exit code) 입력 시 True | 샘플 2종 기대값 일치, exit code 0 | 사전검사 분기 제거 |
| 4 | scripts/agent_queue_worker.py | _completion_report_has_result_and_verification(2193행) |
analyst-* 원문 9건을 입력해 단어 검색이 오탐인지 확인(원문은 jsonl에 240자만 있어 DB 원본 필요). 오탐이면 "근거파일:" 라벨 존재를 결과물 단어로 인정 | 9건 원문 입력 시 통과 여부 | 오탐 건 통과, 진짜 빈 보고는 계속 차단 | 정규식 원복 |
[리스크]
- 1순위가 넓은 키워드를 쓰면 정상적인 신규 점검(예: 새 날짜의 정당한 집계)까지 막는다. 근거: 현재 44건 중 실질적으로 서로 다른 지시문은 소수이고, 임계 3으로 첫 3건은 통과한다. 완화: 기본값 유지 + 환경변수 롤백.
- 게이트가 실행 프로세스에 반영되지 않았다면 코드 수정을 더 해도 효과가 없다. 단일 장애점은 오케스트레이터 프로세스(PID 46446) 한 개다.
- guardian 36건이 중복 방지 규칙에 걸리면 정작 필요한 시스템 점검이 지연될 수 있다. 완화: 키워드 조건은 "needs_evidence + 분류/집계/방지"로 한정하고 cron/health 점검 제목은 제외한다.
- 59건을 상태 종결하는 문제는 이 제안서 범위가 아니다(
261020_claude_needs_evidence_triage.md의 51건 종결안이 해리 승인 대기 상태).
[검증방법]
- KPI 1: 신규 needs_evidence 유입(제목에 needs_evidence/반려 포함). 조회
sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "select count(*) from bus_commands where status='needs_evidence' and created_at>='<적용시각>'". 기대값: 적용 후 72시간 3건 이하(현재 약 2건/일). - KPI 2: 같은 주 반려집계형 태스크 발행 수. 기대값 3건 이하.
- KPI 3:
grep -c NEEDS_EVIDENCE_REISSUE_LOOP_BLOCKED logs/ron_orchestrator.log≥ 1. - KPI 4: 분석형 9건과 같은 유형(IG/HY OAS 분석)의 신규 반려 0건.
- 롤백 조건: 적용 후 24시간 내 guardian 정상 점검 태스크 2건 이상이 BLOCKED로 드롭되면
ORCH_REISSUE_LOOP_THRESHOLD=0으로 되돌린다.
한계 (확인 못 한 것)
- guardian #42233의 분류표 본문(DB 절단), 분석형 9건 원문 전체(jsonl 240자 절단)는 확인하지 못했다.
- 오케스트레이터 프로세스가 새 코드를 로드했는지는 미확인(재시작은 승인 필요라 하지 않았다).