fix(panel): V6 review gaps — honest errors, safe secretary start, real tests

CEO A2A mutations now invalidate the Mine-list query key so the list
refreshes without the socket; the tg Metrics tab renders explicit error
notes instead of confident zero stats when a section's fetch fails; the
tg Secretary chat checks a new registry-backed /secretary/live/active
route before auto-starting, showing a Take Over button instead of
silently killing a session live on another device; the AI-routing card
surfaces roster fetch errors instead of an empty grid; the shared
acceptance-criteria editor caps at the backend's 7-item limit; the
board-tab comment no longer calls the task sheet read-only. Tests:
task-sheet approve/reject interactions (not just visibility), a
non-demo metrics error-state test, secretary take-over branches, and
dashboard-router auth-gate coverage (the e2e harness now mounts the
dashboard router so the gate is actually exercised).
This commit is contained in:
Renn F
2026-07-22 03:31:25 +02:00
parent 5ca8a9c4a6
commit a1233b2aeb
18 changed files with 726 additions and 144 deletions
@@ -158,6 +158,7 @@ async def test_stream_accepts_valid_panel_token(
("GET", "/api/secretary/live/unknown/status", None),
("POST", "/api/secretary/live/unknown/messages", {"text": "hi"}),
("POST", "/api/secretary/live/sess/stop", None),
("GET", "/api/secretary/live/active", None),
],
)
@pytest.mark.asyncio
@@ -176,6 +177,22 @@ async def test_status_send_stop_reject_missing_token_when_required(
assert r.status_code == _HTTP_401
@pytest.mark.asyncio
async def test_is_active_accepts_valid_panel_token_and_reflects_the_registry(
auth_client: AsyncClient, monkeypatch: pytest.MonkeyPatch
) -> None:
_strict(monkeypatch)
headers = {"X-Agent-Token": issue_panel_token()}
r = await auth_client.get("/api/secretary/live/active", headers=headers)
assert r.status_code == HTTPStatus.OK
assert r.json() == {"active": False}
prompter_live.get_live_registry().open("some-device", "secretary-1")
r = await auth_client.get("/api/secretary/live/active", headers=headers)
assert r.json() == {"active": True}
@pytest.mark.asyncio
async def test_events_ungated_in_strict_mode(
auth_client: AsyncClient, monkeypatch: pytest.MonkeyPatch
+18
View File
@@ -221,5 +221,23 @@ async def test_deliver_to_unknown_or_failing_returns_false() -> None:
await client.aclose()
def test_has_live_agent_tracks_any_session_for_that_agent() -> None:
"""Backs the "is the Secretary live under ANY session id" check — distinct
from is_alive, which needs the caller's own session id."""
reg = PrompterLiveRegistry()
assert reg.has_live_agent("secretary-1") is False # nothing open yet
reg.open("device-a", "secretary-1")
assert reg.has_live_agent("secretary-1") is True
assert reg.has_live_agent("intake-1") is False # different agent, untouched
reg.close("device-a")
assert reg.has_live_agent("secretary-1") is False # closed -> gone
# A second session id for the SAME agent still counts as live.
reg.open("device-b", "secretary-1")
assert reg.has_live_agent("secretary-1") is True
def test_registry_singleton() -> None:
assert get_live_registry() is get_live_registry()