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
86 changes: 86 additions & 0 deletions docs/architecture/rfcs/monorepo-distribution-split-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,91 @@ Approval needs a reviewed decision, not implementation progress or silence.
installation, R1 managed minimal or D1–D7. No preset, frontend operation,
permission or persisted state changes; protected execution keeps its owner.

### 2026-11-06 — Selected version loading and matched costs

The independent proposal `8a79d8602e699e51452ca1f43dc9b9527c81aa1b` at baseline
`5a58635028fbef1316dc66531daf5fdb655e9b13` selects the existing version registrar
and handler through `cli_runtime`. It reuses the canonical global grammar,
format precedence, usage hooks and controller guard. Rejected parsing retains
full-CLI fallback and diagnostics; explicitly bound package or full-CLI exports
retain their registrar/handler patch points without triggering lazy exports
on ordinary queries. Public imports, identity and types remain
unchanged. No capability, provider, package, permission, preset or TypeScript
decision owner is added. The separate DSH/helper and negative cost proposal is
[#8185](https://github.com/loopx-project/loopx/pull/8185); its E7/E8 observations
are distinct from this version-path comparison and are not a dependency.

The initial `55e3ef45a` comparison retains 120 ordinary-query observations
(source median 1.546 → 0.059 seconds; wheel 1.554 → 0.072). A later independent
case finds that it ignores a patched package-facade handler, returning 0 instead
of 37. Its passing premerge did not cover that branch. The failure and original
inputs/data remain retained; they do not qualify facade compatibility. The
proposal repairs both package registrar and handler adoption, then freezes the
new exact-head comparison below.

- **Real caller:** source and freshly installed monolithic wheels at both
immutable revisions exercise the actual `loopx` console. All 27 cases per
distribution have identical stdout, stderr and exit status, including
global/local/repeated formats, explicit paths, help, unknown/abbreviated
options, missing/empty values and fallback. Independent unknown-command/
option cases reject with exit 2 and no result. Version works with Node absent
in all four variants; outer-controller read behavior and full-CLI patch points
remain compatible.
- **Loading census:** separate parent instrumentation records 1,157 → 10
LoopX modules in both distributions, with the candidate contained in the
baseline set. Source read-opens are 1,286 → 28 and wheel 1,289 → 29.
Each version capture has zero write-opens, subprocesses, observed local IPC
connections and covered socket bytes. Stdout remains 81 bytes; stderr is empty.
- **Frozen comparison:** all four environments have verified provenance,
CPython 3.13.5 and identical 57 dependency versions. Stdlib, dependencies and
all 1,421 LoopX sources have valid timestamp bytecode in owned cache prefixes;
post-measurement/profile source/header inventories have no missing/invalid
caches and match the preflight. Every sample has fresh Python and disables
bytecode writes; disk cache is uncontrolled. No broker/warm-broker comparison
is made. Order is source then wheel, AB on even pairs and BA on odd pairs.
Both corrected groups complete 30 pairs: 120 accepted observations in 62.246
seconds. Including the first study, aggregate sampling is 166.191 seconds,
below the unchanged 1,200-second cap. All observations are retained.

| Distribution | Baseline seconds, median / p95 | Proposal seconds, median / p95 | CPU seconds, median (base → proposal) | RSS MiB, median (base → proposal) | Median paired proposal minus baseline, seconds |
| --- | --- | --- | --- | --- | --- |
| Source | 0.980 / 1.056 | 0.055 / 0.075 | 0.520 → 0.037 | 90.17 → 16.81 | -0.9242 |
| Monolithic wheel | 0.948 / 1.147 | 0.056 / 0.077 | 0.511 → 0.038 | 89.89 → 16.60 | -0.8993 |

p95 uses nearest rank; paired differences and differences of arm medians are
distinct statistics. Median latency falls about 94% in both source and wheel
on this macOS arm64 environment; CPU and target RSS also fall. One-minute host
load ranges from 8.25 to 9.06. This qualifies a material version-query
improvement under frozen conditions, without adopting portable D6 budgets or
claiming real managed-Turn/long-horizon savings. Usage covers the target and
waited descendants; no child is launched in the census. Native detail and
complete authoring/model/maintenance costs remain unknown.

The heartbeat-to-final-freeze interval is about 2,404 seconds, including
overlapping recovery, initial study, correction, dependency/build/install,
test, cache and parity work; overlapping phases cannot be summed. Cache
preparation is recorded separately. Corrected console/facade parity takes
82.759 seconds, instrumentation 2.539 and four parent profiles 4.155. Earlier
parity/instrumentation/profile costs of 136.239 / 3.830 / 7.089 seconds remain
retained. Cross-study timing levels are not treated as a code comparison.
Existing `performance-diagnosis` recipes show export loading and full parser
construction in baseline sampled stacks; weights remain separate from repeated
latency. Monolithic packaging is verified, without split-install or installed
host-upgrade qualification.

Seven selected-loading cases fail on the baseline and pass on the proposal.
The package registrar/handler case passes on the baseline, fails on the initial
candidate and passes on the correction; canonical diagnostic and full-CLI
patch-point cases pass in both baseline and proposal. All 161 entrypoint cases and
focused lint pass. Owner-scoped mypy with `--follow-imports=skip` fails with
33 identical diagnostics at base/proposal after line normalization; this is
neither a pass nor the full configured type check. Adoption requires final-head
validation, independent review and merge readiness. I3's minimum one minor
release window remains in force; no D3/expiry decision is made. R0's wider census,
R1/minimal, D2/D5/D6, hard-lease/context/model and split-install acceptance remain
open. The bounded refactor reuses its existing parser/handler; larger runtime
and package changes retain their accepted owners.

## Appendix B: Decision log

| Date | Decision | Owner / approval | Alternatives | Normative sections changed |
Expand All @@ -840,6 +925,7 @@ Approval needs a reviewed decision, not implementation progress or silence.
| E4 | Selected CLI loading seam | `9cae3b28939f72fa4aadab5cfe49e19bcbdab372` | Linked entrypoint/CLI in Section 4 | Source-audited | No new timing claim |
| E5 | DSH composition example | Pinned upstream commit | [`minimal.patch.yml`](https://github.com/deepseek-ai/deepseek-harness/blob/f3803c96974ad4a94195fb97e5c637e9c2a3afe3/packages/bundle/web-app/presets/minimal.patch.yml), [`standard.patch.yml`](https://github.com/deepseek-ai/deepseek-harness/blob/f3803c96974ad4a94195fb97e5c637e9c2a3afe3/packages/bundle/web-app/presets/standard.patch.yml), [`sdk-minimal`](https://github.com/deepseek-ai/deepseek-harness/blob/f3803c96974ad4a94195fb97e5c637e9c2a3afe3/packages/bundle/sdk-minimal/README.md) | Source-audited | Shared preset composition and a self-contained SDK bundle; not a LoopX host qualification or permission recommendation |
| E6 | Pi core/context example | Pinned upstream commit | [`agent` core](https://github.com/badlogic/pi-mono/blob/f14813e96510a7cf7562a120e809c6a134af073d/packages/agent/README.md) | Source-audited | Agent/tool/event core with `transformContext`, `convertToLlm`, `prepareRequest` and `finishTurn` seams; no LoopX authority or performance claim |
| E9 | Selected version loading and matched cost | `5a5863502` / `8a79d8602`; macOS arm64 / CPython 3.13.5 | Version checkpoint above; existing console/version and performance-diagnosis owners | Corrected two groups × 30 pairs; 120 observations; public-facade/parity/cache readback pass; material query improvement | Initial 120 observations and facade failure retained; public-safe aggregates; full Turn/minimal, split install, host upgrade and complete costs unqualified; E7/E8 remain with #8185 |

## Appendix D: Rejected or superseded alternatives

Expand Down
64 changes: 64 additions & 0 deletions docs/architecture/rfcs/monorepo-distribution-split-v0.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,69 @@ R0 可以先于目录移动交付,但不代表内核合格。R3/R4 可选,
不关闭完整 R0/V10、M1、拆包安装、R1 managed minimal 或 D1–D7。不改变 preset、
前端操作、权限或持久化状态;受保护执行仍由既有 owner 所有。

### 2026-11-06 — Version 按需加载及匹配成本

独立候选 `8a79d8602e699e51452ca1f43dc9b9527c81aa1b` 对比基线
`5a58635028fbef1316dc66531daf5fdb655e9b13`,由 `cli_runtime` 选择既有
version registrar 与 handler,复用规范全局语法、format 优先级、usage hook
及 controller guard。解析拒绝保留完整 CLI fallback 与诊断;已显式加载完整
CLI 或绑定 package 导出的调用保留其 registrar/handler patch 点;普通查询不会
触发 lazy exports。公开 import、身份及类型不变。
不新增 capability、provider、package、权限、preset 或 TypeScript 决策 owner。
独立 DSH/helper 及负面成本提案仍在 [#8185](https://github.com/loopx-project/loopx/pull/8185);
其 E7/E8 与本次 version 对照分开,也不构成依赖。

初始 `55e3ef45a` 对照的 120 个普通查询观察继续保留:source 中位数
1.546 → 0.059 秒、wheel 1.554 → 0.072 秒。随后独立用例发现它忽略已替换的
package-facade handler,返回 0 而非 37;此前通过的 premerge 未覆盖该分支。
原输入、数据和失败保留,不将其视为 facade 兼容资格。提案补回 package
registrar 与 handler 的采纳后,另行冻结下列精确 head 对照。

- **真实调用:** 两个不可变版本的源码及新安装单体 wheel 均经实际 `loopx`
console 执行。每种发行形态的 27 个用例,stdout、stderr、退出状态完全一致,
覆盖全局/局部/重复 format、显式路径、help、未知/缩写参数、缺失/空值及
fallback。独立未知命令/参数 oracle 以 exit 2 拒绝且无结果。四个组合在缺少
Node 时均可查询 version;outer-controller 读行为及完整 CLI patch 点兼容。
- **加载清点:** 独立 parent 插桩记录,两种发行形态均为 1,157 → 10 个 LoopX
模块,候选是基线的子集。Source read-open 1,286 → 28,wheel 1,289 → 29。
每个 version 捕获的 write-open、子进程、观测到的本地 IPC 连接及覆盖 socket
字节均为零。Stdout 保持 81 字节,stderr 为空。
- **冻结对照:** 四个环境均核验来源,使用 CPython 3.13.5 及相同 57 个依赖
版本。标准库、依赖及全部 1,421 个 LoopX 源文件,在独占 cache prefix 具有
有效时间戳字节码;测量/profile 后的源码及 header 清点与预检一致,无缺失/
无效缓存。每次采样是新 Python 进程,禁止字节码写入;磁盘缓存不受控,不比较
broker/warm broker。顺序为源码先于 wheel,偶数对 AB、奇数对 BA。两组各
完成 30 对,共 120 个有效观察,采样 62.246 秒。计入首轮后合计采样
166.191 秒,低于不变的 1,200 秒上限;全部观察保留。

| 发行形态 | 基线秒数,中位数 / p95 | 候选秒数,中位数 / p95 | CPU 秒数,中位数(基线 → 候选) | RSS MiB,中位数(基线 → 候选) | 配对候选减基线的中位数,秒 |
| --- | --- | --- | --- | --- | --- |
| Source | 0.980 / 1.056 | 0.055 / 0.075 | 0.520 → 0.037 | 90.17 → 16.81 | -0.9242 |
| 单体 wheel | 0.948 / 1.147 | 0.056 / 0.077 | 0.511 → 0.038 | 89.89 → 16.60 | -0.8993 |

p95 使用 nearest rank;配对差中位数与两 arm 中位数之差不同。本次 macOS
arm64 条件下,source 与 wheel 中位延迟均约下降 94%,CPU 与 target RSS
也下降。一分钟宿主负载为 8.25–9.06。本片证明冻结条件下的明显版本查询收益,
不采纳可移植 D6 预算,不声明真实 managed Turn 或长程节省。用量覆盖 target
及等待子进程,清点中未启动子进程;native 细节及完整编写/模型/维护成本未知。

从本次唤醒时间戳到最终冻结约 2,404 秒,包含有重叠的入口恢复、首轮实验、修正、
依赖/构建/安装、测试、缓存及一致性验证;重叠阶段不可求和。缓存准备单独记录。
修正后的 console/facade 一致性为 82.759 秒、插桩 2.539 秒、四个 parent
profile 4.155 秒;首轮 136.239 / 3.830 / 7.089 秒成本继续保留。
不同轮的耗时水平不作为代码对照。既有
`performance-diagnosis` recipe 在基线采样栈中显示 export loading 及完整 parser
构建;栈权重与重复延迟分开。已验证单体打包,不代表拆包安装或已安装宿主升级。

七项 selected-loading 用例在基线失败、候选通过。Package registrar/handler
用例在基线通过、初始候选失败、修正后通过;规范诊断及完整 CLI patch 点在基线/
候选均通过。完整入口 161 项及聚焦 lint 通过。Owner-scoped mypy 使用
`--follow-imports=skip`,基线与候选在行号归一后均有 33 项相同错误,不是通过或
完整配置的类型检查。采纳仍需最终 head 验证、独立评审及 merge readiness。
I3 至少一个 minor release 的窗口继续有效,不作 D3/到期决策。R0 更广清点、
R1/minimal、D2/D5/D6、hard-lease/context/model 及拆包安装验收仍开放。
有界重构复用既有 parser/handler;更大 runtime/package 改动保留在其已接受 owner。

## 附录 B:决策日志

| 日期 | 决策 | 负责人 / 批准 | 备选 | 变更的规范章节 |
Expand All @@ -615,6 +678,7 @@ R0 可以先于目录移动交付,但不代表内核合格。R3/R4 可选,
| E4 | 所选 CLI 加载接缝 | `9cae3b28939f72fa4aadab5cfe49e19bcbdab372` | 第 4 节链接的入口/CLI | 源码审计 | 无新性能测量 |
| E5 | DSH 装配范例 | 固定上游 commit | [`minimal.patch.yml`](https://github.com/deepseek-ai/deepseek-harness/blob/f3803c96974ad4a94195fb97e5c637e9c2a3afe3/packages/bundle/web-app/presets/minimal.patch.yml)、[`standard.patch.yml`](https://github.com/deepseek-ai/deepseek-harness/blob/f3803c96974ad4a94195fb97e5c637e9c2a3afe3/packages/bundle/web-app/presets/standard.patch.yml)、[`sdk-minimal`](https://github.com/deepseek-ai/deepseek-harness/blob/f3803c96974ad4a94195fb97e5c637e9c2a3afe3/packages/bundle/sdk-minimal/README.md) | 源码审计 | 共享预设装配与自包含 SDK bundle;不代表 LoopX 宿主资格或权限建议 |
| E6 | Pi core/上下文范例 | 固定上游 commit | [`agent` core](https://github.com/badlogic/pi-mono/blob/f14813e96510a7cf7562a120e809c6a134af073d/packages/agent/README.md) | 源码审计 | Agent/tool/event core,以及 `transformContext`、`convertToLlm`、`prepareRequest`、`finishTurn` 接缝;无 LoopX authority 或性能声明 |
| E9 | Version 按需加载及匹配成本 | `5a5863502` / `8a79d8602`;macOS arm64 / CPython 3.13.5 | 上述 version checkpoint;既有 console/version 及 performance-diagnosis owner | 修正后两组各 30 对,共 120 个观察;公开 facade/一致性/缓存读回通过;版本查询明显改善 | 首轮 120 个观察及 facade 失败保留;仅公开安全汇总;完整 Turn/minimal、拆包安装、宿主升级及完整成本未取得资格;E7/E8 保留在 #8185 |

## 附录 D:被拒绝或被取代的备选

Expand Down
24 changes: 22 additions & 2 deletions loopx/cli_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"refresh-state", "checkpoint-context", "read-only-map", "reward", "operator-gate",
}
_SELECTED_COMMANDS = _STATUS_COMMANDS | GLOBAL_READ_COMMANDS | PROJECT_LIFECYCLE_COMMANDS | {
"todo", "quota", "task-lease", "change-window", "delegation", "turn", "doctor", "commands",
"todo", "quota", "task-lease", "change-window", "delegation", "turn", "doctor", "commands", "version",
"authority-archive", "coordination-shadow", "extension", "slash-commands",
"manager-inbox",
"agent-context", "agent-directory", "agent-capabilities",
Expand Down Expand Up @@ -396,6 +396,10 @@ def _build_selected_parser(command: str) -> LoopXArgumentParser:
from .help_surface import register_command_reference

register_command_reference(subparsers)
elif command == "version":
from .cli_commands.version import register_version_command

register_version_command(subparsers, add_subcommand_format)
elif command == "performance-diagnosis":
from .capabilities.performance_diagnosis.cli import register_performance_diagnosis_commands

Expand Down Expand Up @@ -710,7 +714,13 @@ def _dispatch_selected(args: argparse.Namespace, raw_argv: list[str]) -> int:
if guard_result is not None:
return guard_result
registry_path, _registry_was_configured = resolve_cli_registry(args, raw_argv)
if args.command == "capability":
if args.command == "version":
from .cli_commands.version import handle_version_command

result = handle_version_command(
args, output_format=output_format, print_payload=print_payload,
)
elif args.command == "capability":
from .cli_commands.capability import handle_capability_command

# Keep the explicit full CLI's handler and protected operations unchanged.
Expand Down Expand Up @@ -766,6 +776,16 @@ def main(argv: list[str] | None = None) -> int:


def _run_command(command: str | None, raw_argv: list[str]) -> int:
if command == "version":
version_exports = sys.modules.get("loopx.cli_commands")
# Inspect bound exports without triggering the lazy facade. Explicit
# package/full-CLI imports retain their registrar and handler patch points.
if "loopx.cli" in sys.modules or (
version_exports is not None
and ("handle_version_command" in vars(version_exports)
or "register_version_command" in vars(version_exports))
):
return _run_full_cli(raw_argv)
if command in _SELECTED_COMMANDS:
try:
args = _build_selected_parser(command).parse_args(raw_argv)
Expand Down
Loading
Loading