needs_evidence 68건 해소 방안 제안서 (guardian #42357 분류 재집계 기반)
needs_evidence 68건 해소 방안 제안서
작성: Cowork(다듬) / CMD#42362 / 조회 2026-10-22 14:44~14:52 KST / 코드·DB·크론·재큐잉 변경 없음(제안서만)
이미 있는 내용은 다시 쓰지 않는다. 겹침 확인 대상: AGENTS.md "대행 태스크 완료보고 검증 근거 정책", config/agent_completion_submission_standard.md, config/needs_evidence_recurrence_policy_proposal_20261022.md, 400-reports/261021_hermes_needs_evidence_prevention.md, 261022_claude_needs_evidence_개선안.md, 261020_claude_needs_evidence_triage.md. 이 문서는 위 문서들에 없는 것만 담았다.
[권고]
→ 1순위 (운영 규칙 + 해리 승인 대기 코드 후보): 성과 지표를 "라이브 needs_evidence 건수"에서 "반려 유입량(라이브+아카이브 합산)"으로 바꾼다. 이유: 기존 제안서 6개의 KPI는 전부 status='needs_evidence' 라이브 건수만 센다. 그런데 2026-10-16 이후 반려 문구가 저장된 310건 중 needs_evidence로 남은 것은 26건(8.4%)뿐이고 284건(91.6%)은 failed로 저장돼 2시간 뒤 아카이브로 빠진다. 지금 KPI로는 반려가 하루 40~60건 계속 나도 "신규 ≤3건/주" 목표가 달성된 것으로 읽힌다. 기대효과: 오판 없는 합격선(아래 [검증방법] 쿼리 한 개).
→ 2순위 (codex 후보, 해리 승인 후): needs_evidence 상태에는 나가는 길이 없다. orchestrator.py::_cleanup_old_commands는 done/cancelled/failed만 아카이브하고 needs_evidence는 대상에서 빠져 있다. 그래서 68건 중 42건(61.8%)이 7일 넘게, 20건(29.4%)이 14일 넘게(최고령 9월 28일, 24일) 쌓여 있다. 오래된 반려 건에 일정 기간 뒤 아카이브로 옮기는 경로를 만든다(초안은 아래 T1). 기대효과: 라이브 68건 → 14일 기준 적용 시 48건, 7일 기준이면 26건. 단 이는 정리일 뿐 재발 방지가 아니므로 1순위와 묶어서만 의미가 있다.
→ 3순위 (기준선 정정, 코드 없음): 261022_claude_needs_evidence_개선안.md의 C1 기대효과 기준선 "집계 태스크 일 4.7건"은 라이브 테이블만 센 값이다. 실측 기준선은 하루 28~36건이다. C1 반영 후 KPI는 이 기준선으로 비교해야 한다. 기대효과: C1 효과를 7배 낮게 평가해 중단하는 판단 오류를 막는다.
[현황]
1. 직접 재집계 (sqlite3 -readonly, 조회 14:44~14:50)
- 상태 전체: claimed 1, done 6, failed 1, needs_evidence 68. needs_evidence 68건의
claimed_by는 guardian 50, cowork 8, analyst-macro 5, analyst-pm 4, ron 1 (합 68). 요청자는 68건 전부 orchestrator다. - 분류 방법: result_note의
차단 사유:~보완 필요구간만 파싱했다. 같은 단어가 "원본 요약" 안에 서술로 쓰인 경우를 세지 않기 위해서다.
| 순위 | 반려 라벨(차단 사유 구간) | 건수 | 비율 | 에이전트 |
|---|---|---|---|---|
| 1 | missing_verification_exit_code | 20 | 29.4% | guardian 19, cowork 1 |
| 2 | missing_result_or_verification | 13 | 19.1% | analyst-macro 5, analyst-pm 4, guardian 3, cowork 1 |
| 3 | invalid_verification_exit_code | 8 | 11.8% | guardian 5, cowork 2, ron 1 |
| 4 | missing_verification_command | 6 | 8.8% | guardian 5, cowork 1 |
| 5 | completion_result_note_forces_rework | 4 | 5.9% | guardian 3, cowork 1 |
| 6 | verification_command_unverifiable | 3 | 4.4% | guardian 2, cowork 1 |
| 6 | missing_execution_artifact | 3 | 4.4% | guardian 2, cowork 1 |
| 6 | execution_artifact_path_not_found | 3 | 4.4% | guardian 3 |
| - | 구체 라벨 없음(껍데기 문구만) | 24 | 35.3% | guardian 21, cowork 3 |
- 한 건에 라벨이 둘 이상인 경우가 10건이라 라벨 합계는 68을 넘는다.
- 상위 2개 라벨: missing_verification_exit_code(20건), missing_result_or_verification(13건). 라벨이 있는 44건 중 검증 줄 계열(exit code 누락·오류, 검증 명령 누락·재현 불가)은 31건(45.6%)이다.
- 편중된 에이전트: guardian 50/68 = 73.5%. 제목에 needs_evidence가 들어간 집계·분류 태스크가 49건(guardian 43, cowork 6, 72.1%)이다. 상위 1위 라벨은 guardian이 19/20, 상위 2위 라벨은 analyst 9건(전부 미국 IG/HY OAS 파일 판독)이 중심이다.
- 요청서가 예시로 든 라벨: missing_source 0건, missing_execution_value 0건, missing_verification_value 0건(차단 사유 구간 기준). 본문 서술에 한 번씩 쓰인 것만 있다(missing_source 1, missing_execution_value 1). execution_artifact_path_not_found는 3건이다.
2. guardian #42357 분류표와의 대조
-
42357(guardian, 13:42:35 생성, 13:44:05 done)의 result_note는 DB에 476자만 저장돼 있다. 결론 줄이 "…#42127..."에서, 근거 줄이 "ORD..."에서, 근거파일 줄이
근거파일: :2 "라벨별 합계: verification=25, unlabeled(코드 없음…)=24, result_or_verification(execution+verificati…에서 잘려 있다. 분류표 본문과 파일 경로는 DB에서 복원되지 않는다. 13:30~13:50에 새로 생긴 파일도 workspace/memory와 knowledge-agent에서 찾지 못했다(find -newermt, 0건). 즉 분류표 전체는 미확인이다. - 보이는 범위에서의 대조:
- "llm_infra_failure와 missing_source 계열은 실제 반려 사유로는 0건": 일치(차단 사유 구간 0건/0건).
- "unlabeled=24": 일치(24건).
- "verification=25": 불일치. 내 재집계는 exit code 계열만 28건(missing 20 + invalid 8), 명령 누락·재현 불가까지 넣으면 31건이다. guardian의 25가 어떤 정의인지 잘려서 알 수 없다. 이 숫자는 인용하지 않는다.
- 문자열 검색으로 세면 llm_infra_failure가 17건으로 나온다(전부 guardian). 차단 사유 구간에는 0건이고, "인프라 때문이 아니다"라고 쓴 문장 때문이다(기존 개선안 문서가 이미 지적한 오분류와 같은 현상이 재현됐다).
3. 새로 확인한 사실 A — 라이브 건수는 유입량의 일부일 뿐이다
- 조회: bus_commands + bus_commands_archive를 합쳐 result_note가
결론: 결과 확인 보류나결론: needs_evidence:로 시작하는 건(created_at 기준).
| 날짜 | failed | needs_evidence | 합 |
|---|---|---|---|
| 10-16 | 49 | 3 | 52 |
| 10-17 | 57 | 5 | 62 |
| 10-18 | 43 | 2 | 45 |
| 10-19 | 38 | 3 | 41 |
| 10-20 | 40 | 4 | 44 |
| 10-21 | 39 | 5 | 44 |
| 10-22(부분) | 18 | 4 | 22 |
| 합계 | 284 | 26 | 310 |
logs/agent-queue-guardian.log에서"worker_status": "needs_evidence"인 줄 621개가 전부"routed_status": "failed"이고, 그중 620줄에block_reasons: non_ron_harry_direct가 있다(누적 로그, 기간 미한정). 즉 워커는 needs_evidence로 판정했지만 저장 단계에서 failed로 기록되는 경로가 대다수다. 어떤 조건에서 나머지 소수만 needs_evidence로 남는지는 미확인이다(server.py 964행, 3124행, 5711행에 needs_evidence 저장 분기가 있다는 것까지만 확인).- 이 중 failed 건은
_cleanup_old_commands가 2시간 뒤 아카이브로 옮기고, 아카이브는 30일 지나면 삭제한다(orchestrator.py 2790~2810행). 아카이브에는 model_used·workflow_id·notify_flag·parent_cmd_id 열이 없다.
4. 새로 확인한 사실 B — 집계 태스크 실제 발행량
- guardian 대상, 제목에 needs_evidence 포함, 라이브+아카이브 합산:
| 날짜 | 합산 발행 | 이 중 done | 라이브 테이블만 본 값 |
|---|---|---|---|
| 10-17 | 18 | 2 | 3 |
| 10-18 | 22 | 2 | 2 |
| 10-19 | 28 | 3 | 2 |
| 10-20 | 34 | 3 | 4 |
| 10-21 | 36 | 3 | 5 |
| 10-22(부분) | 19 | 4 | 5 |
- 10-19~10-21 3일 합계 98건(일 약 33건), done은 9건(9.2%). 261022_claude_needs_evidence_개선안.md [현황]의 "일 평균 약 4.7건"은 라이브만 센 값이라 약 7배 낮다.
- 10-19~10-22 합산 101건의 제목은 숫자를 지워도 86개 서로 다른 문구다(가장 흔한 문구 5건). 재발행 루프 게이트의 계열 키로는 묶이지 않는다는 기존 지적과 같은 방향의 수치다.
- orchestrator.py 911행은 지금도
"counts": counts로 큐 상태를 Ron LLM에 그대로 넘긴다. 파일 수정 시각은 10-19 21:01이고 C1 반영 흔적은 없다.NEEDS_EVIDENCE_REISSUE_LOOP_BLOCKED는logs/ron_orchestrator.log·ron_orchestrator_error.log·orchestrator_rescue.log에 0건이다.
5. 기존 문서와 겹침 확인 (넣지 않은 것)
- 106개 문서(config/.md, 400-reports/needs_evidence*, memory 관련)에서
_cleanup_old_commands, TTL, 아카이브 제외, 일 유입 합산 같은 표현은 0건이다(grep -l). 그래서 위 1~3순위만 새로 제안한다. - 이미 있는 내용이라 다시 쓰지 않는다: exit code 리터럴 규칙(standard §9-4 조항 1), 4블록 템플릿(§3, §9-3), 재발행 루프 게이트 설계(261019 reissue_loop_policy)와 계열 키 확장안(261021 후보 1, 261022 C4), 큐 건수 입력 차단(C1), 제출 전 라벨 사전검사(261021 후보 3), 종결 51건 안(261020 triage, 해리 승인 대기).
T1. codex용 태스크 초안 (코드 수정 필요, 직접 수정하지 않음, 해리 승인 후 발행)
- 제목: orchestrator
_cleanup_old_commands에 오래된 needs_evidence 반려 건 아카이브 경로 추가 - 수정 대상: scripts/orchestrator.py
_cleanup_old_commands(2790~2803행의 INSERT/DELETE 두 구문 부근) - 내용:
status='needs_evidence'이고created_at이 기준일(환경변수, 기본 14일)보다 오래됐고result_note가결론: 결과 확인 보류나결론: needs_evidence:로 시작하는 건만 아카이브로 복사한 뒤 라이브에서 제거한다. 환경변수 0이면 비활성(롤백). 복사 전 건수를 로그로 남긴다. 아카이브에 없는 열(model_used 등) 손실은 로그에 한 줄로 알린다. 삭제가 아니라 이동이므로 30일 아카이브 보존 정책 안에서만 복원 가능함을 로그에 적는다. - 검증 명령:
python3 -m py_compile scripts/orchestrator.py→ exit 0. 신규 pytest(임시 DB에 14일 초과 needs_evidence 2건, 14일 이내 1건, done 1건을 넣고 실행) → 2건만 이동. 실제 DB 시험 전 읽기 전용 예상치sqlite3 -readonly …ops_multiagent.db "SELECT count(*) FROM bus_commands WHERE status='needs_evidence' AND created_at<datetime('now','localtime','-14 days')"→ 2026-10-22 14:50 기준 20. - 기대값: 반영 후 첫 정리 주기에 라이브 needs_evidence 68 → 약 48.
- 롤백 조건: 기준일 설정을 0으로 되돌리고, 이동된 건은 아카이브에서 id 기준으로 되돌린다(열 손실 허용 범위 해리 확인).
- 선행 조건: 해리 승인. 261020_claude_needs_evidence_triage.md의 종결 51건 안과 같은 건들을 건드리므로 둘 중 하나만 실행한다.
T2. codex용 조사 초안 (읽기 전용, 코드 수정 아님)
- 제목: 워커 needs_evidence 판정이 저장 시 failed로 기록되는 조건 확인
- 대상: scripts/server.py 1089행(
non_ron_harry_direct부착), 964행, 3124행, 5711행의 needs_evidence 저장 분기 - 질문: 621줄 중 620줄에 붙은
non_ron_harry_direct가 최종bus_commands.status를 failed로 만드는지, 그렇다면 의도된 동작인지. 확인 못 했으므로 현재는 가설이다. - 검증: 재현 1건을 임시 DB로 돌려 최종 status가 failed인지 needs_evidence인지 로그와 함께 보고. 코드 변경이 필요하면 별도 태스크로 분리한다.
[리스크]
- 합산 KPI도
result_note접두 문구에 의존한다. 게이트 문구가 바뀌면 건수가 누락된다. 대비책: 쿼리의 두 접두어를 문서에 고정하고 분기마다 샘플 5건으로 확인한다. - T1은 라이브 건수만 줄인다. 1순위 기준선이 없으면 "68 → 48 감소"를 개선으로 오해할 수 있다. 성과 판정은 반드시 합산 유입량으로 한다.
- 아카이브는 30일 뒤 삭제된다. 오래된 반려 사유 증거가 장기 보존되지 않는다. 필요한 분류 결과는 400-reports 파일로 남겨야 한다(기존 261021 공백 C와 같은 방향).
- 단일 장애점: orchestrator 프로세스 PID 46446(9월 27일 07:55 기동)이 10-19 이후 수정본을 로드했는지는 이번에도 확인하지 못했다.
ps로 기동 시각은 확인했으나 코드 재로드 여부는 미확인. 재시작은 해리 승인 사항이다. - 미확인: guardian #42357 분류표 본문, 반려가 failed로 기록되는 정확한 조건(T2),
verification=25정의.
[검증방법]
- KPI 1 (유입량, 이 문서의 합격선):
sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT substr(created_at,1,10), count(*) FROM (SELECT created_at, result_note FROM bus_commands UNION ALL SELECT created_at, result_note FROM bus_commands_archive) WHERE created_at>='2026-10-23' AND (result_note LIKE '결론: 결과 확인 보류%' OR result_note LIKE '결론: needs_evidence:%') GROUP BY 1"기대값: 현재 일 41~62건에서 하루 20건 이하로 감소(첫 합격선), 롤백 판단은 7일 평균이 감소하지 않을 때. - KPI 2 (집계 태스크 발행량):
SELECT substr(created_at,1,10), count(*) FROM (SELECT created_at,target_agent,title FROM bus_commands UNION ALL SELECT created_at,target_agent,title FROM bus_commands_archive) WHERE target_agent='guardian' AND title LIKE '%needs_evidence%' AND created_at>='2026-10-23' GROUP BY 1→ C1 반영 뒤 하루 3건 이하(현재 28~36건). - KPI 3 (잔량):
SELECT count(*) FROM bus_commands WHERE status='needs_evidence'→ T1 반영 후 48 안팎, 이후 증가폭 0. - 이 문서 자체: 위 쿼리 결과가 14:50 기준값(310건, 98건)과 어긋나면 재집계한다.
- 롤백 조건: T1 반영 후 24시간 안에 아카이브 이동 건이 기준 밖 상태이거나 정상 점검 태스크가 사라지면 기준일을 0으로 되돌린다.