From f91ba9a16e2525265cb86dbcd15029fff8b21185 Mon Sep 17 00:00:00 2001 From: anti Date: Sun, 19 Apr 2026 18:29:41 -0400 Subject: [PATCH] feat(cli): allow `decnet status` in agent mode Agents run deckies locally and need to inspect their own state. Removed `status` from MASTER_ONLY_COMMANDS so it survives the agent-mode gate. Useful for validating remote updater pushes from the master. --- decnet/cli.py | 5 +++-- tests/test_cli.py | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/decnet/cli.py b/decnet/cli.py index df40568..f513c8a 100644 --- a/decnet/cli.py +++ b/decnet/cli.py @@ -1761,11 +1761,12 @@ def db_reset( # Forgetting to register a new command is a role-boundary bug. Grep for # MASTER_ONLY when touching command registration. # -# Worker-legitimate commands (NOT in these sets): agent, updater, forwarder. +# Worker-legitimate commands (NOT in these sets): agent, updater, forwarder, +# status (agents run deckies locally and should be able to inspect them). # ─────────────────────────────────────────────────────────────────────────── MASTER_ONLY_COMMANDS: frozenset[str] = frozenset({ "api", "swarmctl", "deploy", "redeploy", "teardown", - "probe", "collect", "mutate", "listener", "status", + "probe", "collect", "mutate", "listener", "services", "distros", "correlate", "archetypes", "web", "profiler", "sniffer", "db-reset", }) diff --git a/tests/test_cli.py b/tests/test_cli.py index a656176..ed4e180 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -217,6 +217,28 @@ class TestStatusCommand: result = runner.invoke(app, ["status"]) assert result.exit_code == 0 + def test_status_available_in_agent_mode(self, monkeypatch): + # Agents run deckies locally and must be able to inspect them; + # `status` is intentionally NOT in MASTER_ONLY_COMMANDS. + import importlib + + import decnet.cli as cli_mod + + monkeypatch.setenv("DECNET_MODE", "agent") + monkeypatch.setenv("DECNET_DISALLOW_MASTER", "true") + reloaded = importlib.reload(cli_mod) + try: + names = { + (c.name or c.callback.__name__) + for c in reloaded.app.registered_commands + } + assert "status" in names + assert "deploy" not in names # sanity: master-only still gated + finally: + monkeypatch.delenv("DECNET_MODE", raising=False) + monkeypatch.delenv("DECNET_DISALLOW_MASTER", raising=False) + importlib.reload(cli_mod) + # ── mutate command ────────────────────────────────────────────────────────────