Skip to content
Merged
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
50 changes: 50 additions & 0 deletions docs/architecture/rfcs/monorepo-distribution-split-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -3509,3 +3509,53 @@ exit-only Agent: registration and honest failed-Turn recovery do not prove
natural-language task completion or model benefit. Complete minimal closure,
R1/M3, workspace/meta publication, installed-host adoption and full-cost
acceptance remain open.

### 2026-11-13 — Standalone natural-language startup reaches existing owners

The independently installed core now routes `start-goal`,
`bootstrap-command-pack`, `register-agent` and `bind-agent-thread` to the
ordinary product's existing registrars and handlers. Previously all four
required the omitted full CLI facade. The goal preview preserves exact text,
remains read-only and exposes the same ordered bootstrap, identity, Todo and
host/guard transaction. Fresh registration, collision rejection, global/source
readback and bound-session reuse execute against the default SQLite authority.
No new engine, model service, authority rule or capability activation is added.
The ordinary installation retains its complete-parser diagnostic fallback;
invalid standalone arguments retain the existing explicit unavailable failure.

Installed qualification passes 16 checks, including the guided identity journey
and existing SQLite/File execution, rejected artifacts, renewed/released lease
refusal and confirmed-result recovery/replay. Eight focused comparisons match
the ordinary parser and preview. The original baseline independently installed
wheel refuses natural-language startup; the repaired wheel executes it. These
are executable behavioral deltas, not help-text-only delivery.

A separate isolated generic-CLI task was performed by the current host model:
create a reusable inventory generator and JSON/Markdown reports from source
catalog/movement files, with exact decimal valuation and excluded records. Its
independent validator accepts the result. Killing the driver after its typed
result was journaled, then resuming the original key, completes the Todo and
records one settlement without invoking the model again; a further replay has
no state or quota effects. An earlier pre-work attempt expired while awaiting
model input; its unknown-outcome recovery rejection remains recorded. There
were two host transport dispatches in total and one confirmed model result;
this is not a claim of one dispatch across the entire experiment.

A three-pair local loading census (macOS arm64, Python 3.13.5, Node 26.0.0,
new Python processes with ordinary filesystem/bytecode caches, plus two warm
calls per process) observes 8 core modules for top-level help and 186 for guided
help/preview. The direct ordinary full-facade comparison loads 1,151/1,164
modules. Preview includes two subprocess events and nine Python socket audit
events, so process/IPC costs must remain in the closure inventory. Different
source/install cache and launch conditions, three samples, Python-only audit
coverage and unavailable model-token counters prevent a performance or complete
V10 claim. This does not approve D2 or a minimal preset.

The source-regression attempt that exhausted local disk remains failed; its
recovered run is recorded separately. Complete minimal install/load/context
closure, initial/revised/compacted/lost-ACK context qualification, supported host
adoption, full V1–V5/V10, R1/M3, Standard/workspace/meta splitting and complete
costs remain open. Rollback the routing slice while retaining task authority and
reconciling original attempts. Existing exact-head review, premerge and bilingual
requirements, original failures, budgets and separate research/release authority
remain in force.
39 changes: 39 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 @@ -2736,3 +2736,42 @@ dry-run 拒绝路径的中位数为 142.4→135.1 ms、934.4→911.8 ms。零条
首次 Goal 夹具使用退出式 Agent:登记及如实显示失败 Turn 的恢复不证明自然语言任务
完成或模型收益。完整最小闭包、R1/M3、workspace/meta 发布、安装宿主采用及完整成本
验收仍保持开放。

### 2026-11-13 — 独立发行版的自然语言启动到达既有 owner

独立安装的 core 现在将 `start-goal`、`bootstrap-command-pack`、
`register-agent` 和 `bind-agent-thread` 路由到普通产品既有的 registrar 与
handler。此前四条命令都依赖被排除的完整 CLI facade。目标预览保留完整原文,
保持只读,并返回同一套有序的 bootstrap、身份、Todo 与 host/guard 事务。
新身份注册、冲突拒绝、global/source 回读和绑定会话复用在默认 SQLite authority
上真实执行。没有新增 engine、模型服务、权限规则或 capability 激活。
普通安装仍保留完整 parser 的诊断 fallback;独立 core 的非法参数仍返回既有明确
unavailable 错误。

