feat(ST-qfpqpxzy): SSE + NavBar stand-by badge voor worker quota-gate

- SSE route: WorkerHeartbeatPayload type + shouldEmit handler voor worker_heartbeat
- solo-store: lowQuotaTokenIds Set<string> + setWorkerLowQuota action
- use-solo-realtime: worker_heartbeat event → setWorkerLowQuota; worker_disconnected verwijdert uit set
- nav-status-indicators: stand-by badge (bg-warning) als alle workers low quota
- docs/runbooks/mcp-integration.md: get_worker_settings + worker_heartbeat tools + pre-flight quota-check sectie

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scrum4Me Agent 2026-05-06 03:53:12 +02:00
parent 3a73b4f1c9
commit 661601e833
6 changed files with 114 additions and 10 deletions

View file

@ -64,7 +64,15 @@ type WorkerPayload = {
product_id?: string
}
type NotifyPayload = EntityPayload | JobPayload | WorkerPayload
type WorkerHeartbeatPayload = {
type: 'worker_heartbeat'
user_id: string
token_id: string
last_quota_pct: number | null
is_low: boolean
}
type NotifyPayload = EntityPayload | JobPayload | WorkerPayload | WorkerHeartbeatPayload
function isJobPayload(p: NotifyPayload): p is JobPayload {
return 'type' in p && (p.type === 'claude_job_enqueued' || p.type === 'claude_job_status')
@ -74,6 +82,10 @@ function isWorkerPayload(p: NotifyPayload): p is WorkerPayload {
return 'type' in p && (p.type === 'worker_connected' || p.type === 'worker_disconnected')
}
function isWorkerHeartbeatPayload(p: NotifyPayload): p is WorkerHeartbeatPayload {
return 'type' in p && p.type === 'worker_heartbeat'
}
function shouldEmit(
payload: NotifyPayload,
productId: string,
@ -90,6 +102,10 @@ function shouldEmit(
return payload.user_id === userId
}
if (isWorkerHeartbeatPayload(payload)) {
return payload.user_id === userId
}
// M11 (ST-1104): question-events horen op /api/realtime/notifications, niet hier.
if (payload.entity === 'question') return false