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
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@ Disposable source/normal-wheel probes remove the facade, the whole legacy Todo
writer and four shadow producers together; real File/SQLite CLI lifecycle,
once-only settlement, Monitor replay and App cold-import/action/restart journeys
must still work, with missing-provider/lease and changed-source/backup refusals.
The App HTTP receiver now also removes `bootstrap.py` from that same copied
distribution and checks the complete removed set before each server start,
restart and auxiliary CLI. Separate fixture results cannot prove this combined
absence. The ordinary canonical CLI creation entrypoint remains with its owner;
removing it from the cold-import receiver is a disposable qualification probe,
not a supported package format or permission to break the additive 1.x line.
中文:App 冷导入、后续写入和重启使用同一份缺少旧入口、writer 与 source producer 的
隔离副本;不能拼接两组各自缺少一部分模块的结果。正常 canonical 创建仍保留其
现有入口,这个临时卸除验收不等于已完成整族退役、自然试用或正式安装采用。
Lark dry-run and Explore replay qualify local consumers only, not live external
adoption. The fresh research execution path added by [#5280](https://github.com/loopx-project/loopx/pull/5280)
reintroduced a function-local historic import after the earlier caller inventory.
Expand Down
4 changes: 3 additions & 1 deletion tests/control_plane/test_chat_cold_source_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ def cold_api(tmp_path, monkeypatch, request, capture_present):
for name in ("todos.py", "bootstrap.py",
"control_plane/coordination/runtime_shadow_writer_adapter.py",
"control_plane/coordination/local_authority_shadow_outbox.py"):
(receiver / "loopx" / name).unlink()
# The consumer-retirement fixture can already have removed part
# of this same set before the cold receiver is copied.
(receiver / "loopx" / name).unlink(missing_ok=True)
registry = tmp_path / "project/.loopx/registry.json"
if request.param:
# The configured registry may live outside conventional Goal folders.
Expand Down
18 changes: 17 additions & 1 deletion tests/control_plane/test_todo_consumer_host_retirement.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import os
import subprocess
import sys
from pathlib import Path
from types import SimpleNamespace

import pytest
Expand All @@ -33,12 +34,27 @@ def isolated_workspace(*args):
env["PYTHONPATH"] = os.pathsep.join([env["PYTHONPATH"], os.environ["PYTHONPATH"]])
return tuple(result)

def require_retired_receiver(env):
receiver = Path(env["PYTHONPATH"].split(os.pathsep)[0]) / "loopx"
# One copied distribution, before every server start/restart and
# auxiliary CLI: neither earlier fixture alone proves this boundary.
for name in ("todos.py", "bootstrap.py",
"control_plane/todos/legacy_mutation.py", "control_plane/todos/line_update.py",
"control_plane/scheduler/legacy_monitor_poll.py",
"control_plane/coordination/runtime_shadow.py",
"control_plane/coordination/runtime_shadow_writer_adapter.py",
"control_plane/coordination/local_authority_shadow_adapter.py",
"control_plane/coordination/local_authority_shadow_outbox.py"):
assert not (receiver / name).exists(), name

def selected_process(command, **kwargs):
assert command[0] == sys.executable
require_retired_receiver(kwargs["env"])
return subprocess.Popen([command[0], "-S", *command[1:]], **kwargs)

def selected_run(command, **kwargs):
assert command[0] == sys.executable
require_retired_receiver(kwargs["env"])
return subprocess.run([command[0], "-S", *command[1:]], **kwargs)

# Reuse the existing independent cold-import HTTP oracle and process
Expand All @@ -47,7 +63,7 @@ def selected_run(command, **kwargs):
monkeypatch.setattr(cold, "subprocess", SimpleNamespace(
Popen=selected_process, run=selected_run, DEVNULL=subprocess.DEVNULL))
yield from cold.cold_api.__wrapped__(
tmp_path, monkeypatch, SimpleNamespace(param=False), True)
tmp_path, monkeypatch, SimpleNamespace(param=False), False)


@pytest.mark.parametrize("provider", ["file", "sqlite"])
Expand Down
Loading