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
8.8 KiB
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초 간격
progressheartbeat 발행. 코드 수정 없음.
- 안전 규칙 준수: 실제 홈이나 등록된 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_ENV5종 중 하나가 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_useoverride(: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단계 revalidateverify_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, autorc 0, agent agy, 2조각 purge, residual[]아무것도 없음 rc 5, agent null(미해결과 구분 유지)회귀: claude transcript 만 있음 auto→ claude 로 해결회귀: opencode 공유 저장소만 있음, 무작위 uuid has_artifactsFalse,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.py23건 포함 —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건으로 묶기를 권장)
VERSIONS.md:52테스트 수 정정: 24/17 → 26/19. 목록에 "presence lock 만 연 보유자 거부, 고아 부속 파일로 agy 해결·purge" 추가. 병합 전 권장.- R-a: 어댑터
purge_artifacts에서 in-use 이면 전체 건너뛰기(§1-(2)). - R-1: 에이전트 판정의 이름 의존 → 알려진 헬퍼만 제외.
- 위임 래퍼의 브리프 argv 전달:
ps노출이자f5a6575이 겪은 argv 충돌의 근본 원인. 파일이나 stdin 으로 전달 권장. - 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]