Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -344,16 +344,16 @@ def exercise_route_edges(root: Path) -> None:
write_target(target_a, source_registry=ambiguous_registry, goal=ambiguous_goal)
write_target(target_b, source_registry=ambiguous_registry, goal=ambiguous_goal)
os.environ["LOOPX_RUNTIME_ROOT"] = str(target_a)
original_default = route_module.select_default_runtime_root
route_module.select_default_runtime_root = lambda: target_b
original_default = route_module.paths.DEFAULT_RUNTIME_ROOT
route_module.paths.DEFAULT_RUNTIME_ROOT = target_b
try:
ambiguous = record_operator_gate(
ambiguous_registry,
ambiguous_source,
sync_global=True,
)
finally:
route_module.select_default_runtime_root = original_default
route_module.paths.DEFAULT_RUNTIME_ROOT = original_default
if original_runtime is None:
os.environ.pop("LOOPX_RUNTIME_ROOT", None)
else:
Expand Down
2 changes: 1 addition & 1 deletion examples/core-control-plane-diagrams-smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def main() -> None:
assert "Core Pattern Map" in docs["interaction-catalog.md"]
assert "State Definitions" in docs["state-definitions.md"]
assert "Canonical State Bodies" in docs["state-definitions.md"]
assert "Derived Runtime States" in docs["state-definitions.md"]
assert "Runtime Decisions, Phases, And Read Conditions" in docs["state-definitions.md"]
assert "State Machines" in docs["state-machine.md"]
for section in (
"Todo Lifecycle Machine",
Expand Down
2 changes: 1 addition & 1 deletion examples/fresh-clone-quickstart-smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ def main() -> int:
assert "loopx-project.github.io/loopx/install.sh" in bootstrap["archive_fallback_install_command"], bootstrap
assert "loopx doctor" in bootstrap["install_repair_command"], bootstrap
assert (project / ".loopx" / "registry.json").is_file(), bootstrap
assert (project / ".codex" / "goals" / GOAL_ID / "ACTIVE_GOAL_STATE.md").is_file(), bootstrap
assert (project / ".loopx" / "goals" / GOAL_ID / "ACTIVE_GOAL_STATE.md").is_file(), bootstrap

registry = project / ".loopx" / "registry.json"
status = run_loopx("--registry", str(registry), "status", cwd=project, env=cli_env)
Expand Down
3 changes: 2 additions & 1 deletion examples/loopx-chat-actions-smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,8 @@ def assert_http_action_api(root: Path) -> None:
)
assert history_after_goal["goals"][0]["display_name"] == "New Goal", history_after_goal
assert new_goal["coordination"]["registered_agents"] == ["codex"], new_goal
new_state = state_path.parent.parent / "new-goal" / "ACTIVE_GOAL_STATE.md"
assert new_goal["state_file"] == ".loopx/goals/new-goal/ACTIVE_GOAL_STATE.md", new_goal
new_state = registry_path.parent.parent / new_goal["state_file"]
assert new_state.exists(), new_state
new_state_text = new_state.read_text(encoding="utf-8")
assert new_state_text.count("Verify the new Goal projection") == 1
Expand Down
4 changes: 3 additions & 1 deletion examples/multi-goal-same-repo-smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ def main() -> int:
assert "project_local_goal_state_not_detected" in external_map["residual_risks"], external_map

registry = json.loads(registry_path.read_text(encoding="utf-8"))
registry["goals"][2]["state_file"] = f".codex/goals/{MAIN_GOAL}/ACTIVE_GOAL_STATE.md"
registry["goals"][2]["state_file"] = next(
goal["state_file"] for goal in registry["goals"] if goal["id"] == MAIN_GOAL
)
registry_path.write_text(json.dumps(registry, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
duplicate_payload = run_cli(root, registry_path, "registry", check=False)
assert duplicate_payload["ok"] is False, duplicate_payload
Expand Down
3 changes: 2 additions & 1 deletion examples/project/bootstrap-force-preserve-todos-smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ def main() -> int:
with tempfile.TemporaryDirectory(prefix="loopx-bootstrap-preserve-") as tmp:
project = Path(tmp) / "project"
project.mkdir()
state_file = project / ".codex/goals/bootstrap-preserve-fixture/ACTIVE_GOAL_STATE.md"

initial = run_cli(
"bootstrap",
Expand All @@ -49,6 +48,8 @@ def main() -> int:
)
assert initial["ok"] is True, initial
assert initial["state_action"] == "created", initial
state_file = Path(initial["state_file"])
assert state_file == (project / ".loopx/goals/bootstrap-preserve-fixture/ACTIVE_GOAL_STATE.md").resolve()

todo_state = "# Active Goal State\n\n## Agent Todo\n\n- [ ] Preserve this during reconnect.\n"
state_file.write_text(todo_state, encoding="utf-8")
Expand Down
2 changes: 1 addition & 1 deletion loopx/chat_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from pathlib import Path
from typing import Any, Callable, Iterator

from .chat_activity import CodexActivitySteps
from .presentation.codex_activity import CodexActivitySteps
from .chat import (
CHAT_AGENT_RESPONSE_SCHEMA_VERSION,
CHAT_REVIEW_CLOSE_TAG,
Expand Down
4 changes: 4 additions & 0 deletions loopx/help_surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,10 @@ def register_command_reference(subparsers: argparse._SubParsersAction) -> None:
},
{"command": "loopx multi-agent", "purpose": "Launch visible role-scoped Codex TUI agents."},
{"command": "loopx canary", "purpose": "Plan or run catalog-informed smoke profiles."},
{
"command": "loopx performance-diagnosis --help",
"purpose": "Plan an explicit local capture or inspect an existing profile without executing or uploading it.",
},
{
"command": "loopx promotion-readiness",
"purpose": "Record release-scoped canary readiness evidence in the shared runtime ledger.",
Expand Down
5 changes: 5 additions & 0 deletions loopx/presentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ Python code that starts as a user-visible capability may keep a thin facade
under `loopx.capabilities.*`, but the reusable display implementation should
live here.

`codex_activity.py` projects Codex host items into redacted, owner-visible Turn
steps. It owns display normalization only; step completion does not establish
Goal acceptance or execution authority. The Chat adapter consumes this projection
without exposing a separate top-level module.

## Explore Result Layer

Only the display side of software-exploration topology belongs here:
Expand Down
File renamed without changes.
3 changes: 3 additions & 0 deletions man/loopx.1
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,9 @@ Launch visible role\-scoped Codex TUI agents.
\fBloopx canary\fR
Plan or run catalog\-informed smoke profiles.
.TP
\fBloopx performance\-diagnosis \-\-help\fR
Plan an explicit local capture or inspect an existing profile without executing or uploading it.
.TP
\fBloopx promotion\-readiness\fR
Record release\-scoped canary readiness evidence in the shared runtime ledger.
.TP
Expand Down
2 changes: 1 addition & 1 deletion tests/test_chat_activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import pytest
from pathlib import Path

from loopx.chat_activity import (
from loopx.presentation.codex_activity import (
COMMAND_VERBS,
REASONING_UPDATE_INTERVAL_SEC,
STEP_KINDS,
Expand Down
Loading