Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions loopx/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
12 changes: 12 additions & 0 deletions loopx/cli_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"handoff", "handoff-mode",
"performance-diagnosis",
"heartbeat-prompt",
"goal-acceptance",
}


Expand Down Expand Up @@ -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
Expand All @@ -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

Expand Down
23 changes: 23 additions & 0 deletions tests/test_cli_entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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
Expand Down
Loading