---
name: msg-identity-w2-f034
description: MSG-IDENTITY W2 (F-034) test patterns — seed consume-after-bind, session-id fallback, group-level adapter hint
metadata:
  type: project
---

MSG-IDENTITY W2 (F-034) tests — the 3 F-034 legs (perri/hertz field bug, /sptc:live late-session bringup).

**REQ-ADAPTER-UNRESOLVED-HINT-FORM** (leg a, impl+unit): ResolveError Display (resolve.rs) hints print the GROUP-LEVEL `spt api --adapter <name[:profile]> <cmd> ...` (both NoExe + NoCandidate). Unit `resolve_error_hints_print_the_group_level_adapter_form` in spt-runtime resolve.rs asserts `matches("--adapter").count() == matches("spt api --adapter").count()` (every flag is group-level, no stray post-subcommand form) + no `"pass --adapter"`. Cli.rs unit `api_adapter_flag_is_group_level_not_post_subcommand` proves clap-validity: group-level parses, `listen someid --adapter x` ERRORS (the dead end). Uses cli.rs `parse(&["spt","api",...])` helper (full Cli, line ~11525).

**REQ-LISTEN-SEED-CONSUME-AFTER-BIND** (leg b, hertz headline, doc+impl+unit+int): `bind_from_seed` = take → `bind_taken_seed`; on ANY post-take Err it RESTORES via `put_seed` (loud SEED_RESTORE_FAIL). Unit `prebind_refusal_restores_the_seed_for_retry`: force post-take Conflict by pre-`establish_perch`-ing the id under a DIFFERENT sid owned by this (alive) process, then a 2nd bind_from_seed re-hits Conflict (NOT NoSeed) = seed re-takeable. `successful_bind_consumes_the_seed_exactly_once`: reg.peek(anchor).is_none() after + 2nd = NoSeed. Int (listen_seed_retry_e2e.rs) forces post-take HOME_REFUSED via multi-subnet (seed_subnets(["home","work"]) in-proc), first `api listen` no-`--subnet` refuses (stderr HOME_REFUSED not NO_SEED), retry `--subnet work` BINDs. RED-verified: neuter `if result.is_err()`→`if false && ...` and the unit goes red (NoSeed).

**REQ-LISTEN-SESSION-ID-FALLBACK** (leg c, doc+impl+unit+int): `Listen` gained `--session-id`; cmd_listen falls to private `bind_from_session_id` ONLY on `Err(BindError::NoSeed(_))` with non-empty sid (loud SID_BIND). Units test bind_from_session_id directly (reachable via super::*): empty sid→EmptySession, DEAD pid→StaleSeed, alive+fresh→Ok(token) w/ sid recorded + live_agent; `no_seed_is_the_fallback_trigger_then_sid_binds` documents the NoSeed→sid seam without invoking cmd_listen (blocks on relay). Int: no seed planted, `api listen <id> --parent-pid <alive> --session-id <sid> --once` → SID_BIND + BOUND.

Int fixture: model on contract_e2e.rs (in-proc `start_inproc_daemon` on SPT_HOME seed socket, explicit `--adapter mock` = no-registry deterministic path, `--once` bounds at ~500ms via check_message_blocking, pre-spool a msg for deterministic drain-exit). File-local `E2E_LOCK` Mutex (SPT_HOME process-global). Run int with `--test-threads=1`.

See [[msg-identity-w1-f036]], [[spt-test-conventions]], [[f028-wavefinal-int-patterns]].
