From 09db0eda98fa09e74f118e005e0f7be9796bc7bf Mon Sep 17 00:00:00 2001 From: claude Date: Tue, 23 Jun 2026 02:05:40 +0000 Subject: [PATCH] fix: don't archive gitleaks-allow response before gate reads it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The TUI was calling archive_proposal for gitleaks-allow immediately after write_response, moving the response file to processed/ within microseconds. The git-gate shell loop polls queue_dir for the response file every second — it never sees it and hangs until timeout. capability-block is handled by the MCP sidecar which archives after reading; gitleaks-allow is handled by the shell gate which archives after processing. Let the gate own the archive step. --- bot_bottle/cli/supervise.py | 2 +- tests/unit/test_supervise_cli.py | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/bot_bottle/cli/supervise.py b/bot_bottle/cli/supervise.py index da15cbe..3ba2648 100644 --- a/bot_bottle/cli/supervise.py +++ b/bot_bottle/cli/supervise.py @@ -157,7 +157,7 @@ def approve( qp, action=status, notes=notes, diff_before=diff_before, diff_after=diff_after, ) - if qp.proposal.tool in (TOOL_CAPABILITY_BLOCK, TOOL_GITLEAKS_ALLOW): + if qp.proposal.tool == TOOL_CAPABILITY_BLOCK: archive_proposal(qp.queue_dir, qp.proposal.id) diff --git a/tests/unit/test_supervise_cli.py b/tests/unit/test_supervise_cli.py index 69240bd..bef4645 100644 --- a/tests/unit/test_supervise_cli.py +++ b/tests/unit/test_supervise_cli.py @@ -157,12 +157,14 @@ class TestApproveReject(_FakeHomeMixin, unittest.TestCase): supervise_cli.approve(qp) self.assertEqual([], read_audit_entries("egress", "dev")) - def test_approve_archives_gitleaks_allow(self): + def test_approve_gitleaks_allow_leaves_response_for_gate(self): qp = self._enqueue(tool=TOOL_GITLEAKS_ALLOW) supervise_cli.approve(qp, notes="dummy fixture") - resp = read_response(qp.queue_dir / "processed", qp.proposal.id) + # Gate polls the queue dir for the response; TUI must not archive it. + resp = read_response(qp.queue_dir, qp.proposal.id) self.assertEqual(STATUS_APPROVED, resp.status) self.assertEqual("dummy fixture", resp.notes) + self.assertFalse((qp.queue_dir / "processed").exists()) def test_tui_gitleaks_allow_requires_reason(self): qp = self._enqueue(tool=TOOL_GITLEAKS_ALLOW) @@ -176,7 +178,7 @@ class TestApproveReject(_FakeHomeMixin, unittest.TestCase): with patch.object(supervise_cli, "_prompt", return_value="test fixture"): status = supervise_cli._approve_from_tui(None, qp) # type: ignore[arg-type] self.assertIn("approved gitleaks-allow", status) - resp = read_response(qp.queue_dir / "processed", qp.proposal.id) + resp = read_response(qp.queue_dir, qp.proposal.id) self.assertEqual("test fixture", resp.notes)