Files
multi-agent-mux/.agents/reports/planner-reviewer-claude-01/report-aa16fa5c.md
T
GodopuandClaude Fable 5.1 1cc84282f3 docs(reports): archive v4.4.3 unanimous PASS review reports (Issues #10, #11, #13, #15)
Final-round reports of the fix/issue-10-11-13-15 review loop: planner-reviewer-claude-01
(aa16fa5c), reviewer-agy-01 (0f41ea47), reviewer-grok-01 (3ea06fb6) and
planner-reviewer-codex-01 (79204d61), all [VERDICT: PASS] on fae70c1.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
2026-09-13 10:53:59 +09:00

8.8 KiB

🔍 Review Report — Job aa16fa5c (branch fix/issue-10-11-13-15 루프 2회차, HEAD fae70c1)

  • Reviewer: planner-reviewer-claude-01 (role: planner,reviewer) · 2026-09-13
  • 대상: git log bd3df89..HEAD — c82ea75, 0282312(release v4.4.3), 7610258(N1), f5a6575(테스트 uuid4), fae70c1(codex R1/R2). 앞선 라운드에서 PASS 한 부분은 회귀 여부 중심으로, 새 커밋 3건 중 fae70c1 은 정밀 검토했다(7610258·f5a6575 는 앞선 라운드에서 정밀 검토했고 이번에는 회귀만 확인).
  • 방법:
    • 코드 정독
    • 샌드박스 재현: 임시 HOME 을 $TMPDIR 아래 생성하고 실행 전 resolve_home() 이 그곳인지 확인했다. 대화 id 는 모두 런타임 uuid4().
    • 선택 테스트(실제 .mam/jobs 스냅샷 비교)
    • 정적 검사
    • 리뷰 중 45초 간격 progress heartbeat 발행. 코드 수정 없음.
  • 안전 규칙 준수: 실제 홈이나 등록된 orchestrator UUID 로 purge 를 실행하지 않았다. ../multi-agent-mux-b2 는 건드리지 않았다.

0. 직전 루프(반복 3, HEAD f5a6575) 결과와 처리

리뷰어 판정
planner-reviewer-claude-01(037af8e0) · reviewer-agy-01(433a74dc) · reviewer-grok-01(1752c893) PASS
planner-reviewer-codex-01(f315859f) NOT PASS — R1: agy in-use 검사가 DB 만 lsof 에 넘겨 presence lock 만 연 보유자를 놓침 / R2: DB 가 없는 고아 부속 파일은 purge 대상으로 해결되지 않음

creator 는 반론 없이 fae70c1 로 두 지적을 반영하고 테스트 2개를 더했다. 검증 잡(9c3e6f9b)에서 250 passed 를 확인했고, VERSIONS.md 의 신규 테스트 수가 낡았다고 스스로 기록했다(§2-(3)).

1. 새 커밋 정밀 검토

(1) 7610258 base.conversation_in_use — ✅ (회귀 없음, 잔여 한계 R-1)

  • 세션 env 검사: AGENT_SESSION_ENV 5종 중 하나가 uuid 와 같으면 즉시 사용 중이다. 앞선 라운드에서 이 세션으로 실측했다(env 만으로도, env 없이 argv 만으로도 True).
  • 헬퍼 사슬 제외는 첫 에이전트 CLI 조상에서 멈춘다. _is_agent_cli 는 첫 옵션 이전 토큰의 basename 을 본다. 토큰 판독 사례:
    • node …/claude …, env X=1 claude …, /bin/sh …/agy … → 에이전트 ✓
    • sh -c "…", bash orc_onboard.sh --remove …, python -m lib_py.agents purge … → 에이전트 아님(첫 옵션에서 판독 중단) ✓
  • 오탐: 위치 인자의 basename 이 우연히 에이전트 이름인 비-에이전트 프로세스(vim notes/claude, python tools/codex)는 에이전트로 판정된다. 다만 걷기가 거기서 멈춰도 purge 와 orc_onboard.sh 는 그 아래 헬퍼 사슬에 남으므로, 그런 프로세스가 둘 사이에 끼어야만 영향이 있다. 사실상 영향 없음.
  • 미탐(R-1, 앞선 라운드 재현 A): 에이전트 이름으로 보이지 않는 조상(python -m <agent>, node …/cli.js)이 uuid 를 argv 에 갖고 있고 세션 env 도 없으면 헬퍼 사슬로 제외된다. 현재 배포(claude)는 이름과 env 양쪽으로 잡히므로 비차단이다. "알려진 헬퍼만 제외" 방식을 후속으로 권장한다.

(2) fae70c1 agy in-use · has_artifacts · 해결기 2단계 — ✅ (잔여 한계 R-a)

  • 코드:

    • AgyAgentAdapter._artifact_paths(agy.py:77-84): DB, -wal/-shm/-journal, brain/<uuid>, annotation, presence lock 7경로.
    • has_artifacts(:86-90): 그중 하나라도 있으면 True.
    • conversation_in_use override(:92-96): 7경로 전부를 lsof 에 넘긴다.
    • BaseAgentAdapter.has_artifacts 기본값(base.py:194-200): uuid in path and os.path.exists(path) — 기존 해결기의 경로 폴백과 동일하다. 그래서 claude·hermes·grok·codex 의 해결은 그대로이고, 공유 DB 인 opencode 는 경로에 uuid 가 없어 매치되지 않는다.
    • _resolve_purge_target(__main__.py:34-39): 2단계가 has_artifacts 로 바뀌었다(1단계 revalidate verify_artifact 는 그대로).
  • 샌드박스 재현(HEAD fae70c1, 매 케이스 새 uuid4):

    경우 결과
    R1: 보유자가 presence lock 만 flock 으로 열고 argv·env 어디에도 uuid 가 없음(argv 에 uuid 없음을 확인) adapter.conversation_in_use → True, CLI purge → rc 4, 존재하던 4조각 모두 보존
    R2: DB 없이 -wal + annotation 만 남음, agy 명시 rc 0, agent agy, 2조각 purge, residual []
    R2, auto rc 0, agent agy, 2조각 purge, residual []
    아무것도 없음 rc 5, agent null(미해결과 구분 유지)
    회귀: claude transcript 만 있음 auto → claude 로 해결
    회귀: opencode 공유 저장소만 있음, 무작위 uuid has_artifacts False, auto → rc 5
  • R-a (이미 보류된 항목, 이번 재현으로 증거 추가):

    • 어댑터 purge_artifacts 는 여전히 lock 을 지울지 정할 때만, 그것도 DB·brain·annotation 을 지운 뒤에 in-use 를 본다.
    • 이 메서드를 직접 부르는 stop_session.sh:329 경로에서 lock 보유자가 있으면 DB·brain·annotation 을 지우고 lock 만 남긴다(재현: 3조각 삭제, lock 보존).
    • CLI·orc_onboard 경로는 파괴 작업 전에 7경로 전체로 검사하므로 codex R1 의 "파괴 전 검사" 요구를 충족한다. stop_session 은 herdr 사망 pre-gate 를 거치므로 남는 경우는 "다른 프로세스가 같은 대화를 쥔" 드문 상황이다.
    • 권장: purge_artifacts 첫머리에서 conversation_in_use 가 참이면 빈 목록과 경고로 전체를 건너뛸 것(후속 이슈).

2. 검증 항목별 결과

# 항목 결과
(1) 7610258 헬퍼 사슬·_is_agent_cli ✅ §1-(1). R-1 비차단
(2) fae70c1 agy in-use·has_artifacts·해결기 ✅ §1-(2). 다른 어댑터 해결 영향 없음. R-a 비차단(보류 항목)
(3) orc_onboard.sh 흐름 · SKILL.md · VERSIONS.md 정합 ✅ purge 선행·exit 4(--yes 없음)/5(in-use, 등록 유지)·dry-run 무변경. SKILL.md 의 고아 조각·lock lsof 문단과 VERSIONS 항목 1·2 가 코드와 일치. 단 VERSIONS.md:52 "신규 테스트 24개 … test_issue10_13_purge.py 17개" 가 낡았다 — 실제 19 + 7 = 26(fae70c1 이 2개 추가). 병합 전 한 줄 정정 권장(비차단)
(4) #15 경로 · job_subscriber --registry-dir ✅ 무변경(default_registry_dir(), 운영 호출은 모두 명시)
(5) 버전 락스텝 ✅ lib.sh:32·eager.py:16 = 4.4.3, verify_framework_version 통과, 릴리스 커밋 0282312 제목 그대로
(6) 테스트 · 정적 검사 아래
  • 선택 실행 9파일(브리프 지정 8 + test_version_consistency): 250 passed in 163.4 s, rc 0(test_issue10_13_purge.py 23건 포함 — fae70c1 의 lock 전용 보유자·고아 부속 파일 테스트 포함).
  • #15 누수 실측: 실행 전후 실제 .mam/jobs 레코드 목록이 동일했다(추가 0건).
  • 정적 검사:
    • py_compile: base.py, agy.py, __main__.py, 테스트 파일 통과
    • bash -n orc_onboard.sh 통과
    • git diff --check bd3df89...HEAD 클린
    • verify_framework_version 통과
    • 작업 트리 깨끗, HEAD fae70c1
    • purge 테스트 파일의 고정 UUID 리터럴 0건

3. 비차단 권고 (후속 이슈 1건으로 묶기를 권장)

  1. VERSIONS.md:52 테스트 수 정정: 24/17 → 26/19. 목록에 "presence lock 만 연 보유자 거부, 고아 부속 파일로 agy 해결·purge" 추가. 병합 전 권장.
  2. R-a: 어댑터 purge_artifacts 에서 in-use 이면 전체 건너뛰기(§1-(2)).
  3. R-1: 에이전트 판정의 이름 의존 → 알려진 헬퍼만 제외.
  4. 위임 래퍼의 브리프 argv 전달: ps 노출이자 f5a6575 이 겪은 argv 충돌의 근본 원인. 파일이나 stdin 으로 전달 권장.
  5. R-b / R-c / R-e: 등록 UUID 확인, claude 교차 프로젝트 탐색, 상속 WORKSPACE_ROOT.

4. GM 참고

  • codex 의 NOT PASS(R1/R2)는 fae70c1 에서 해소되었다(위 재현). codex 가 이 HEAD 를 다시 확인하는 것이 만장일치 판정의 전제다.
  • agy·grok 의 직전 PASS 는 f5a6575 기준이라 fae70c1 은 포함하지 않는다.

5. 종합

  • fae70c1 은 codex R1(lock 만 연 보유자)과 R2(고아 부속 파일)를 정확한 위치에서 최소 변경으로 고쳤다. 기본 has_artifacts 가 기존 폴백과 같아 다른 어댑터의 해결은 바뀌지 않았다. 앞선 라운드 결과(N1·N2·#10·#11·#15·락스텝)도 회귀 없이 유지된다.
  • 남은 항목은 이미 보류된 R-a·R-1 과 changelog 테스트 수 한 줄이다. 설계 재검토는 필요 없다.

[VERDICT: PASS]