"""Console Board v2 (/board, L19), UI chrome, and agent discovery routes.""" from __future__ import annotations import re import subprocess from pathlib import Path from typing import Any from fastapi.testclient import TestClient from tessera import ChildSpec, QueueConfig, Store, TaskSpec from tessera.access import ServiceSettings from tessera.service import create_app _ROW_RE = re.compile(r"(.*?)", re.DOTALL) _COL_RE = re.compile(r"([^<]*)") def _parse_board_queue_counts(html_text: str) -> dict[str, dict[str, int]]: parsed: dict[str, dict[str, int]] = {} for q_name, inner in _ROW_RE.findall(html_text): cols = dict(_COL_RE.findall(inner)) parsed[q_name] = { state: int(cols[state]) for state in ("ready", "leased", "waiting", "done", "dead", "cancelled") } return parsed def test_board_matches_counts_on_empty_and_populated_fabric(tmp_path: Path) -> None: db_path = tmp_path / "board.db" store = Store(db_path) admin_secret, _ = store.issue_key("admin", queues=["*"], scopes=["admin", "store"]) worker_a_secret, worker_a_grant = store.issue_key( "worker-a", queues=["*"], effect_classes=["read", "write-internal", "write-repo"] ) app = create_app(store, ServiceSettings(db_path=str(db_path), reaper_seconds=3600)) with TestClient(app) as client: # 1. Empty board renders cleanly with zero queues and zero write controls. empty_resp = client.get("/board") assert empty_resp.status_code == 200 empty_html = empty_resp.text assert "No queues yet." in empty_html assert "Live Verb Queues" in empty_html assert "Task Dependency & Split Wave DAG" in empty_html assert "Parked Tiles" in empty_html assert "Monotonic Cursor Event Feed" in empty_html assert ".table-wrap{overflow-x:auto" in empty_html counts_empty = client.get( "/v1/counts", headers={"authorization": f"Bearer {admin_secret}"} ).json()["queues"] assert _parse_board_queue_counts(empty_html) == counts_empty # 2. Populate all states, split waves, dependencies, parked tiles, and delta feeds. store.define_queue(QueueConfig(name="alpha", max_attempts=1)) store.define_queue(QueueConfig(name="beta", max_attempts=3)) # Done task + dependent task (waiting on another unresolved task) t_done = store.enqueue(TaskSpec(queue="alpha", brief={"step": "done"})) l_done = store.claim("alpha", "w1", key_id=worker_a_grant.key_id) assert l_done is not None store.submit( t_done, l_done.fencing_token, {"ok": 1}, idempotency_key="b-done", completed_by_key=worker_a_grant.key_id, ) # Dead task (max_attempts=1 on alpha) t_dead = store.enqueue(TaskSpec(queue="alpha", brief={"step": "fail"})) l_dead = store.claim("alpha", "w1", key_id=worker_a_grant.key_id) assert l_dead is not None store.submit( t_dead, l_dead.fencing_token, {"err": 1}, idempotency_key="b-dead", ok=False, error="boom", completed_by_key=worker_a_grant.key_id, ) # Cancelled task t_cancel = store.enqueue(TaskSpec(queue="alpha", brief={"step": "cancel"})) store.cancel(t_cancel, "no longer needed") # Parked task (waiting for input) t_park = store.enqueue(TaskSpec(queue="beta", brief={"step": "park"})) l_park = store.claim("beta", "w1", key_id=worker_a_grant.key_id) assert l_park is not None store.park(t_park, l_park.fencing_token, reason="awaiting reviewer", resume_within=600) # Split parent + wave children (child 0 ready, child 1 waiting on child 0) t_parent = store.enqueue(TaskSpec(queue="beta", brief={"step": "split"})) l_parent = store.claim("beta", "w1", key_id=worker_a_grant.key_id) assert l_parent is not None kids = store.split( t_parent, l_parent.fencing_token, [ ChildSpec(brief={"wave": 1}), ChildSpec(brief={"wave": 2}, after=[0]), ], ) # Leased task (claim child 0) + ready task + dependent task l_kid0 = store.claim("beta", "w2", key_id=worker_a_grant.key_id) assert l_kid0 is not None and l_kid0.task_id == kids[0] t_ready = store.enqueue(TaskSpec(queue="beta", brief={"step": "ready"})) t_dep = store.enqueue( TaskSpec(queue="alpha", brief={"step": "dep"}, depends_on=[t_done, t_ready]) ) # Monotonic feed entry store.publish_feed("ops.live", {"tile": t_ready}, summary="queued ready tile") # 3. Verify every queue's counts on /board match GET /v1/counts (L19). board_resp = client.get("/board") assert board_resp.status_code == 200 board_html = board_resp.text api_counts: dict[str, Any] = client.get( "/v1/counts", headers={"authorization": f"Bearer {admin_secret}"} ).json()["queues"] board_counts = _parse_board_queue_counts(board_html) assert board_counts == api_counts # Verify DAG, Parked Tiles, and Feed entries appear in the read-only HTML. assert t_parent in board_html and t_dep in board_html assert t_park in board_html and "input" in board_html assert "ops.live" in board_html and "queued ready tile" in board_html # Strictly read-only: zero forms, inputs, textareas, or buttons on /board, and zero leaked secrets. for forbidden_tag in (" None: db_path = tmp_path / "chrome.db" store = Store(db_path) app = create_app(store, ServiceSettings(db_path=str(db_path), reaper_seconds=3600)) with TestClient(app) as client: for route in ("/", "/connect", "/board", "/work"): resp = client.get(route) assert resp.status_code == 200, route assert "
" in resp.text assert "