guardian 완료보고 종료코드 누락·허구 경로 반려 반복 방지안 (#40260·#40275·#40276·#40282)
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.py7086~7106행. codex만_codex_has_verification_result_field()(6832행)로 exit code 숫자를 요구하고, 나머지는 "검증 결과: 통과" 같은 문구도 인정한다(7087행 주석 "[패치 2026-09-01] … exit code 숫자 요구는 codex 실행 결과 검증 전용으로 유지"). - 서버:
scripts/server.py746행_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.py333행 guardian 프롬프트:"검증: <실행한 검증 명령> → <실제 결과값/exit code>\n"— "/"가 "둘 중 하나"로 읽힌다.config/agent_completion_submission_standard.md579행 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.py720~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 위임 후보 (코드 미수정 — 대상 파일·함수만)
- 제출 전 자가 점검 자동화(#1973 본체) —
scripts/agent_queue_worker.py완료 제출 직전 경로(_completion_required_evidence_gaps호출부, 7086~7106행 부근). 서버 게이트scripts/server.py::_completion_storage_required_result_gaps()(746행)와 같은 판정을 워커에서 먼저 돌려 걸리면 부족 항목을 붙여 1회 보완 요청 후 제출. - 워커·서버 exit code 기준 통일 —
scripts/agent_queue_worker.py7090행if agent_key == "codex":분기와scripts/server.py807행. 한쪽 기준으로 맞춘다(서버가 최종 관문이므로 워커를 서버 기준으로 올리는 방향이 반려 0건에 가깝다). 어느 쪽을 택할지는 codex 검토 후 결정. - guardian 프롬프트 문구 수정 —
scripts/agent_registry.py333행→ <실제 결과값/exit code>를→ <실제 결과값>, exit code <N>으로, G2 경로표 요약 3줄 추가. 다른 에이전트(240/268/301/382/427/472/503행)도 같은 문구라 동시 검토 대상. - 경로 소실 확인 — #40260·#40293 제출문에서 경로 자리가
로 비어 있다. 공개용 정리 함수(표준 §9-3 "필수 주의"가 지목한format_harry_public_brief()/contains_internal_trace())가 절대경로를 지우는지 codex가 재현 확인. 지워진다면 G2의 절대경로 규칙이 오히려 소실을 부를 수 있으므로 우선순위 높음.
6. 문서 쪽 정정 필요 항목 (cowork 다음 정책 개정 때)
config/agent_completion_submission_standard.md579행 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를 우선 실행.