docs(reports): archive v4.4.5 unanimous PASS review reports (Issue #19)

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
This commit is contained in:
GodopuandClaude Fable 5.1 committed 2026-09-13 17:54:52 +09:00
1 parent 134fe9704c
commit 1bd643e979
4 files changed
+383

No files matched your search

@@ -0,0 +1,51 @@
# 🔍 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]