# Issue #40 교차 코드 리뷰 ## 검토 범위와 기준선 리뷰는 브리프가 지정한 immutable 검증 경로 `/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261020T133532Z-a1684a/1`에서만 했습니다. HEAD는 `feccfd5e0356c8acf0438bc68bce7ea36ce2588e`, tree는 브리프의 `0f0f33cc22f5e492a0ddfccb6bac5be888c10d1a`와 일치하고, `git status`는 깨끗합니다. diff는 기준선 `ff8b381520ae04e80c73a9e18bfad73d47e853c9` 대비 19개 파일, 1128 insertions / 338 deletions입니다. 검토한 경계는 `autopin.py`와 adapter capture/verify, agy presence-lock 소유 PID 확인, wrapper/create/loop 호출 경로, reconcile drift C 통합, atomic YAML/SQLite 기록, Issue #40/64 회귀 및 기존 tier 테스트입니다. 소스 작업 트리에서는 실행하거나 수정하지 않았습니다. 기준선 checkout으로 테스트를 재실행하지 않았습니다. 리뷰 지침상 지정된 immutable head 검증 경로에서만 실행할 수 있었고 별도 baseline worktree를 만들지 않았기 때문입니다. ## 코드 리뷰 결과 - **agy cross-workspace 및 same-cwd 격리:** cache는 workspace 키에 해당하는 UUID 후보만 제공하며, 후보가 다른 cwd에도 매핑되면 `verify_artifact()`가 거절합니다. sibling UUID 검사는 cache hit와 무관하게 적용됩니다. `capture_active_session_id()`는 pane PID 또는 그 자손이 presence lock/DB 경로를 점유함을 확인하기 전에는 ID를 반환하지 않습니다. lsof/ps, pane PID, 점유자 확인 불능은 fail-closed이고, 다른 행이 이미 UUID를 가졌으면 거절합니다. 이 경로가 `autopin.capture()`와 reconcile drift C에서 공유됩니다. - **completed 수신과 중복 처리:** wrapper/create 및 loop 복구가 동일 handler를 호출합니다. handler는 terminal status, local transport, session row와 dispatch token을 검사하고 job-scoped flock와 `(job_id, dispatch_token, attempt_id)` marker로 중복 호출을 억제합니다. publisher는 제어 평면에 쓰지 않습니다. pin 성공은 atomic mutation 안에서 ID와 `session_id_source`/`session_id_verified`를 함께 기록합니다. - **기존 안전장치:** epoch/workspace 검증과 sibling exclusion 이후 단일 후보만 선택하고, viewport mismatch에서는 pin을 막습니다. 모호성은 pin하지 않고 행에 사유를 남깁니다. 실패한 pin은 job의 성공 terminal 상태를 덮어쓰지 않습니다. Claude/Grok 및 이미 ID가 있는 행은 capture 경로에서 보존됩니다. - **변경 범위:** reconcile의 agent별 후보 검색을 공용 Python capture로 줄이고, create/delegate/loop 호출과 문서·테스트를 더했습니다. stop/purge 구현과 publisher 소유권 경계를 건드리지 않았습니다. 기존 reconcile의 비-0/1 viewport 결과를 degraded pin으로 처리하는 동작은 유지했습니다. 차단성 결함은 발견하지 못했습니다. 비차단 관찰로, reconcile drift C는 `ambiguous`일 때만 구체적 capture 사유를 `last_visible_status`/drifts에 남기고 `unverifiable-owner`, `owner-mismatch`, `rejected`는 조용히 건너뜁니다. completed handler 경로는 이 사유를 기록하므로 안전성 문제는 아니지만, completed 처리 뒤 재시도/운영 진단을 돕기 위해 reconcile에서도 이 세 상태를 warning drift로 노출하면 추적성이 좋아집니다. ## 검증 - `tests/test_issue40_auto_pin.py tests/test_issue64_ro_connect.py`: **70 passed** (42.64s). same-cwd A/B 소유 pane test, presence 소유자 일치/자손/불일치/lsof 불가, 다른 workspace 거절, completed dedupe, ambiguous 및 publisher 경계 포함. - `tests/test_issue60_linux_fixes.py tests/test_issue60_opencode_v2.py tests/test_tier1_unit.py tests/test_tier2_component.py`: **176 passed** (390.99s). - 변경 shell 파일(`lib.sh`, create script, delegate wrapper, reconcile): `bash -n` 통과. - `git diff --check ff8b381..HEAD`: 통과. 기준선에서 새 테스트가 실패하고 HEAD에서 통과한다는 A/B 재실행은 이 리뷰의 격리 경로 제한상 수행하지 않았습니다. HEAD 테스트와 코드 경로 검토만으로 verdict를 냈습니다. 전체 테스트 스위트는 브리프대로 상위 오케스트레이터 검증에 남깁니다. ## 남은 위험 agy 자동 pin은 `lsof`와 `ps`의 소유자 계보 확인에 의존하므로 제한된 권한 환경에서는 정상 대화도 자동 등록되지 않을 수 있습니다. 현재 동작은 오등록보다 false negative를 택해 안전하게 실패합니다. process snapshot과 completed event 처리 사이의 race는 이미 종료된 후보를 보수적으로 거절할 수 있지만, 다른 pane의 ID를 승인하게 하지는 않습니다. 위 reconcile 진단 개선 외에 설계 재계획이 필요한 문제는 발견되지 않았습니다. 리뷰 가능한 변경분에서 자동 pin의 핵심 안전 경로를 확인했고, 관련 회귀 묶음이 모두 통과했습니다. 다른 workspace 또는 동일 cwd sibling의 agy 대화를 잘못 pin할 차단성 우회는 발견하지 못했습니다. [VERDICT: PASS]