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
92 changes: 92 additions & 0 deletions examples/bootstrap-command-pack-smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,97 @@ def test_skill_slash_fallback_contract() -> None:
assert "The five sections are output structure, while the execution contract is the evidence authority" in pr_review_normalized


def test_start_goal_guided_derives_display_name_from_goal_text() -> None:
with tempfile.TemporaryDirectory() as tmp:
project = Path(tmp) / "display-name-project"
project.mkdir()
write_connected_goal_fixture(project, goal_id="display-goal", agent_id="codex-test-agent")

derived = run_json(
"start-goal",
"--guided",
"--project",
str(project),
"--goal-id",
"display-goal",
"--agent-id",
"codex-test-agent",
"--host-surface",
"codex-app",
"--goal-text",
"修复 scheduler state path 覆盖问题",
"--include-command-pack-detail",
)
connect_command = str(
derived["command_pack"]["commands"]["goal_start_connect_if_needed"]
)
assert "--display-name" not in connect_command, connect_command
assert derived["command_pack"].get("display_name") is None

run_json(
"bootstrap",
"--project",
str(project),
"--goal-id",
"derived-display-goal",
"--objective",
"修复 scheduler state path 覆盖问题",
"--no-onboarding-scan",
"--no-global-sync",
)
registry = json.loads(
(project / ".loopx" / "registry.json").read_text(encoding="utf-8")
)
registry_goal = next(
goal for goal in registry["goals"] if goal["id"] == "derived-display-goal"
)
assert registry_goal.get("display_name") == "修复 scheduler state path 覆盖问题"

explicit = run_json(
"start-goal",
"--guided",
"--project",
str(project),
"--goal-id",
"display-goal",
"--agent-id",
"codex-test-agent",
"--host-surface",
"codex-app",
"--goal-text",
"some objective",
"--display-name",
"Custom Title",
"--include-command-pack-detail",
)
explicit_command = str(
explicit["command_pack"]["commands"]["goal_start_connect_if_needed"]
)
assert "--display-name 'Custom Title'" in explicit_command, explicit_command
assert explicit["command_pack"].get("display_name") == "Custom Title"

rejected = run_json(
"start-goal",
"--guided",
"--project",
str(project),
"--goal-id",
"display-goal",
"--agent-id",
"codex-test-agent",
"--host-surface",
"codex-app",
"--goal-text",
"/private/secret/path should not leak",
"--include-command-pack-detail",
)
rejected_command = str(
rejected["command_pack"]["commands"]["goal_start_connect_if_needed"]
)
assert "--display-name" not in rejected_command, rejected_command
assert rejected["command_pack"].get("display_name") is None


def main() -> int:
test_missing_project_stops_before_mutation()
test_goal_text_invocation_plans_ranked_todos_before_activation()
Expand All @@ -730,6 +821,7 @@ def main() -> int:
test_connected_project_reuses_existing_state()
test_linked_git_worktree_reuses_canonical_source_registry()
test_skill_slash_fallback_contract()
test_start_goal_guided_derives_display_name_from_goal_text()
print("bootstrap command pack smoke passed")
return 0

Expand Down
7 changes: 7 additions & 0 deletions loopx/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from typing import Any

from .control_plane.runtime.time import now_local_iso
from .control_plane.runtime.public_safety import public_safe_compact_text
from .control_plane.todos.active_state_editing import (
TODO_SECTION_HEADINGS,
insertion_anchor,
Expand Down Expand Up @@ -76,6 +77,12 @@ def default_goal_id(project: Path) -> str:
return f"{slugify_goal_id(project.name)}-goal"


def derive_goal_display_name(goal_text: str | None) -> str | None:
"""Derive a public-safe display title from user-supplied goal text."""

return public_safe_compact_text(goal_text, limit=132)


def now_iso() -> str:
return now_local_iso()

Expand Down
60 changes: 27 additions & 33 deletions loopx/bootstrap_command_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
build_goal_start_contract,
build_goal_start_prompt,
)
from .control_plane.goals.start_goal_todo_delta import (
append_todo_delta_render_line,
existing_runnable_agent_frontier,
todo_authoring_steps,
)
from .control_plane.scheduler.execution_context import (
GUIDED_START_TURN_RUNTIME_PROFILES,
)
Expand All @@ -32,16 +37,13 @@
DEFAULT_HANDOFF_ADAPTER_STATUS,
render_available_capability_args,
render_cli_command_prefix,
render_goal_start_bootstrap_command,
render_optional_cli_arg,
render_quota_guard_command,
render_refresh_state_command,
shell_arg,
)
from .paths import resolve_runtime_root
from .control_plane.goals.start_goal_todo_delta import (
append_todo_delta_render_line,
existing_runnable_agent_frontier,
todo_authoring_steps,
)
from .registry import registry_goals, resolve_state_file
from .slash_commands import build_slash_command_catalog
from .thread_agent_binding import normalize_thread_id, resolve_thread_agent_binding
Expand Down Expand Up @@ -201,20 +203,21 @@


