Round 3 at 134fe97: claude, agy, grok and codex all PASS.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
3.2 KiB
🔍 Review Report — Job b6915b56 (fix/issue-19 @ 134fe97)
- Reviewer:
reviewer-grok-01(role: reviewer) · 2026-09-13 - 범위:
git log/git diff8e7282c...HEAD - HEAD:
134fe97fix(issue-19): arm the subscriber's stop handlers before it connects; read $! with nounset off - 선행 NOT PASS:
0dc6400bN1 (핸들러가 subscribe 이후), B1 (set -u에서 빈$!) - 안전: 실제
.mam/monitor.lock·워크스페이스 데몬 미접촉. 소스 무변경.
커밋: ce315d8 → 38d8ccb → 4da4a50 → c096cb4 → 8f9745b → 134fe97. git diff --check 클린.
N1 닫힘 — SIGTERM 핸들러를 connect 앞에
reconcile.sh:300-341: signal.signal(SIGTERM/INT) 을 client.connect / loop_start 앞에 둔다. CONNACK 대기는 stop_event.wait(0.1). 시그널이 있으면 sys.exit(3) 을 타지 않아 폴링 폴백으로 안 떨어진다. 메인 루프가 "signal N received, exiting" 을 찍고 finally: loop_stop/disconnect, 파이썬 rc 0, 래퍼 143.
test_sigterm_during_broker_handshake_takes_the_clean_path: 응답 없는 로컬 listen 포트, connecting to 후 1s, SIGTERM → 143, 로그에 signal 15, falling back to polling 없음. 직전 실패 테스트 test_mqtt_loop_sigterm_exits_cleanly 도 통과(핸들러가 subscribe 이전에 이미 있음).
paho loop_start 스레드는 핸들러가 만지지 않고, 메인만 stop_event 를 깨운 뒤 loop_stop — 충돌 없음.
B1 닫힘 — 첫 & 전 set -u
_sub_stop (reconcile.sh:80-97): _sub_pid 가 비면 set +u; child="$!"; set -u. bash 3.2 에서 ${!:-} 가 unbound 로 죽던 경로가 143 으로 끝남. test_sub_stop_trap_exits_143_before_the_first_background_child 가 자식 없음/있음 둘 다 143.
& 와 _sub_pid=$! 사이는 $! 로 커버. 이미 끝난 자식은 kill/wait no-op.
유지되는 계약
- 래퍼: 자식 0 →
exit 0; 자식 3 → 폴링 후 0; 자식 1(lock 예외) → 폴링 없이 0; TERM → 143. _workspace_gone:(st_dev, st_ino),getcwdOSError, lock 교체/삭제.- 폴링: lock 존재만. sleep
& wait. 트랩은 sleep 자식을 안 죽임(문서화, ≤ POLL_INTERVAL). - 옵트아웃 리터럴
1, 기존 PID 보고, stdout 비움. argv 형태 회수, 접두/래퍼/공백 경로. 세션 가드 basetemp.
문서·락스텝
SKILL.md: 핸들러는 connect 전, 폴링은 presence, sleep 잔여. VERSIONS.md 항목 3·테스트 16개가 134fe97 과 맞음. 4.4.5 lockstep 유지 (38d8ccb 이후는 패치 커밋).
테스트
env -u MAM_VERSION .venv/bin/python -m pytest -q \
tests/test_issue19_subscriber_daemon_lifecycle.py \
tests/test_issue5_phase1_delegation.py tests/test_tier2_component.py \
tests/test_version_consistency.py tests/test_herdr_shim_contract.py
144 passed in 284.23s (직전 141+1 fail → N1/B1 테스트 2 + 실패분 회복). issue19 16 collected. bash -n 클린. 실제 pytest-of-*/…/bash …/reconcile.sh --subscribe 0건(argv 에 브리프를 실은 래퍼만 pgrep -f 에 걸림). 워크스페이스 모니터 미접촉.
종합
N1·B1 이 코드·테스트로 닫혔고, 1회차 #19 수명 계약은 회귀 없음. 설계 재작업 불필요.
[VERDICT: PASS]