virtual-insanity
← 리포트 목록

needs_evidence 반려 최다 원인(검증 exit code 누락) 방지안

2026-10-12 claude [needs_evidence, completion-gate, exit-code, guardian, 방지안]

needs_evidence 반려 최다 원인(검증 exit code 누락) 방지안

[권고]

1순위: 태스크 body 와 에이전트 프롬프트의 검증 예시를 게이트가 실제로 읽는 문구 exit code 0 으로 통일한다. 근거: 게이트 정규식은 "exit code"/"exit_code"/"return code"/"returncode"/"rc" 뒤에 숫자가 오는 경우만 인정한다(scripts/agent_queue_worker.py:7030-7033, scripts/server.py:733-736). 그런데 scripts/orchestrator.py:812 는 검증 예시를 → exit 0 으로 가르친다. 이 문구는 정규식에 걸리지 않는다(직접 실행: 'python3 scripts/health_check.py → exit 0' → 매치 None). 기대효과: 같은 형식 오류로 인한 missing_verification_exit_code 재발 차단(현재 11건, 전체 반려 36건의 30.6%).

2순위: 반려 건수를 집계하는 보고서의 검증 줄에서, 라벨 이름 바로 뒤에 숫자를 붙여 쓰지 않는다. 이유: 서버 게이트는 노트 전체에서 첫 번째 exit_code <숫자> 패턴을 exit code 로 읽는다(server.py:733-736 에 앞쪽 단어 경계가 없다). 그래서 missing_verification_exit_code 15건 은 exit_code 15 로 읽혀 invalid_verification_exit_code 로 반려된다(직접 실행: 'missing_verification_exit_code 15건' → code=15, 'missing_verification_exit_code: 9건' → code=9). 반려 분류 보고서 12건이 이 유형에 몰린 구조적 이유다. 기대효과: invalid_verification_exit_code 7건(19.4%) 중 분류·집계형 6건 재발 차단.

[현황]

조회: sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT result_note FROM bus_commands WHERE id=41504" → 1행(guardian, needs_evidence, result_note 386자, 조회 2026-10-12 11:02 KST). 본문은 "결과 확인 보류" 템플릿으로 바뀌어 있고 원본 요약이 잘려 있다. 남은 문장은 "needs_evidence 36건 … missing/invalid_verification_exit_code 로 15건(41.7%), 결과 확인 보류 6건, missing_result_or_verification 6건" 까지다.

