virtual-insanity
← 리포트 목록

guardian 완료보고 검증값 누락 방지안 — 점검 유형별 한 줄 템플릿 6종

2026-10-14 claude [guardian, completion-evidence, missing_verification_value, exit-code, 제안서]

guardian 완료보고 검증값 누락 방지안 (문서 제안, 코드 변경 없음)

1. [권고]

1순위: guardian 완료보고의 "검증:" 줄을 점검 유형별 한 줄 템플릿 6종 중 하나로 고정한다. - 형식은 검증: <명령 한 개> → <관측 수치>, exit code 0 이다. 명령은 끝에 ; echo "exit code $?"를 붙이거나, 마지막 파이프 단계가 판정하는 형태로 써서 exit code 0이 실제로 나오게 한다. - 이유: 게이트(_codex_has_verification_result_field)가 "검증:" 값에서 exit code N 리터럴을 찾고, 없으면 missing_verification_exit_code, 0이 아니면 invalid_verification_exit_code로 반려한다. guardian의 점검 명령은 "문제를 찾으면 비0으로 끝나는" 것이 많아 판정과 exit code가 어긋나기 쉽다. - 기대효과: 같은 유형 반려(guardian 누적 exit code 계열 20건)를 템플릿 적용 후 7일간 0~1건으로 줄인다(목표 90% 이상 감소).

2순위: guardian 전용 프롬프트 파일에 이 6종을 그대로 넣도록 codex에 위임한다(실행은 codex, 이 문서는 제안만). - 이유: 정책서 §9-3-1에 "시스템 점검용 예시" 1종은 있으나, 그 예시는 → exit 1로 끝나서 곧바로 invalid_verification_exit_code가 되는 모양이다. guardian 전용 프롬프트 파일은 2026-09-08 실측에서 없었다(미재확인). - 기대효과: guardian이 임기응변 형식으로 제출하는 경우를 0으로 만든다.

