From 7414699a3f637f4a9b9ad84d990a09336001b10f Mon Sep 17 00:00:00 2001 From: "duanjialing.777" Date: Sun, 20 Sep 2026 17:07:03 +0800 Subject: [PATCH 1/2] refactor(cli): extract goal channel operation owner Signed-off-by: duanjialing.777 --- ...-ownership-command-modularization-smoke.py | 6 +- loopx/cli_commands/goal_channel.py | 378 +++++------------- loopx/cli_commands/goal_channel_operation.py | 351 ++++++++++++++++ tests/extensions/test_lark_goal_channel.py | 19 +- .../test_lark_goal_channel_operation.py | 2 +- 5 files changed, 481 insertions(+), 275 deletions(-) create mode 100644 loopx/cli_commands/goal_channel_operation.py diff --git a/examples/cli-command-module-size-ownership-command-modularization-smoke.py b/examples/cli-command-module-size-ownership-command-modularization-smoke.py index 100f60ea68..1ba5e2d46d 100644 --- a/examples/cli-command-module-size-ownership-command-modularization-smoke.py +++ b/examples/cli-command-module-size-ownership-command-modularization-smoke.py @@ -26,6 +26,8 @@ } STARTER_COMMAND_OWNERS = { "start-goal": "start_goal.py", + "prepare-operation": "goal_channel_operation.py", + "deliver-operation": "goal_channel_operation.py", "new-project-prompt": "starter_bootstrap_registration.py", "codex-cli-bootstrap-message": "starter_bootstrap_registration.py", "codex-cli-tui-bootstrap-smoke-bundle": "starter_bootstrap_registration.py", @@ -75,7 +77,9 @@ def module_limit(module_name: str) -> int: def assert_module_size_budgets() -> None: module_names = {path.name for path in python_modules()} stale_budgets = sorted(set(STARTER_MODULE_LIMITS) - module_names) - require(not stale_budgets, f"size budgets reference missing modules: {stale_budgets}") + require( + not stale_budgets, f"size budgets reference missing modules: {stale_budgets}" + ) for path in python_modules(): count = line_count(path) diff --git a/loopx/cli_commands/goal_channel.py b/loopx/cli_commands/goal_channel.py index 3a91547875..0644d58d6e 100644 --- a/loopx/cli_commands/goal_channel.py +++ b/loopx/cli_commands/goal_channel.py @@ -1,15 +1,10 @@ from __future__ import annotations import argparse -import json -import tempfile from collections.abc import Callable, Mapping from pathlib import Path from typing import Any -from ..chat_action_store import ChatActionStore -from ..chat_actions import ChatActionService - from ..extensions.lark import ( LARK_EXTENSION_ID, LARK_GOAL_CHANNEL_PERMISSION, @@ -19,7 +14,6 @@ configure_lark_goal_channel_automation, default_goal_channel_binding_path, default_goal_channel_target_path, - deliver_goal_channel_operation_card, doctor_lark_goal_channel, goal_channel_target_for_name, list_goal_channel_targets, @@ -30,13 +24,6 @@ sync_lark_goal_channel, ) from ..extensions.lark.goal_channel_contracts import binding_for_goal, operation_packet -from ..extensions.lark.goal_channel_message_delivery import ( - GoalChannelDeliveryStageError, -) -from ..extensions.lark.goal_channel_operation import ( - OperationExecutorDriftError, - confirmed_operation_executor, -) from ..extensions.lark.goal_topic_batch import upgrade_lark_goal_topics from ..extensions.runtime import ( default_extension_state_file, @@ -49,6 +36,11 @@ register_goal_channel_runtime_commands, run_goal_channel_runtime, ) +from .goal_channel_operation import ( + GoalChannelOperationContext, + register_goal_channel_operation_commands, + run_goal_channel_operation, +) from ..history import load_registry from ..paths import registry_project_root, resolve_runtime_root from ..quota import build_quota_should_run @@ -63,7 +55,7 @@ def register_goal_channel_commands( - subparsers: argparse._SubParsersAction, + subparsers: argparse._SubParsersAction[argparse.ArgumentParser], add_subcommand_format: Callable[[argparse.ArgumentParser], None], ) -> None: parser = subparsers.add_parser( @@ -214,32 +206,11 @@ def register_goal_channel_commands( ) notify.add_argument("--execute", action="store_true") - prepare = sub.add_parser( - "prepare-operation", - help=( - "Validate and persist one canonical typed-operation proposal. " - "Dry-run unless --execute." - ), + register_goal_channel_operation_commands( + sub, + add_subcommand_format, + _add_common_args, ) - add_subcommand_format(prepare) - _add_common_args(prepare) - prepare.add_argument("--agent-id", required=True) - prepare.add_argument("--summary", required=True) - prepare.add_argument("--idempotency-key", required=True) - prepare.add_argument("--request-json", required=True) - prepare.add_argument("--execute", action="store_true") - - deliver = sub.add_parser( - "deliver-operation", - help=( - "Deliver one canonical typed-operation confirmation card through " - "the bound project Bot. Dry-run unless --execute." - ), - ) - add_subcommand_format(deliver) - _add_common_args(deliver) - deliver.add_argument("--proposal-id", required=True) - deliver.add_argument("--execute", action="store_true") register_goal_channel_runtime_commands(sub, add_subcommand_format) @@ -456,91 +427,6 @@ def _quota_packet( ) -def _prepare_goal_channel_operation( - *, - registry_path: Path, - runtime_root: Path, - goal_id: str, - agent_id: str, - summary: str, - idempotency_key: str, - request_path: Path, - execute: bool, - executor_binding_resolver: Callable[[Mapping[str, Any], Path], Mapping[str, Any]] - | None = None, -) -> dict[str, Any]: - request = json.loads(request_path.read_text(encoding="utf-8")) - if not isinstance(request, dict): - raise ValueError("operation request JSON must be an object") - parameters = {**request, "goal_id": goal_id, "agent_id": agent_id} - if isinstance(parameters.get("executor"), Mapping): - # Resolve the declared executor and compare the active revision - # before any durable proposal or idempotency entry exists, so a - # stale proposal can never become an unreachable gated record. - confirmed_operation_executor( - parameters, runtime_root, executor_binding_resolver - ) - - def preview(store_root: Path) -> dict[str, Any]: - return ChatActionService( - store=ChatActionStore(store_root), - registry_path=registry_path, - ).preview( - { - "action_kind": "operation.execute", - "summary": summary, - "idempotency_key": idempotency_key, - "context": {"kind": "goal", "goal_id": goal_id}, - "normalized_parameters": parameters, - } - ) - - durable_store_root = runtime_root / "chat" / "actions" - if execute: - proposal = preview(durable_store_root) - readback = ChatActionStore(durable_store_root).load( - str(proposal["proposal_id"]) - ) - readback_verified = bool( - readback is not None - and readback.get("request_digest") == proposal.get("request_digest") - and readback.get("operation") == proposal.get("operation") - ) - if not readback_verified: - raise ValueError("operation proposal durable readback did not match") - else: - with tempfile.TemporaryDirectory(prefix="loopx-operation-preview-") as root: - proposal = preview(Path(root) / "actions") - readback_verified = False - operation = proposal.get("operation") - if not isinstance(operation, Mapping): - raise ValueError("operation preview did not produce a canonical envelope") - return operation_packet( - ok=True, - goal_id=goal_id, - operation="prepare_operation", - execute=execute, - status="awaiting_confirmation" if execute else "preview_ready", - public_summary=( - "persisted one canonical operation awaiting card delivery" - if execute - else "validated one canonical operation proposal without persistence" - ), - external_write_performed=False, - readback_verified=readback_verified, - idempotency_key=idempotency_key, - receipt_id=str(proposal["proposal_id"]) if execute else None, - details={ - "operation_id": str(proposal["proposal_id"]) if execute else None, - "lifecycle_state": operation["lifecycle_state"], - "confirmation_digest": operation["confirmation_digest"], - "payload_digest": operation["payload_digest"], - "projection_digest": operation["projection_digest"], - "durable_proposal_written": execute, - }, - ) - - def handle_goal_channel_command( args: argparse.Namespace, *, @@ -704,155 +590,113 @@ def handle_goal_channel_command( goal_id=goal_id, binding_path_arg=getattr(args, "binding_path", None), ) - if command == "deliver-operation": - target_path = _target_path(args, source_runtime_root) - target_name = str(getattr(args, "target", None) or "") - if not target_name: - target_name = _binding_target_name(binding_path, goal_id) - provider_target = ( - _provider_target( - target_path=target_path, - target_name=target_name, - ) - if target_name - else None - ) - if command == "upgrade": - payload = upgrade_lark_goal_topics( - registry=source_registry, - registry_path=source_registry_path, - goal_id=goal_id, - binding_path=binding_path, - target_path=target_path, - connection_id=args.connection_id, - agent_id=args.agent_id, - execute=execute, - ) - elif target_name and provider_target is None: - payload = _error_packet( - goal_id=goal_id, - operation=command.replace("-", "_"), - execute=execute, - blocker="provider_target_missing", - summary="configure the named shared provider target first", - ) - elif command == "setup": - payload = setup_lark_goal_channel( - registry=source_registry, - registry_path=source_registry_path, - goal_id=goal_id, - binding_path=binding_path, - target_name=target_name or None, - provider_target=provider_target, - chat_id=args.chat_id, - chat_name=args.chat_name, - base_url=args.base_url, - base_token=args.base_token, - table_id=args.table_id, - identity_mode=args.identity_mode, - sender_profile=args.sender_profile, - sender_identity=args.sender_identity, - bot_app_id=getattr(args, "bot_app_id", None), - bot_display_name=args.bot_display_name, - cli_bin=args.cli_bin, - execute=execute, - ) - elif command == "configure": - payload = configure_lark_goal_channel_automation( - registry=source_registry, - goal_id=goal_id, - binding_path=binding_path, - human_gate_auto_notify=bool(args.auto_notify_human_gates), - execute=execute, - ) - elif command == "doctor": - payload = doctor_lark_goal_channel( - registry=source_registry, - registry_path=source_registry_path, - goal_id=goal_id, + operation_payload = run_goal_channel_operation( + args, + context=GoalChannelOperationContext( + invoked_runtime_root=runtime_root, + source_registry_path=source_registry_path, + source_runtime_root=source_runtime_root, binding_path=binding_path, - provider_target=provider_target, - ) - elif command == "sync": - payload = sync_lark_goal_channel( - registry=source_registry, - registry_path=source_registry_path, - goal_id=goal_id, - binding_path=binding_path, - provider_target=provider_target, - agent_id=args.agent_id, - execute=execute, + ), + ) + if operation_payload is not None: + payload = operation_payload + else: + target_name = str(getattr(args, "target", None) or "") + if not target_name: + target_name = _binding_target_name(binding_path, goal_id) + provider_target = ( + _provider_target( + target_path=target_path, + target_name=target_name, + ) + if target_name + else None ) - elif command == "notify-gate": - payload = notify_lark_goal_channel_gate( - registry=source_registry, - goal_id=goal_id, - binding_path=binding_path, - provider_target=provider_target, - quota_packet=_quota_packet( - registry_path=registry_path, - runtime_root_arg=runtime_root_arg, + if command == "upgrade": + payload = upgrade_lark_goal_topics( + registry=source_registry, + registry_path=source_registry_path, goal_id=goal_id, + binding_path=binding_path, + target_path=target_path, + connection_id=args.connection_id, agent_id=args.agent_id, - ), - execute=execute, - ) - elif command == "prepare-operation": - payload = _prepare_goal_channel_operation( - registry_path=source_registry_path, - runtime_root=source_runtime_root, - goal_id=goal_id, - agent_id=args.agent_id, - summary=args.summary, - idempotency_key=args.idempotency_key, - request_path=Path(str(args.request_json)).expanduser(), - execute=execute, - ) - elif command == "deliver-operation": - payload = deliver_goal_channel_operation_card( - proposal_id=args.proposal_id, - action_store_root=source_runtime_root / "chat" / "actions", - runtime_root=source_runtime_root, - binding_path=binding_path, - target_path=target_path, - expected_goal_id=goal_id, - execute=execute, - ) - else: - raise ValueError(f"unknown goal-channel command: {command}") + execute=execute, + ) + elif target_name and provider_target is None: + payload = _error_packet( + goal_id=goal_id, + operation=command.replace("-", "_"), + execute=execute, + blocker="provider_target_missing", + summary="configure the named shared provider target first", + ) + elif command == "setup": + payload = setup_lark_goal_channel( + registry=source_registry, + registry_path=source_registry_path, + goal_id=goal_id, + binding_path=binding_path, + target_name=target_name or None, + provider_target=provider_target, + chat_id=args.chat_id, + chat_name=args.chat_name, + base_url=args.base_url, + base_token=args.base_token, + table_id=args.table_id, + identity_mode=args.identity_mode, + sender_profile=args.sender_profile, + sender_identity=args.sender_identity, + bot_app_id=getattr(args, "bot_app_id", None), + bot_display_name=args.bot_display_name, + cli_bin=args.cli_bin, + execute=execute, + ) + elif command == "configure": + payload = configure_lark_goal_channel_automation( + registry=source_registry, + goal_id=goal_id, + binding_path=binding_path, + human_gate_auto_notify=bool(args.auto_notify_human_gates), + execute=execute, + ) + elif command == "doctor": + payload = doctor_lark_goal_channel( + registry=source_registry, + registry_path=source_registry_path, + goal_id=goal_id, + binding_path=binding_path, + provider_target=provider_target, + ) + elif command == "sync": + payload = sync_lark_goal_channel( + registry=source_registry, + registry_path=source_registry_path, + goal_id=goal_id, + binding_path=binding_path, + provider_target=provider_target, + agent_id=args.agent_id, + execute=execute, + ) + elif command == "notify-gate": + payload = notify_lark_goal_channel_gate( + registry=source_registry, + goal_id=goal_id, + binding_path=binding_path, + provider_target=provider_target, + quota_packet=_quota_packet( + registry_path=registry_path, + runtime_root_arg=runtime_root_arg, + goal_id=goal_id, + agent_id=args.agent_id, + ), + execute=execute, + ) + else: + raise ValueError(f"unknown goal-channel command: {command}") if payload.get("ok"): payload["extension_activation"] = activation - except OperationExecutorDriftError as exc: - payload = _error_packet( - goal_id=goal_id, - operation=command.replace("-", "_"), - execute=execute, - blocker=exc.blocker, - summary=str(exc), - external_write_performed=exc.external_write_performed, - failure_stage=exc.failure_stage, - details=exc.details, - ) - except GoalChannelDeliveryStageError as exc: - outcome = exc.external_write_performed - payload = _error_packet( - goal_id=goal_id, - operation=command.replace("-", "_"), - execute=execute, - blocker=exc.blocker, - summary=str(exc), - # An unknown provider outcome must never be projected as a - # clean not-performed receipt: assume the write happened. - external_write_performed=( - True if outcome is None else outcome - ), - failure_stage=exc.failure_stage, - details=( - {"external_write_outcome": "unknown"} - if outcome is None - else None - ), - ) except ValueError: payload = _error_packet( goal_id=goal_id, diff --git a/loopx/cli_commands/goal_channel_operation.py b/loopx/cli_commands/goal_channel_operation.py new file mode 100644 index 0000000000..c1070551eb --- /dev/null +++ b/loopx/cli_commands/goal_channel_operation.py @@ -0,0 +1,351 @@ +"""Registration and dispatch for Goal Channel operation commands.""" + +from __future__ import annotations + +import argparse +import json +import tempfile +from collections.abc import Callable, Mapping +from dataclasses import dataclass +from enum import Enum +from pathlib import Path +from typing import Any, ClassVar, Self + +from ..chat_action_store import ChatActionStore +from ..chat_actions import ChatActionService +from ..extensions.lark.goal_channel import ( + default_goal_channel_target_path, + deliver_goal_channel_operation_card, + goal_channel_target_for_name, + read_goal_channel_binding, + read_goal_channel_targets, +) +from ..extensions.lark.goal_channel_contracts import binding_for_goal, operation_packet +from ..extensions.lark.goal_channel_message_delivery import ( + GoalChannelDeliveryStageError, +) +from ..extensions.lark.goal_channel_operation import ( + OperationExecutorDriftError, + confirmed_operation_executor, +) + + +@dataclass(frozen=True, slots=True) +class GoalChannelOperationContext: + invoked_runtime_root: Path + source_registry_path: Path + source_runtime_root: Path + binding_path: Path + + +class _GoalChannelOperationCommand(str, Enum): + PREPARE = "prepare-operation" + DELIVER = "deliver-operation" + + @classmethod + def parse(cls, value: object) -> Self | None: + try: + return cls(str(value)) + except ValueError: + return None + + +@dataclass(frozen=True, slots=True) +class _PrepareOperation: + goal_id: str + agent_id: str + summary: str + idempotency_key: str + request_path: Path + execute: bool + target_path_override: Path | None + command: ClassVar[_GoalChannelOperationCommand] = ( + _GoalChannelOperationCommand.PREPARE + ) + + +@dataclass(frozen=True, slots=True) +class _DeliverOperation: + goal_id: str + proposal_id: str + execute: bool + target_path_override: Path | None + command: ClassVar[_GoalChannelOperationCommand] = ( + _GoalChannelOperationCommand.DELIVER + ) + + +_OperationRequest = _PrepareOperation | _DeliverOperation + + +def register_goal_channel_operation_commands( + subparsers: argparse._SubParsersAction[argparse.ArgumentParser], + add_subcommand_format: Callable[[argparse.ArgumentParser], None], + add_common_args: Callable[[argparse.ArgumentParser], None], +) -> None: + prepare = subparsers.add_parser( + "prepare-operation", + help=( + "Validate and persist one canonical typed-operation proposal. " + "Dry-run unless --execute." + ), + ) + add_subcommand_format(prepare) + add_common_args(prepare) + prepare.add_argument("--agent-id", required=True) + prepare.add_argument("--summary", required=True) + prepare.add_argument("--idempotency-key", required=True) + prepare.add_argument("--request-json", required=True) + prepare.add_argument("--execute", action="store_true") + + deliver = subparsers.add_parser( + "deliver-operation", + help=( + "Deliver one canonical typed-operation confirmation card through " + "the bound project Bot. Dry-run unless --execute." + ), + ) + add_subcommand_format(deliver) + add_common_args(deliver) + deliver.add_argument("--proposal-id", required=True) + deliver.add_argument("--execute", action="store_true") + + +def _parse_operation_request(args: argparse.Namespace) -> _OperationRequest | None: + command = _GoalChannelOperationCommand.parse( + getattr(args, "goal_channel_command", None) + ) + if command is None: + return None + target_path_arg = getattr(args, "target_path", None) + target_path_override = ( + Path(str(target_path_arg)).expanduser() if target_path_arg else None + ) + if command is _GoalChannelOperationCommand.PREPARE: + return _PrepareOperation( + goal_id=str(args.goal_id), + agent_id=str(args.agent_id), + summary=str(args.summary), + idempotency_key=str(args.idempotency_key), + request_path=Path(str(args.request_json)).expanduser(), + execute=bool(getattr(args, "execute", False)), + target_path_override=target_path_override, + ) + return _DeliverOperation( + goal_id=str(args.goal_id), + proposal_id=str(args.proposal_id), + execute=bool(getattr(args, "execute", False)), + target_path_override=target_path_override, + ) + + +def _operation_target_path( + request: _OperationRequest, + context: GoalChannelOperationContext, +) -> Path: + if request.target_path_override is not None: + return request.target_path_override + runtime_root = ( + context.invoked_runtime_root + if request.command is _GoalChannelOperationCommand.PREPARE + else context.source_runtime_root + ) + return default_goal_channel_target_path(runtime_root) + + +def _operation_error_packet( + *, + request: _OperationRequest, + blocker: str, + summary: str, + external_write_performed: bool = False, + failure_stage: str | None = None, + details: Mapping[str, Any] | None = None, +) -> dict[str, Any]: + packet = operation_packet( + ok=False, + goal_id=request.goal_id, + operation=request.command.value.replace("-", "_"), + execute=request.execute, + status="blocked", + blocker=blocker, + public_summary=summary, + external_write_performed=external_write_performed, + details=details, + ) + if failure_stage: + packet["failure_stage"] = failure_stage + return packet + + +def run_goal_channel_operation( + args: argparse.Namespace, + *, + context: GoalChannelOperationContext, +) -> dict[str, Any] | None: + request = _parse_operation_request(args) + if request is None: + return None + try: + target_path = _operation_target_path(request, context) + binding = ( + binding_for_goal( + read_goal_channel_binding(context.binding_path), + request.goal_id, + ) + or {} + ) + target_name = str(binding.get("target_ref") or "") + provider_target = ( + goal_channel_target_for_name( + read_goal_channel_targets(target_path), + target_name, + ) + if target_name + else None + ) + if target_name and provider_target is None: + return _operation_error_packet( + request=request, + blocker="provider_target_missing", + summary="configure the named shared provider target first", + ) + if isinstance(request, _PrepareOperation): + return _prepare_goal_channel_operation( + registry_path=context.source_registry_path, + runtime_root=context.source_runtime_root, + goal_id=request.goal_id, + agent_id=request.agent_id, + summary=request.summary, + idempotency_key=request.idempotency_key, + request_path=request.request_path, + execute=request.execute, + ) + return deliver_goal_channel_operation_card( + proposal_id=request.proposal_id, + action_store_root=context.source_runtime_root / "chat" / "actions", + runtime_root=context.source_runtime_root, + binding_path=context.binding_path, + target_path=target_path, + expected_goal_id=request.goal_id, + execute=request.execute, + ) + except OperationExecutorDriftError as exc: + return _operation_error_packet( + request=request, + blocker=exc.blocker, + summary=str(exc), + external_write_performed=exc.external_write_performed, + failure_stage=exc.failure_stage, + details=exc.details, + ) + except GoalChannelDeliveryStageError as exc: + outcome = exc.external_write_performed + return _operation_error_packet( + request=request, + blocker=exc.blocker, + summary=str(exc), + # Unknown provider outcomes cannot be projected as clean no-writes. + external_write_performed=True if outcome is None else outcome, + failure_stage=exc.failure_stage, + details=( + {"external_write_outcome": "unknown"} if outcome is None else None + ), + ) + except ValueError: + return _operation_error_packet( + request=request, + blocker="invalid_configuration", + summary="the Goal Channel configuration is invalid", + ) + except Exception: + return _operation_error_packet( + request=request, + blocker="provider_api_failed", + summary=( + "the Goal Channel operation failed before a verified provider receipt" + ), + ) + + +def _prepare_goal_channel_operation( + *, + registry_path: Path, + runtime_root: Path, + goal_id: str, + agent_id: str, + summary: str, + idempotency_key: str, + request_path: Path, + execute: bool, + executor_binding_resolver: Callable[[Mapping[str, Any], Path], Mapping[str, Any]] + | None = None, +) -> dict[str, Any]: + request = json.loads(request_path.read_text(encoding="utf-8")) + if not isinstance(request, dict): + raise ValueError("operation request JSON must be an object") + parameters = {**request, "goal_id": goal_id, "agent_id": agent_id} + if isinstance(parameters.get("executor"), Mapping): + # Reject executor drift before a durable proposal or idempotency row exists. + confirmed_operation_executor( + parameters, runtime_root, executor_binding_resolver + ) + + def preview(store_root: Path) -> dict[str, Any]: + return ChatActionService( + store=ChatActionStore(store_root), + registry_path=registry_path, + ).preview( + { + "action_kind": "operation.execute", + "summary": summary, + "idempotency_key": idempotency_key, + "context": {"kind": "goal", "goal_id": goal_id}, + "normalized_parameters": parameters, + } + ) + + durable_store_root = runtime_root / "chat" / "actions" + if execute: + proposal = preview(durable_store_root) + readback = ChatActionStore(durable_store_root).load( + str(proposal["proposal_id"]) + ) + readback_verified = bool( + readback is not None + and readback.get("request_digest") == proposal.get("request_digest") + and readback.get("operation") == proposal.get("operation") + ) + if not readback_verified: + raise ValueError("operation proposal durable readback did not match") + else: + with tempfile.TemporaryDirectory(prefix="loopx-operation-preview-") as root: + proposal = preview(Path(root) / "actions") + readback_verified = False + operation = proposal.get("operation") + if not isinstance(operation, Mapping): + raise ValueError("operation preview did not produce a canonical envelope") + return operation_packet( + ok=True, + goal_id=goal_id, + operation="prepare_operation", + execute=execute, + status="awaiting_confirmation" if execute else "preview_ready", + public_summary=( + "persisted one canonical operation awaiting card delivery" + if execute + else "validated one canonical operation proposal without persistence" + ), + external_write_performed=False, + readback_verified=readback_verified, + idempotency_key=idempotency_key, + receipt_id=str(proposal["proposal_id"]) if execute else None, + details={ + "operation_id": str(proposal["proposal_id"]) if execute else None, + "lifecycle_state": operation["lifecycle_state"], + "confirmation_digest": operation["confirmation_digest"], + "payload_digest": operation["payload_digest"], + "projection_digest": operation["projection_digest"], + "durable_proposal_written": execute, + }, + ) diff --git a/tests/extensions/test_lark_goal_channel.py b/tests/extensions/test_lark_goal_channel.py index 638c7d0c2d..d478bc9938 100644 --- a/tests/extensions/test_lark_goal_channel.py +++ b/tests/extensions/test_lark_goal_channel.py @@ -10,6 +10,7 @@ import pytest from loopx.cli_commands import goal_channel as goal_channel_cli +from loopx.cli_commands import goal_channel_operation as goal_channel_operation_cli from loopx.extensions.lark import goal_channel_contracts from loopx.extensions.lark.goal_channel import ( GOAL_CHANNEL_BINDING_SCHEMA_VERSION, @@ -2142,7 +2143,6 @@ def test_cli_deliver_operation_uses_source_registry_runtime( "resolve_extension_activation", lambda *args, **kwargs: {"ok": True}, ) - monkeypatch.setattr(goal_channel_cli, "_binding_target_name", lambda *args: "") def capture_delivery(**kwargs: Any) -> dict[str, Any]: captured.update(kwargs) @@ -2159,7 +2159,9 @@ def capture_delivery(**kwargs: Any) -> dict[str, Any]: } monkeypatch.setattr( - goal_channel_cli, "deliver_goal_channel_operation_card", capture_delivery + goal_channel_operation_cli, + "deliver_goal_channel_operation_card", + capture_delivery, ) result = goal_channel_cli.handle_goal_channel_command( argparse.Namespace( @@ -2181,6 +2183,7 @@ def capture_delivery(**kwargs: Any) -> dict[str, Any]: assert result == 0 assert printed["ok"] is True + assert printed["extension_activation"] == {"ok": True} assert captured["proposal_id"] == "proposal-public-fixture" assert captured["action_store_root"] == source_runtime / "chat" / "actions" assert captured["runtime_root"] == source_runtime @@ -2335,7 +2338,6 @@ def test_cli_deliver_operation_projects_typed_stage_blockers( "resolve_extension_activation", lambda *args, **kwargs: {"ok": True}, ) - monkeypatch.setattr(goal_channel_cli, "_binding_target_name", lambda *args: "") def deliver_raises(**kwargs: object) -> object: raise GoalChannelDeliveryStageError( @@ -2346,7 +2348,9 @@ def deliver_raises(**kwargs: object) -> object: ) monkeypatch.setattr( - goal_channel_cli, "deliver_goal_channel_operation_card", deliver_raises + goal_channel_operation_cli, + "deliver_goal_channel_operation_card", + deliver_raises, ) printed: dict[str, Any] = {} result = goal_channel_cli.handle_goal_channel_command( @@ -2372,6 +2376,7 @@ def deliver_raises(**kwargs: object) -> object: assert printed["blocker"] == "provider_send_rejected" assert printed["failure_stage"] == "send_operation_card" assert printed["external_write_performed"] is False + assert "extension_activation" not in printed assert "provider rejected" not in json.dumps(printed) _assert_public_packet(printed) @@ -2405,7 +2410,6 @@ def test_cli_deliver_operation_treats_unknown_write_as_performed( "resolve_extension_activation", lambda *args, **kwargs: {"ok": True}, ) - monkeypatch.setattr(goal_channel_cli, "_binding_target_name", lambda *args: "") def deliver_unknown(**kwargs: object) -> object: raise GoalChannelDeliveryStageError( @@ -2416,7 +2420,9 @@ def deliver_unknown(**kwargs: object) -> object: ) monkeypatch.setattr( - goal_channel_cli, "deliver_goal_channel_operation_card", deliver_unknown + goal_channel_operation_cli, + "deliver_goal_channel_operation_card", + deliver_unknown, ) printed: dict[str, Any] = {} result = goal_channel_cli.handle_goal_channel_command( @@ -2443,4 +2449,5 @@ def deliver_unknown(**kwargs: object) -> object: assert printed["failure_stage"] == failure_stage assert printed["external_write_performed"] is True assert printed["details"]["external_write_outcome"] == "unknown" + assert "extension_activation" not in printed _assert_public_packet(printed) diff --git a/tests/extensions/test_lark_goal_channel_operation.py b/tests/extensions/test_lark_goal_channel_operation.py index 451d69ffb2..c4c179eede 100644 --- a/tests/extensions/test_lark_goal_channel_operation.py +++ b/tests/extensions/test_lark_goal_channel_operation.py @@ -13,7 +13,7 @@ from loopx.chat_action_store import ActionConflictError, ChatActionStore from loopx.chat_actions import ChatActionService -from loopx.cli_commands.goal_channel import _prepare_goal_channel_operation +from loopx.cli_commands.goal_channel_operation import _prepare_goal_channel_operation from loopx.extensions.lark.goal_channel_contracts import ( GOAL_CHANNEL_BINDING_SCHEMA_VERSION, write_goal_channel_binding, From b05bb53bfc1006a6dad1ea00b40c6691d8038ac3 Mon Sep 17 00:00:00 2001 From: "duanjialing.777" Date: Sun, 20 Sep 2026 17:08:26 +0800 Subject: [PATCH 2/2] docs(contributors): mark GH-C06 in review Signed-off-by: duanjialing.777 --- docs/development/contributor-tasks.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/development/contributor-tasks.md b/docs/development/contributor-tasks.md index 79f05a2118..2157148ee7 100644 --- a/docs/development/contributor-tasks.md +++ b/docs/development/contributor-tasks.md @@ -69,7 +69,7 @@ identity rather than copying the whole plan here. | P1 | Shared coordination | Qualify the selected local authority durability and crash/replay boundary against existing D2 acceptance | #4224 / #3245 | Needs design | | P1 | Core hardening | One budget-aware CLI output ergonomics slice | #2881 | Needs design | | P2 | Project docs | Release docs install, activation, and recovery guidance through v0.5.4 | GH-C04 | Landed via #3982 | -| P2 | Maintainability | CLI ownership and hot-module extraction | GH-C06 | Available | +| P2 | Maintainability | CLI ownership and hot-module extraction | GH-C06 / #4803 | In review | ## Product Manager Cut @@ -149,7 +149,7 @@ for contributors who can run local CLI smokes and keep changes scoped. | ID | Area | Task | Validation | | --- | --- | --- | --- | -| GH-C06 | cli | Characterize one remaining oversized CLI ownership seam after the recent quota, status, todo, history, and scheduler command-plumbing extractions, then move only a cohesive command or rule group into its bounded module. Preserve public invocations, avoid compatibility wrappers without a real caller, and keep the module-size/import budget honest. A focused issue tracks the Goal Channel runtime slice (#3710). | Command-specific smoke, `python3 examples/cli-command-module-size-ownership-command-modularization-smoke.py`, `python3 regression/cli-command-module-contract.py`, and focused pytest if rules move | +| GH-C06 | cli | Claimed: PR #4803 extracts the `goal-channel prepare-operation` and `deliver-operation` command owner while preserving the public invocation, source-runtime routing, provider error mapping, and parent rendering/exit contract. The operation owner and parent remain below the module budget, and no compatibility wrapper was added. | Command-specific smoke, `python3 examples/cli-command-module-size-ownership-command-modularization-smoke.py`, `python3 regression/cli-command-module-contract.py`, and focused pytest if rules move | | GH-C88 | cli | Implement one budget-aware CLI output ergonomics slice for #2881: shorter default summaries with a typed `--json` escape hatch on one command family, keeping hot-path payload budgets and differential allowances intact. | `python3 examples/control_plane/cli-output-budget-regression-smoke.py`, focused command smoke, and `loopx check --scan-path docs/status-data-contract.md --scan-path docs/development/contributor-tasks.md` | | GH-C70 | runtime | Claimed: PR #3664 narrows host-loop parity to one producer-generated bounded-wait scheduler-hint contract between the external scheduler worker and Pi: both real consumers must produce the same provider-neutral stop/wait plan, including the final quota/replan recheck triggered by the third unchanged poll. | `python3 -m pytest -q tests/test_host_loop_runtime_parity.py tests/test_external_scheduler_worker.py tests/test_pi_goal_mode.py`, `node --test tests/pi_goal_loop_runtime.test.mjs`, `python3 examples/external-scheduler-worker-smoke.py`, and `loopx check --scan-path docs/integrations/runtime-connector-catalog.md --scan-path docs/development/contributor-tasks.md` | | GH-C100 | state | Characterize the shipped file-backed `claim_work` executor with a provider-neutral parity fixture (#3700): same-target competition has exactly one winner, independent targets rebase, replay returns the original receipt, same-operation-id with different command semantics is rejected with no mutation, and stale provider generation does not duplicate transitions. Keep fixtures synthetic and public-safe. | `python3 -m pytest -q tests/control_plane/test_coordination_executor.py tests/control_plane/test_coordination_file_provider.py`, the new parity fixture, and `loopx check --scan-path loopx/control_plane/coordination --scan-path docs/architecture/rfcs/shared-goal-authority-state-provider-v0.md --scan-path docs/development/contributor-tasks.md` |