현재 needs_evidence 전체: SELECT count(*) … WHERE status='needs_evidence' → 37건(id 40276~41504). 41504 를 뺀 36건을 각 행 result_note 의 "차단 사유:" 구간 기준으로 다시 셌다(조회 2026-10-12 11:0x KST, 읽기 전용).

  • exit code 계열 합계: 18건 / 36건 = 50.0% (missing_verification_exit_code 11건, invalid_verification_exit_code 7건). guardian 이 41504 에 쓴 15건(41.7%)과 3건 차이가 난다. 그 사이 행이 갱신됐거나 집계 기준이 다른 것으로 보이며, 이 차이는 확인하지 못했다.
  • 에이전트별(exit code 계열 18건): guardian 16건(missing 11 + invalid 5), ron 1건(invalid, #40297), cowork 1건(invalid, #41348). analyst-* 는 0건.
  • 전체 36건 중 guardian 소유 26건, 그중 16건(61.5%)이 exit code 계열.
  • 태스크 유형별(18건):
  • 반려/실패 분류·집계형 12건: 40842, 40854, 40869, 40902, 41274, 41295, 41348, 41377, 41385, 41420, 41431, 41498. 제목에 "needs_evidence N건 … 집계/분류"가 들어 있다.
  • 지식사랑방 실패 원인 분류 2건: 40633, 40994
  • 코드 패치 반영 확인 1건: 40276
  • 프로세스 조회 1건: 40346
  • 크론 사전점검 1건: 41323
  • 데이터 예열 실행 1건: 40297 (원본 요약에 "exit code 1" 이 들어 있었는데, 스크립트 자체가 실패한 사실을 보고한 것)
  • exit code 계열이 아닌 나머지 18건: missing_result_or_verification 7, llm_infra_failure 5, placeholder 3, missing_execution_artifact 2, 기타 1.

한계: 반려된 원문은 "결과 확인 보류" 템플릿으로 덮어써져 있어 bus_commands.result_note 에 원본 검증 줄이 거의 없다. logs/completion_evidence_blocked.jsonl 의 note_preview 도 240자까지만 보관한다. 그래서 개별 건에서 어떤 문구가 걸렸는지는 위 정규식 동작과 대조해 추정한 것이다. 건별 확정은 못 했다.

[게이트가 요구하는 형식 — 읽은 곳]

  • scripts/agent_queue_worker.py:7127-7156 _codex_has_verification_result_field: "검증 결과:" 필드, exit code N 필드, 또는 "검증: … → …exit code N" 화살표 형태를 찾는다. 값에 "없음/미실행/대기/예정" 등이 있으면 invalid_verification_result, N failed/errors 가 있으면 invalid_verification_exit_code, exit code 숫자가 아예 없으면 missing_verification_exit_code, 0 이 아니면 invalid_verification_exit_code.
  • scripts/agent_queue_worker.py:7387-7408: 이 엄격 검사는 agent_key == "codex" 일 때만 적용된다. 다른 에이전트는 "검증 결과: 통과" 같은 관측 문구도 인정한다.
  • scripts/server.py:762-800 _completion_storage_required_result_gaps: 저장(done) 단계의 서버 게이트는 에이전트 구분 없이 exit code 0 을 요구한다. guardian/cowork/ron 이 반려된 이유는 이 경로다(server.py:800-830 에서 숫자가 없으면 missing_verification_exit_code, 0 이 아니면 invalid_verification_exit_code).
  • 문서 규정: config/agent_completion_submission_standard.md:187-195("결과값에는 게이트가 읽는 리터럴 exit code 0 을 그대로 쓴다. exit=0 표기는 … 반려된다"), :112(검증 형식), :126(짧은 운영 문구), :245(invalid_verification_exit_code 사례 행), :653-663(analyst-fundamental 전용 exit code 0 조항). config/completion_evidence_policy.md:93(missing_verification_value 정의), :200(py_compile exit code 인용).

문서와 코드의 간극 두 가지: 1. exit=0 은 문서가 금지하고 있는데, exit 0(code 없음)은 금지 목록에 없고 orchestrator.py:812 가 오히려 권장한다. 2. "부정형 grep" 규칙(standard.md:174-195)은 grep 한 줄 검증만 다루고, 집계·분류 보고서에서 라벨 이름 옆 숫자가 exit code 로 오인되는 경우는 다루지 않는다.

[태스크 body 작성 규칙에 넣을 검증 문구 예시 3개]

예시 1 (DB 조회형, guardian 분류·집계 태스크 용): 검증: sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT count(*) FROM bus_commands WHERE status='needs_evidence'" → 37, exit code 0

예시 2 (저장 파일 확인형, 보고서 작성 태스크 용): 검증: ls -l /Users/ron/knowledge-agent/400-reports/261012_claude_needs_evidence_exitcode_방지안.md → 파일 존재(크기 표시), exit code 0

예시 3 (스크립트 실행형, 헬스체크·예열·크론 점검 용): 검증: python3 /Users/ron/.hermes/workspace/scripts/health_check.py → 전체 통과, exit code 0

작성 규칙(태스크 body 에 같이 넣는다): - 검증 줄의 첫 exit code 뒤 숫자가 0 이어야 한다. 노트 어디든 그보다 앞에 exit_code <숫자> 모양이 나오면 안 된다. - 반려 라벨 이름(missing_verification_exit_code 등)을 설명할 때는 라벨 뒤에 숫자를 붙이지 말고 "exit code 누락 11건"처럼 한글로 풀어 쓴다. - 조사 대상 스크립트가 실패한 사실을 보고하는 경우(예: #40297), 그 실패의 exit code 1 은 "대상 스크립트 종료값"이라고 앞에 쓰고, 검증 줄에는 내가 실행한 조회 명령의 exit code 0 을 따로 쓴다. - exit=0, exit 0, 종료코드 0 은 쓰지 않는다. 모두 정규식에 안 걸린다(직접 실행 확인). - 부재 확인(grep 일치 0건)은 기존 규정대로 ! grep -rlq … ; echo "exit code $?" 형태를 쓴다.

[기존 문서에서 보강할 문장 위치]

  1. config/agent_completion_submission_standard.md:187-190 바로 뒤: "exit 0(code 없음), 종료코드 0 도 같은 이유로 반려된다. 반드시 exit code 0 이라고 쓴다." 한 문장 추가.
  2. config/agent_completion_submission_standard.md:195 뒤(부재 확인 절 끝)에 새 소절: "집계·분류 보고서 주의 — 노트 안에 missing_verification_exit_code 15건 처럼 라벨 이름 바로 뒤에 숫자를 쓰면 게이트가 15 를 exit code 로 읽어 invalid_verification_exit_code 로 반려한다. 라벨은 한글로 풀어 쓰고, 첫 exit code 는 반드시 검증 줄의 0 이어야 한다."
  3. config/agent_completion_submission_standard.md:245 의 invalid_verification_exit_code 행 끝에 "분류·집계형 보고서의 라벨+숫자 오인 사례(#41295, #41377, #41385, #41420)" 추가.
  4. config/completion_evidence_policy.md:93 의 missing_verification_value 줄 아래에 "exit code 는 exit code N 리터럴만 인정(exit 0/exit=0 불가)" 한 줄 추가.
  5. config/completion_evidence_policy.md 파일 말미에 새 절(v 번호는 마지막 절 다음)로 이번 18건 표(에이전트·유형 건수)를 요약해 남긴다.

위 5건은 문서 수정이라 이 제안서에서는 반영하지 않았다. 해리 확인 없이 정책 문서를 바꾸지 않고, 반영은 아래 위임 항목과 함께 진행한다.

[리스크]

  • 단일 장애점: 정규식이 워커(agent_queue_worker.py:7030)와 서버(server.py:733)에 두 벌로 있다. 한쪽만 고치면 다른 쪽에서 반려된다.
  • 게이트를 느슨하게(예: exit 0 허용) 바꾸면 "exit 0" 가 아닌 문장 속 숫자까지 잡힐 위험이 커진다. 예시 문구 쪽을 고치는 것이 안전하다.
  • 반려 시 원문이 템플릿으로 덮어써져 건별 원인 확정이 안 된다. 이 방지안의 원인 귀속 일부는 정규식 동작 대조에 근거한 추정이다.
  • guardian 이 같은 유형 태스크(needs_evidence N건 분류)를 거의 하루 한두 건씩 계속 발행받으므로(41485, 41494, 41498 등), 문구를 바꾸지 않으면 같은 반려가 반복된다.

[검증방법]

  • 지표: needs_evidence 중 exit code 계열 비율. 현재 18/36 = 50%. 기대값은 규칙 반영 뒤 신규 반려 중 exit code 계열 0건.
  • 명령: sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT claimed_by,count(*) FROM bus_commands WHERE status='needs_evidence' AND id>41504 AND result_note LIKE '%exit_code%' GROUP BY 1" 결과가 0행이면 성공.
  • 정규식 회귀 확인: python3 -c 로 예시 3개 문구가 _STORAGE_EXIT_CODE_RE 에서 code=0 으로 읽히는지 확인(이번에 같은 방식으로 exit code 0 → 0 확인).
  • 롤백 조건: 규칙 반영 후 7일간 신규 needs_evidence 가 줄지 않거나, 예시 문구를 따랐는데도 exit code 계열 반려가 나오면 반영을 되돌리고 logs/completion_evidence_blocked.jsonl 원문을 먼저 확인한다.

codex 위임 항목 (코드 수정, 이 제안서에서는 하지 않음)

  1. scripts/orchestrator.py:812 의 예시 → exit 0 을 → exit code 0 으로 교체(같은 파일에서 exit 0 예시가 더 있는지 grep -n "exit 0" 로 확인).
  2. scripts/server.py:733-736, scripts/agent_queue_worker.py:7030-7033 정규식에 앞쪽 단어 경계 추가((?<![A-Za-z_]))를 검토. 라벨 이름 속 exit_code 를 exit code 로 읽는 오인을 없앤다. 두 파일 동시 수정과 회귀 테스트(missing_verification_exit_code 15건 이 code 로 읽히지 않는 것, exit code 0 은 읽히는 것) 필요.
  3. 반려 시 result_note 원본을 템플릿으로 덮어쓰기 전에 별도 컬럼이나 로그에 보존(현재 note_preview 240자 제한). 건별 원인 확정에 필요하다.

결론: bus_commands #41504 와 needs_evidence 36건을 읽기 전용으로 대조해, exit code 누락·오류 18건(50%)이 guardian 16건·ron 1건·cowork 1건에 몰려 있고 분류·집계형 태스크가 12건임을 확인해 방지안을 작성했다. 근거: SQL SELECT result_note FROM bus_commands WHERE id=41504 → 1행, SELECT claimed_by,count(*) … WHERE status='needs_evidence' GROUP BY 1 → 5행(guardian 26, cowork 4, analyst-pm 4, analyst-macro 2, ron 1), 조회 2026-10-12 11:02 KST. 읽은 곳: scripts/agent_queue_worker.py:7030-7033, 7127-7156, 7387-7408 / scripts/server.py:733-736, 762-830 / scripts/orchestrator.py:812 / config/agent_completion_submission_standard.md:187-195, 245, 653-663 / config/completion_evidence_policy.md:93, 200. 검증: ls -l /Users/ron/knowledge-agent/400-reports/261012_claude_needs_evidence_exitcode_방지안.md → 파일 존재 확인, exit code 0 (통과) 근거파일: /Users/ron/knowledge-agent/400-reports/261012_claude_needs_evidence_exitcode_방지안.md:9 "# needs_evidence 반려 최다 원인(검증 exit code 누락) 방지안"