Review loop (--review-only, --all-reviewer, focused on this Mac: macOS, /usr/bin/python3 3.9.6, bash 3.2): round 1 (@63d8164) agy and grok PASS, claude and codex NOT PASS (F1 paho via the /usr/bin/python3 fallback, F2 logs default path, R1 disk-fallback redispatch interleaving, R2 symlinked registry), sent as a PR comment and fixed by the author in four commits; round 2 (@a7cb90e) 4/4 PASS. Full suite on macOS / Python 3.9.6 @a7cb90e: 1867 passed, 56 skipped, 1 error (the known #55 false positive: WAL/SHM of an agy conversation running in another workspace). Real herdr panes and ~/.claude/projects unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
8.6 KiB
PR #58 Mac review — NOT PASS
Job: 863e2edf. Role: Reviewer. 소스 수정 없이 리뷰 및 임시 디렉터리 안의 검증만 수행했다.
- loop:
loop-20261014T152849Z-f1a415 - base:
e32c9574644a9185813a4dc881812694d62b6204 - head:
63d816468e6d48d01bd96f31d8a25eeadfbaab60 - tree:
e8f162f74b7ce8ee8cc6ba7954b7d28dfa3f89f6 - 검증 트리:
/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261014T152849Z-f1a415/1 - 범위: base..head 11 commits / 21 files. 아래 파일:라인은 이 head 기준이다.
관련 테스트 77 passed in 177.28s, exit 0. 그러나 테스트가 다루지 않는 두 경우를 추가 탐침으로 재현했다. 병합 전에 아래 두 항목을 수정하고 회귀 테스트를 추가해야 한다. 국소 수정으로 해결 가능하므로 설계 재계획 에스컬레이션은 필요하지 않다.
R1 — [P1] 디스크 폴백이 다른 dispatch의 완료를 이전 dispatch의 성공으로 오인한다
근거:
.agents/skills/lib_py/delegation/job_subscriber.py:89: 레지스트리의 status/token/attempt/transition_seq를 먼저 읽는다.- 같은 파일
:100,:114,:121: 나중에 읽은 감사 상태의 seq가 그 스냅샷 이상이면 상태를 채택한다. - 같은 파일
:126,:132: 토큰/attempt 검증에는 여전히 처음 읽은 레코드만 사용한다. .agents/skills/lib_py/delegation/engine.py:322: redispatch는 새 토큰을 발급한다. 감사 상태에는 토큰/attempt가 기록되지 않는다(:383).
재현 절차:
- 임시 cwd/WORKSPACE_ROOT 및 별도 registry에서 토큰 A로 잡을 등록하고
started로 전이시켜 running 상태로 만든다. _check_disk_fallback을 expected token A로 실행한다.read_logged_status를 감싸서, 레지스트리 read가 끝나고 감사 read가 시작되는 지점에 다음 실제 engine 전이를 실행한다: A의error→redispatch(attempt_id=2)→ 새 토큰 B로completed.- 실제
read_logged_status결과를 반환한다. 즉 감사 파일을 조작한 것이 아니라 정상 engine 전이 사이에 subscriber가 일시 중단된 순서를 결정적으로 재현했다.
기대: 토큰 B의 성공으로 A의 대기를 완료하면 안 된다. 최신 레코드와 비교해 토큰 변경을 거부하거나 A의 실제 실패를 구분해야 한다.
실제: 초기 레코드는 A/running이고 최종 레코드는 B/completed인데, pending=[], terminal={job_id: "completed"}가 된다. 출력도 completed [disk-fallback]이다. 이전 시도가 실패했는데도 호출자가 성공으로 종료할 수 있다.
탐침 출력 발췌:
RACE {"initial_status": "running", "initial_token": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "latest_token": "7b761cb2ea2d4514bbd631467997ad9d", "pending": [], "terminal": {"5b5cd6e8": "completed"}}
위 토큰은 임시 테스트 잡의 식별자이다. 이전 감사 상태를 거부하는 현재 회귀 테스트는 통과하지만, 레코드를 읽은 이후 다음 attempt의 더 새로운 감사 상태가 도착하는 경우는 검사하지 않는다. seq는 최신성만 나타내며 dispatch identity를 보장하지 않는다.
수정 방향: 감사 상태를 채택하기 직전에 레지스트리를 다시 읽어 token/attempt/seq가 같은 관찰에 속하는지 확인하고 변경 시 재시도/거부한다. 또는 레지스트리 lock 아래에서 일관된 관찰을 보장한다. 감사 상태에 dispatch identity를 기록·검증하는 방식도 가능하다. 단순히 aud_seq >= rec_seq만으로 다른 시도의 상태를 채택하지 않도록 위 interleaving을 회귀 테스트로 추가한다.
R2 — [P2] 레지스트리 자체가 심볼릭 링크이면 submit과 logs의 로그 경로가 갈라진다
근거:
.agents/skills/lib_py/delegation/mqtt_common.py:189: sibling 계산은abspath만 사용한다..agents/skills/multi-agent-mux-delegate-job/multi-agent-mux-delegate-job:84: submit의_abs_registry_dir는cd -P/pwd -P로 링크를 해석한다.- 같은 파일
:280: 물리 경로로 바꾼 다음 로그 루트를 계산한다. - 같은 파일
:1108: logs는 전달받은 링크 경로 그대로 registry CLI에 넘긴다. .agents/skills/lib_py/control_plane.py:34,:52: control-plane binding도 realpath로 정규화하므로 직접 Python resolver와 다를 수 있다.
재현 절차(모두 임시 디렉터리 안에서, DELEGATE_JOB_LOGS_DIR 없이):
<tmp>/actual/jobs와<tmp>/alias를 만들고<tmp>/alias/jobs -> <tmp>/actual/jobs심볼릭 링크를 만든다.- cwd와 WORKSPACE_ROOT를
<tmp>로 둔다. /bin/bash <review>/.agents/skills/multi-agent-mux-delegate-job/multi-agent-mux-delegate-job submit --dry-run --agent human --registry-dir <tmp>/alias/jobs --workdir <tmp> --prompt symlink-wrapper실행.- 생성된 job ID로 같은 wrapper의
logs <id> --registry-dir <tmp>/alias/jobs실행.
기대: 동일한 registry 인수로 만든 잡의 감사 로그를 조회할 수 있어야 한다.
실제: submit은 rc 0이며 <tmp>/actual/delegate_job_logs/<id>에 감사 로그를 생성하지만, logs는 <tmp>/alias/delegate_job_logs에서 찾아 rc 1로 실패한다.
job_id: a6cdb85e
submit_log_root: /private/tmp/review-863e2edf-m7fmcbsw/probes-igd0iy09/actual/delegate_job_logs/a6cdb85e
actual_audit_exists: true
logs_rc: 1
no audit log for job a6cdb85e under /tmp/review-863e2edf-m7fmcbsw/probes-igd0iy09/alias/delegate_job_logs
별도 직접 registry 호출도 같은 레코드를 가리키면서 alias 옆에 로그를 쓰고, control_plane.from_env는 actual 옆을 기록함을 확인했다. /tmp -> /private/tmp처럼 부모 전체가 같은 위치를 가리키는 별칭은 통과하며, 이 문제는 jobs 디렉터리 자체가 다른 부모 아래로 연결되는 링크에서 발생한다.
수정 방향: 기본 감사 경로를 산출하기 전에 registry 경로를 정규화하는 정책을 중앙 resolver에 통일한다. 예를 들어 registry의 realpath에서 sibling을 구하면 submit/control_plane과 일치한다. 명시적 DELEGATE_JOB_LOGS_DIR 우선권은 유지한다. submit --dry-run 후 동일한 symlink 인수로 logs를 조회하는 회귀 테스트를 추가한다.
검증 결과 및 범위
- 실제 Mac Python 3.9.6에서 변경된 Python 13개 파일 AST 파싱 통과. 변경된 shell/wrapper 5개를 각각
/bin/bash -n으로 검사하여 통과. Bash는3.2.57(1)-release (arm64-apple-darwin25)이다. - 관련 pytest 77건 통과:
test_issue57_logs_follow_registry.py,test_issue15_registry_isolation.py,test_issue12_registry_secrets.py,test_issue21_worktree_prereqs.py,test_issue21_acceptance.py전체;test_tier1_unit.py::test_b9_logs_dir_follows_cwd_changes; issue18의 subscriber state/seq/liveness 및 remote redispatch 관련 4건. - 실행은 지정 venv Python,
PYTHONDONTWRITEBYTECODE=1,-p no:cacheprovider, 검증 트리 밖/tmp/review-863e2edf-m7fmcbsw/pytestbasetemp를 사용했다. 지정된 HERDR/WORKSPACE_ROOT/MAM/DELEGATE 환경변수를env -u로 제거했고, HOME도 임시 위치로 격리했다. create/resume은 mock fixture를 사용했다. 실제 에이전트/monitor/herdr 서버를 시작하지 않았다. - 일반 기본 경로, 명시적 로그 override, 상대 registry, 이동 registry, control-plane row 및 prefix, worktree create/resume, audit-only status, 오래된 감사 seq 거부는 관련 테스트로 검증했다.
- 추가 Mac 부모 경로 별칭 탐침(
/tmp와/var): 정규화된 binding에서 sibling 로그 키를 전달하지 않는 동작 통과. git diff --check base HEAD통과. 검증 후 HEAD/tree 일치 및 clean git status 확인. 소스/문서 변경 없음.- 전체 스위트는 이 리뷰에서 실행하지 않았다(브리프에 따라 오케스트레이터가 별도 실행). 알려진 purge 모듈도 이번 선택에 포함되지 않았다. 선택 테스트에서는 #55 가드 오탐이나 teardown 오류가 없었다.
- 테스트의 Linux 결과를 Mac 결과로 대신 인용하지 않았다. 검증 트리 바깥 creator 소스에서 테스트를 실행하지 않았다.
재현 스크립트: /tmp/review-863e2edf-m7fmcbsw/probes.py (실제 대상 모듈 import, 임시 디렉터리 안에서 실행).
탐침 로그: /tmp/review-863e2edf-m7fmcbsw/probes.log.
선택 테스트 로그: /tmp/review-863e2edf-m7fmcbsw/pytest.log.
재실행: 검증 트리 cwd에서 PYTHONDONTWRITEBYTECODE=1 /Users/godopu16/PuKi/laa/canary_projects/multi-agent-mux/.venv/bin/python /tmp/review-863e2edf-m7fmcbsw/probes.py. 스크립트가 제어 평면 관련 환경을 제거하고 cwd/WORKSPACE_ROOT/HOME을 새 임시 디렉터리로 설정한다.
[VERDICT: NOT PASS]