Problem
The loopx wheel is one distribution that installs the kernel, the CLI, 33 built-in capabilities, the chat/workspace server, and the Python side of the TS effect runtime. On main@3e443ad7c:
loopx/ top level: 143 flat *.py files / ~78.8k lines, including 37 chat_*.py modules and 9 *_goal_mode/ host packages next to the kernel.
loopx/control_plane ≈131k lines, loopx/capabilities ≈115k lines, loopx/extensions ≈44k lines in one package.
pyproject.toml declares dependencies = [] and describes "a lightweight ... control plane", but the effect runtime requires Node.js ≥ 22.22.3 for every install, including CLI-only or kernel-only use.
- Coupling is bidirectional: 52 kernel/CLI/top-level modules import
loopx.capabilities; 74 capability modules import loopx.control_plane.
packages/ already hosts 9 independently packaged extensions (loopx-finance-*, loopx-jev, loopx-obelisk, loopx-repo-health, ...), so the repository has two packaging conventions at once.
Effects: first-use installs pull everything; contributors cannot find module boundaries from the tree; the import-boundary tests protect control_plane inward edges but nothing stops the top level from growing.
Proposal (monorepo stays; distributions split)
Do not split the repository. Keep one repo and one PR/CI flow, especially while the TypeScript control-plane migration is in its transaction-cutover phase. Instead:
- Top-level regrouping first (pure moves + compat re-exports):
loopx/chat_*.py → loopx/chat/; loopx/*_goal_mode/ → loopx/hosts/; keep import paths working through re-export shims for at least one minor release.
- Architecture test "top-level file count does not grow": alongside
tests/architecture/test_control_plane_import_boundaries.py, pin the current count of loopx/*.py and only allow it to decrease.
- Distributions:
loopx-core (kernel + CLI + minimal host adapters; Node runtime declared as an optional extra or bundled), loopx-workspace (chat server, apps/presentation, desktop), and per-capability packages migrated into packages/ behind the existing CapabilityRegistry provider boundary.
- Package graduation to separate repos is explicitly out of scope until the kernel migration is complete and a package has its own maintainers.
Acceptance sketch
pip install loopx-core on a clean machine without Node succeeds and loopx --help / read-only status work; effect-runtime commands report a typed node_unavailable diagnostic instead of failing at import time.
loopx/*.py count is pinned and decreasing; the architecture test fails on any new top-level module.
- Existing
import loopx.chat_server style imports keep working for one minor release with a deprecation note.
- Capability packages moved to
packages/ install/uninstall independently and off-state preserves core behavior (same rule as existing extensions).
RFC PR: #5073
Problem
The
loopxwheel is one distribution that installs the kernel, the CLI, 33 built-in capabilities, the chat/workspace server, and the Python side of the TS effect runtime. Onmain@3e443ad7c:loopx/top level: 143 flat*.pyfiles / ~78.8k lines, including 37chat_*.pymodules and 9*_goal_mode/host packages next to the kernel.loopx/control_plane≈131k lines,loopx/capabilities≈115k lines,loopx/extensions≈44k lines in one package.pyproject.tomldeclaresdependencies = []and describes "a lightweight ... control plane", but the effect runtime requires Node.js ≥ 22.22.3 for every install, including CLI-only or kernel-only use.loopx.capabilities; 74 capability modules importloopx.control_plane.packages/already hosts 9 independently packaged extensions (loopx-finance-*,loopx-jev,loopx-obelisk,loopx-repo-health, ...), so the repository has two packaging conventions at once.Effects: first-use installs pull everything; contributors cannot find module boundaries from the tree; the import-boundary tests protect
control_planeinward edges but nothing stops the top level from growing.Proposal (monorepo stays; distributions split)
Do not split the repository. Keep one repo and one PR/CI flow, especially while the TypeScript control-plane migration is in its transaction-cutover phase. Instead:
loopx/chat_*.py→loopx/chat/;loopx/*_goal_mode/→loopx/hosts/; keep import paths working through re-export shims for at least one minor release.tests/architecture/test_control_plane_import_boundaries.py, pin the current count ofloopx/*.pyand only allow it to decrease.loopx-core(kernel + CLI + minimal host adapters; Node runtime declared as an optional extra or bundled),loopx-workspace(chat server,apps/presentation, desktop), and per-capability packages migrated intopackages/behind the existingCapabilityRegistryprovider boundary.Acceptance sketch
pip install loopx-coreon a clean machine without Node succeeds andloopx --help/ read-only status work; effect-runtime commands report a typednode_unavailablediagnostic instead of failing at import time.loopx/*.pycount is pinned and decreasing; the architecture test fails on any new top-level module.import loopx.chat_serverstyle imports keep working for one minor release with a deprecation note.packages/install/uninstall independently and off-state preserves core behavior (same rule as existing extensions).RFC PR: #5073