Skip to content

Commit e9430cb

Browse files
authored
refactor(control-plane): render bootstrap steps through effect program (#2955)
1 parent 1a7cc56 commit e9430cb

3 files changed

Lines changed: 85 additions & 51 deletions

File tree

loopx/bootstrap_command_pack.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
ISSUE_FIX_GOAL_CANDIDATE_DISCOVERY_COMMAND_TEMPLATE,
1414
build_issue_fix_goal_command_templates,
1515
)
16+
from .control_plane.effect_program import effect_program_from_ordered_steps
1617
from .host_loop_activation import (
1718
agent_type_for_host_surface,
1819
build_host_loop_activation_packet,
@@ -1787,48 +1788,47 @@ def actionable_shell_command(value: Any) -> str:
17871788
commands = commands if isinstance(commands, dict) else {}
17881789
selected_route = transaction.get("selected_capability_route")
17891790
selected_route = selected_route if isinstance(selected_route, dict) else {}
1790-
steps = transaction.get("ordered_steps")
1791-
steps = steps if isinstance(steps, list) else []
1791+
ordered_steps = transaction.get("ordered_steps")
1792+
ordered_steps = ordered_steps if isinstance(ordered_steps, list) else []
1793+
program = effect_program_from_ordered_steps(ordered_steps)
17921794
step_lines: list[str] = []
1793-
for index, step in enumerate(steps, start=1):
1794-
if not isinstance(step, dict):
1795-
continue
1795+
for index, step in enumerate(program.steps, start=1):
1796+
raw_step = step.raw
17961797
command = (
1797-
step.get("command")
1798-
or step.get("command_template")
1799-
or step.get("command_source")
1800-
or step.get("prompt")
1798+
step.command
1799+
or raw_step.get("command_source")
1800+
or raw_step.get("prompt")
18011801
)
1802-
if step.get("kind") == "capability_guard":
1802+
if step.kind == "capability_guard":
18031803
entry_key = str(selected_route.get("entry_command_key") or "")
18041804
admission_key = str(selected_route.get("admission_command_key") or "")
18051805
entry_command = commands.get(entry_key)
18061806
admission_command = commands.get(admission_key)
1807-
discovery_command = step.get("candidate_discovery_command_template")
1807+
discovery_command = raw_step.get("candidate_discovery_command_template")
18081808
authority = (
18091809
"open public issue; source clues are evidence only"
1810-
if step.get("candidate_authority") == "public_open_tracker_issue"
1811-
else step.get("candidate_authority")
1810+
if raw_step.get("candidate_authority") == "public_open_tracker_issue"
1811+
else raw_step.get("candidate_authority")
18121812
)
18131813
step_lines.extend(
18141814
[
1815-
f"{index}. `{step.get('id')}` ({step.get('kind')})",
1815+
f"{index}. `{step.step_id}` ({step.kind})",
18161816
f" - authority: {authority}",
18171817
]
18181818
)
18191819
if discovery_command:
18201820
step_lines.append(
18211821
f" - discover: `{str(discovery_command).splitlines()[0]}`"
18221822
)
1823-
preflight = step.get("candidate_preflight")
1823+
preflight = raw_step.get("candidate_preflight")
18241824
if isinstance(preflight, dict):
18251825
required_evidence = " + ".join(
18261826
str(field)
18271827
for field in preflight.get("required_evidence_fields") or []
18281828
)
18291829
step_lines.append(
18301830
" - preflight: refresh "
1831-
f"{step.get('authority_refresh_required')}; "
1831+
f"{raw_step.get('authority_refresh_required')}; "
18321832
f"provide {required_evidence}; "
18331833
f"{preflight.get('decision_rule')}"
18341834
)
@@ -1839,12 +1839,12 @@ def actionable_shell_command(value: Any) -> str:
18391839
]
18401840
)
18411841
continue
1842-
step_label = f"{index}. `{step.get('id')}` ({step.get('kind')}): "
1843-
step_lines.append(step_label + str(step.get("purpose")))
1842+
step_label = f"{index}. `{step.step_id}` ({step.kind}): "
1843+
step_lines.append(step_label + str(step.purpose))
18441844
if command:
18451845
rendered_command = (
18461846
actionable_shell_command(command)
1847-
if step.get("id") == "connect_if_needed"
1847+
if step.step_id == "connect_if_needed"
18481848
else str(command).splitlines()[0]
18491849
)
18501850
step_lines.append(f" - command/source: `{rendered_command}`")

loopx/control_plane/effect_program.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class EffectStep:
5757
kind: str | None = None
5858
command: str | None = None
5959
purpose: str | None = None
60+
raw: Mapping[str, Any] = field(default_factory=dict)
6061

6162

