Dataface Tasks

Improve tasks serve status UI for operator triage

IDINFRA_TOOLING-IMPROVE_TASKS_SERVE_STATUS_UI_FOR_OPERATOR_TRIAGE
Statuscompleted
Priorityp1
Milestonem1-ft-analytics-analyst-pilot
Ownersr-engineer-architect
Completed bydave
Completed2026-03-24

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.pyTaskInfo 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

  1. 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.

  2. Jinja2 templates — Add a templates directory and render with Jinja2. Overkill for one page; adds a dependency and file.

  3. 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 /status as 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