DF's determination of death of civs is buggy. Firstly, DF culls all civs declared as dead from the list of embarkable civs (this is probably by design), which means if there is a single healthy dwarven civ in the list none of them are truly dead, merely "struggling"/"dying".
A civ can have had neither members nor sites for 1000 years and still be considered struggling because the entity population accounting is bugged and tends to settle on a positive number that stays unchanged until the end of world gen after a bit of fluctuation after the last site is lost (I think refugees can occasionally rebuild during the fluctuation period), rather than drop to zero.
As mentioned, a third migrant wave means the civ was struggling, not dead. Dead civs don't get dwarven caravans either (and never will), nor outpost liaisons.
The only known certain way to determine if a civ is truly dead is to embark and check the civ screen. If the civ section is completely blank the civ is dead, but if the dwarven civ is present, even without any important members, the civ is not dead. As soon as the civ gets in contact with any other civ (peaceful or otherwise) the dwarven civ appears on this menu, and so that determination method can no longer be used.
It can also be noted that if your struggling civ doesn't have a monarch off site, you'll be saddled with one at the two year mark at the latest. If it happens prior to that, a random dorf will take the position of monarch after a polite discussion, while the two year timeout seems to usually (always?) select the expedition leader, allowing you some room to groom one that won't spew harmful mandates.
The "hard coded" waves are made up of void dorfs if no eligible ones are used/exist. The necros are not eligible as they're no longer members of any civs beside their own necro ones(s). Dead civs get two migrant waves, but I'm unsure if a necro siege blocking a wave will postpone the migrants or if the wave is lost. Setting a pop cap works, and can obviously result in waves not appearing.