virtual-insanity
← 리포트 목록

guardian 반려 22건 result_note 4블록 누락 패턴 분류 및 방지안 제안서

2026-10-11 claude [guardian, completion-evidence, needs_evidence, 4블록, 제안서, hermes-ops]

guardian 반려 result_note 4블록 누락 패턴 분류 및 방지안 제안서

[권고]

1순위: 집계·분류형 guardian 태스크의 "검증:" 줄에서 반려 라벨 이름과 건수를 붙여 쓰지 않게 한다 (예: missing_verification_exit_code 4건을 쓰지 말고 라벨 4종, 합계 22건처럼 쓴다). 이유: 게이트의 exit code 정규식이 exit_code 4를 "exit code 4(실패)"로 읽는다 (아래 [현황] 3번 재현). 기대효과: invalid_verification_exit_code 5건(22건 중 22.7%)과 이 패턴이 겹치는 재반려 고리를 끊는다. 단, 원문이 잘려 이 5건 전부의 원인이 이것인지는 미확인이다.

2순위: guardian 완료 보고는 반드시 아래 "작성 예시" 4블록 틀로 쓰고, 검증 줄에는 명령 → 결과값, exit code 0을 한 줄로 쓴다. 이유: 22건 중 15건(68.2%, A·B·E·F)이 exit code 코드(missing_/invalid_verification_exit_code) 계열이고, 나머지 7건은 "결과 확인 보류"·검증 근거 없음·명령 재현 불가로 막혔다. 기대효과: 같은 유형의 재발행 고리(분류 태스크가 분류 태스크를 낳는 구조)를 줄인다.

3순위(코드 수정이므로 codex 위임 제안, 이번 작업에서는 수정하지 않음): guardian의 분류 태스크 프롬프트에 위 틀과 금지 문구를 넣고, 게이트가 결과값 안의 <라벨>_exit_code <숫자> 형태를 exit code로 오인하지 않도록 정규식에 단어 경계를 주는 안을 검토한다. 현재 agent_completion_submission_standard.md §9-3-1에 템플릿이 있으나, 실제 guardian 프롬프트 파일에 배선됐는지는 이번에 확인하지 못했다 (completion_evidence_policy.md 1706~1709행이 "guardian 전용 프롬프트 파일 자체가 없다"고 적은 상태 그대로인지 미확인).

[현황]

