Skip to content

Commit 2cd3f8d

Browse files
d4ncerclaude
andcommitted
feat(dag): add AutoTransition enum and refactor set_task_status return type
Change set_task_status() from Result<()> to Result<Vec<AutoTransition>> so callers can observe which auto-transitions fired (unblock, parent complete/fail, feature done/fail). Refactor all internal auto-transition functions, force_complete/fail/reset_task, and dag/mod.rs wrappers (complete_task, fail_task, retry_task) to propagate the new type. Fix existing gap in force_fail_task done→failed path which called auto_fail_parent but omitted auto_update_feature_on_fail. Add 4 tests verifying AutoTransition returns for unblock, parent complete, parent fail, and force_complete combined transitions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3fcbd4e commit 2cd3f8d

2 files changed

Lines changed: 254 additions & 62 deletions

File tree

src/dag/mod.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub use dependencies::{add_dependency, remove_dependency};
2929
pub use ids::{generate_and_insert_task_id, generate_feature_id, generate_task_id};
3030
#[allow(unused_imports)]
3131
pub use tasks::{compute_parent_status, get_task_status};
32-
pub use transitions::{force_complete_task, force_fail_task, force_reset_task};
32+
pub use transitions::{force_complete_task, force_fail_task, force_reset_task, AutoTransition};
3333

3434
/// A task in the DAG.
3535
#[derive(Debug, Clone, Serialize)]
@@ -195,7 +195,8 @@ pub fn get_task_counts(db: &Db) -> Result<TaskCounts> {
195195
/// Claim a task for execution by an agent.
196196
pub fn claim_task(db: &Db, task_id: &str, agent_id: &str) -> Result<()> {
197197
// Transition to in_progress and set claimed_by atomically
198-
transitions::set_task_status(db.conn(), task_id, "in_progress")?;
198+
// pending→in_progress produces no auto-transitions, so discard the vec
199+
let _transitions = transitions::set_task_status(db.conn(), task_id, "in_progress")?;
199200
db.conn().execute(
200201
"UPDATE tasks SET claimed_by = ? WHERE id = ?",
201202
rusqlite::params![agent_id, task_id],
@@ -204,19 +205,19 @@ pub fn claim_task(db: &Db, task_id: &str, agent_id: &str) -> Result<()> {
204205
}
205206

206207
/// Mark a task as completed.
207-
pub fn complete_task(db: &Db, task_id: &str) -> Result<()> {
208+
pub fn complete_task(db: &Db, task_id: &str) -> Result<Vec<AutoTransition>> {
208209
// Transition to done (auto-transitions handled in set_task_status)
209-
transitions::set_task_status(db.conn(), task_id, "done")?;
210+
let transitions = transitions::set_task_status(db.conn(), task_id, "done")?;
210211
// Clear claimed_by
211212
db.conn()
212213
.execute("UPDATE tasks SET claimed_by = NULL WHERE id = ?", [task_id])?;
213-
Ok(())
214+
Ok(transitions)
214215
}
215216

216217
/// Mark a task as failed.
217-
pub fn fail_task(db: &Db, task_id: &str, reason: &str) -> Result<()> {
218+
pub fn fail_task(db: &Db, task_id: &str, reason: &str) -> Result<Vec<AutoTransition>> {
218219
// Transition to failed (auto-transitions handled in set_task_status)
219-
transitions::set_task_status(db.conn(), task_id, "failed")?;
220+
let transitions = transitions::set_task_status(db.conn(), task_id, "failed")?;
220221
// Clear claimed_by
221222
db.conn()
222223
.execute("UPDATE tasks SET claimed_by = NULL WHERE id = ?", [task_id])?;
@@ -226,7 +227,7 @@ pub fn fail_task(db: &Db, task_id: &str, reason: &str) -> Result<()> {
226227
"INSERT INTO task_logs (task_id, message, timestamp) VALUES (?, ?, ?)",
227228
rusqlite::params![task_id, reason, timestamp],
228229
)?;
229-
Ok(())
230+
Ok(transitions)
230231
}
231232

232233
/// Check if all DAG tasks are resolved (done or failed).
@@ -322,15 +323,15 @@ pub fn get_feature_task_counts(db: &Db, feature_id: &str) -> Result<TaskCounts>
322323
}
323324

324325
/// Retry a failed task: transition back to pending and increment retry_count.
325-
pub fn retry_task(db: &Db, task_id: &str) -> Result<()> {
326-
// Transition failed -> pending
327-
transitions::set_task_status(db.conn(), task_id, "pending")?;
326+
pub fn retry_task(db: &Db, task_id: &str) -> Result<Vec<AutoTransition>> {
327+
// Transition failed -> pending (typically produces no auto-transitions)
328+
let transitions = transitions::set_task_status(db.conn(), task_id, "pending")?;
328329
// Increment retry_count and set verification_status to failed
329330
db.conn().execute(
330331
"UPDATE tasks SET retry_count = retry_count + 1, verification_status = 'failed', claimed_by = NULL WHERE id = ?",
331332
[task_id],
332333
)?;
333-
Ok(())
334+
Ok(transitions)
334335
}
335336

336337
/// Release the claim on a task (set to pending if in_progress).
@@ -343,7 +344,8 @@ pub fn release_claim(db: &Db, task_id: &str) -> Result<()> {
343344
})?;
344345

345346
if status == "in_progress" {
346-
transitions::set_task_status(db.conn(), task_id, "pending")?;
347+
// in_progress→pending produces no auto-transitions, so discard the vec
348+
let _transitions = transitions::set_task_status(db.conn(), task_id, "pending")?;
347349
db.conn()
348350
.execute("UPDATE tasks SET claimed_by = NULL WHERE id = ?", [task_id])?;
349351
}

0 commit comments

Comments
 (0)