feat(supervise): show the bottle's human slug, not its opaque id

Consolidated proposals are keyed by the orchestrator-assigned bottle_id,
so the supervise TUI was rendering a hex id (e.g. 3601cbe883c2786d) as
the bottle name — and the resume hint printed `./cli.py resume <id>`,
which resume can't take (it wants the human identity/slug).

`supervise_pending` now tags each dict with `bottle_label` — the human
slug resolved from registry metadata, falling back to the id when the
bottle is gone. `QueuedProposal` carries the label; every display site
(list rows, detail view, status lines, resume hint) shows it, while
approve/reject still key on `proposal.bottle_slug` (the id).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UoEZHDjv84ChoZbozQERhJ
This commit is contained in:
2026-07-16 22:05:21 -04:00
parent 5f59df9e10
commit b1df380ae1
4 changed files with 75 additions and 10 deletions
+17
View File
@@ -78,6 +78,23 @@ class TestDiscoverPending(_ClientMixin, unittest.TestCase):
pending = supervise_cli.discover_pending()
self.assertEqual([early.id, late.id], [qp.proposal.id for qp in pending])
def test_label_comes_from_bottle_label(self) -> None:
# The server tags each dict with the human slug; the CLI displays it
# while the proposal stays keyed by the opaque bottle_id.
client = MagicMock()
d = _proposal("3601cbe883c2786d").to_dict()
d["bottle_label"] = "codex-dev-a1b2c"
client.supervise_pending.return_value = [d]
with patch.object(supervise_cli, "_client", return_value=client):
pending = supervise_cli.discover_pending()
self.assertEqual("codex-dev-a1b2c", pending[0].label)
self.assertEqual("3601cbe883c2786d", pending[0].proposal.bottle_slug)
def test_label_falls_back_to_slug_when_absent(self) -> None:
# Legacy dicts without bottle_label (e.g. an older orchestrator).
self._install_client([_proposal("dev")])
self.assertEqual("dev", supervise_cli.discover_pending()[0].label)
class TestApproveReject(_ClientMixin, unittest.TestCase):
def _qp(self, tool: str = TOOL_EGRESS_ALLOW) -> "supervise_cli.QueuedProposal":