From 8a06403d698da338f12a23c0c9e339f0d542f2d8 Mon Sep 17 00:00:00 2001 From: "lusendong.6789" Date: Fri, 30 Oct 2026 18:46:54 +0800 Subject: [PATCH] perf(cli): load goal-acceptance through the selected runtime Route goal-acceptance help and execution through the selected command parser so the command no longer imports the full CLI graph. The full CLI keeps registration and reaches the same handler through the shared common-command dispatch. Cover owner-only help loading, parser diagnostic parity, and refusal parity without loading loopx.cli. Signed-off-by: lusendong.6789 Co-authored-by: TRAE CLI --- loopx/cli.py | 12 +----------- loopx/cli_runtime.py | 12 ++++++++++++ tests/test_cli_entrypoint.py | 23 +++++++++++++++++++++++ 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/loopx/cli.py b/loopx/cli.py index c346f98989..efc48c1904 100644 --- a/loopx/cli.py +++ b/loopx/cli.py @@ -176,10 +176,7 @@ handle_shared_goal_alignment_command, register_shared_goal_alignment_command, ) -from .cli_commands.goal_acceptance import ( - handle_goal_acceptance_command, - register_goal_acceptance_command, -) +from .cli_commands.goal_acceptance import register_goal_acceptance_command from .cli_commands.goal_direction import register_goal_direction, handle_goal_direction from .cli_commands.goal_amendment_proposal import ( handle_goal_amendment_proposal_command, @@ -844,13 +841,6 @@ def _main(argv: list[str] | None = None) -> int: if authority_shadow_result is not None: return authority_shadow_result - goal_acceptance_result = handle_goal_acceptance_command( - args, registry_path=registry_path, runtime_root_arg=args.runtime_root, - output_format=output_format, print_payload=print_payload, - ) - if goal_acceptance_result is not None: - return goal_acceptance_result - shared_goal_alignment_result = handle_shared_goal_alignment_command( args, registry_path=registry_path, diff --git a/loopx/cli_runtime.py b/loopx/cli_runtime.py index 3f243524c3..c62569e188 100644 --- a/loopx/cli_runtime.py +++ b/loopx/cli_runtime.py @@ -78,6 +78,7 @@ "handoff", "handoff-mode", "performance-diagnosis", "heartbeat-prompt", + "goal-acceptance", } @@ -399,6 +400,10 @@ def _build_selected_parser(command: str) -> LoopXArgumentParser: from .cli_commands.support_control_heartbeat_registration import register_heartbeat_control_commands register_heartbeat_control_commands(subparsers, add_subcommand_format) + elif command == "goal-acceptance": + from .cli_commands.goal_acceptance import register_goal_acceptance_command + + register_goal_acceptance_command(subparsers, add_subcommand_format) else: # pragma: no cover - caller guards the private interface raise ValueError(f"unsupported selected command: {command}") return parser @@ -418,6 +423,13 @@ def _dispatch_common_command( registry_was_supplied=not allow_missing_registry, print_payload=print_payload, output_format=output_format, ) + if args.command == "goal-acceptance": + from .cli_commands.goal_acceptance import handle_goal_acceptance_command + + return handle_goal_acceptance_command( + args, registry_path=registry_path, runtime_root_arg=args.runtime_root, + output_format=output_format, print_payload=print_payload, + ) if args.command == "performance-diagnosis": from .capabilities.performance_diagnosis.cli import handle_performance_diagnosis_command diff --git a/tests/test_cli_entrypoint.py b/tests/test_cli_entrypoint.py index a011c354a8..77a10a98cc 100644 --- a/tests/test_cli_entrypoint.py +++ b/tests/test_cli_entrypoint.py @@ -284,6 +284,7 @@ def test_command_reference_does_not_require_default_runtime_route( (["agent-context", "--help"], "loopx.cli_commands.agent_context", "loopx.cli_commands.agent_context"), (["agent-directory", "--help"], "loopx.cli_commands.agent_directory", "loopx.cli_commands.agent_directory"), (["agent-capabilities", "--help"], "loopx.cli_commands.agent_capabilities", "loopx.cli_commands.agent_capabilities"), + (["goal-acceptance", "--help"], "loopx.cli_commands.goal_acceptance", "loopx.cli_commands.goal_acceptance"), (["goal-portfolio", "--help"], "loopx.cli_commands.summary_all_registration", "loopx.cli_commands.summary_all"), (["global-summary", "--help"], "loopx.cli_commands.summary_all_registration", "loopx.cli_commands.summary_all"), (["global-gates", "--help"], "loopx.cli_commands.summary_all_registration", "loopx.cli_commands.summary_all"), @@ -482,6 +483,9 @@ def test_selected_parser_matches_full_help_and_diagnostics() -> None: argv_cases.extend([[command, "--help"], [command], [command, "--unknown-option"], [command, "--goal-id", "goal", "--agent-i", "agent"]]) argv_cases.append(["agent-context", "--goal-id", "goal", "--agent-id", "agent", "--phase", "unknown"]) + argv_cases.extend([["goal-acceptance", "--help"], ["goal-acceptance", "inspect"], + ["goal-acceptance", "unknown-action", "--goal-id", "goal"], + ["goal-acceptance", "inspect", "--goal-id", "goal", "--unknown-option"]]) selected = run_cli_batch("loopx.entrypoint", argv_cases) full = run_cli_batch("loopx.cli", argv_cases) @@ -621,6 +625,25 @@ def test_selected_lifecycle_refusals_match_without_full_cli(tmp_path, arguments) assert registry.read_bytes() == before +@pytest.mark.parametrize("arguments", [ + ["inspect"], + ["inspect-proposal", "--proposal-id", "missing-proposal"], + ["verify", "--proposal-id", "missing-proposal"], +]) +def test_selected_goal_acceptance_refusals_match_without_full_cli(tmp_path, arguments): + registry, runtime = write_command_fixture(tmp_path) + before = registry.read_bytes() + argv = ["--registry", str(registry), "--runtime-root", str(runtime), "--format", "json", + "goal-acceptance", *arguments, "--goal-id", "missing-goal"] + selected = run_cli_main("loopx.entrypoint", argv, forbidden_modules=("loopx.cli",)) + full = run_cli_main("loopx.cli", argv) + assert selected.returncode == full.returncode == 1 + assert selected.stdout == full.stdout + assert selected.stderr == full.stderr + assert json.loads(selected.stdout)["ok"] is False + assert registry.read_bytes() == before + + @pytest.mark.parametrize("provider", ["file", "sqlite"]) def test_selected_refresh_preview_keeps_canonical_state_without_full_cli(tmp_path, monkeypatch, provider): from tests.control_plane.canonical_authority_fixture import initialize_canonical_source_fixture, isolate_sqlite_runtime