Improve tasks serve status UI for operator triage
Problem
Replace raw JSON blocks on /status with a simple, readable operator UI: top-level health cards, escalation table, ready/blocked/active lists, and direct links to task files/PRs/dispatch logs. Keep JSON endpoint for tooling
Also add a lightweight homepage/landing page that lists the local app surfaces typically started by just serve (Core, Cloud, Playground, Docs, A Lie, Nimble, Master Plans/tasks serve) with clickable links so operators can jump directly from one place.
Context
The /status endpoint in tasks/tools/tasks_server.py currently renders the snapshot as raw JSON in <pre> blocks — counts, register entries, and summary text. This is hard for operators to scan during triage. The snapshot payload (from scripts/task_manager_lib.py:snapshot_payload) already contains structured data: task lists with status/dispatch/PR/escalation fields, counts by category, and escalation signals. The /status.json endpoint serves the same data for tooling and must remain unchanged.
Key files:
- tasks/tools/tasks_server.py — FastAPI server, status_page() handler and _render_layout() shared shell
- scripts/task_manager_lib.py — TaskInfo dataclass, snapshot_payload(), format_age()
- tests/core/test_tasks_server.py — existing test coverage for status/browse endpoints
Constraints: server-side HTML only (no JS frameworks), keep _render_layout() shared shell, keep /status.json untouched.
Future: dispatch log and snapshot paths may move to <repo>/.tasks/ per rename-master-plans-tree-to-tasks; triage links should use shared path helpers, not hard-coded tasks/logs/....
Possible Solutions
-
Inline HTML rendering from snapshot dict — Parse the snapshot dict in
status_page()and emit semantic HTML: health-card divs for counts, an<table>for escalation signals, and categorized<ul>lists for tasks with links. Add CSS to existing<style>block. Recommended — minimal change, no new dependencies, keeps everything in one file. -
Jinja2 templates — Add a templates directory and render with Jinja2. Overkill for one page; adds a dependency and file.
-
Client-side JS fetching
/status.json— Violates the Django-first/no-SPA design philosophy.
Plan
Selected: approach 1 — inline HTML rendering.
Files to modify:
- tasks/tools/tasks_server.py — rewrite status_page(), extend _render_layout() styles
- tests/core/test_tasks_server.py — add tests for new UI elements
Steps:
1. Write tests asserting: health cards with count values, escalation table rows, task lists by category with links, paused banner
2. Rewrite status_page() to extract tasks/counts/escalation from snapshot and render structured HTML
3. Add CSS for health cards (grid), status badges, escalation table
4. Verify /status.json still passes existing tests unchanged
5. Add a / landing page section/card list as an app index (jump-off links to local services), with simple defaults and optional env overrides.
Implementation Progress
Scope update (2026-03-23)
- Added requirement: tasks server homepage should act as a local jump-off index for services commonly started by
just serve: - Core (
http://127.0.0.1:9876) - Cloud (
http://127.0.0.1:8000) - Playground (
http://127.0.0.1:8080) - Docs (
http://127.0.0.1:8001) - A Lie (
http://127.0.0.1:8113) - Nimble (
http://127.0.0.1:8003) - Master Plans / tasks server (
http://127.0.0.1:8005) - Delivery expectation: keep
/statusas triage page; add/upgrade/as an operator home with these links.
Changes made
tasks/tools/tasks_server.py:
- Added _format_age() — human-readable age strings (120s → "2m", 7200s → "2h 0m")
- Added _badge() — reusable HTML badge helper with color classes
- Added _DISPATCH_BADGE / _CI_BADGE — color maps for dispatch/CI states
- Added _task_row_html() — renders a single task as <li> with status badge, PR link, CI badge, conflict badge, blocker list, age, and attention signals
- Added _render_status_body() — main renderer:
- Paused banner when snap["paused"] is true
- Health cards grid (Ready, Blocked, Active, Attention, Escalation) with highlight colors
- Escalation signals table (task, code, detail, tier)
- Task lists categorized into Needs Attention, Ready, Blocked, Active sections
- Heartbeat timestamp footer
- Extended _render_layout() CSS: cards grid, card/attention/escalation styles, banner, badges, task-list
- Rewrote status_page() to delegate to _render_status_body()
- /status.json endpoint unchanged
tests/core/test_tasks_server.py:
- Added RICH_SNAPSHOT fixture with realistic multi-task data
- test_status_page_health_cards — verifies count cards with labels and values
- test_status_page_escalation_table — verifies <table> with signal rows
- test_status_page_task_lists_with_links — verifies PR links and browse links
- test_status_page_paused_banner — verifies paused banner appears
- test_status_page_empty_snapshot — verifies graceful empty-state rendering
All 12 tests pass. Lint/format clean.
QA Exploration
N/A — server-side HTML rendering; validated via test assertions on response content. No browser-interactive behavior to explore.
- [x] QA exploration completed (or N/A for non-UI tasks)
Review Feedback
- [ ] Review cleared