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
6 changes: 3 additions & 3 deletions src-tauri/src/core/agent_session_execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1021,17 +1021,17 @@ impl AgentSession {
// meets the quality contract enforced by the system prompt.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review completed for this PR diff. No concrete inline issue was selected after aggregation.

if artifact.title == "Implementation Plan" {
return agent_error_result(
"update_plan requires a non-empty title that describes the change (not the default placeholder).",
"update_plan failed: missing a real \"title\". Pass all required fields as non-empty top-level arguments: title, summary, context, design, keyImplementation, steps, verification, risks. Minimal example: {\"title\": \"Add X to Y\", \"summary\": \"...\", \"context\": \"...\", \"design\": \"...\", \"keyImplementation\": \"...\", \"steps\": [\"...\"], \"verification\": \"...\", \"risks\": [\"...\"]}.",
);
}
if artifact.context.trim().is_empty() {
return agent_error_result(
"update_plan requires a non-empty context section. Describe the current state of the relevant code with inspected file paths and confirmed facts.",
"update_plan failed: \"context\" is empty. Provide a non-empty top-level \"context\" string describing the current state of the relevant code with inspected file paths and confirmed facts.",
);
}
if artifact.design.trim().is_empty() {
return agent_error_result(
"update_plan requires a non-empty design section. Explain the recommended approach, architecture changes, data flow, and tradeoffs.",
"update_plan failed: \"design\" is empty. Provide a non-empty top-level \"design\" string explaining the recommended approach, architecture changes, data flow, and tradeoffs.",
);
}

Expand Down
35 changes: 27 additions & 8 deletions src-tauri/src/core/agent_session_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1944,14 +1944,33 @@ Used for prompt assembly coverage.
assert!(properties.contains_key("verification"));
assert!(properties.contains_key("assumptions"));

let nested_plan_properties = update_plan.parameters["properties"]["plan"]["properties"]
.as_object()
.expect("nested plan properties should be object");
assert!(nested_plan_properties.contains_key("context"));
assert!(nested_plan_properties.contains_key("design"));
assert!(nested_plan_properties.contains_key("keyImplementation"));
assert!(nested_plan_properties.contains_key("verification"));
assert!(nested_plan_properties.contains_key("assumptions"));
assert!(
!properties.contains_key("plan"),
"update_plan should no longer expose a nested plan object"
);

let required = update_plan.parameters["required"]
.as_array()
.expect("update_plan required should be an array");
let required: Vec<&str> = required
.iter()
.filter_map(serde_json::Value::as_str)
.collect();
for field in [
"title",
"summary",
"context",
"design",
"keyImplementation",
"steps",
"verification",
"risks",
] {
assert!(
required.contains(&field),
"update_plan required should contain {field}"
);
}
}

#[test]
Expand Down
54 changes: 12 additions & 42 deletions src-tauri/src/core/agent_session_tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ Phase 4 — Call update_plan:\n\
- risks: main risks, edge cases, compatibility concerns, regression areas.\n\
- assumptions (optional): only non-blocking assumptions, not open questions.\n\n\
Prohibited: unresolved core ambiguities (use clarify first), TODO placeholders, vague steps, architecture guesses not backed by exploration, lengthy background essays without actionable information.\n\n\
All required fields (title, summary, context, design, keyImplementation, steps, verification, risks) must be passed as non-empty top-level arguments. Do not wrap them in a nested object and never call this tool with empty arguments.\n\n\
You may call this tool multiple times in a run to incrementally refine the plan. Each call overwrites the previous version.",
serde_json::json!({
"type": "object",
Expand Down Expand Up @@ -310,49 +311,18 @@ You may call this tool multiple times in a run to incrementally refine the plan.
"assumptions": {
"type": "array",
"items": { "type": "string" }
},
"plan": {
"type": "object",
"description": "Optional nested plan payload. If provided, the runtime reads planning fields from this object.",
"properties": {
"title": { "type": "string" },
"summary": { "type": "string" },
"context": { "type": "string" },
"design": { "type": "string" },
"keyImplementation": { "type": "string" },
"steps": {
"type": "array",
"items": {
"oneOf": [
{ "type": "string" },
{
"type": "object",
"properties": {
"id": { "type": "string" },
"title": { "type": "string" },
"description": { "type": "string" },
"status": { "type": "string" },
"files": {
"type": "array",
"items": { "type": "string" }
}
}
}
]
}
},
"verification": { "type": "string" },
"risks": {
"type": "array",
"items": { "type": "string" }
},
"assumptions": {
"type": "array",
"items": { "type": "string" }
}
}
}
}
},
"required": [
"title",
"summary",
"context",
"design",
"keyImplementation",
"steps",
"verification",
"risks"
]
}),
),
];
Expand Down
5 changes: 1 addition & 4 deletions src-tauri/src/core/plan_checkpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,7 @@ pub fn build_plan_artifact_from_tool_input(
tool_input: &serde_json::Value,
plan_revision: u32,
) -> PlanArtifact {
let root = tool_input
.get("plan")
.and_then(serde_json::Value::as_object)
.or_else(|| tool_input.as_object());
let root = tool_input.as_object();

let title = root
.and_then(|value| value.get("title"))
Expand Down
Loading