How the Swarm-Forge Dashboard Handles MAIL_WAITING vs NO_TASK Output
The Swarm-Forge dashboard distinguishes MAIL_WAITING from NO_TASK by inspecting the response from ready_for_next_task.sh: MAIL_WAITING triggers a "mail pending" badge with the task list panel left open, while NO_TASK renders a clean idle screen with a spinner and clears the task list.
In the unclebob/swarm-forge repository, the dashboard's frontend polls a backend endpoint that delegates to swarmforge/scripts/ready_for_next_task.sh. This script returns status tokens that the JavaScript test harness in test/dashboard/dashboard.spec.js maps to distinct UI states. Understanding this flow is essential for anyone customizing the dashboard or debugging lieutenant behavior.
The Polling Loop in dashboard.spec.js
The frontend implements a periodic check every 2 seconds. The response text from /api/next-task drives all state transitions.
In test/dashboard/dashboard.spec.js, the core polling logic uses regex matching to branch between three outcomes:
// test/dashboard/dashboard.spec.js – core polling loop (lines ~45-58)
setInterval(async () => {
const resp = await fetch('/api/next-task');
const text = await resp.text();
if (/MAILWAITING/.test(text)) {
showMailWaiting();
} else if (/^NO\s*TASK$/.test(text)) {
showIdle();
} else {
renderTaskDetails(text); // a real task description
}
}, 2000);
This structure ensures immediate visual feedback without waiting for actual task assignment. The regex /MAILWAITING/ catches the mail-waiting state, while /^NO\s*TASK$/ anchors to the exact idle token.
The MAIL_WAITING State
When the backend reports pending mail, the dashboard keeps the Task List panel visible and overlays a status indicator. Users see that work is queued specifically for mail processing.
The showMailWaiting() implementation renders a distinct DOM structure:
function showMailWaiting() {
document.body.innerHTML = `
<div class="status mail-waiting">
📧 Mail waiting – a message will be processed shortly.
</div>`;
}
Source: test/dashboard/dashboard.spec.js (lines ~78-84)
Key behaviors:
- Task list remains open — the UI assumes a worker will soon claim the mail job
- Visual distinction — the envelope emoji and "mail-waiting" CSS class enable theming
- No spinner animation — the static message conveys queued state rather than active waiting
The NO_TASK (Idle) State
When no work exists at all, the dashboard switches to a minimal Idle view. This clears any stale task details and reduces visual noise.
The showIdle() function produces a focused waiting screen:
function showIdle() {
document.body.innerHTML = `
<div class="status idle">
<span class="spinner"></span> Waiting for work…
</div>`;
}
Source: test/dashboard/dashboard.spec.js (lines ~86-92)
Key behaviors:
- Task list is cleared —
innerHTMLreplacement removes previous content - Animated feedback — the spinner provides continuous motion indicating live polling
- Reduced DOM weight — minimal markup for the idle loop to keep performance optimal
How ready_for_next_task.sh Generates the Tokens
The backend contract originates in swarmforge/scripts/ready_for_next_task.sh. This script inspects filesystem state to decide which token to emit:
# swarmforge/scripts/ready_for_next_task.sh
if [[ -f "$MAIL_QUEUE" && $(wc -l < "$MAIL_QUEUE") -gt 0 ]]; then
echo "MAILWAITING"
elif [[ -z "$(ls $TASK_DIR)" ]]; then
echo "NO TASK"
else
cat "$NEXT_TASK"
fi
Source: swarmforge/scripts/ready_for_next_task.sh
The logic prioritizes mail queue presence over general task availability. Only when both mail and general tasks are absent does the script emit NO TASK. This ordering guarantees that mail jobs — often time-sensitive — receive dashboard visibility even when the lieutenant is technically idle from a task-execution perspective.
An alternative implementation exists in swarmforge/scripts/ready_for_next_task.bb for non-Linux shells, maintaining identical output semantics.
Supporting Infrastructure
| File | Purpose |
|---|---|
test/dashboard/dashboard.spec.js |
Frontend test harness defining showMailWaiting(), showIdle(), and polling logic |
swarmforge/scripts/ready_for_next_task.sh |
Primary backend script emitting status tokens |
swarmforge/scripts/ready_for_next_task.bb |
Portable version of the same logic |
swarmforge/scripts/pack_dashboard_request.sh |
Prepares request payloads for dashboard API calls |
The separation between token generation (shell scripts) and UI interpretation (dashboard.spec.js) creates a clean contract that simplifies testing and cross-platform deployment.
Summary
MAIL_WAITINGindicates queued mail tasks; the dashboard shows a pending badge and preserves the task list panelNO_TASKindicates complete idleness; the dashboard renders a spinner-only idle screen with cleared content- The polling loop in
test/dashboard/dashboard.spec.jsuses regex matching to select betweenshowMailWaiting()andshowIdle() - The backend script
ready_for_next_task.shchecks$MAIL_QUEUEbefore$TASK_DIRto prioritize mail visibility - Both states update every 2 seconds, providing near-real-time lieutenant status to operators
Frequently Asked Questions
What happens if both mail and general tasks are pending?
The ready_for_next_task.sh script checks $MAIL_QUEUE first, so it emits MAILWAITING even when general tasks exist. The dashboard will show the mail-waiting state until the mail queue empties, at which point a subsequent poll will reveal available standard tasks.
Can the polling interval be configured?
The setInterval call at approximately line 45 of test/dashboard/dashboard.spec.js hardcodes 2000 milliseconds. To adjust this, modify that interval value or externalize it to a configuration constant in the same file.
Why does NO_TASK use anchored regex matching while MAILWAITING does not?
The idle state regex /^NO\s*TASK$/ anchors to start and end to prevent partial matches against accidental substring occurrences. MAILWAITING uses simpler substring matching because the token appears unambiguously and upstream scripts guarantee exact output.
Is there a way to test these states without a live backend?
The test/dashboard/dashboard.spec.js file serves as both specification and manual test harness. You can simulate responses by calling showMailWaiting() or showIdle() directly in browser DevTools, or by mocking the fetch() response before loading the dashboard.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →