Skip to content

Commit 18b777c

Browse files
committed
Bump version to 0.2.35: stop auto-marking tasks done on workflow completion
Workflow completion no longer auto-transitions tasks to Done. Only an agent (via MCP tool) or human (via CLI) should mark tasks done after verifying the work actually landed. Failed workflows still auto-block.
1 parent 024fd83 commit 18b777c

5 files changed

Lines changed: 22 additions & 12 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/orchestrator-cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "orchestrator-cli"
3-
version = "0.2.34"
3+
version = "0.2.35"
44
edition = "2021"
55
license = "Elastic-2.0"
66

crates/orchestrator-cli/src/services/runtime/runtime_daemon/daemon_tick_executor.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,13 @@ impl DefaultProjectTickServices for CliProjectTickServices {
8585
let any_success = task_workflows
8686
.iter()
8787
.any(|w| matches!(w.status, WorkflowStatus::Completed | WorkflowStatus::Escalated));
88-
let new_status = if any_success { TaskStatus::Done } else { TaskStatus::Blocked };
89-
let _ = hub.tasks().set_status(&task.id, new_status, false).await;
90-
reconciled += 1;
88+
// Only auto-transition to Blocked on failure. Task completion is never
89+
// automatic — only an agent or human should mark a task done after
90+
// verifying the work actually landed.
91+
if !any_success {
92+
let _ = hub.tasks().set_status(&task.id, TaskStatus::Blocked, false).await;
93+
reconciled += 1;
94+
}
9195
}
9296
}
9397
Ok(reconciled)

crates/orchestrator-core/src/execution_projection.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ pub async fn project_task_execution_fact(hub: Arc<dyn ServiceHub>, _root: &str,
6767
match status {
6868
WorkflowStatus::Pending | WorkflowStatus::Running | WorkflowStatus::Paused => return,
6969
WorkflowStatus::Completed => {
70-
let _ = project_task_status(hub, task_id, TaskStatus::Done).await;
70+
// Workflow completion does not auto-mark the task done.
71+
// Only an agent or human should mark a task done after verifying
72+
// that the work actually landed (e.g. PR merged).
7173
return;
7274
}
7375
WorkflowStatus::Cancelled => {
@@ -79,7 +81,8 @@ pub async fn project_task_execution_fact(hub: Arc<dyn ServiceHub>, _root: &str,
7981
}
8082

8183
if fact.success {
82-
let _ = project_task_status(hub, task_id, TaskStatus::Done).await;
84+
// Successful execution does not auto-mark the task done.
85+
// Only an agent or human should mark a task done after verification.
8386
return;
8487
}
8588

@@ -210,7 +213,7 @@ mod tests {
210213
}
211214

212215
#[tokio::test]
213-
async fn project_execution_fact_uses_task_projector_for_subject_kind() {
216+
async fn project_execution_fact_does_not_auto_mark_task_done_on_success() {
214217
let hub = Arc::new(InMemoryServiceHub::new());
215218
upsert_task(&hub, "TASK-1", TaskStatus::Ready).await;
216219

@@ -232,11 +235,11 @@ mod tests {
232235

233236
assert!(projected);
234237
let updated = hub.tasks().get("TASK-1").await.expect("task should exist");
235-
assert_eq!(updated.status, TaskStatus::Done);
238+
assert_eq!(updated.status, TaskStatus::Ready, "task should NOT be auto-marked done");
236239
}
237240

238241
#[tokio::test]
239-
async fn project_execution_fact_preserves_legacy_task_fact_compatibility() {
242+
async fn project_execution_fact_does_not_auto_mark_done_for_legacy_facts() {
240243
let hub = Arc::new(InMemoryServiceHub::new());
241244
upsert_task(&hub, "TASK-2", TaskStatus::Ready).await;
242245

@@ -259,7 +262,7 @@ mod tests {
259262
assert!(projected);
260263
assert_eq!(execution_fact_subject_kind(&fact), Some(SUBJECT_KIND_TASK));
261264
let updated = hub.tasks().get("TASK-2").await.expect("task should exist");
262-
assert_eq!(updated.status, TaskStatus::Done);
265+
assert_eq!(updated.status, TaskStatus::Ready, "task should NOT be auto-marked done");
263266
}
264267

265268
#[tokio::test]

crates/orchestrator-core/src/execution_projection/project_task_terminal_workflow_status.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ pub async fn project_task_terminal_workflow_status(
2323

2424
match workflow_status {
2525
WorkflowStatus::Completed => {
26-
let _ = project_task_status(hub, task_id, TaskStatus::Done).await;
26+
// Task completion is intentionally NOT automatic.
27+
// Only an agent (via MCP tool) or a human (via CLI) should mark a task done
28+
// after verifying the work actually landed. Workflow completion means the
29+
// workflow ran — not that the task is finished.
2730
}
2831
WorkflowStatus::Failed | WorkflowStatus::Escalated => {
2932
let reason = failure_reason.unwrap_or_else(|| default_failure_reason(workflow_status));

0 commit comments

Comments
 (0)