def _start_goal_command(
*,
project: str,
goal_id: str | None,
agent_id: str | None,
thread_id: str | None,
new_peer: bool,
cli_bin: str,
runtime_root: str | None = None,
host_surface: str,
goal_text: str,
available_capabilities: list[str] | None,
capability_route: str | None,
fine_grained: bool,
include_command_pack_detail: bool,
display_name: str | None = None,

Check warning on line 220 in loopx/bootstrap_command_pack.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Function "_start_goal_command" has 14 parameters, which is greater than the 13 authorized.

See more on https://sonarcloud.io/project/issues?id=huangruiteng_loopx&issues=AaBDF1joIw2TJI0zMmeO&open=AaBDF1joIw2TJI0zMmeO&pullRequest=3603
) -> str:
return (
f"{render_cli_command_prefix(cli_bin=cli_bin, runtime_root=runtime_root)} "
Expand All @@ -233,6 +236,7 @@
else ""
)
+ f" --goal-text {shell_arg(goal_text)}"
+ render_optional_cli_arg("--display-name", display_name)
+ (" --include-command-pack-detail" if include_command_pack_detail else "")
)

Expand All @@ -251,6 +255,7 @@
available_capabilities: list[str] | None,
capability_route: str | None,
fine_grained: bool,
display_name: str | None = None,
) -> str:
return _start_goal_command(
project=project,
Expand All @@ -266,6 +271,7 @@
capability_route=capability_route,
fine_grained=fine_grained,
include_command_pack_detail=True,
display_name=display_name,
)