조회: 2026-10-11 14:13 KST, sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db, claimed_by='guardian' 전체 상태별 건수 → done 1, failed 1, needs_evidence 21. 반려 대상(needs_evidence+failed)은 22행이다. 작업 지시문의 "23건"은 이전 집계 시점 값이고, 현재 조회는 22행이다 (#41431 자신이 이미 이 22건에 포함됨 — 이 작업의 이전 시도로 추정).

1. 핵심 사실: 저장된 result_note는 게이트가 다시 쓴 문장이다

22행 모두 result_note가 게이트 자동 문구("결론: 결과 확인 보류 / 근거: 결과물과 검증 근거가 없음. 차단 사유: ... / 다음 행동: ...")로 덮여 있고, guardian이 쓴 원문은 "원본 요약:" 뒤 약 200자만 남는다. 따라서 4블록 중 어느 라벨이 빠졌는지는 원문이 아니라 "차단 사유" 코드로 분류했다. 코드가 라벨 누락인지 값 누락인지는 아래 표에 구분했다.

2. 분류표 (22건)

분류 차단 사유(게이트 코드) 의미 건수 id
A missing_verification_exit_code "검증:" 값에 exit code 숫자 없음 7 40276, 40346, 40633, 40854, 40902, 40994, 41274
B invalid_verification_exit_code exit code가 0이 아닌 숫자로 읽힘 5 40869, 41295, 41377, 41385, 41420
C 결과 확인 보류 단독 (구체 코드 없음) 원문이 게이트 문구로 완전히 대체됨 3 40825, 41101, 41151
D 검증 근거 없음 + 결과물과 검증 근거가 없음 + 결과 확인 보류 검증 라벨/값 모두 부재 취급 3 41233, 41316, 41387
E missing_execution_artifact + missing_verification_command + missing_verification_exit_code 결과물 경로·검증 명령·exit code 3종 동시 누락 2 40842, 41431
F execution_artifact_path_not_found:/Users/ron/.hermes/workspace/jobs.json + missing_verification_command + missing_verification_exit_code 인용 경로가 실존하지 않음 (실제 크론 장부는 /Users/ron/.hermes/cron/jobs.json) 1 41323
G verification_command_unverifiable 계열 (status=failed) 재현 가능한 검증 명령 없음 1 41428
합계 22

제목 유형: 17건이 "반려 사유 분류·집계"류 메타 태스크(40825, 40842, 40854, 40869, 40902, 41101, 41151, 41233, 41274, 41295, 41316, 41377, 41385, 41387, 41420, 41428, 41431), 2건이 지식사랑방 인사이트 실패 원인 분류(40633, 40994), 3건이 프로세스·크론 점검(40276, 40346, 41323). 즉 guardian 반려의 대다수는 "반려를 분류하는 태스크가 또 반려되는" 재귀 구조다.

placeholder 문구는 한 건에서 직접 확인했다: #40902의 원문 첫 줄이 "결론: 작업 결과가 정리됨." (무엇을 했는지 없는 placeholder)이고, #40633은 "결론: 는 원인 (c) 증거 게이트 반려로..."처럼 문장이 깨진 상태로 제출됐다. 나머지는 원문이 잘려 placeholder 여부를 확인하지 못했다.

3. 재현으로 확인한 가능 원인 (B 분류)

/tmp/g/re_test.py로 agent_queue_worker.py 7030행 _CODEX_VERIFICATION_EXIT_CODE_RE를 그대로 복사해 시험했다. 결과: 문자열 missing_verification_exit_code 4건에서 exit_code 4가 매치되어 코드 4로 읽힌다. sqlite3 ... → 22행, exit code 0은 정상적으로 0으로 읽힌다. missing_verification_exit_code는 4블록 미비(숫자 없음)는 매치되지 않는다. 실제로 #40869의 원문에 - missing_verification_exit_code 4건: guardian #40...이 있다. 이 사실로 B 5건 중 #40869 1건은 이 오인이 원인일 수 있다. 나머지 4건(41295, 41377, 41385, 41420)은 원문이 잘려 확인하지 못했고, 이 정규식 경로가 guardian에 실제로 적용되는지(7127행 함수가 codex 전용 분기인지)도 끝까지 추적하지 않았다. 따라서 이 항목은 "가능성이 확인된 가설"이다.

4. 기존 정책과의 대조

  • config/agent_completion_submission_standard.md 179~185행: grep처럼 일치 0건이면 exit 1이 되는 명령은 "invalid_verification_exit_code로 반려한다". 부재 확인은 ! grep -rlq ...; echo "exit code $?" 형태로 쓰라고 이미 정해져 있다. guardian의 B 분류에는 이 규칙이 닿지 않았다 (집계 태스크는 grep이 아니라 sqlite3 숫자를 쓴다).
  • 같은 문서 570~586행 §9-3-1: guardian 시스템 점검용 템플릿이 이미 있다. 같은 문서 604~608행: "근거파일:에 게이트 자신의 로그(completion_evidence_blocked.jsonl 등 자기참조 경로)를 적지 않는다". 다만 해당 파일 /Users/ron/.hermes/logs/completion_evidence_blocked.jsonl은 이번 조회에서 존재하지 않았다 (ls → No such file or directory). 이 경로를 근거로 인용하면 F와 같은 execution_artifact_path_not_found가 난다.
  • config/completion_evidence_policy.md 1665~1672행: 2026-09-08 시점 guardian 반려율이 7일 8건 중 6건(75.0%)이었고, 1728행에서 7일 후 30%로 낮추는 것이 기대값이었다. 지금은 guardian 전체 23행 중 22행이 반려(95.7%, 조회 14:13)라 오히려 악화됐다.

[리스크]

  • 재귀 고리: 분류 태스크가 반려되면 "증거 보강 재발행" 태스크가 새로 생기고, 그 재발행이 또 반려된다. #41377, #41385 제목에 "재발행"·"증거 포함 재발행"이 붙어 있다. 큐 용량(에이전트당 2개)과 guardian 호출 횟수를 반복 소모한다.
  • 원문 소실: 게이트가 result_note를 자기 문구로 덮어써 guardian이 무엇을 빠뜨렸는지 사후에 볼 수 없다. 그래서 이번 분류도 "차단 사유 코드"까지만 가능했다. 단일 장애점(분석 근거의 유일한 저장 위치가 덮어쓰인 필드)이다.
  • 정규식 오탐 가능성(위 3번)은 게이트 쪽 문제일 수 있다. guardian만 고쳐서는 해결되지 않을 수 있다. 이 경우 에이전트 규율 문제로만 진단하면 반려가 계속된다.
  • 정책 문서가 실제 guardian 실행 프롬프트에 배선되지 않았다는 completion_evidence_policy.md 1706~1709행의 기존 지적이 현재도 유효한지 미확인이다.

[검증방법]

  • 지표: guardian의 needs_evidence+failed 비율. 현재 22/23 = 95.7% (2026-10-11 14:13 KST). 목표: 방지안 적용 후 7일 내 30% 이하 (completion_evidence_policy.md 1728행의 기존 기대값과 동일).
  • 명령: sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT status,count(*) FROM bus_commands WHERE claimed_by='guardian' GROUP BY status;"
  • B 분류 가설 검증: 새로 완료되는 guardian 분류 태스크 3건에서 "검증:" 줄에 라벨+숫자 조합(..._exit_code N건)을 쓰지 않게 한 뒤, invalid_verification_exit_code가 0건이면 가설 성립. 같은 조건에서도 계속 나오면 가설 기각.
  • 롤백/재검토 조건: 적용 후 guardian이 3회 연속 같은 코드로 반려되면 문서 방지안이 아니라 게이트 쪽(정규식 또는 덮어쓰기 로직)을 codex에 의뢰한다.

guardian 점검 태스크용 4블록 작성 예시

(프로세스/DB/크론/큐/디스크 5종. 라벨은 줄 맨 앞에, 영문 코드명 뒤에 숫자를 붙이지 말 것)

예시 1. DB 반려 집계

결론: bus_commands에서 guardian 소유 반려 22건(needs_evidence 21, failed 1)을 조회해 차단 사유 7종으로 분류했다. 코드·설정은 수정하지 않았다.
근거: sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT status,count(*) FROM bus_commands WHERE claimed_by='guardian' GROUP BY status;" → 3행 반환, 조회 2026-10-11 14:13 KST
검증: ls -l /Users/ron/knowledge-agent/400-reports/261011_claude_guardian_rejection_prevention.md → 파일 존재 확인, exit code 0
근거파일: /Users/ron/knowledge-agent/400-reports/261011_claude_guardian_rejection_prevention.md:37 "| 합계 | | | 22 | |"

예시 2. 프로세스 점검

결론: 게이트웨이 PID 38542가 실행 중이고 열린 파일이 /Users/ron/.hermes/* 임을 확인했다. 재시작·종료는 하지 않았다.
근거: ps -axo pid,lstart,command | grep 'gateway run' → 1행, lsof -p 38542 → state.db 확인, 조회 YYYY-MM-DD HH:MM KST
검증: ps -p 38542 -o pid= → 38542, exit code 0
근거파일: /Users/ron/.hermes/logs/gateway.log:<마지막 줄 번호> "<해당 줄 원문 1줄>"

예시 3. 크론 점검

결론: 크론 5c45c26045be가 enabled=true, 다음 실행 일요일 09:00 KST임을 확인했다.
근거: /Users/ron/.hermes/cron/jobs.json 에서 id 5c45c26045be 조회 → 1건, 조회 YYYY-MM-DD HH:MM KST
검증: grep -c '5c45c26045be' /Users/ron/.hermes/cron/jobs.json → 1, exit code 0
근거파일: /Users/ron/.hermes/cron/jobs.json:<줄번호> "\"id\": \"5c45c26045be\","

(주의: 크론 근거 경로는 /Users/ron/.hermes/cron/jobs.json이다. /Users/ron/.hermes/workspace/jobs.json은 존재하지 않아 #41323이 execution_artifact_path_not_found로 막혔다.)

예시 4. 큐/디스크

결론: 에이전트별 queued 건수 최대 N건, 디스크 사용률 N%를 확인했고 기준치 이내였다.
근거: sqlite3 -readonly ...ops_multiagent.db "SELECT claimed_by,count(*) FROM bus_commands WHERE status='queued' GROUP BY 1;" → N행, df -h / → N%, 조회 YYYY-MM-DD HH:MM KST
검증: df -h / | tail -1 → 사용률 N%, exit code 0
근거파일: /Users/ron/.hermes/logs/agent-queue-guardian.log:<줄번호> "<원문 1줄>"

금지 목록 (이번 22건에서 실제로 확인된 형태만)

  1. "결론: 작업 결과가 정리됨" 같이 무엇을 했는지 없는 문장 (#40902).
  2. 결론이 중간에 끊긴 문장 (#40633).
  3. 존재하지 않는 경로를 근거로 인용 (#41323의 workspace/jobs.json, 정책 604~608행의 자기참조 로그 경로).
  4. "검증:" 줄에 명령 없이 "확인함/통과"만 쓰는 것, 또는 exit code 숫자 생략 (A·E·F 10건).
  5. 반려 라벨 이름 바로 뒤에 숫자를 붙여 쓰는 것 (missing_verification_exit_code 4건 형태).

한계 (확인하지 못한 것)

  • 22건의 원문 전체: DB에는 게이트 문구로 덮인 상태만 있고 원문은 약 200자만 남아, 라벨별 누락을 건별로 직접 확인하지 못했다. 분류는 "차단 사유" 코드 기준이다.
  • B 분류 5건 중 정규식 오탐이 원인인 것은 #40869 1건만 원문에서 문자열을 직접 확인했다.
  • guardian 실행 프롬프트에 §9-3-1 템플릿이 들어 있는지 여부.