Six regression tests pinning the dispatcher contract that was broken
in #28712:
* test_worker_block_is_not_auto_promoted_by_recompute_ready —
kanban_block survives five back-to-back ticks (compressed dispatcher
loop).
* test_worker_block_on_child_with_done_parents_is_still_sticky —
the parent-completion code path was the worst false-positive; even
when every parent is done, an explicit worker block stays blocked.
* test_circuit_breaker_block_still_auto_promotes — preserves the
pre-#28712 recovery semantics for circuit-breaker blocks (direct
UPDATE + no "blocked" event).
* test_gave_up_event_alone_does_not_make_block_sticky — explicit
guard so the gave_up event is never accidentally treated as
sticky; covers the second leg of the protocol_violation loop.
* test_unblock_clears_sticky_state_and_lets_block_recover — only
unblock_task resolves the sticky state; subsequent circuit-breaker
blocks recover normally.
* test_protocol_violation_loop_is_broken — full bug-shaped
reproduction: block → tick → (would-be) crash + gave_up → next tick
still blocked. Without the fix this would loop indefinitely.
The seventh test from the original PR (legacy-DB init recovery) was
dropped during salvage — the schema-init half of #28712 is already
fixed on main by #28754 and #28781, and the contract is covered by
test_kanban_db.py::test_connect_migrates_legacy_db_before_optional_column_indexes.