[Feature]: 统一默认本地状态路径为 .loopx,并提供从 .codex 的显式迁移 #4800
Description
Preflight
- I searched existing issues, discussions, and contributor tasks for this request.
- This request contains no credentials or private/internal material.
Request origin
Observed need in a real workflow after a clean local LoopX reset.
Problem or unmet outcome
LoopX is product/host neutral, but the default local routes still mix product-owned .loopx state with Codex-named paths: the global registry defaults under $HOME/.codex/loopx, while project Goal state is commonly placed under .codex/goals. This is surprising outside Codex, fragments a project's state across two hidden directories, and leaves generated host commands and protocol documents coupled to a Codex-specific default.
The related runtime-route continuity defect has already been fixed in #3709: after a caller explicitly selects --runtime-root, every generated executable continuation must preserve that route. This issue is different: it proposes a host-neutral default path and a safe migration contract.
Proposed outcome
- New installations default global LoopX runtime state to
$HOME/.loopx. - New project registrations and bootstraps store Goal-local state under
.loopx/goals/<goal-id>/, alongside the project registry. - Every built-in route, generated CLI action, bootstrap packet, doctor result, and public document resolves the same default-path helper. Explicit
--runtime-rootand documented environment overrides retain their existing precedence. - Existing
.codex/loopxand.codex/goalsstate remains usable until an operator runs an explicit migration. Discovery/doctor should explain the detected legacy route and selected target. - Migration is previewable and recoverable: validate source/target, create an auditable backup or rollback receipt, move one authoritative state set, and fail rather than leave both old and new copies writable. No silent copy-on-read or dual-authority fallback.
- Update release/install guidance and regression fixtures so they do not recreate Codex-named defaults after migration.
Scope and non-goals
In scope: runtime-root/default-path resolution, project Goal state placement, explicit migration and rollback behavior, generated command routes, docs, and cross-platform regression coverage.
Out of scope: changing Todo/quota semantics, changing output projection policy (#2881), moving arbitrary user-owned .codex files, or silently migrating existing state during ordinary commands.
Acceptance criteria
- A fresh install resolves the global registry/runtime beneath
$HOME/.loopx; a fresh project stores Goal state beneath.loopx/goals. doctor, status, bootstrap, and generateddetail_ref/continuation commands agree on the selected route.- An explicit custom
--runtime-rootcontinues to win and is preserved in every generated executable command, including cold-path refs. - A legacy-only installation is detected without mutation; the explicit migration supports preview and leaves one authoritative writable state location.
- Failures during migration are recoverable from the declared backup/rollback mechanism and do not silently run against the wrong default.
- Public docs and tests contain no stale hard-coded default
$HOME/.codex/loopxor.codex/goalsroutes, except explicitly documented legacy-migration examples.
Alternatives considered
Keep .codex indefinitely and rely on --runtime-root: this preserves compatibility but does not make the host-neutral product default legible, and generated-command path regressions remain easier to miss.
Use a hidden compatibility symlink: rejected because it obscures authority and makes rollback/cross-platform behavior harder to reason about.
Activity
huangruiteng commentedon Sep 20, 2026
合理