From 93cb3d9a2b4cdeece1e3215e5b41ed24e99e76bb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Apr 2026 02:55:38 +0000 Subject: [PATCH] fix(coord): restore reload-time pending approval gate Agent-Logs-Url: https://github.com/turnstonelabs/turnstone/sessions/30f630fe-3ded-4abe-991b-b5a95f699127 Co-authored-by: eous <13773563+eous@users.noreply.github.com> --- tests/test_coordinator_page.py | 6 +++++ .../console/static/coordinator/coordinator.js | 25 ++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/tests/test_coordinator_page.py b/tests/test_coordinator_page.py index 472394cb..0515f3b6 100644 --- a/tests/test_coordinator_page.py +++ b/tests/test_coordinator_page.py @@ -119,3 +119,9 @@ def test_coordinator_js_exposes_inline_approval_helpers(): # call short-circuits on non-visible rows, leaving them stuck. assert "_maybeStartJudgePoll" in body assert "_judgePollTick" in body + # Reload parity for the coord-self approval gate: init() must + # consume the authoritative GET /workstreams snapshot's + # pending_approval_detail so a freshly opened tab can render + # Approve/Deny before SSE replay arrives. + assert "wsSnapshot.pending_approval_detail" in body + assert "appendToolBatch(pendingDetail.items" in body diff --git a/turnstone/console/static/coordinator/coordinator.js b/turnstone/console/static/coordinator/coordinator.js index ff4a885e..702568d0 100644 --- a/turnstone/console/static/coordinator/coordinator.js +++ b/turnstone/console/static/coordinator/coordinator.js @@ -3046,12 +3046,13 @@ // ------------------------------------------------------------------ async function init() { + let wsSnapshot = null; try { - const data = await getJSON( + wsSnapshot = await getJSON( "/v1/api/workstreams/" + encodeURIComponent(wsId), ); - nameEl.textContent = data.name || ""; - statusEl.textContent = data.state || ""; + nameEl.textContent = wsSnapshot.name || ""; + statusEl.textContent = wsSnapshot.state || ""; } catch (e) { appendText("error", "Failed to load coordinator: " + e.message); return; @@ -3226,6 +3227,24 @@ appendText(role, content, { label: role }); } }); + // History alone can't tell whether an orphaned assistant + // tool_calls turn is awaiting approval or merely still running. + // The live workstream snapshot can: if pending_approval_detail is + // present, upgrade the matching batch immediately so a reload + // still exposes Approve/Deny even before SSE reconnects. + const pendingDetail = + wsSnapshot && + wsSnapshot.pending_approval && + wsSnapshot.pending_approval_detail && + Array.isArray(wsSnapshot.pending_approval_detail.items) + ? wsSnapshot.pending_approval_detail + : null; + if (pendingDetail) { + appendToolBatch(pendingDetail.items, { + pending: true, + judgePending: !!pendingDetail.judge_pending, + }); + } } catch (e) { console.warn("history load failed", e); }