6263
@dataclass(frozen=True)
@@ -94,6 +95,7 @@ def effect_program_from_ordered_steps(
9495
or None
9596
),
9697
purpose=str(step.get("purpose") or "") or None,
98+
raw=dict(step),
9799
)
98100
)
99101
return EffectProgram(

tests/control_plane/test_effect_program_ordered_steps.py

Lines changed: 64 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,47 @@
33
import json
44
from pathlib import Path
55

6-
from loopx.bootstrap_command_pack import build_start_goal_guided_packet
6+
from loopx.bootstrap_command_pack import (
7+
build_start_goal_guided_packet,
8+
render_start_goal_guided_markdown,
9+
)
710
from loopx.control_plane.effect_program import effect_program_from_ordered_steps
811

12+
GOAL_ID = "guided-program-goal"
13+
AGENT_ID = "codex-guided-program"
14+
15+
16+
def _write_connected_project(tmp_path: Path) -> Path:
17+
project = tmp_path / "project"
18+
state_file = project / ".codex" / "goals" / GOAL_ID / "ACTIVE_GOAL_STATE.md"
19+
state_file.parent.mkdir(parents=True)
20+
state_file.write_text("# Active Goal State\n", encoding="utf-8")
21+
registry = project / ".loopx" / "registry.json"
22+
registry.parent.mkdir(parents=True)
23+
registry.write_text(
24+
json.dumps(
25+
{
26+
"schema_version": "0.1",
27+
"goals": [
28+
{
29+
"id": GOAL_ID,
30+
"status": "active",
31+
"repo": str(project),
32+
"state_file": str(state_file.relative_to(project)),
33+
"coordination": {
34+
"agent_model": "peer_v1",
35+
"registered_agents": [AGENT_ID],
36+
},
37+
}
38+
],
39+
}
40+
)
41+
+ "\n",
42+
encoding="utf-8",
43+
)
44+
return project
45+
46+
947

1048
def test_ordered_steps_map_to_effect_program() -> None:
1149
steps = [
@@ -58,40 +96,12 @@ def test_ordered_steps_ignore_non_mapping_entries() -> None:
5896
def test_real_bootstrap_ordered_steps_map_to_effect_program(
5997
tmp_path: Path,
6098
) -> None:
61-
project = tmp_path / "project"
62-
state_file = (
63-
project / ".codex" / "goals" / "guided-program-goal" / "ACTIVE_GOAL_STATE.md"
64-
)
65-
state_file.parent.mkdir(parents=True)
66-
state_file.write_text("# Active Goal State\n", encoding="utf-8")
67-
registry = project / ".loopx" / "registry.json"
68-
registry.parent.mkdir(parents=True)
69-
registry.write_text(
70-
json.dumps(
71-
{
72-
"schema_version": "0.1",
73-
"goals": [
74-
{
75-
"id": "guided-program-goal",
76-
"status": "active",
77-
"repo": str(project),
78-
"state_file": str(state_file.relative_to(project)),
79-
"coordination": {
80-
"agent_model": "peer_v1",
81-
"registered_agents": ["codex-guided-program"],
82-
},
83-
}
84-
],
85-
}
86-
)
87-
+ "\n",
88-
encoding="utf-8",
89-
)
99+
project = _write_connected_project(tmp_path)
90100

91101
payload = build_start_goal_guided_packet(
92102
project=project,
93-
goal_id="guided-program-goal",
94-
agent_id="codex-guided-program",
103+
goal_id=GOAL_ID,
104+
agent_id=AGENT_ID,
95105
cli_bin="loopx",
96106
host_surface="codex-app",
97107
goal_text="Ship a bounded public issue triage workflow.",
@@ -108,3 +118,25 @@ def test_real_bootstrap_ordered_steps_map_to_effect_program(
108118
assert program.steps
109119
assert program.steps[0].step_id == "inspect_connection"
110120
assert program.steps[0].kind == "read_only"
121+
122+
123+
def test_start_goal_guided_render_consumes_effect_program(
124+
tmp_path: Path,
125+
) -> None:
126+
project = _write_connected_project(tmp_path)
127+
payload = build_start_goal_guided_packet(
128+
project=project,
129+
goal_id=GOAL_ID,
130+
agent_id=AGENT_ID,
131+
cli_bin="loopx",
132+
host_surface="codex-app",
133+
goal_text="Ship a bounded public issue triage workflow.",
134+
available_capabilities=["network"],
135+
include_command_pack_detail=False,
136+
)
137+
138+
rendered = render_start_goal_guided_markdown(payload)
139+
140+
assert "inspect_connection" in rendered
141+
assert "connect_if_needed" in rendered
142+
assert "quota_guard" in rendered

0 commit comments

Comments
 (0)