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.7 KiB
PR #58 Mac 2차 리뷰 — PASS
Job 2e06828a, Reviewer. 이전 네 지적 사항(F1/F2/R1/R2)이 해결됐음을 확인했다. 관련 테스트 83건이 통과했으며, 수정 직전 커밋에서는 해당 회귀 테스트 6건이 각각 예상한 이유로 실패했다. 이번 검토 범위에서 새 차단 이슈는 발견하지 못했다. 소스 수정은 하지 않았다.
검증 identity
- loop:
loop-20261015T123502Z-1b9df6 - base:
e32c9574644a9185813a4dc881812694d62b6204 - head:
a7cb90e63abf454ccf22f6ff887cc25393755402 - tree:
96c5c5f82cb89e4383011d52fb1dcb21d4e787e6 - 검증 경로:
/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261015T123502Z-1b9df6/1 - 누적 범위: base..head 15 commits / 23 files. 이전 검토 head
63d8164이후 4개 수정 커밋을 집중 검토하고 누적 변경과의 정합성을 대조했다. - 실제 환경: macOS, Python 3.9.6, GNU Bash 3.2.57(arm64-apple-darwin25).
지적 사항별 확인
| 항목 | 수정 전 검증 | 현재 head 검증 | 판정 |
|---|---|---|---|
| F1: paho 없는 Python 경로 계산 | 63d8164에서 binding 1건 및 status json/text 2건이 ModuleNotFoundError로 실패 |
같은 3건 통과. 별도로 실제 /usr/bin/python3의 paho spec이 None임을 확인하고 mam_control_plane_json 및 status의 두 get_job_status 함수를 실행해 성공 |
해결 |
| F2: 다른 cwd의 기본 logs | 75c0042에서 WORKSPACE_ROOT의 잡 대신 elsewhere/.mam 로그 루트를 조회하여 실패 |
WORKSPACE_ROOT=ws, cwd=elsewhere에서 logs --list와 logs <id> 모두 잡/registered 이벤트 조회 성공 |
해결 |
| R1: 다른 dispatch 완료 오인 | 151af99에서 A error → redispatch → B completed interleaving이 A를 completed로 종료시켜 실패 |
동일 interleaving에서 A는 pending 유지, terminal 비어 있음. B 토큰으로 다음 조회 시 completed. 별도 탐침도 동일 결과 | 해결 |
| R2: registry 자체의 symlink | 1c598bb에서 alias/jobs의 sibling이 actual이 아닌 alias로 계산되어 실패 |
alias/jobs → actual/jobs에 submit --dry-run 후 같은 alias 인수로 logs 조회 성공. alias 옆에는 로그를 생성하지 않음 | 해결 |
수정 전 테스트는 검증 저장소에서 git archive <각 수정 커밋의 부모>로 만든 임시 복사본에서 실행했다. 해당 복사본에는 현재 head의 tests/test_issue57_logs_follow_registry.py만 복사해 새 회귀 테스트를 실행했다. 실제 코드의 이전 동작 때문에 실패했으며 수집 오류나 환경 오류로 실패한 것이 아니다. 원본 검증 트리나 creator 브랜치는 변경하지 않았다.
각 회귀 테스트:
- F1:
test_control_plane_binding_works_without_paho,test_status_works_without_paho[json],test_status_works_without_paho[text]. - F2:
test_logs_without_registry_dir_follows_the_workspace_from_any_cwd. - R1:
test_disk_fallback_rejects_a_terminal_that_belongs_to_a_later_dispatch. - R2:
test_a_symlinked_registry_dir_resolves_to_one_audit_log.
코드 및 추가 탐침 근거
F1: .agents/skills/lib_py/delegation/logroot.py가 표준 라이브러리만으로 경로 규칙을 정의한다. control_plane.py, lib.sh의 경로 helper, status.sh가 이 모듈을 사용한다. 패키지 초기화의 전이 import도 mqtt_common.py:33 및 publisher.py:17의 선택적 paho import로 통과한다. 실제 paho 미설치 /usr/bin/python3 + AGENT_PYTHON_BIN=/usr/bin/python3에서 lib.sh의 mam_control_plane_json을 실행했다. status.sh의 두 get_job_status 정의를 그대로 추출해 동일 인터프리터에서 audit-only completed 레코드를 읽었으며 둘 다 ('probejob', 'completed')를 반환했다. 경로 조회가 MQTT 접속을 필요로 하지 않고, 실제 client 생성은 paho가 없으면 명시적으로 실패한다.
F2: wrapper의 cmd_logs는 --registry-dir가 명시된 경우에만 배열에 넣어 registry.py로 넘긴다. 기본 실행은 registry.py의 MAM_JOBS_DIR → WORKSPACE_ROOT → cwd 규칙을 사용한다. 비어 있는 배열은 ${reg[@]+"${reg[@]}"} 형태로 전개되므로 Bash 3.2 + set -u에서도 동작한다. 기본 인수 및 명시적 registry 인수 두 경우 모두 실제 테스트로 통과했다.
R1: job_subscriber.py:128에서 감사 상태를 읽은 뒤 레지스트리를 재조회하고 :132에서 dispatch_token/attempt_id/transition_seq를 비교한다. 첫 관찰과 다르면 그 라운드에서는 채택하지 않는다. 따라서 정상 엔진이 토큰을 교체하고 seq를 증가시키는 재디스패치가 감사 read 전후에 끼어들어도 이전 토큰에 다음 시도의 성공을 붙이지 않는다. 추가 재조회 이후에 새로운 전이가 일어나더라도 이미 읽어 둔 감사 상태를 새 상태로 바꾸지는 않는다. 기존 레지스트리 terminal 경로는 추가 read 없이 처리한다. 감사 상태를 채택할 후보에만 파일 read 최대 1회가 추가되며 새 내부 polling loop, sleep, 장시간 lock은 없다. 성능 판단은 이 코드 경로에 근거하며 대규모 잡 부하 벤치마크를 수행했다는 뜻은 아니다.
R2: logroot.py:51이 registry의 realpath에서 sibling을 구한다. submit의 pwd -P, control_plane의 realpath와 일치한다. control_plane.py:82의 비교도 로그 경로 양쪽을 정규화한다. 추가 탐침에서 /tmp//private/tmp, /var//private/var 부모 별칭 및 lexical 별칭을 사용하는 기존 row에서도 파생 로그 키를 제외하는 동작이 일치했다. 명시적 DELEGATE_JOB_LOGS_DIR 우선권은 유지된다. 일반 기본 경로는 같은 물리적 위치이며 Mac에서 문자열의 /private 접두사가 정규화되는 것은 의도된 변화이다.
기존 import 호환성: 실제 /usr/bin/python3에서 mqtt_common.sibling_logs_dir, get_logs_dir, default_registry_dir가 logroot의 해당 함수와 동일 객체임을 확인했다. venv Python에서 lib_py.loop.eager.eager_load() 실행 후 lib_py.delegation.logroot가 검증 트리 경로로 sys.modules에 적재됐음을 확인했다. 명시적 eager 목록에 logroot를 중복 추가하지 않아도 mqtt_common의 최상위 import를 통해 시작 시 적재된다.
이전 R1/R2 임시 탐침 파일은 더 이상 존재하지 않아, 이전 리포트에 기록한 동일한 전이 순서 및 symlink submit/logs 절차를 새 임시 스크립트로 재구성했다. R1은 실제 engine 전이를 사용하고 audit read 경계에만 순서를 삽입했으며, R2는 실제 wrapper의 dry-run/logs를 호출했다.
실행 결과와 한계
- 현재 head 선택 테스트: 83 passed in 181.30s, exit 0.
- 모듈 전체:
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. - 개별 테스트: tier1의
test_b9_logs_dir_follows_cwd_changes; issue18의test_subscriber_records_seq_gaps_and_recovers_terminal_from_state,test_subscriber_state_renews_liveness_only_when_it_advances,test_remote_runner_ignores_a_resent_dispatch_of_a_finished_attempt,test_remote_runner_never_rolls_a_newer_attempt_back. - 변경 Python 파일 전체에 실제 Python 3.9.6의 AST parse 적용, 변경 shell/wrapper 각각
/bin/bash -n검사 통과.git diff --check base HEAD통과. - 테스트마다 브리프의 지정 환경변수를
env -u로 제거했고, 추가로 에이전트 관련 환경과 HOME/XDG 위치를 격리했다. 지정 venv Python,PYTHONDONTWRITEBYTECODE=1,-p no:cacheprovider, 검증 트리 밖 basetemp 사용. create/resume은 mock fixture로 검증했다. - 실제 herdr 서버/monitor/에이전트를 시작하지 않았다. 실제 제어 평면에는 지시된 job lifecycle 이벤트와 본 리포트만 기록했다. creator 작업 트리에서 실행하지 않았다.
- 전체 스위트는 이 리뷰에서 다시 실행하지 않았다. 오케스트레이터의 별도 전체 스위트 결과를 이 리뷰 결과로 포함하지 않았다. 선택 테스트에서 #55 가드 오탐 및 teardown 오류는 없었다.
- 최종 검증 트리 HEAD/tree는 브리프와 일치하고 git status는 clean이다.
검증 산출물 디렉터리: /tmp/review-2e06828a-66fn_mpg/.
before-F1.log: 3 failed, 각각 paho import 실패.before-F2.log: 1 failed, 잘못된 cwd 로그 루트.before-R1.log: 1 failed, B 완료를 A에 귀속.before-R2.log: 1 failed, alias와 actual sibling 불일치.head.log: 83 passed.system-probe.py,system-probe.log: 실제 시스템 Python/no-paho 및 import/eager/구문 검증.repro-r1-r2.py,repro-r1-r2.log: 이전 두 재현 절차 및 Mac 별칭 검증.
[VERDICT: PASS]