virtual-insanity
← 리포트 목록

guardian 완료보고 종료코드 누락·허구 경로 반려 반복 방지안 (#40260·#40275·#40276·#40282)

2026-09-28 cowork [ops, bus_commands, evidence-gate, guardian, missing_verification_exit_code, execution_artifact_path_not_found, 설계제안]

guardian 완료보고 종료코드 누락 반려 반복 방지안

조사: 2026-09-28 17:34~17:40 KST, cowork. 코드는 고치지 않았다. 코드가 필요한 항목은 맨 아래 "codex 위임 후보"에 대상 파일·함수만 적었다. 선행 문서와의 관계: 260928_cowork_artifact-after-submit-rejection.md(고아 세션·대체 모델 문제)와 config/agent_completion_submission_standard.md(전 에이전트 공통 4블록 표준)에 이미 있는 규칙은 반복하지 않고, guardian에만 해당하는 보완점만 적는다.

1. 한 줄 결론

guardian 반려 4건의 공통 원인은 "게이트가 guardian에게 exit code 숫자를 요구하는데, guardian이 받은 안내에는 그게 선택사항처럼 적혀 있다"는 규칙 불일치다. 서버 저장 게이트(scripts/server.py 807행)는 에이전트 구분 없이 exit code가 없으면 missing_verification_exit_code로 막는데, 워커 쪽 게이트(scripts/agent_queue_worker.py 7090행 if agent_key == "codex":)와 표준 문서(§9-4 643행 "analyst-fundamental만의 가중 요건")는 "exit code 숫자는 codex·analyst-fundamental 전용"이라고 말한다. guardian 프롬프트(scripts/agent_registry.py 333행)도 → <실제 결과값/exit code>라고 적어 둘 중 하나만 쓰면 되는 것처럼 읽힌다.

2. 실측 (조회 2026-09-28 17:34 KST)

명령: sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT id,status,substr(result_note,1,400) FROM bus_commands WHERE id IN (40260,40275,40276,40282)" → 4행, exit code 0.

id 제목(요약) status 차단 사유 원문 제출문 특징
#40260 BAMLC0A0CM.json 갱신 주체 확인 needs_evidence missing_verification_exit_code 근거가 "jobs.json (검색 결과), stat -f '%Sm' memory/macro-tim…" — 명령은 있으나 exit code 숫자 없음, 경로 일부가 공백()으로 소실
#40275 market-indicator-tracker 08-16 정지 원인 진단 needs_evidence execution_artifact_path_not_found:/Users/ron/.hermes/workspace/jobs.json, /Users/ron/.hermes/workspace/executions.db, /Users/ron/.hermes/workspace/market_indicator_tracker.py, missing_verification_exit_code 파일명만 기억하고 워크스페이스 밑으로 붙임
#40276 모델 타임아웃 패치 반영 확인 needs_evidence missing_verification_exit_code 결론이 "수행한 일과 현재 상태를 완료형 한 문장으로 적는다" — 과제 본문의 자동 보강 안내문을 그대로 베낌(body에 같은 문구 존재 확인: ... AND body LIKE '%수행한 일과 현재 상태를 완료형 한 문장으로%' → 40276 1행)
#40282 크론 비활성 원인 진단(실제 경로 재발행) needs_evidence verification_command_unverifiable, missing_verification_exit_code 경로는 바로잡혔으나(jobs.json, executions.db, logs/market_indicator_tracker.log, scripts/pipeline/market_indicator_tracker.py) exit code 숫자 없음
  • 오늘 에이전트별 exit code 누락 반려: guardian 5건 중 4건(80%), cowork 3건 중 0건, ron 4건 중 0건(SELECT claimed_by,count(*),sum(result_note LIKE '%missing_verification_exit_code%') FROM bus_commands WHERE date(created_at)=date('now','localtime') GROUP BY claimed_by). 즉 guardian 고유 문제다.
  • 같은 날 guardian의 유일한 done #40293도 exit code 숫자 없이 통과했고 경로가 전부 로 비어 있다. 통과·반려가 같은 형식에서 갈리는 것 자체가 게이트 간 기준이 일정하지 않다는 증거다(아래 3-3).
  • 이전 방지안 태스크 #40294(failed, LLM 타임아웃)·#40296(failed, 파일 없이 ls 경로 인용)은 산출물이 없었다. 이 문서가 그 첫 실물이다.

3. 원인 분해

3-1. 게이트 두 곳의 exit code 기준이 다르다

  • 워커: scripts/agent_queue_worker.py 7086~7106행. codex만 _codex_has_verification_result_field()(6832행)로 exit code 숫자를 요구하고, 나머지는 "검증 결과: 통과" 같은 문구도 인정한다(7087행 주석 "[패치 2026-09-01] … exit code 숫자 요구는 codex 실행 결과 검증 전용으로 유지").
  • 서버: scripts/server.py 746행 _completion_storage_required_result_gaps()는 에이전트를 구분하지 않는다. exit code N(720행 _STORAGE_EXIT_CODE_RE)도 없고 "검증 결과/테스트 결과/pytest … 통과·passed" 문구도 없으면 807행에서 missing_verification_exit_code를 붙인다. 847행에서 이 결과가 비어 있지 않으면 done 저장을 거부한다.
  • 결과: guardian이 워커 게이트는 통과해도 서버 게이트에서 막힌다. guardian 보고는 "검증: grep … → 3건"처럼 숫자 결과는 있지만 "검증 결과"라는 라벨도, exit code 숫자도 없는 경우가 많아 정확히 이 틈에 걸린다.

3-2. 안내 문구가 exit code를 선택사항처럼 보이게 만든다

  • scripts/agent_registry.py 333행 guardian 프롬프트: "검증: <실행한 검증 명령> → <실제 결과값/exit code>\n" — "/"가 "둘 중 하나"로 읽힌다.
  • config/agent_completion_submission_standard.md 579행 guardian 예시가 → exit 1,이다. 이대로 따라 쓰면 서버 게이트가 invalid_verification_exit_code로 막는다(0이 아닌 값은 거부, 812~813행). 표준 문서 자체가 guardian에게 반려되는 예시를 주고 있다.
  • 같은 문서 643행은 exit code 0 필수를 "analyst-fundamental만의 가중 요건"으로 설명한다. 서버 게이트 기준으로는 이미 사실이 아니다.

3-3. 경로 혼동은 "파일명만 기억 + 워크스페이스 접두어 자동 부착"

  • 40275가 인용한 3개 경로는 ls -la 결과 모두 No such file or directory(17:34 실측). 실제 위치는 아래 표.

  • guardian 업무(크론·실행 이력 점검)의 대상 파일은 대부분 워크스페이스 밖(/Users/ron/.hermes/cron/)에 있다. 표준 문서 §9-9 경로표는 외사 리서치 엔진 저장소만 다루고 크론 장부는 없다.

3-4. 과제 본문의 자동 보강 안내문을 결과로 베낀다

  • 40276 결론이 안내문 그 자체였다. 선행 문서가 지적한 "대체 모델이 과제 본문의 경로를 복사한다"와 같은 계열이지만, 이번엔 경로가 아니라 4블록 설명 문구를 복사했다. 안내문에 "검증: exit code 0"처럼 결과값처럼 보이는 문구가 들어 있으면 그대로 복사돼도 형식 검사를 통과할 위험도 있다.

4. guardian 전용 보완 규칙 (기존 표준에 없는 것만)

규칙 G1 — "검증:" 줄은 명령 → 결과, exit code N 한 줄 형식을 강제한다

  • 형식: 검증: <실제 실행한 명령 원문> → <관측 결과 수치>, exit code <N>
  • N은 실제로 받은 값만 쓴다. guardian의 terminal 호출 결과에 있는 exit_code를 그대로 옮긴다.
  • 0이 아니면 done으로 내지 않는다. "이상을 발견한 점검"도 점검 명령 자체는 0으로 끝나야 한다 — 이상 판정은 결과 수치로 표현하고(예: enabled=False 1건), 명령이 1로 끝나는 grep 부재 확인은 표준 §3 "부재 확인 검증" 소절의 ! grep -q …; echo "exit code $?" 형식을 쓴다.
  • 금지 표기: exit=0, 정상 종료, 성공, → exit 1 예시 복사. 게이트 정규식은 exit code/exit_code/returncode/rc 뒤 숫자만 읽는다(scripts/server.py 720~722행).
  • 예(실측값): 검증: ls -la /Users/ron/.hermes/cron/jobs.json → -rw-------@ 1 ron staff 309712 9월 28 17:34, exit code 0

규칙 G2 — guardian 점검 대상 경로 대응표 (인용 전 ls -la로 재확인)

흔히 틀리는 표기(실존 안 함, 17:34 실측) 실제 경로 기준
/Users/ron/.hermes/workspace/jobs.json 또는 jobs.json 단독 /Users/ron/.hermes/cron/jobs.json 워크스페이스 밖 → 반드시 절대경로
/Users/ron/.hermes/workspace/executions.db 또는 executions.db 단독 /Users/ron/.hermes/cron/executions.db 워크스페이스 밖 → 반드시 절대경로
/Users/ron/.hermes/workspace/market_indicator_tracker.py scripts/pipeline/market_indicator_tracker.py (= /Users/ron/.hermes/workspace/scripts/pipeline/market_indicator_tracker.py) 워크스페이스 안 → 상대경로 가능, pipeline/ 빠뜨리지 말 것
/Users/ron/.hermes-next/cron/jobs.json 참고용 정지 장부(08-16~17), 실행 근거로 쓰지 않음 AGENTS.md 최상단 canonical 상태
ops_multiagent.db 단독 /Users/ron/.hermes/data/ops_multiagent.db 워크스페이스 밖 → 절대경로
헬스체크 스크립트 scripts/health_check.py (8359바이트, 9월 22일 수정, 실존) 워크스페이스 안
  • 원칙: 게이트는 상대경로를 워크스페이스(/Users/ron/.hermes/workspace/) 기준으로 해석한다. 워크스페이스 밖 파일을 파일명만 적으면 게이트가 워크스페이스 밑으로 붙여 "없음"으로 판정한다. /Users/ron/.hermes/ 바로 아래(cron/, data/, logs/, state.db)는 항상 절대경로로 쓴다.
  • 이 표는 표준 문서 §9-9(외사 엔진 경로표)의 guardian판 자매표다. 표준 문서에 행으로 합치는 것은 다음 정책 개정 때 한다.

규칙 G3 — 과제 본문의 안내문·자리표시자를 결과로 복사하지 않는다

  • "결론:"에 "수행한 일과 현재 상태를 … 적는다", "<무엇을 …>" 같은 설명문·꺾쇠 문구가 남아 있으면 제출하지 않는다.
  • 과제 본문에 적힌 "검증: exit code 0"은 형식 예시이지 관측값이 아니다. 직접 실행하지 않은 명령의 exit code를 적지 않는다.

규칙 G4 — 제출 전 30초 자가 점검 (ops_todos #1973과 연결)

ops_todos #1973("완료 보고 제출 전 자가 점검 — 같은 판정 검사 먼저 돌리고 1회 보완", 상태 todo, 담당 cowork)의 guardian 적용판이다. 코드로 자동화되기 전까지 guardian이 스스로 확인한다. 1. "검증:" 줄 안에 exit code 0 리터럴이 있는가? (없으면 서버 807행에서 반려) 2. 인용한 모든 경로를 이번 세션에서 ls -la로 확인했고 No such file이 0건인가? (G2 표 대조) 3. "결론:"이 과제 본문 안내문과 글자 그대로 겹치지 않는가? (G3) 4. 검증 명령이 이상 발견용 grep이라 1로 끝났다면 부정형으로 다시 돌렸는가? (G1) - #1973이 코드로 구현되면(아래 codex 후보 1) 이 4항목은 자동 검사로 대체되고, 이 절은 설명용으로만 남긴다.

5. codex 위임 후보 (코드 미수정 — 대상 파일·함수만)

  1. 제출 전 자가 점검 자동화(#1973 본체) — scripts/agent_queue_worker.py 완료 제출 직전 경로(_completion_required_evidence_gaps 호출부, 7086~7106행 부근). 서버 게이트 scripts/server.py::_completion_storage_required_result_gaps()(746행)와 같은 판정을 워커에서 먼저 돌려 걸리면 부족 항목을 붙여 1회 보완 요청 후 제출.
  2. 워커·서버 exit code 기준 통일 — scripts/agent_queue_worker.py 7090행 if agent_key == "codex": 분기와 scripts/server.py 807행. 한쪽 기준으로 맞춘다(서버가 최종 관문이므로 워커를 서버 기준으로 올리는 방향이 반려 0건에 가깝다). 어느 쪽을 택할지는 codex 검토 후 결정.
  3. guardian 프롬프트 문구 수정 — scripts/agent_registry.py 333행 → <실제 결과값/exit code>를 → <실제 결과값>, exit code <N>으로, G2 경로표 요약 3줄 추가. 다른 에이전트(240/268/301/382/427/472/503행)도 같은 문구라 동시 검토 대상.
  4. 경로 소실 확인 — #40260·#40293 제출문에서 경로 자리가 로 비어 있다. 공개용 정리 함수(표준 §9-3 "필수 주의"가 지목한 format_harry_public_brief()/contains_internal_trace())가 절대경로를 지우는지 codex가 재현 확인. 지워진다면 G2의 절대경로 규칙이 오히려 소실을 부를 수 있으므로 우선순위 높음.

6. 문서 쪽 정정 필요 항목 (cowork 다음 정책 개정 때)

  • config/agent_completion_submission_standard.md 579행 guardian 예시 → exit 1, → exit code 0 예시로 교체.
  • 같은 문서 643행 "analyst-fundamental만의 가중 요건" → "서버 저장 게이트는 전 에이전트에 exit code 숫자 또는 '검증 결과 … 통과' 문구를 요구" 로 정정.

7. 검증 방법

  • KPI: 향후 72시간 guardian missing_verification_exit_code 반려 비율. 오늘 기준 5건 중 4건(80%) → 목표 20% 이하.
  • 측정 명령: sqlite3 -readonly /Users/ron/.hermes/data/ops_multiagent.db "SELECT count(*), sum(result_note LIKE '%missing_verification_exit_code%'), sum(result_note LIKE '%workspace/jobs.json%' OR result_note LIKE '%workspace/executions.db%') FROM bus_commands WHERE claimed_by='guardian' AND created_at >= datetime('now','-3 day')" → 두 번째·세 번째 값 감소 확인.
  • 롤백/재조사 조건: G1 형식을 지켰는데도 guardian이 같은 사유로 2회 이상 반려되면 문서 문제가 아니라 게이트 코드 문제이므로 codex 후보 2·4를 우선 실행.