安装验证通过 16 项检查,覆盖 guided 身份旅程及既有 SQLite/File 执行、产物拒绝、
续租/释放后的完成拒绝和已确认结果恢复/重放。八项聚焦对照与普通 parser 和预览
一致。原始独立安装基线 wheel 拒绝自然语言启动,修复 wheel 能执行这条路径。
这是真实可执行的行为差异,不是仅修改帮助文案。

另一个隔离 generic-CLI 任务由当前 host 模型实际完成:依据 catalog/movement
源文件生成可复用库存脚本及 JSON/Markdown 报告,保留精确小数计价和排除记录。
独立 validator 接受结果。typed result 已入 journal 后杀掉 driver,再用原始 key
恢复,可完成 Todo 并只结算一次,且不再次调用模型;再次重放无状态或额度副作用。
更早一次任务前尝试在等待模型输入期间过期,其 unknown-outcome 恢复拒绝仍保留。
整个实验共两次 host transport dispatch、一个已确认模型结果,不能宣称全实验
只 dispatch 一次。

三对本地 loading census 使用 macOS arm64、Python 3.13.5、Node 26.0.0,
新 Python 进程保留普通文件系统/bytecode 缓存,每进程再运行两次 warm 调用。
core 顶层帮助加载 8 个模块,guided 帮助/预览加载 186 个;直接普通 full-facade
对照为 1,151/1,164 个。预览出现两次 subprocess 和九次 Python socket audit
事件,process/IPC 成本必须保留在闭包清单。源码/安装的缓存与启动条件不同、仅三
个样本、仅 Python audit 范围及缺失模型 token 计数,使其不能支持性能或完整
V10 结论,也不批准 D2 或 minimal preset。

