From a21f2358c625afaa6ba9aea6bab527fa2bbf76c3 Mon Sep 17 00:00:00 2001 From: didericis Date: Fri, 24 Jul 2026 17:31:14 -0400 Subject: [PATCH] refactor(cli): trim _common to a PROG constants leaf; inline os.getcwd() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _common had rotted into a junk drawer. Trim it to what actually justifies a shared leaf module and rename for legibility: * REPO_DIR: deleted (dead — nothing imported it). * read_tty_line: dropped the pointless re-export; cleanup/start/init now import it straight from bot_bottle.util. * USER_CWD: deleted. It captured os.getcwd() at import time, but nothing chdirs and no test patched it, so it was equivalent to a live os.getcwd() — inlined at the six call sites. * PROG: kept, now the sole member. It's still a leaf (both the dispatcher and the commands it imports need it) so it can't move into __init__ without a circular import. _common.py -> constants.py. Full unit suite green (2243); CLI dispatch verified. Co-Authored-By: Claude Opus 4.8 --- bot_bottle/cli/__init__.py | 2 +- bot_bottle/cli/_common.py | 12 ------------ bot_bottle/cli/commands/__init__.py | 2 +- bot_bottle/cli/commands/backend.py | 2 +- bot_bottle/cli/commands/cleanup.py | 2 +- bot_bottle/cli/commands/commit.py | 2 +- bot_bottle/cli/commands/edit.py | 4 ++-- bot_bottle/cli/commands/info.py | 5 +++-- bot_bottle/cli/commands/init.py | 5 +++-- bot_bottle/cli/commands/list.py | 4 ++-- bot_bottle/cli/commands/resume.py | 7 ++++--- bot_bottle/cli/commands/start.py | 9 +++++---- bot_bottle/cli/commands/supervise.py | 2 +- bot_bottle/cli/constants.py | 8 ++++++++ 14 files changed, 33 insertions(+), 33 deletions(-) delete mode 100644 bot_bottle/cli/_common.py create mode 100644 bot_bottle/cli/constants.py diff --git a/bot_bottle/cli/__init__.py b/bot_bottle/cli/__init__.py index 41ffa7d4..b26642a7 100644 --- a/bot_bottle/cli/__init__.py +++ b/bot_bottle/cli/__init__.py @@ -11,7 +11,7 @@ from ..errors import MissingEnvVarError from ..log import Die, die, error from ..manifest import ManifestError from ..orchestrator.store.store_manager import StoreManager -from ._common import PROG +from .constants import PROG from .commands import list as _list_mod from .commands.backend import cmd_backend from .commands.cleanup import cmd_cleanup diff --git a/bot_bottle/cli/_common.py b/bot_bottle/cli/_common.py deleted file mode 100644 index 5fc6c332..00000000 --- a/bot_bottle/cli/_common.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Shared constants and tty helper for cli subcommands.""" - -from __future__ import annotations - -import os -from pathlib import Path - -from ..util import read_tty_line as read_tty_line - -PROG = "cli.py" -USER_CWD = os.getcwd() -REPO_DIR = str(Path(__file__).resolve().parent.parent.parent) diff --git a/bot_bottle/cli/commands/__init__.py b/bot_bottle/cli/commands/__init__.py index 0daac76b..7f34d763 100644 --- a/bot_bottle/cli/commands/__init__.py +++ b/bot_bottle/cli/commands/__init__.py @@ -2,5 +2,5 @@ Each module exposes a `cmd_(argv)` handler that the dispatcher (`bot_bottle.cli`) registers in its COMMANDS table. Shared CLI helpers -(`_common`, `tui`) stay one level up in the `cli` package. +(`constants`, `tui`) stay one level up in the `cli` package. """ diff --git a/bot_bottle/cli/commands/backend.py b/bot_bottle/cli/commands/backend.py index 2997db36..a06e44f5 100644 --- a/bot_bottle/cli/commands/backend.py +++ b/bot_bottle/cli/commands/backend.py @@ -16,7 +16,7 @@ from __future__ import annotations import argparse from ...backend import get_bottle_backend, known_backend_names -from .._common import PROG +from ..constants import PROG def cmd_backend(args: list[str]) -> int: diff --git a/bot_bottle/cli/commands/cleanup.py b/bot_bottle/cli/commands/cleanup.py index 685f6bcb..d83ef14c 100644 --- a/bot_bottle/cli/commands/cleanup.py +++ b/bot_bottle/cli/commands/cleanup.py @@ -23,7 +23,7 @@ import sys from ...backend import get_bottle_backend, has_backend, known_backend_names from ...log import info -from .._common import read_tty_line +from ...util import read_tty_line def cmd_cleanup(_argv: list[str]) -> int: diff --git a/bot_bottle/cli/commands/commit.py b/bot_bottle/cli/commands/commit.py index 502ae697..fcf454d2 100644 --- a/bot_bottle/cli/commands/commit.py +++ b/bot_bottle/cli/commands/commit.py @@ -16,7 +16,7 @@ from ...backend import enumerate_active_agents from ...backend.freeze import CommitCancelled, get_freezer from ...bottle_state import read_metadata from ...log import die -from .._common import PROG +from ..constants import PROG from .. import tui diff --git a/bot_bottle/cli/commands/edit.py b/bot_bottle/cli/commands/edit.py index 82ca91b4..86075175 100644 --- a/bot_bottle/cli/commands/edit.py +++ b/bot_bottle/cli/commands/edit.py @@ -8,7 +8,7 @@ import os from pathlib import Path from ...log import die -from .._common import PROG, USER_CWD +from ..constants import PROG def cmd_edit(argv: list[str]) -> int: @@ -20,7 +20,7 @@ def cmd_edit(argv: list[str]) -> int: if args.scope == "user": target_file = Path(os.environ["HOME"]) / "bot-bottle.json" else: - target_file = Path(USER_CWD) / "bot-bottle.json" + target_file = Path(os.getcwd()) / "bot-bottle.json" if not target_file.is_file(): die(f"{target_file} does not exist") diff --git a/bot_bottle/cli/commands/info.py b/bot_bottle/cli/commands/info.py index d15b5612..7850a2d1 100644 --- a/bot_bottle/cli/commands/info.py +++ b/bot_bottle/cli/commands/info.py @@ -3,10 +3,11 @@ from __future__ import annotations import argparse +import os from ...log import info from ...manifest import ManifestIndex -from .._common import PROG, USER_CWD +from ..constants import PROG def cmd_info(argv: list[str]) -> int: @@ -14,7 +15,7 @@ def cmd_info(argv: list[str]) -> int: parser.add_argument("name", help="agent name defined in bot-bottle.json") args = parser.parse_args(argv) - names = ManifestIndex.resolve(USER_CWD) + names = ManifestIndex.resolve(os.getcwd()) names.require_agent(args.name) manifest = names.load_for_agent(args.name) diff --git a/bot_bottle/cli/commands/init.py b/bot_bottle/cli/commands/init.py index ca169f12..34441779 100644 --- a/bot_bottle/cli/commands/init.py +++ b/bot_bottle/cli/commands/init.py @@ -11,7 +11,8 @@ from pathlib import Path from typing import Any from ...log import die, info, warn -from .._common import PROG, USER_CWD, read_tty_line +from ..constants import PROG +from ...util import read_tty_line def cmd_init(argv: list[str]) -> int: @@ -22,7 +23,7 @@ def cmd_init(argv: list[str]) -> int: if args.scope == "user": target_file = Path(os.environ["HOME"]) / "bot-bottle.json" else: - target_file = Path(USER_CWD) / "bot-bottle.json" + target_file = Path(os.getcwd()) / "bot-bottle.json" print(file=sys.stderr) info(f"bot-bottle init — adding a new agent to {target_file}") diff --git a/bot_bottle/cli/commands/list.py b/bot_bottle/cli/commands/list.py index 5c0caf35..6b83c4eb 100644 --- a/bot_bottle/cli/commands/list.py +++ b/bot_bottle/cli/commands/list.py @@ -8,7 +8,7 @@ import sys from ...backend import enumerate_active_agents from ...manifest import ManifestIndex -from .._common import PROG, USER_CWD +from ..constants import PROG _ANSI_COLOR_CODES: dict[str, str] = { "red": "\033[91m", @@ -40,7 +40,7 @@ def cmd_list(argv: list[str]) -> int: args = parser.parse_args(argv) if args.scope == "available": - manifest = ManifestIndex.resolve(USER_CWD) + manifest = ManifestIndex.resolve(os.getcwd()) for name in manifest.all_agent_names: print(name) return 0 diff --git a/bot_bottle/cli/commands/resume.py b/bot_bottle/cli/commands/resume.py index 6d8224af..e3b6bc28 100644 --- a/bot_bottle/cli/commands/resume.py +++ b/bot_bottle/cli/commands/resume.py @@ -15,12 +15,13 @@ to bring up the replacement from the recorded state. from __future__ import annotations import argparse +import os from ...backend import BottleSpec from ...bottle_state import read_metadata from ...log import die from ...manifest import ManifestIndex -from .._common import PROG, USER_CWD +from ..constants import PROG from .start import _launch_bottle @@ -40,14 +41,14 @@ def cmd_resume(argv: list[str]) -> int: f"check ~/.bot-bottle/state/ or run `cli.py start` to create a new bottle" ) - manifest = ManifestIndex.resolve(USER_CWD) + manifest = ManifestIndex.resolve(os.getcwd()) manifest.require_agent(metadata.agent_name) spec = BottleSpec( manifest=manifest, agent_name=metadata.agent_name, copy_cwd=metadata.copy_cwd, - user_cwd=metadata.cwd or USER_CWD, + user_cwd=metadata.cwd or os.getcwd(), identity=metadata.identity, bottle_names=tuple(metadata.bottle_names), ) diff --git a/bot_bottle/cli/commands/start.py b/bot_bottle/cli/commands/start.py index 24c2e9c4..2082f928 100644 --- a/bot_bottle/cli/commands/start.py +++ b/bot_bottle/cli/commands/start.py @@ -39,7 +39,8 @@ from ...bottle_state import ( from ...image_cache import StaleImageError from ...log import info, die from ...manifest import Manifest, ManifestIndex -from .._common import PROG, USER_CWD, read_tty_line +from ..constants import PROG +from ...util import read_tty_line from .. import tui @@ -116,7 +117,7 @@ def cmd_start(argv: list[str]) -> int: # threading a no_cache field through every backend's plan dataclass. os.environ["BOT_BOTTLE_NO_CACHE"] = "1" - manifest = ManifestIndex.resolve(USER_CWD) + manifest = ManifestIndex.resolve(os.getcwd()) if args.headless: return _start_headless( @@ -167,7 +168,7 @@ def cmd_start(argv: list[str]) -> int: manifest=manifest, agent_name=agent_name, copy_cwd=args.cwd, - user_cwd=USER_CWD, + user_cwd=os.getcwd(), label=label, color=color, bottle_names=bottle_names, @@ -235,7 +236,7 @@ def _start_headless( manifest=manifest, agent_name=agent_name, copy_cwd=args.cwd, - user_cwd=USER_CWD, + user_cwd=os.getcwd(), label=label, color=args.color or "", bottle_names=bottle_names, diff --git a/bot_bottle/cli/commands/supervise.py b/bot_bottle/cli/commands/supervise.py index c2beb030..cbb349f4 100644 --- a/bot_bottle/cli/commands/supervise.py +++ b/bot_bottle/cli/commands/supervise.py @@ -34,7 +34,7 @@ from ...supervisor.types import ( TOOL_GITLEAKS_ALLOW, TOOL_EGRESS_TOKEN_ALLOW, ) -from .._common import PROG +from ..constants import PROG _REFRESH_INTERVAL_MS = 1000 diff --git a/bot_bottle/cli/constants.py b/bot_bottle/cli/constants.py new file mode 100644 index 00000000..4df182ea --- /dev/null +++ b/bot_bottle/cli/constants.py @@ -0,0 +1,8 @@ +"""Shared CLI constants. + +Kept as a leaf module (imports nothing from the `cli` package) so both the +dispatcher (`cli/__init__.py`) and the command modules it imports can share +`PROG` without a circular import. +""" + +PROG = "cli.py"