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
2 changes: 1 addition & 1 deletion scripts/loopx.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ $isNativeSchedulerFollowup = (
$env:LOOPX_KUNLUNCODE_OUTER_CONTROLLER -ne "1"
)
if ($isNativeSchedulerFollowup) {
$node = Get-Command node -CommandType Application -ErrorAction SilentlyContinue
$node = Get-Command node -CommandType Application -ErrorAction SilentlyContinue | Select-Object -First 1
if ($null -eq $node) {
throw "Native scheduler follow-up requires Node.js 22.22.3 or newer"
}
Expand Down
15 changes: 14 additions & 1 deletion tests/capabilities/test_machine_configuration_goal_defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,10 +366,23 @@ def test_stride_version_inherits_as_one_review_configuration_and_rolls_back(tmp_
configure_goal(registry_path=registry_path, goal_id=GOAL_ID,
execution_stride_strategy="off", execute=True)
assert _history_goal(registry_path, runtime_root)["execution_profile"]["stride_strategy"] == "off"
clear_options = _goal_capability_options("todo_replan_cadence", None)
before = registry_path.read_bytes()
preview = configure_goal(registry_path=registry_path, goal_id=GOAL_ID, **clear_options)
assert preview["changed"] is True
assert registry_path.read_bytes() == before
configure_goal(registry_path=registry_path, goal_id=GOAL_ID,
clear_execution_replan_after_turns=True, execute=True)
execute=True, **clear_options)
assert "stride_strategy" not in json.loads(registry_path.read_text())["goals"][0]["execution_profile"]
assert _history_goal(registry_path, runtime_root)["execution_profile"]["stride_strategy"] == "evidence_conditioned_v1"
inspected = inspect_goal_capabilities(registry_path=registry_path, runtime_root=runtime_root,
goal_id=GOAL_ID)["configuration"]
review = next(item for item in inspected["capability_catalog"]["capabilities"]
if item["capability_id"] == "todo_replan_cadence")
assert "current" not in review
assert review["effective_configuration"]["source"] == "machine_default"
assert review["effective_configuration"]["inherited"] is True
assert _history_goal(registry_path, runtime_root)["execution_profile"]["replan_after_effective_turns"] == 6
# Unsupported versions fail before any registry mutation.
before = registry_path.read_bytes()
with pytest.raises(ValueError, match="stride_strategy"):
Expand Down
64 changes: 48 additions & 16 deletions tests/control_plane/test_scheduler_compat_state_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
import os
from pathlib import Path
import subprocess
import sys

import pytest

from examples.control_plane.quota_plan_fixtures import (
SCOPED_AGENT_ID,
write_cli_fixture,
write_codex_heartbeat_fixture,
)
from loopx.control_plane.quota.scheduler_ack import (
record_quota_scheduler_ack_for_decision,
Expand Down Expand Up @@ -43,8 +45,9 @@ def test_compat_followup_preserves_the_read_authority_through_public_entry_point
registry, runtime, project = write_cli_fixture(
tmp_path / "fixture", scoped_agents=True
)
monkeypatch.setenv("CODEX_HOME", str(tmp_path / "codex-home"))
monkeypatch.delenv("CODEX_THREAD_ID", raising=False)
codex_home = tmp_path / "codex-home"
monkeypatch.setenv("CODEX_HOME", str(codex_home))
monkeypatch.setenv("CODEX_THREAD_ID", "scheduler-fixture")
turn_id = "scheduler-compat-turn"

def guard() -> dict:
Expand Down Expand Up @@ -118,21 +121,50 @@ def guard() -> dict:
assert app["stateful_backoff"]["progression_index"] == 1
assert app["stateful_backoff"]["state_key"] == selected_key
hint = compat["ack_hint" if operation == "ack" else "failure_hint"]
if caller == "native_cli":
completed = subprocess.run(
[
str(REPO_ROOT / "scripts" / "loopx"),
"--format",
"json",
*hint["cli_args"],
],
cwd=project,
check=False,
capture_output=True,
text=True,
env={**os.environ, "LOOPX_PYTHON": str(tmp_path / "python-must-not-run")},
timeout=30,
if operation == "ack":
write_codex_heartbeat_fixture(
codex_home, goal_id=GOAL_ID, agent_id=SCOPED_AGENT_ID,
rrule="FREQ=MINUTELY;INTERVAL=60",
)
if caller == "native_cli":
def invoke_launcher() -> subprocess.CompletedProcess[str]:
return subprocess.run(
[str(REPO_ROOT / "scripts" / "loopx"), "--format", "json", *hint["cli_args"]],
cwd=project, check=False, capture_output=True, text=True,
env={**os.environ, "LOOPX_PYTHON": (
sys.executable if operation == "ack" else str(tmp_path / "python-must-not-run")
)},
timeout=30,
)

if operation == "ack":
# Current Host readback belongs to the Python entrypoint; failure
# hints still prove the exact native route with Python unavailable.
manifest = codex_home / "automations/scheduler-fixture/automation.toml"
selected_path = scheduler_state_path(
runtime, goal_id=GOAL_ID, agent_id=SCOPED_AGENT_ID, state_key=selected_key,
)
selected_bytes = selected_path.read_bytes()
for observed in (None, "FREQ=MINUTELY;INTERVAL=30"):
if observed is None:
manifest.unlink()
else:
write_codex_heartbeat_fixture(
codex_home, goal_id=GOAL_ID, agent_id=SCOPED_AGENT_ID, rrule=observed,
)
refused = invoke_launcher()
assert refused.returncode == 1, refused.stdout + refused.stderr
refused_result = json.loads(refused.stdout)
assert refused_result["scheduler_commit"]["reason_code"] == "rrule_mismatch"
assert refused_result["scheduler_commit"]["written"] is False
assert selected_path.read_bytes() == selected_bytes
if state_layout == "coexisting":
assert old_path.read_bytes() == old_bytes
write_codex_heartbeat_fixture(
codex_home, goal_id=GOAL_ID, agent_id=SCOPED_AGENT_ID,
rrule="FREQ=MINUTELY;INTERVAL=60",
)
completed = invoke_launcher()
assert completed.returncode == 0, completed.stdout + completed.stderr
result = json.loads(completed.stdout)
elif caller == "python_cli":
Expand Down
1 change: 1 addition & 0 deletions tests/test_chat_goal_configuration_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ def test_machine_inheritable_goal_capabilities_can_clear_their_overrides() -> No
assert _goal_capability_options("todo_replan_cadence", None) == {
"clear_execution_replan_after_todos": True,
"clear_execution_replan_after_turns": True,
"clear_execution_stride_strategy": True,
}
assert _goal_capability_options("change_quality_qualification", None) == {
"clear_change_quality_configuration": True
Expand Down
13 changes: 12 additions & 1 deletion tests/test_scheduler_native_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,20 @@ def test_receipt_bound_trae_hint_executes_native_without_python(

@pytest.mark.skipif(shutil.which("node") is None, reason="Node.js is required")
@pytest.mark.parametrize("launcher", ["unix", "powershell"])
@pytest.mark.parametrize("node_layout", ["single", "multiple"])
def test_receipt_bound_failure_hint_executes_native_without_python(
tmp_path: Path, launcher: str,
tmp_path: Path, monkeypatch, launcher: str, node_layout: str,
) -> None:
if node_layout == "multiple":
real_node = Path(shutil.which("node"))
later_bin = tmp_path / "later Node candidate"
later_bin.mkdir()
later_node = later_bin / real_node.name
later_node.write_text("This later PATH candidate must not execute.\n", encoding="utf-8")
later_node.chmod(0o755)
monkeypatch.setenv("PATH", os.pathsep.join([
str(real_node.parent), str(later_bin), os.environ.get("PATH", ""),
]))
registry_path, runtime_root, project = write_cli_fixture(
tmp_path / "fixture-failure",
scoped_agents=True,
Expand Down
Loading