源码回归因本地磁盘耗尽而中止的尝试仍为失败,恢复后的运行单独记录。
完整最小 install/load/context 闭包、initial/revised/compacted/lost-ACK 上下文
资格、受支持 host 采用、完整 V1–V5/V10、R1/M3、Standard/workspace/meta 拆包
和完整成本仍未完成。回滚路由切片时保留 task authority 并协调原始尝试。
既有 exact-head 评审、premerge、双语要求、原始失败、预算及独立研究/发布授权
继续有效。
31 changes: 28 additions & 3 deletions loopx/cli_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@
_REGISTRY_INSPECTION_COMMANDS = frozenset({"registry", "registry-boundary"})
_SELECTED_COMMANDS = _STATUS_COMMANDS | GLOBAL_READ_COMMANDS | PROJECT_LIFECYCLE_COMMANDS | _REGISTRY_INSPECTION_COMMANDS | {
"todo", "quota", "task-lease", "change-window", "delegation", "turn", "doctor", "commands", "version",
"bootstrap", "connect", "configure-goal",
"bootstrap", "connect", "configure-goal", "start-goal", "bootstrap-command-pack",
"register-agent", "bind-agent-thread",
"authority-archive", "coordination-shadow", "extension", "slash-commands",
"manager-inbox",
"agent-context", "agent-directory", "agent-capabilities",
Expand Down Expand Up @@ -393,7 +394,19 @@ def _handle_registry_inspection_command(

def _build_selected_parser(command: str) -> LoopXArgumentParser:
parser, subparsers = build_cli_parser(parser_class=_SelectedArgumentParser)
if command in {"bootstrap", "connect"}:
if command == "start-goal":
from .cli_commands.start_goal import register_start_goal_command

register_start_goal_command(subparsers)
elif command == "bootstrap-command-pack":
from .cli_commands.starter_bootstrap_registration import register_starter_bootstrap_commands

register_starter_bootstrap_commands(subparsers)
elif command in {"register-agent", "bind-agent-thread"}:
from .cli_commands.registry_admin import register_registry_admin_commands

register_registry_admin_commands(subparsers)
elif command in {"bootstrap", "connect"}:
from .cli_commands.bootstrap_connect import register_bootstrap_connect_command

register_bootstrap_connect_command(subparsers)
Expand Down Expand Up @@ -526,13 +539,25 @@ def _dispatch_common_command(
registry_path: Path,
allow_missing_registry: bool,
) -> int | None:
if args.command == "start-goal":
from .cli_commands.start_goal import handle_start_goal_command

return handle_start_goal_command(
args, print_payload, runtime_root_arg=args.runtime_root,
)
if args.command == "bootstrap-command-pack":
from .cli_commands.starter_bootstrap import handle_loopx_bootstrap_command_pack_command

return handle_loopx_bootstrap_command_pack_command(
args, print_payload, runtime_root_arg=args.runtime_root,
)
if args.command in {"bootstrap", "connect"}:
from .cli_commands.bootstrap_connect import handle_bootstrap_connect_command

return handle_bootstrap_connect_command(
args, registry_path=registry_path, print_payload=print_payload,
)
if args.command == "configure-goal":
if args.command in {"configure-goal", "register-agent", "bind-agent-thread"}:
from .cli_commands.registry_admin import handle_registry_admin_command

return handle_registry_admin_command(
Expand Down
2 changes: 2 additions & 0 deletions loopx/help_surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,8 @@ def render_concise_help(program: str = "loopx", *, standalone_core: bool = False
"LoopX keeps long-running agent work moving with durable state and evidence.",
"", "Usage:", f" {program} [global options] <command> [command options]",
"", "Start:",
' loopx start-goal --guided --project . --goal-text "<goal>"',
" Start from a goal with your existing model host.",
" loopx connect --help Connect a project and its objective.",
" loopx configure-goal --help Configure its Agent and execution budget.",
" loopx todo --help Create, claim and complete work.",
Expand Down
16 changes: 14 additions & 2 deletions packages/loopx-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,20 @@ tasks requires a qualified Node runtime (22.22.3+ and the existing SQLite
reliability checks), an explicitly selected host and its own prerequisites.
Use the existing `turn run-once --host generic-cli` entry, a separate validation
command, `turn inspect-journal` and `--resume-turn-key` for execution and recovery.
Bootstrap with `connect`, configure one Agent with `configure-goal`, and create
and claim work through the existing `todo` commands. An ordinary managed claim
Start with one natural-language goal in your existing model host:

```sh
loopx start-goal --guided --project . --goal-text "Create and check an inventory report."
```

Follow its returned host choice and ordered transaction. The preview preserves
the exact goal text and writes no state. Its project bootstrap, fresh identity
registration, session binding and subsequent Todo/guard commands execute in
this standalone distribution through their existing owners. The host supplies
the model, tools and scheduler; the wheel does not provide them or activate an
optional capability from goal wording. `connect` and `configure-goal` remain
available for explicit setup. Create and claim work through the existing `todo`
commands. An ordinary managed claim
prepares the default SQLite lease without asking the task model to manage lease
flags. Completion carries the original captured lease generation; recovery
refuses a renewed, released or replaced generation rather than adopting it.
Expand Down
35 changes: 35 additions & 0 deletions tests/test_cli_entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -2056,3 +2056,38 @@ def test_selected_connect_preview_keeps_full_cli_result_without_workspace(tmp_pa
assert selected.returncode == ordinary.returncode == 0, (selected.stderr, ordinary.stderr)
assert json.loads(selected.stdout) == json.loads(ordinary.stdout)
assert not registry.exists()


@pytest.mark.parametrize('arguments', [
['start-goal', '--help'],
['bootstrap-command-pack', '--help'],
['register-agent', '--help'],
['bind-agent-thread', '--help'],
['start-goal', '--guided', '--goal-text', '完整 goal', '--host-surface', 'unsupported'],
['register-agent', '--goal-id', 'missing'],
['bind-agent-thread', '--goal-id', 'missing', '--agent-id', 'test'],
])
def test_guided_core_routes_match_complete_parser(arguments):
# Invalid argv retains the ordinary installation's canonical full-parser
# diagnostic fallback; valid selected help must never load that facade.
selected = run_cli_main('loopx.entrypoint', arguments,
forbidden_modules=('loopx.cli',) if '--help' in arguments else ())
full = run_cli_main('loopx.cli', arguments)
assert (selected.returncode, selected.stdout, selected.stderr) == (full.returncode, full.stdout, full.stderr)


def test_guided_core_preview_matches_complete_owner_without_writes(tmp_path):
project = tmp_path / 'project'
project.mkdir()
argv = ['--runtime-root', str(tmp_path / 'runtime'), '--format', 'json',
'start-goal', '--guided', '--project', str(project),
'--host-surface', 'shell', '--goal-text', 'Report "inventory" and 总计.']
environment = {'CODEX_THREAD_ID': '', 'TRAECLI_THREAD_ID': '', 'LOOPX_USAGE_PING': '0'}
selected = run_cli_main('loopx.entrypoint', argv, forbidden_modules=('loopx.cli',), environment=environment)
full = run_cli_main('loopx.cli', argv, environment=environment)
assert selected.returncode == full.returncode == 0
assert selected.stdout == full.stdout and selected.stderr == full.stderr
packet = json.loads(selected.stdout)
assert packet['goal_text'] == 'Report "inventory" and 总计.'
assert packet['guided_transaction']['writes_now'] is False
assert not list(project.iterdir()) and not (tmp_path / 'runtime').exists()
49 changes: 48 additions & 1 deletion tests/test_core_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def test_installed_core_identity_help_and_unavailable_workspace(core_python, tmp
assert not Path(json.loads(probe.stdout)["package"]).is_relative_to(REPOSITORY)
help_text = _run(core_python, ["--help"], tmp_path, environment={"PATH": str(tmp_path)}).stdout
assert "loopx connect --help" in help_text and "loopx turn run-once --help" in help_text
assert "preset list" not in help_text and "start-goal" not in help_text
assert "preset list" not in help_text and "loopx start-goal --guided" in help_text
reference = json.loads(_run(core_python, ["commands", "--format", "json"], tmp_path).stdout)
commands = [entry["command"] for group in reference["groups"] for entry in group["commands"]]
assert "loopx configure-goal --help" in commands
Expand All @@ -132,6 +132,53 @@ def test_installed_core_identity_help_and_unavailable_workspace(core_python, tmp
assert not list(tmp_path.iterdir())


def test_installed_core_guided_start_identity_and_readback(core_python, tmp_path, monkeypatch):
from tests.control_plane.canonical_authority_fixture import isolate_sqlite_runtime

isolate_sqlite_runtime(tmp_path, monkeypatch)
project, runtime = tmp_path / "project", tmp_path / "runtime"
project.mkdir()
prefix = ["--runtime-root", str(runtime), "--format", "json"]
objective = 'Produce an inventory report; preserve "quoted" source names and 总计.'
start = [*prefix, "start-goal", "--guided", "--project", str(project),
"--goal-id", GOAL, "--host-surface", "shell", "--goal-text", objective]

def command(*arguments, expected=0):
return json.loads(_run(core_python, list(arguments), project, expected=expected).stdout)

preview = command(*start)
assert preview["goal_text"] == objective
assert preview["guided_transaction"]["writes_now"] is False
assert preview["guided_transaction"]["spends_quota_now"] is False
assert preview["recommended_next_step"]["identity_selection_gate"]["default_action"] == "register_fresh_agent"
assert not list(project.iterdir()) and not runtime.exists()
# These are the real bootstrap and identity owners advertised by the
# preview, running from the standalone wheel with the full facade absent.
created = command(*prefix, "bootstrap", "--project", str(project), "--goal-id", GOAL,
"--objective", objective, "--write-scope", "docs/**")
assert created["storage_selection"]["provider"] == "sqlite"
assert created["global_sync"]["ok"] is True
registered = command(*prefix, "register-agent", "--goal-id", GOAL,
"--agent-id", AGENT, "--require-new", "--execute")
assert registered["registration_readback"]["verified"] is True
assert registered["global_sync"]["ok"] is True
collision = command(*prefix, "register-agent", "--goal-id", GOAL,
"--agent-id", AGENT, "--require-new", "--execute", expected=1)
assert collision["ok"] is False and collision["written"] is False
binding = command(*prefix, "bind-agent-thread", "--goal-id", GOAL,
"--agent-id", AGENT, "--thread-id", "core-session", "--host-surface", "shell", "--execute")
assert binding["global_sync"]["ok"] is True
assert binding["registration_readback"]["verified"] is True
resumed = command(*start, "--thread-id", "core-session")
assert resumed["agent_id"] == AGENT
assert resumed["project_connection"]["goal_found"] is True
assert "identity_selection_gate" not in resumed["guided_transaction"]
pack = command(*prefix, "bootstrap-command-pack", "--project", str(project),
"--goal-id", GOAL, "--agent-id", AGENT, "--host-surface", "shell", "--goal-text", objective)
assert pack["goal_start_contract"]["goal_text"] == objective
assert pack["goal_start_contract"]["explicit_invocation_confirms_project_local_state_writes"] is True


def test_installed_core_catalog_entries_have_executable_parsers(core_python, tmp_path):
reference = json.loads(_run(core_python, ["commands", "--format", "json"], tmp_path).stdout)
for group in reference["groups"]:
Expand Down
Loading