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
13 changes: 13 additions & 0 deletions docs/reference/protocols/loopx-goal-command-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,19 @@ but the shape depends on how clear the goal already is:
concise todos to make the approach explicit, without arbitrary item-count
caps or management-only filler.

The shared `budget_policy` now explicitly asks for the minimum plan needed to
begin useful work: reuse covered Todos, identify the next executable step and its
decisive validation, and defer uncertain later work to replan. Diagnostic validation,
including permitted feedback, can be that first step before dependent implementation
to strengthen the first deliverable. The quality objective and diagnostic means
coexist: a diagnostic result does not replace the requested deliverable. Do not
require exhaustive upfront decomposition. This changes default
planning guidance for both `/loopx` and `todo plan`, in ordinary and fine-grained
mode; it adds no fixed step/time limit or permission to skip planning/readback,
task acceptance, quota admission or genuine blockers. The existing fine-grained
one-checkpoint rule and broad-goal lane suggestions still apply. Lightweight
planning does not mean early task completion or weaker delivery requirements.

The shared planner now includes `first_delivery_guidance`, also rendered in the
guided `/loopx` start prompt and the existing `todo plan` packet. This changes
default Agent guidance in both ordinary and fine-grained planning: preserve a
Expand Down
6 changes: 5 additions & 1 deletion loopx/control_plane/goals/start_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ def goal_planner_contract(*, fine_grained: bool = False) -> dict[str, Any]:
"default_task_class": "advancement_task",
"required_fields": ["priority", "text", "task_class", "action_kind"],
"public_safe_only": True,
"budget_policy": "minimum sufficient plan; no fixed-count filler",
"budget_policy": (
"minimum sufficient plan: next step and decisive validation; no fixed-count "
"filler or exhaustive decomposition. Diagnostics and feedback may come first "
"to strengthen delivery; replan uncertain later work."
),
"first_delivery_guidance": _FIRST_DELIVERY_GUIDANCE,
}
if fine_grained:
Expand Down
27 changes: 27 additions & 0 deletions tests/control_plane/test_task_planning.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,33 @@ def test_existing_plan_is_an_incremental_frontier_not_a_new_goal(bound_goal):
assert all(item["todo_id"] != "todo_peer" for item in packet["existing_todos"])


@pytest.mark.parametrize("fine_grained", [False, True])
def test_planning_scope_is_sufficient_to_start_without_exhaustive_decomposition(bound_goal, fine_grained):
registry = bound_goal["registry_path"]
contents = json.loads(registry.read_text())
if fine_grained:
contents["goals"][0]["execution_profile"] = {"turn_granularity": "fine"}
registry.write_text(json.dumps(contents))
packet = build_task_planning_packet(**bound_goal)
planner = packet["planner"]
assert planner == goal_planner_contract(fine_grained=fine_grained)
for clause in (
"minimum sufficient plan: next step and decisive validation",
"Diagnostics and feedback may come first to strengthen delivery",
"replan uncertain later work",
"no fixed-count filler or exhaustive decomposition",
):
assert clause in planner["budget_policy"]
assert planner["profiles"]["clear_bounded_problem"][
"may_reuse_current_todo_when_it_already_represents_the_plan"] is True
assert planner["required_before_todo_write"] is True
assert packet["execution_handoff"]["requires_quota_guard"] is True
assert packet["execution_handoff"]["planning_is_advancement"] is False
assert "do not substitute them for the requested deliverable" in planner["first_delivery_guidance"]
assert "existing acceptance, feedback and authority limits" in planner["first_delivery_guidance"]
assert planner.get("maximum_runnable_todos_written_ahead") == (1 if fine_grained else None)


def test_unknown_identity_rejected_without_creating_it(bound_goal):
with pytest.raises(ValueError, match="not registered"):
build_task_planning_packet(**(bound_goal | {"agent_id": "unknown"}))
Expand Down
Loading