From b23a8c43c49ec932bba0132dc5891eb0b322a403 Mon Sep 17 00:00:00 2001 From: "lusendong.6789" Date: Tue, 3 Nov 2026 21:54:41 +0800 Subject: [PATCH 1/2] perf(cli): load host-mode selection without the full CLI graph Signed-off-by: lusendong.6789 Co-authored-by: TRAE CLI --- .../rfcs/monorepo-distribution-split-v0.md | 22 +++++ .../monorepo-distribution-split-v0.zh-CN.md | 18 +++++ loopx/cli_runtime.py | 11 +++ tests/test_cli_entrypoint.py | 81 +++++++++++++++++++ 4 files changed, 132 insertions(+) diff --git a/docs/architecture/rfcs/monorepo-distribution-split-v0.md b/docs/architecture/rfcs/monorepo-distribution-split-v0.md index 86daaa0750..6d6c9715bd 100644 --- a/docs/architecture/rfcs/monorepo-distribution-split-v0.md +++ b/docs/architecture/rfcs/monorepo-distribution-split-v0.md @@ -736,6 +736,28 @@ Approval needs a reviewed decision, not implementation progress or silence. by the guard, and covering it would be a runtime change with its own acceptance, not a documentation change. +### 2026-11-03 — Selected host-mode discovery loading + +- **Baseline:** `6a6a8590e`. Earlier selected routes for `performance-diagnosis` + and `goal-acceptance` are already on this baseline; the Section 4 audit above + remains historical, not the current implementation inventory. +- **Delta:** `host-mode-plan` uses its existing registrar and handler through + `cli_runtime`, without loading the full CLI or Chat graph on valid requests. + Rejected syntax retains the full-parser diagnostic path. The host selector, + preview commands, readiness and authority rules do not move or change. +- **Evidence:** `tests/test_cli_entrypoint.py` checks owner-only help, JSON and + Markdown parity, unavailable-host previews, invalid requests and zero process, + network or file-write activation. A separately installed wheel exercises help, + ready/unavailable previews and rejection without Node or a live registry. + Local paired fresh-process measurements use 20 samples per revision/workload, + one discarded warm-up and alternating order, with telemetry off and warm file + caches. On macOS arm64/Python 3.13.5, the help/preview LoopX closure falls + from 1,149 to 57 modules; byte-identical output is retained. Timing/RSS belong + to the PR's scoped evidence, not a portable threshold or task-outcome claim. +- **Remaining:** this extends R0-style loading qualification to discovery; + it does not complete R0's full V10 census, M1 public-import migration, split + packaging or R1 managed minimal. D1–D7 remain open. No new preset or default. + ## Appendix B: Decision log | Date | Decision | Owner / approval | Alternatives | Normative sections changed | diff --git a/docs/architecture/rfcs/monorepo-distribution-split-v0.zh-CN.md b/docs/architecture/rfcs/monorepo-distribution-split-v0.zh-CN.md index 7471d15138..5f10af868b 100644 --- a/docs/architecture/rfcs/monorepo-distribution-split-v0.zh-CN.md +++ b/docs/architecture/rfcs/monorepo-distribution-split-v0.zh-CN.md @@ -530,6 +530,24 @@ R0 可以先于目录移动交付,但不代表内核合格。R3/R4 可选, 待处理的入口收据仍不被该栅栏覆盖;要覆盖它是一次带自有验收的运行时变更, 而不是文档变更。 +### 2026-11-03 — 所选宿主模式发现路径的加载 + +- **基线:** `6a6a8590e`。此前 `performance-diagnosis` 与 `goal-acceptance` + 的 selected 路由已在该基线上;第 4 节审计仍为历史记录,不是当前实现清单。 +- **变化:** `host-mode-plan` 经 `cli_runtime` 使用原有 registrar 与 handler, + 合法请求不再加载完整 CLI 或 Chat 依赖图。非法语法保留完整 parser 的诊断路径。 + 宿主选择器、预览命令、readiness 与 authority 规则均不移动、不改变。 +- **证据:** `tests/test_cli_entrypoint.py` 覆盖仅加载 owner 的 help、JSON 与 + Markdown 一致性、宿主不可用预览、非法请求及零进程、网络或文件写入激活。 + 独立安装的 wheel 在没有 Node 或实时 registry 时验证 help、ready/unavailable + 预览及拒绝。每个版本/负载做 20 次本地成对新进程测量,丢弃一次预热、交替 + 顺序、关闭遥测并保留热文件缓存。在 macOS arm64/Python 3.13.5 上,help/ + preview 的 LoopX 加载闭包从 1,149 降到 57 个模块,输出字节保持一致。时间/RSS + 留在 PR 的限定证据中,不作为可移植阈值或任务成果收益声明。 +- **剩余:** 将 R0 类型的加载验证扩展到发现路径;不关闭 R0 的完整 V10 清点、 + M1 公开 import 迁移、发行物拆分或 R1 managed minimal。D1–D7 仍未决, + 不新增预设或改变默认值。 + ## 附录 B:决策日志 | 日期 | 决策 | 负责人 / 批准 | 备选 | 变更的规范章节 | diff --git a/loopx/cli_runtime.py b/loopx/cli_runtime.py index 511305ec8f..d2ed3aabab 100644 --- a/loopx/cli_runtime.py +++ b/loopx/cli_runtime.py @@ -79,6 +79,7 @@ "performance-diagnosis", "heartbeat-prompt", "goal-acceptance", + "host-mode-plan", } @@ -404,6 +405,10 @@ def _build_selected_parser(command: str) -> LoopXArgumentParser: from .cli_commands.goal_acceptance import register_goal_acceptance_command register_goal_acceptance_command(subparsers, add_subcommand_format) + elif command == "host-mode-plan": + from .cli_commands.host_mode_plan import register_host_mode_plan_command + + register_host_mode_plan_command(subparsers, add_subcommand_format) else: # pragma: no cover - caller guards the private interface raise ValueError(f"unsupported selected command: {command}") return parser @@ -415,6 +420,12 @@ def _dispatch_common_command( registry_path: Path, allow_missing_registry: bool, ) -> int | None: + if args.command == "host-mode-plan": + from .cli_commands.host_mode_plan import handle_host_mode_plan_command + + return handle_host_mode_plan_command( + args, output_format=output_format, print_payload=print_payload, + ) if args.command == "heartbeat-prompt": from .cli_commands.support_control_heartbeat import handle_heartbeat_prompt_command diff --git a/tests/test_cli_entrypoint.py b/tests/test_cli_entrypoint.py index 797593b59c..821368a360 100644 --- a/tests/test_cli_entrypoint.py +++ b/tests/test_cli_entrypoint.py @@ -286,6 +286,7 @@ def test_command_reference_does_not_require_default_runtime_route( (["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"), + (["host-mode-plan", "--help"], "loopx.cli_commands.host_mode_plan", "loopx.cli_commands.host_mode_plan"), (["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"), @@ -837,6 +838,86 @@ def test_selected_goal_acceptance_refusals_match_without_full_cli(tmp_path, argu assert registry.read_bytes() == before +@pytest.mark.parametrize("format_name", ["json", "markdown"]) +@pytest.mark.parametrize("arguments, expected_code", [ + (["--intent", "watch_each_turn", "--host-capability", "visible_session", + "--host-identity", "codex-cli", "--registered-agent", "fixture-agent"], 0), + (["--intent", "watch_each_turn", "--host-capability", "visible_session"], 0), + (["--intent", "unsupported-intent"], 1), + (["--host-capability", "unsupported-capability"], 1), +]) +def test_selected_host_mode_plan_preserves_results_without_activation( + tmp_path, format_name, arguments, expected_code, +): + registry, runtime = tmp_path / "absent.json", tmp_path / "runtime" + argv = ["--registry", str(registry), "--runtime-root", str(runtime), + "--format", "markdown", "host-mode-plan", "--goal-id", "fixture-goal", + "--cli-bin", "fixture-loopx", "--format", format_name, *arguments] + # An explicit absent registry must not turn a read-only selector into an + # authority read. Its preview is not permission to launch the named host. + environment = {"LOOPX_USAGE_PING": "0"} + selected = run_cli_main("loopx.entrypoint", argv, + forbidden_modules=("loopx.cli", "loopx.chat_server", "loopx.chat_runtime", + "loopx.cli_commands.benchmark_dispatch", "loopx.capabilities.content_ops.cli"), + environment=environment) + full = run_cli_main("loopx.cli", argv, environment=environment) + assert selected.returncode == full.returncode == expected_code, (selected.stderr, full.stderr) + assert selected.stdout == full.stdout + assert selected.stderr == full.stderr == "" + assert not registry.exists() and not runtime.exists() + if format_name == "json" and expected_code == 0: + payload = json.loads(selected.stdout) + assert payload["schema_version"] == "host_mode_plan_v0" + assert payload["goal_id"] == "fixture-goal" + if "--host-identity" in arguments: + assert payload["agent_id"] == "fixture-agent" + assert payload["selected_connector_id"] == "codex_cli_tui" + else: + # A valid preview may expose missing readiness; it must not silently + # select or activate a default host to make the plan executable. + assert payload["selected_connector_id"] is None + assert payload["selected_capability_ready"] is False + + +def test_selected_host_mode_plan_diagnostics_keep_full_parser_fallback(): + cases = [ + ["host-mode-plan"], ["host-mode-plan", "--help"], + ["host-mode-plan", "--goal-id", "fixture-goal", "--unknown"], + ["host-mode-plan", "--goal-id", "fixture-goal", "--format", "yaml"], + ["host-mode-plan", "--goal-id", "fixture-goal", "--host-identity", "unknown"], + ["host-mode-plan", "--goal-id", "fixture-goal", "--host-cap"], + ] + assert run_cli_batch("loopx.entrypoint", cases) == run_cli_batch("loopx.cli", cases) + + +def test_selected_host_mode_plan_does_not_start_processes_or_use_network(tmp_path): + script = f""" +import os +import sys +os.environ["LOOPX_USAGE_PING"] = "0" +sys.dont_write_bytecode = True +os.chdir({str(tmp_path)!r}) + +def reject_activation(event, args): + assert event not in ("subprocess.Popen", "os.system", "os.posix_spawn", "socket.connect"), event + if event == "open": + mode, flags = args[1:3] + assert not (isinstance(mode, str) and any(c in mode for c in "wax+")), args + assert not (isinstance(flags, int) and flags & (os.O_WRONLY | os.O_RDWR | os.O_CREAT)), args + +sys.addaudithook(reject_activation) +from loopx.entrypoint import main +assert main(["host-mode-plan", "--goal-id", "fixture-goal", "--intent", "watch_each_turn", + "--host-capability", "visible_session", "--host-identity", "codex-cli", + "--agent-id", "fixture-agent", "--format", "json"]) == 0 +assert "loopx.cli" not in sys.modules +""" + result = run_isolated_script(script) + assert result.returncode == 0, result.stderr + assert json.loads(result.stdout)["selected_connector_id"] == "codex_cli_tui" + assert not list(tmp_path.iterdir()) + + @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 From cc2ac42c62ff29491631d3e73d55c8e6ca818e1b Mon Sep 17 00:00:00 2001 From: "lusendong.6789" Date: Tue, 3 Nov 2026 23:07:57 +0800 Subject: [PATCH 2/2] docs(rfc): record merged internal Chat ownership boundary Signed-off-by: lusendong.6789 Co-authored-by: TRAE CLI --- docs/architecture/rfcs/monorepo-distribution-split-v0.md | 4 ++++ .../architecture/rfcs/monorepo-distribution-split-v0.zh-CN.md | 3 +++ 2 files changed, 7 insertions(+) diff --git a/docs/architecture/rfcs/monorepo-distribution-split-v0.md b/docs/architecture/rfcs/monorepo-distribution-split-v0.md index 6d6c9715bd..b9d3750275 100644 --- a/docs/architecture/rfcs/monorepo-distribution-split-v0.md +++ b/docs/architecture/rfcs/monorepo-distribution-split-v0.md @@ -745,6 +745,10 @@ Approval needs a reviewed decision, not implementation progress or silence. `cli_runtime`, without loading the full CLI or Chat graph on valid requests. Rejected syntax retains the full-parser diagnostic path. The host selector, preview commands, readiness and authority rules do not move or change. +- **M1 integration:** [#7878](https://github.com/loopx-project/loopx/pull/7878) + is merged at `ffe84a693`: 17 internal-only Chat owners are under `loopx/chat/`, + with the top-level count and budget both 128 (145 before this move group). + This is a structural delta, not a performance or full-M1 qualification. - **Evidence:** `tests/test_cli_entrypoint.py` checks owner-only help, JSON and Markdown parity, unavailable-host previews, invalid requests and zero process, network or file-write activation. A separately installed wheel exercises help, diff --git a/docs/architecture/rfcs/monorepo-distribution-split-v0.zh-CN.md b/docs/architecture/rfcs/monorepo-distribution-split-v0.zh-CN.md index 5f10af868b..be8f579997 100644 --- a/docs/architecture/rfcs/monorepo-distribution-split-v0.zh-CN.md +++ b/docs/architecture/rfcs/monorepo-distribution-split-v0.zh-CN.md @@ -537,6 +537,9 @@ R0 可以先于目录移动交付,但不代表内核合格。R3/R4 可选, - **变化:** `host-mode-plan` 经 `cli_runtime` 使用原有 registrar 与 handler, 合法请求不再加载完整 CLI 或 Chat 依赖图。非法语法保留完整 parser 的诊断路径。 宿主选择器、预览命令、readiness 与 authority 规则均不移动、不改变。 +- **M1 集成:** [#7878](https://github.com/loopx-project/loopx/pull/7878) 已在 + `ffe84a693` 合入:17 个仅内部使用的 Chat owner 位于 `loopx/chat/`,顶层模块 + 数量和预算均为 128(该移动组之前为 145)。这是结构变化,不代表性能或完整 M1 合格。 - **证据:** `tests/test_cli_entrypoint.py` 覆盖仅加载 owner 的 help、JSON 与 Markdown 一致性、宿主不可用预览、非法请求及零进程、网络或文件写入激活。 独立安装的 wheel 在没有 Node 或实时 registry 时验证 help、ready/unavailable