2. [현황] (조회 2026-10-14 09:10 KST, sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db)

  • 작업 지시문의 "missing_verification_value 16건"은 DB에서 그대로 재현되지 않았다. 확인한 범위(bus_commands+bus_commands_archive의 guardian, status가 needs_evidence 또는 failed, 합 417건)에서 result_note에 missing_verification_value가 들어간 건은 1건이다. 같은 계열의 exit code 라벨은 missing_verification_exit_code 14건, invalid_verification_exit_code 6건, invalid_verification_result 5건, missing_verification_result 5건이다. 즉 "검증값 누락" 문제의 실체는 대부분 exit code 쪽이다. (16건이라는 수치의 출처는 미확인 — 버스 메시지 원문을 열지 않았다.)
  • guardian 현재 상태: needs_evidence 30건, failed 3건. 최근 failed 3건(#41656, #41657, #41659)은 "검증 근거가 없음/확인 보류"형이고, #41659는 execution_artifact_path_not_found:/Users/ron/.hermes/workspace/jobs.json(실존하지 않는 경로 인용)이 겹쳤다.
  • 문서 쪽 현황:
  • config/agent_completion_submission_standard.md 59~60행: "검증값 … 실행한 검증 명령 + 그 결과(수치, exit code, pass/fail 카운트 등). 없으면 missing_verification_value."
  • 같은 문서 182~195행: 부재 확인은 ! grep -rlq …; echo "exit code $?" 형태로 쓰고, exit=0 표기는 못 읽으며, 결과값에 "없음/없다"를 쓰면 반려.
  • 같은 문서 570~588행(§9-3-1): guardian 예시가 → exit 1, … (2/4 무응답)로 끝난다. 예시 자체가 비0 exit를 정답처럼 보여준다.
  • config/completion_evidence_policy.md 93행: "missing_verification_value — 실행한 검증 명령 + 결과값(수치/exit code)".
  • 같은 문서 1644~1731행(v11): guardian 반려율 75.0%(6/8, 2026-09-08)와 전용 프롬프트 부재, 자기참조 경로 금지.
  • 게이트 코드(읽기만 함): scripts/agent_queue_worker.py 7081~7090행 정규식, 7180~7209행 판정 함수. 정규식은 exit code/exit_code/return code/returncode/rc 뒤 숫자만 읽는다. "없음|없다|미실행|예정|대기|확인 못" 단어가 "검증:" 값에 있으면 invalid_verification_result.

3. 템플릿 6종 (모두 한 줄, 값은 2026-10-14 09:10 KST 실제 실행 결과)

공통 규칙 - "검증:" 한 줄에 명령 → 관측 수치, exit code 0 순서로 쓴다. - 판정이 "문제 있음"이어도 exit code는 점검 명령 자체의 종료 코드다. 이상 건수는 수치로 쓰고, 명령은 정상 종료(0)가 나오게 짠다. 이상이 있어서 보고하는 경우에도 "점검 실행은 성공(exit code 0), 이상 N건"으로 쓴다. - 결과값에 "없음/없다/예정/확인 못"을 쓰지 않고 0건, 0개처럼 숫자로 쓴다. - "근거파일:"에는 점검 대상(로그/DB/설정) 실존 경로를 쓰고, completion_evidence_blocked.jsonl 같은 게이트 자신의 로그는 쓰지 않는다.

템플릿 1 — 프로세스

검증: pgrep -f "agent_queue_worker.py --agent guardian" | wc -l → 1개 기동 중, exit code 0
  • 이유: pgrep 자체는 0개일 때 exit 1이다. | wc -l로 마지막 단계를 세는 명령으로 바꿔 exit code를 0으로 고정하고, 판정은 숫자(1개)로 한다. 0개면 "0개 기동 중, exit code 0"이라고 쓰고 결론에 이상으로 적는다.
  • 실측: 위 명령 → 1, 종료 코드 0.

템플릿 2 — DB

검증: sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "PRAGMA integrity_check;" → ok, exit code 0
  • 실측: 출력 ok, 종료 코드 0. 읽기 전용 옵션으로 DB를 바꾸지 않는다.

템플릿 3 — 크론

검증: python3 -c "import json;j=json.load(open('/Users/ron/.hermes/cron/jobs.json'))['jobs'];print(len(j),sum(x.get('lastStatus')=='running' for x in j),sum((x.get('consecutiveErrors') or 0)>=3 for x in j))" → 전체 160개, running 0개, 연속오류 3회 이상 0개, exit code 0
  • 실측: 출력 160 0 0, 종료 코드 0. 크론 장부는 ~/.hermes/cron/jobs.json(라이브)만 쓴다. ~/.hermes-next/cron/jobs.json은 정지 장부라 근거로 쓰지 않는다.
  • 주의: 존재하지 않는 workspace/jobs.json을 근거로 쓰다가 #41659가 execution_artifact_path_not_found로 반려됐다.

템플릿 4 — 큐

검증: sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT COUNT(*) FROM bus_commands WHERE status='queued';" → queued 0건, exit code 0
  • 실측: 조회 시점 에이전트별 queued 행이 없었다(0건). 종료 코드 0. 에이전트별 상세가 필요하면 GROUP BY claimed_by를 붙이고 줄 끝 수치에 건수를 쓴다.
  • 주의: 이 명령은 COUNT(*)라 항상 한 행이 나오고 exit code 0이다. 템플릿 1~6 중 판정이 숫자로만 갈리는 가장 단순한 형태다.

템플릿 5 — 디스크

검증: df -P /Users/ron | awk 'NR==2{print $5}' → 사용률 83%, exit code 0
  • 실측: 출력 83%, 종료 코드 0. 임계값(예: 90%)은 결론 줄에 판정으로 쓰고 검증 줄에는 관측값만 쓴다.

템플릿 6 — 설정 드리프트

검증: python3 -c "import yaml;yaml.safe_load(open('/Users/ron/.hermes/config.yaml'));print('yaml_ok')" → yaml_ok, exit code 0
  • 실측: 출력 yaml ok, 종료 코드 0. 운영 설정의 canonical은 ~/.hermes/config.yaml(라이브 게이트웨이가 물고 있는 파일)이다. ~/.hermes-next/config.yaml은 대시보드용이라 드리프트 기준으로 쓰지 않는다.
  • 두 설정을 비교하는 드리프트 점검은 diff -q A B; echo "exit code $?" 대신 diff -q A B | wc -l → 0줄(차이 0건), exit code 0로 쓴다(diff가 차이를 찾으면 exit 1이라서).

4. 완료보고 전체 예시 (템플릿 1 적용)

결론: guardian 워커 프로세스 점검을 실행해 기동 1개를 확인했다.
근거: source_log_path: /Users/ron/.hermes/logs/agent-queue-guardian.log, 조회 2026-10-14 09:10 KST
검증: verification_command: pgrep -f "agent_queue_worker.py --agent guardian" | wc -l → 1개 기동 중, exit code 0
근거파일: /Users/ron/.hermes/logs/agent-queue-guardian.log:<마지막 확인한 줄 번호> "<그 줄 원문 1줄>"
다음 행동: 추가 조치 없음

5. [리스크]

  • 파이프(| wc -l, | awk)는 앞 명령의 실패를 가린다. 템플릿 1·5는 프로세스 0개나 df 실패도 exit code 0으로 보일 수 있으므로 반드시 수치(1개, 83%)를 같이 쓴다. 수치가 없는 "exit code 0"만으로는 점검 증거가 되지 않는다.
  • exit code 0을 맞추려고 || true를 붙이면 게이트는 통과하지만 위조에 가깝다. 이 안은 || true를 쓰지 않는다.
  • 게이트 함수 직접 호출 결과(2026-10-14, 읽기 전용 호출, agent_queue_worker._codex_has_verification_result_field): 템플릿 1~6의 "검증:" 줄 6개와 verification_command: 라벨을 붙인 4절 예시 1개가 모두 (True, '')로 통과했다. 대조군 → exit=0은 missing_verification_result, → exit 1, 무응답도 missing_verification_result로 반려됐다. 이 호출은 "검증:" 줄 한 개의 형식만 본 것이고, 완료보고 전체(근거·근거파일 포함)가 completion_required_evidence_gaps() 전체 게이트를 통과하는지는 돌리지 않았다(미확인).
  • guardian 전용 프롬프트에 실제로 들어가기 전에는 guardian이 이 템플릿을 쓰지 않는다(문서만으로는 배선되지 않음).

6. [검증방법]

  • 지표: 적용 후 7일간 guardian의 missing_verification_exit_code·invalid_verification_exit_code·missing_verification_value 합계 0~1건(현재 누적 21건).
  • 측정 명령: sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT COUNT(*) FROM bus_commands WHERE claimed_by='guardian' AND status IN ('needs_evidence','failed') AND updated_at>='<적용일>' AND (result_note LIKE '%verification_exit_code%' OR result_note LIKE '%missing_verification_value%');"
  • 롤백 조건: 적용 후 3회 연속 같은 사유가 재발하면 문서 문구 문제가 아니라 생성 로직 문제로 보고 codex에 템플릿 강제 삽입을 위임한다.