Repository navigation
Conversation
… detection Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds DispatchHealth interface to api/types.ts, extends DaemonStatusResponse in useDaemon.ts with an optional health field (also tightens poll to 5s), and creates the DispatchHealthBanner component that renders an amber warning when hasStuckQueue is true. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…pages Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…pper Banner now takes an optional className applied to its outer element so each mount site controls its own page-specific padding. The workspaces route previously wrapped the banner in a div with px-6 pt-4 which left 16px of empty padding when the banner self-hides (queue healthy or dismissed). The wrapper is gone; the banner mounts directly with className="mx-6 mt-4" passed in.
Replaces the per-tick rate-limited warn with state-transition logging: - Healthy → Stuck: single STUCK warn line with the count and a clear hint. - Stuck → Healthy: single RESUMED info line confirming dispatch is flowing. - No periodic reminders. A long-running stuck state does not spam the log. Drops the stuckWarnTickInterval config option (was 20 ticks, 100s spacing in production). Distinctive STUCK/RESUMED prefixes make the lines findable in a chatty log stream. Tests: - Verifies STUCK warn fires on first stuck tick AND does not fire again on subsequent stuck ticks (was the periodic-spam regression risk). - Verifies RESUMED info fires on the next healthy tick after stuck.
komoreka
force-pushed
the
feat/dispatch-stuck-warning
branch
from
May 5, 2026 06:58
f74ea8a to
7782bbe
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Internal review PR before opening upstream against
stoneforge-ai/stoneforge.Summary
Closes upstream stoneforge-ai#59. Surfaces a clear signal when the dispatch worker queue is stuck (ready unassigned tasks > 0, no available workers). Three surfaces:
[dispatch] N task(s) ready, no available workers..., rate-limited to once per 20 ticks (configurable viaDispatchDaemonConfig.stuckWarnTickInterval), re-warns immediately after the queue clears and re-stuckens.GET /api/daemon/statusnow includes ahealthfield with{ readyUnassignedTasks, availableWorkers, stuck, hasStuckQueue, computedAt }.DispatchHealthBanneron the agents and workspaces pages whenhasStuckQueueis true. Dismissible per page-load.The model is intentionally simple: existing dispatch logic does not route by role at the data layer (
assignTaskToWorkerindispatch-daemon.ts:2705grabs the first unassigned task without filtering by role), so the stuck-queue concept is exclusively about workers. Directors are interactive (humans drive them); stewards run on triggers; neither pulls from the unassigned queue. An "available worker" is one that is registered, not disabled, and not terminated. At-capacity workers do not count as stuck (the queue is busy, not stuck) to avoid misleading warnings.Validation
bun test src/services/dispatch-daemon.bun.test.tscovers four detection cases (no tasks, no workers, available worker, disabled worker) plus the warn-on-tick test. 1549 pass / 0 fail in smithy.vitest src/server/routes/daemon.test.tscovers status payload with daemon, without daemon, and withgetDispatchHealththrowing. 42 pass / 0 fail in routes suite.NODE_ENV=development npx turbo run typecheckpasses (16/16 packages).NODE_ENV=development pnpm buildpasses (13/13).Cross-PR dependency note
This branch contains a 5-line type addition (
disabled?: booleanonBaseAgentMetadata) and a 10-line file (isAgentDisabled/isAgentEnabledhelpers) that overlap with PR stoneforge-ai#60 against upstream. The duplication is byte-identical (verified during Task 1 review); when PR stoneforge-ai#60 merges first the rebase here is trivial.Out of scope
Manual smoke recipe