# Cross-review: Issue #3 implementation (daemon detach + Class A resume)

- **Reviewer**: `reviewer-creator-grok-01`
- **Job**: `dccd6220`
- **Diff**: `lib.sh` shim bootstrap, `resume_session.sh`, `update_yaml_resumed.sh`, tests (`test_uuid_target.py`, `test_herdr_shim_contract.py`)
- **Method**: live code + `pytest` of t8/t14/t15/t16/h26 and full `test_uuid_target.py`. `verify_session.py` has **no** git diff.

---

## 1. Daemon spawn (`lib.sh` / `.mam/shim/herdr`)

Replaces `nohup … & disown` with:

```bash
_mam_server_pid=$(python3 -c '
import subprocess, sys
p = subprocess.Popen(sys.argv[1:], start_new_session=True, ...)
print(p.pid)
' "$REAL_HERDR" --session "$_MAM_SESSION" server)
```

- `python3 -c` → `sys.argv[0]=='-c'`, `sys.argv[1:]` is the herdr argv. Correct.
- Single-quoted `-c` body, so `$_MAM_SESSION` is expanded by bash as an argument, not inside Python. Correct.
- Child is session-leader via `os.setsid`; short-lived Python parent exits; herdr is reparented. PGID no longer follows the shim.
- `test_h26` extracts the **shipped** statement and asserts child PGID ≠ shell PGID.

**Met.** Portable (no macOS `setsid` binary).

## 2. Class A 0-turn resume

Empty UUID: `agy|hermes|opencode` → `FRESH_SPAWN=1` + `spawn-spec` (not `resume-spec`). `claude|grok` still `exit 1`. YAML update allows empty `--uuid`, stamps `herdr_session_epoch` / `pending-discovery` / `session_id_verified: false` so reconcile cannot pin a pre-resume transcript.

Tests: t14 (agy dry-run, no `--conversation`), t15 (claude never-created still RC=1), t16 (live resume bumps epoch).

**Met.** `--role` handoff is no longer required for Class A 0-turn recovery.

## 3. Class B hatch — preserved

`verify_session.py:99-101` unchanged (`git diff` empty). `test_t8_resume_unmaterialized_assigned_id` **passed** in this run.

## Tests (this reviewer)

```
pytest tests/test_uuid_target.py \
       tests/test_uuid_target.py::test_t8_… \
       tests/test_uuid_target.py::test_t14_… \
       tests/test_uuid_target.py::test_t15_… \
       tests/test_uuid_target.py::test_t16_… \
       tests/test_herdr_shim_contract.py::test_h26_…
→ 20 passed in 246.19s
```

`bash -n` on `lib.sh`, `resume_session.sh`, `update_yaml_resumed.sh` clean.

## Residual nits (do not block)

- Already-running Class A + empty UUID still calls `update_yaml_resumed.sh --uuid ""`, which **re-stamps epoch** without respawning. Rare (resume-when-alive). Prefer skipping the epoch reset on the has-session attach path.
- No `MAM_VERSION` bump (still `4.1.2`). Fine if this lands in the same unreleased PATCH; bump to 4.1.3 if 4.1.2 already shipped.
- Resume `SKILL.md` still says empty UUID → create. Docs drift only.

No `[ESCALATE: PLANNER]`.

---

[VERDICT: PASS]
