A watch installed after its target's death has, until now, only NoProc to
report — but the bridge's proxies install their native watch asynchronously
after acquire returns, so a link established before a crash (from the BEAM's
view) could still lose the panic's translated reason to that blanket NoProc
(width-20 soak signature 4: link_test.exs:26, 1/600 full-suite, 3/2000
link-only, all whereis-miss; deterministic repro in the bridge suite).
Two primitives, no change to monitor()'s own Erlang-faithful stale-pid
semantics — the upgrade is the caller's deliberate act:
- finalize_actor stamps the slot with (generation, DownReason) under the same
cold-lock block that publishes the outcome. The record survives reclaim,
registry pruning, and the next tenant's install; only the slot's next death
overwrites it. terminal_reason(pid) reads it generation-matched.
- resolve_name(name) is whereis with the corpse kept: the dead-holder arm
returns the stored pid it prunes (NameResolution::Corpse) instead of
discarding the only evidence of who died — whereis itself prunes on the way
out, so a whereis-then-lookup consumer would find the evidence already
destroyed. Live/Unbound match whereis's Some/None; the name heals exactly
as before.
Contract pinned in tests/terminal_outcome_after_death.rs: one record per way
of dying (Exit/Panic/Stopped), no record while live, corpse capture + heal on
resolve_name, record independence from registry pruning, survival across slot
re-tenancy, overwrite at the next tenancy's death.