From 29342f3918c16886865140a4c792f67df1137e09 Mon Sep 17 00:00:00 2001 From: santoshkumarradha Date: Mon, 20 Apr 2026 19:45:53 -0400 Subject: [PATCH] feat: surface post_condition symmetrically with pre_condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit post_condition was stored on tasks and emitted in JSON payloads but never shown in the text output an agent sees when claiming or completing a task. Only pre_condition printed on `go`, so agents had to opt into JSON mode to see their own acceptance criteria. Changes: - `plandb go` now prints post_condition as "post-condition (acceptance)" right after pre_condition. Symmetric with how pre is already handled. - `plandb done` missing-result hint now mentions post_condition so the agent knows a verifiable result is expected (previously only fired when downstream dependents existed). - The existing trailing echo of post_condition on done transition is preserved — it reads as a verification reminder. Zero schema change. Pure surfacing fix. JSON payload unchanged. Test: tests/functional_test.sh adds three assertions verifying the text-mode output on go/done. --- src/cli/task/commands.rs | 18 +++++++++++++++--- tests/functional_test.sh | 12 ++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/cli/task/commands.rs b/src/cli/task/commands.rs index a229ba2..e7f3ae7 100644 --- a/src/cli/task/commands.rs +++ b/src/cli/task/commands.rs @@ -877,6 +877,11 @@ pub fn go_cmd(db: &Database, args: &GoArgs, json: bool) -> Result<()> { eprintln!("pre-condition: {}", pre); } + if let Some(post) = response["task"]["post_condition"].as_str() { + eprintln!(); + eprintln!("post-condition (acceptance): {}", post); + } + // Concise action hints — just the essentials if !json { let ready = response["remaining"]["ready"].as_u64().unwrap_or(0); @@ -977,11 +982,18 @@ pub fn done_cmd(db: &Database, args: DoneArgs, json: bool, compact: bool) -> Res let has_downstream = list_dependencies(db, &task.id) .map(|deps| deps.iter().any(|d| d.from_task == task.id)) .unwrap_or(false); + let has_post_condition = task.post_condition.is_some(); - if !result_provided && has_downstream { + if !result_provided && (has_downstream || has_post_condition) { + let reason = match (has_downstream, has_post_condition) { + (true, true) => "task has downstream dependents and a post-condition", + (true, false) => "task has downstream dependents", + (false, true) => "task has a post-condition to verify", + _ => unreachable!(), + }; eprintln!( - "hint: this task has downstream dependents. Consider: plandb done {} --result ''", - task.id + "hint: {}. Consider: plandb done {} --result ''", + reason, task.id ); } diff --git a/tests/functional_test.sh b/tests/functional_test.sh index f64b8d9..3d4b56d 100755 --- a/tests/functional_test.sh +++ b/tests/functional_test.sh @@ -639,6 +639,18 @@ assert_eq "get returns post_condition" "all endpoints return JSON" "$(jq_field " PLAIN_TASK=$($PLANDB --db "$DB" --json task create --project "$PROJ_ID" "No Conditions") assert_eq "no pre_condition is empty" "" "$(jq_field "$PLAIN_TASK" "pre_condition")" +# Verify pre/post condition surfaces in go/done text output (not just JSON) +COND_PROJ=$($PLANDB --db "$DB" --json project create "conditions-surfacing") +COND_PROJ_ID=$(jq_field "$COND_PROJ" "id") +$PLANDB --db "$DB" --json task create --project "$COND_PROJ_ID" "Conditioned Go" --pre "env vars set" --post "result must include summary" >/dev/null +GO_TEXT=$($PLANDB --db "$DB" task go --project "$COND_PROJ_ID" --agent cond-agent 2>&1 || true) +assert_contains "go text output shows pre-condition" "pre-condition: env vars set" "$GO_TEXT" +assert_contains "go text output shows post-condition" "post-condition (acceptance): result must include summary" "$GO_TEXT" + +# done without --result on a task with post_condition should hint + echo acceptance criteria +DONE_HINT=$($PLANDB --db "$DB" task done --agent cond-agent 2>&1 || true) +assert_contains "done hints about post-condition when no result" "post-condition" "$DONE_HINT" + echo "" # ─────────────────────────────────────────────