Use case
src/internal/ActorCell.ts:83-90 documents the hazard precisely, in the code, as the reason watch bookkeeping is keyed the way it is:
ActorPath.toString() is the canonical address and deliberately omits the uid — location transparency depends on it staying stable across a restart. Watch bookkeeping needs the opposite: a name that is re-spawned (a restarted parent recreating a named child, a router pool rebuilding its routees) must be a different subject, or the previous incarnation's pending Terminated is delivered against its successor and the successor is never registered at all, because the address is already in the map.
So the mechanism exists and the reasoning is written down. What is missing is a test that binds it.
tests/unit/internal/WatchProvenance.test.ts has three cases, and all three are about a fabricated Terminated — one arriving from a party that was never watched. That is the forgery case. It is not the collision case, where the Terminated is entirely legitimate but belongs to a dead incarnation of a path that has since been reused.
The distinction matters because the two are fixed by different code. Forgery is rejected by provenance checking; collision is prevented by the uid keying the comment above describes. Removing the uid from the watch key would leave all three provenance tests green.
The scenario is worth constructing because it is a genuine race and not a synthetic one: a supervisor restarts a named child, and the Terminated for the old instance is still in flight when the new one registers.
Proposed shape
- Construct the collision directly: watch a named child, cause a restart that re-creates it under the same name, and arrange for the old incarnation's
Terminated to be delivered after the new one is registered.
- Assert the new incarnation does not receive it, and that its own watch registration survives.
- Assert the reverse too — that the watcher of the old incarnation is notified correctly, so the fix is not "drop everything ambiguous".
- Prove the test discriminates: remove the uid from the watch key and confirm this test goes red while the three provenance tests stay green. That two-sided result is the evidence, and it is worth recording on the issue.
Acceptance
Verification status
Confirmed by reading. The comment is quoted verbatim from src/internal/ActorCell.ts:83-90. tests/unit/internal/WatchProvenance.test.ts was read in full; its three test names are "a fabricated Terminated is not delivered and does not retire the watch", "a fabricated Terminated is dead-lettered rather than silently consumed", and "a fabricated Terminated does not consume a watchWith substitution". None constructs a legitimate Terminated for a superseded incarnation.
Use case
src/internal/ActorCell.ts:83-90documents the hazard precisely, in the code, as the reason watch bookkeeping is keyed the way it is:So the mechanism exists and the reasoning is written down. What is missing is a test that binds it.
tests/unit/internal/WatchProvenance.test.tshas three cases, and all three are about a fabricatedTerminated— one arriving from a party that was never watched. That is the forgery case. It is not the collision case, where theTerminatedis entirely legitimate but belongs to a dead incarnation of a path that has since been reused.The distinction matters because the two are fixed by different code. Forgery is rejected by provenance checking; collision is prevented by the uid keying the comment above describes. Removing the uid from the watch key would leave all three provenance tests green.
The scenario is worth constructing because it is a genuine race and not a synthetic one: a supervisor restarts a named child, and the
Terminatedfor the old instance is still in flight when the new one registers.Proposed shape
Terminatedto be delivered after the new one is registered.Acceptance
Terminatedfor a previous incarnation of a reused path.Verification status
Confirmed by reading. The comment is quoted verbatim from
src/internal/ActorCell.ts:83-90.tests/unit/internal/WatchProvenance.test.tswas read in full; its three test names are "a fabricated Terminated is not delivered and does not retire the watch", "a fabricated Terminated is dead-lettered rather than silently consumed", and "a fabricated Terminated does not consume a watchWith substitution". None constructs a legitimateTerminatedfor a superseded incarnation.