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

@ -63,6 +63,7 @@ interface SoloStore {
claudeJobsByTaskId: Record<string, JobState>
connectedWorkers: number
lowQuotaTokenIds: Set<string>
initTasks: (tasks: SoloTask[]) => void
optimisticMove: (taskId: string, toStatus: TaskStatus) => TaskStatus | null
@ -82,6 +83,7 @@ interface SoloStore {
setWorkers: (count: number) => void
incrementWorkers: () => void
decrementWorkers: () => void
setWorkerLowQuota: (tokenId: string, isLow: boolean) => void
handleRealtimeEvent: (event: RealtimeEvent) => void
}
@ -93,6 +95,7 @@ export const useSoloStore = create<SoloStore>((set, get) => ({
showConnectingIndicator: false,
claudeJobsByTaskId: {},
connectedWorkers: 0,
lowQuotaTokenIds: new Set<string>(),
initTasks: (tasks) =>
set({ tasks: Object.fromEntries(tasks.map(t => [t.id, t])) }),
@ -146,6 +149,13 @@ export const useSoloStore = create<SoloStore>((set, get) => ({
setWorkers: (count) => set({ connectedWorkers: Math.max(0, count) }),
incrementWorkers: () => set(s => ({ connectedWorkers: s.connectedWorkers + 1 })),
decrementWorkers: () => set(s => ({ connectedWorkers: Math.max(0, s.connectedWorkers - 1) })),
setWorkerLowQuota: (tokenId, isLow) =>
set(s => {
const next = new Set(s.lowQuotaTokenIds)
if (isLow) next.add(tokenId)
else next.delete(tokenId)
return { lowQuotaTokenIds: next }
}),
handleJobEvent: (event) => {
const { job_id, task_id } = event