Expand Down Expand Up @@ -326,6 +332,7 @@
capability_route: str | None = None,
fine_grained: bool = False,
include_command_pack_detail: bool = False,
display_name: str | None = None,
runtime_root_arg: str | None = None,
) -> dict[str, Any]:
"""Fail closed when the caller has not identified the current Codex host."""
Expand Down Expand Up @@ -378,6 +385,7 @@
else ""
)
+ f" --goal-text {shell_arg(normalized_goal_text)}"
+ render_optional_cli_arg("--display-name", display_name)
+ (" --include-command-pack-detail" if include_command_pack_detail else "")
)
choices.append(
Expand Down Expand Up @@ -406,6 +414,7 @@
"writes_now": False,
"spends_quota_now": False,
"goal_text": normalized_goal_text,
"display_name": display_name,
"blocked_by": "host_surface_selection",
"host_surface_selection_gate": gate,
"ordered_steps": [
Expand Down Expand Up @@ -435,6 +444,7 @@
"new_peer": new_peer,
"host_surface": None,
"goal_text": normalized_goal_text,
"display_name": display_name,
"host_surface_selection_gate": gate,
"recommended_next_step": {
"kind": "select_host_surface",
Expand Down Expand Up @@ -677,33 +687,6 @@
return "\n".join([f"cd {shell_arg(project)}", command])


def _goal_start_bootstrap_command(
*,
project: str,
goal_id: str,
goal_text: str | None,
cli_bin: str,
runtime_root: str | None,
fine_grained: bool,
) -> str:
objective = goal_text or "<exact /loopx goal text>"
lines = [
f"cd {shell_arg(project)}",
f"{render_cli_command_prefix(cli_bin=cli_bin, runtime_root=runtime_root)} bootstrap \\",
" --project . \\",
f" --goal-id {shell_arg(goal_id)} \\",
f" --objective {shell_arg(objective)} \\",
f" --adapter-kind {shell_arg(DEFAULT_HANDOFF_ADAPTER_KIND)} \\",
f" --adapter-status {shell_arg(DEFAULT_HANDOFF_ADAPTER_STATUS)} \\",
" --no-onboarding-scan \\",
" --codex-app-heartbeat ask",
]
if fine_grained:
lines[-1] += " \\"
lines.append(" --fine-grained")
return "\n".join(lines)


def _selected_goal_capability_route(
capability_route: str | None,
) -> dict[str, Any] | None:
Expand Down Expand Up @@ -754,20 +737,21 @@


def build_loopx_bootstrap_command_pack(
*,
project: Path,
goal_id: str | None,
agent_id: str | None,
cli_bin: str,
host_surface: str,
goal_text: str | None = None,
thread_id: str | None = None,
new_peer: bool = False,
available_capabilities: list[str] | None = None,
capability_route: str | None = None,
fine_grained: bool = False,
resolve_linked_worktree_alias: bool = True,
display_name: str | None = None,
runtime_root_arg: str | None = None,

Check warning on line 754 in loopx/bootstrap_command_pack.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Function "build_loopx_bootstrap_command_pack" has 14 parameters, which is greater than the 13 authorized.

See more on https://sonarcloud.io/project/issues?id=huangruiteng_loopx&issues=AaBDF1joIw2TJI0zMmeP&open=AaBDF1joIw2TJI0zMmeP&pullRequest=3603
) -> dict[str, Any]:
inspection = inspect_bootstrap_connection(
project,
Expand Down Expand Up @@ -893,13 +877,14 @@
runtime_root=command_runtime_root,
)
status_command = _project_command(resolved_project, f"{command_prefix} status")
goal_start_bootstrap_command = _goal_start_bootstrap_command(
goal_start_bootstrap_command = render_goal_start_bootstrap_command(
project=resolved_project,
goal_id=resolved_goal_id,
goal_text=normalized_goal_text,
cli_bin=cli_bin,
runtime_root=command_runtime_root,
fine_grained=fine_grained,
display_name=display_name,
)
goal_start_plan_prompt = build_goal_start_prompt(
goal_text=normalized_goal_text,
Expand Down Expand Up @@ -980,9 +965,11 @@
if normalized_goal_text
else ""
)
+ render_optional_cli_arg("--display-name", display_name)
),
"read_only": True,
"goal_text": normalized_goal_text,
"display_name": display_name,
"project": resolved_project,
"goal_id": resolved_goal_id,
"agent_id": selected_agent_id,
Expand Down Expand Up @@ -1122,6 +1109,7 @@
capability_route: str | None,
fine_grained: bool,
include_command_pack_detail: bool,
display_name: str | None = None,
) -> dict[str, Any] | None:
inspection = inspect_bootstrap_connection(
project,
Expand Down Expand Up @@ -1328,6 +1316,7 @@
available_capabilities=available_capabilities,
capability_route=capability_route,
fine_grained=fine_grained,
display_name=display_name,
)
selected_command_pack = (
command_pack
Expand Down Expand Up @@ -1383,20 +1372,21 @@


def build_start_goal_guided_packet(
*,
project: Path,
goal_id: str | None,
agent_id: str | None,
cli_bin: str,
host_surface: str,
goal_text: str,
thread_id: str | None = None,
new_peer: bool = False,
available_capabilities: list[str] | None = None,
capability_route: str | None = None,
fine_grained: bool = False,
include_command_pack_detail: bool = False,
display_name: str | None = None,
runtime_root_arg: str | None = None,

Check warning on line 1389 in loopx/bootstrap_command_pack.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Function "build_start_goal_guided_packet" has 14 parameters, which is greater than the 13 authorized.

See more on https://sonarcloud.io/project/issues?id=huangruiteng_loopx&issues=AaBDF1joIw2TJI0zMmeQ&open=AaBDF1joIw2TJI0zMmeQ&pullRequest=3603
) -> dict[str, Any]:
if goal_id is None:
selection_packet = _build_multi_goal_start_selection_packet(
Expand All @@ -1412,6 +1402,7 @@
capability_route=capability_route,
fine_grained=fine_grained,
include_command_pack_detail=include_command_pack_detail,
display_name=display_name,
)
if selection_packet is not None:
return selection_packet
Expand All @@ -1428,6 +1419,7 @@
capability_route=capability_route,
fine_grained=fine_grained,
resolve_linked_worktree_alias=False,
display_name=display_name,
runtime_root_arg=runtime_root_arg,
)
commands = command_pack.get("commands")
Expand All @@ -1451,6 +1443,7 @@
capability_route=capability_route,
fine_grained=fine_grained,
include_command_pack_detail=False,
display_name=str(command_pack.get("display_name") or display_name or ""),
)

fresh_registration = identity_selection_gate.get("fresh_agent_registration")
Expand Down Expand Up @@ -1702,6 +1695,7 @@
available_capabilities=available_capabilities,
capability_route=capability_route,
fine_grained=fine_grained,
display_name=str(command_pack.get("display_name") or display_name or ""),
)
selected_command_pack = (
command_pack
Expand Down
9 changes: 9 additions & 0 deletions loopx/cli_commands/bootstrap_connect.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
DEFAULT_DOMAIN,
DEFAULT_OBJECTIVE,
bootstrap_project,
derive_goal_display_name,
render_bootstrap_markdown,
)
PrintPayload = Callable[
Expand All @@ -29,6 +30,13 @@ def register_bootstrap_connect_command(subparsers: argparse._SubParsersAction) -
help="Create a new forked goal id instead of reusing an existing global goal route.",
)
bootstrap_parser.add_argument("--objective", default=DEFAULT_OBJECTIVE, help="Initial goal objective.")
bootstrap_parser.add_argument(
"--display-name",
help=(
"Public display title for the goal. When omitted, a public-safe title is "
"derived from the objective; the project name remains the fallback."
),
)
bootstrap_parser.add_argument("--domain", default=DEFAULT_DOMAIN, help="Goal domain label.")
bootstrap_parser.add_argument("--role", choices=["controller", "subagent"], default="controller")
bootstrap_parser.add_argument("--parent-goal-id", help="Parent goal id when --role subagent.")
Expand Down Expand Up @@ -195,6 +203,7 @@ def handle_bootstrap_connect_command(
runtime_root=runtime_root,
goal_id=goal_id,
objective=args.objective,
display_name=args.display_name or derive_goal_display_name(args.objective),
domain=args.domain,
role=args.role,
parent_goal_id=args.parent_goal_id,
Expand Down
Loading