# πŸ” Review Report β€” Job b6915b56 (`fix/issue-19` @ `134fe97`) - **Reviewer**: `reviewer-grok-01` (role: reviewer) Β· 2026-09-13 - **λ²”μœ„**: `git log`/`git diff` **`8e7282c...HEAD`** - **HEAD**: `134fe97` `fix(issue-19): arm the subscriber's stop handlers before it connects; read $! with nounset off` - **μ„ ν–‰ NOT PASS**: `0dc6400b` N1 (ν•Έλ“€λŸ¬κ°€ 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)`, `getcwd` OSError, 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]