Workspaces restart with status='provisioning' and never transition to
'online' because the runtime never calls /registry/register after
container start — only the heartbeat loop runs post-boot. The heartbeat
handler had transitions for online→degraded, degraded→online, and
offline→online, but NOT provisioning→online, leaving newly-started
workspaces in a phantom-idle state where the scheduler defers dispatch
and the A2A proxy rejects them even though they're running fine.
Fix: add provisioning→online transition to evaluateStatus(), guarded by
`AND status = 'provisioning'` in the UPDATE WHERE clause so a concurrent
Delete cannot flip 'removed' back to 'online'. Broadcasts WORKSPACE_ONLINE
with recovered_from='provisioning' so dashboard/scheduler reflect reality.
Add TestHeartbeatHandler_ProvisioningToOnline to cover the new path.
Issue: Molecule-AI/molecule-core#1784
Co-authored-by: Molecule AI Core-BE <core-be@agents.moleculesai.app>
Co-authored-by: molecule-ai[bot] <276602405+molecule-ai[bot]@users.noreply.github.com>