TaskManager

Struct TaskManager 

Source
pub struct TaskManager<'a> { /* private fields */ }

Implementations§

Source§

impl<'a> TaskManager<'a>

Source

pub fn new(pool: &'a SqlitePool) -> Self

Source

pub fn with_project_path(pool: &'a SqlitePool, project_path: String) -> Self

Create a TaskManager with project path for CLI notifications

Source

pub fn with_websocket( pool: &'a SqlitePool, ws_state: Arc<WebSocketState>, project_path: String, ) -> Self

Create a TaskManager with WebSocket notification support

Source

pub async fn add_task( &self, name: &str, spec: Option<&str>, parent_id: Option<i64>, owner: Option<&str>, ) -> Result<Task>

Add a new task owner: ‘human’ (created via CLI/Dashboard) or ‘ai’ (created via MCP)

Source

pub async fn create_task_in_tx( &self, tx: &mut Transaction<'_, Sqlite>, name: &str, spec: Option<&str>, priority: Option<i32>, status: Option<&str>, active_form: Option<&str>, owner: &str, ) -> Result<i64>

Create a task within a transaction (no notification)

This is used by PlanExecutor for batch operations where:

  • Multiple tasks need atomic creation
  • Notification should happen after all tasks are committed
§Arguments
  • tx - The active transaction
  • name - Task name
  • spec - Optional task specification
  • priority - Optional priority (1=critical, 2=high, 3=medium, 4=low)
  • status - Optional status string (“todo”, “doing”, “done”)
  • active_form - Optional active form description
  • owner - Task owner (“human” or “ai”)
§Returns

The ID of the created task

Source

pub async fn update_task_in_tx( &self, tx: &mut Transaction<'_, Sqlite>, task_id: i64, spec: Option<&str>, priority: Option<i32>, status: Option<&str>, active_form: Option<&str>, ) -> Result<()>

Update a task within a transaction (no notification)

Only updates fields that are Some - supports partial updates. Does NOT update name (used for identity) or timestamps.

§Arguments
  • tx - The active transaction
  • task_id - ID of the task to update
  • spec - New spec (if Some)
  • priority - New priority (if Some)
  • status - New status (if Some)
  • active_form - New active form (if Some)
Source

pub async fn set_parent_in_tx( &self, tx: &mut Transaction<'_, Sqlite>, task_id: i64, parent_id: i64, ) -> Result<()>

Set parent_id for a task within a transaction (no notification)

Used to establish parent-child relationships after tasks are created.

Source

pub async fn clear_parent_in_tx( &self, tx: &mut Transaction<'_, Sqlite>, task_id: i64, ) -> Result<()>

Clear parent_id for a task in a transaction (make it a root task)

Used when explicitly setting parent_id to null in JSON.

Source

pub async fn count_incomplete_children_in_tx( &self, tx: &mut Transaction<'_, Sqlite>, task_id: i64, ) -> Result<i64>

Count incomplete children of a task within a transaction

Returns the number of child tasks that are not in ‘done’ status. Used to validate that all children are complete before marking parent as done.

Source

pub async fn complete_task_in_tx( &self, tx: &mut Transaction<'_, Sqlite>, task_id: i64, ) -> Result<()>

Complete a task within a transaction (core business logic)

This is the single source of truth for task completion logic:

  • Validates all children are complete
  • Updates status to ‘done’
  • Sets first_done_at timestamp

Called by both done_task() and PlanExecutor.

Source

pub async fn notify_batch_changed(&self)

Notify Dashboard about a batch operation

Call this after committing a transaction that created/updated multiple tasks. Sends a single “batch_update” notification instead of per-task notifications.

Source

pub async fn get_task(&self, id: i64) -> Result<Task>

Get a task by ID

Source

pub async fn get_task_with_events(&self, id: i64) -> Result<TaskWithEvents>

Get a task with events summary

Source

pub async fn get_task_ancestry(&self, task_id: i64) -> Result<Vec<Task>>

Get full ancestry chain for a task

Returns a vector of tasks from the given task up to the root: [task itself, parent, grandparent, …, root]

Example:

  • Task 42 (parent_id: 55) → [Task 42, Task 55, …]
  • Task 100 (parent_id: null) → [Task 100]
Source

pub async fn get_task_context(&self, id: i64) -> Result<TaskContext>

Get task context - the complete family tree of a task

Returns:

  • task: The requested task
  • ancestors: Parent chain up to root (ordered from immediate parent to root)
  • siblings: Other tasks at the same level (same parent_id)
  • children: Direct subtasks of this task
Source

pub async fn get_descendants(&self, task_id: i64) -> Result<Vec<Task>>

Get all descendants of a task recursively (children, grandchildren, etc.) Uses recursive CTE for efficient querying

Source

pub async fn get_status( &self, task_id: i64, with_events: bool, ) -> Result<StatusResponse>

Get status response for a task (the “spotlight” view) This is the main method for ie status command

Source

pub async fn get_root_tasks(&self) -> Result<Vec<Task>>

Get root tasks (tasks with no parent) for NoFocusResponse

Source

pub async fn update_task( &self, id: i64, name: Option<&str>, spec: Option<&str>, parent_id: Option<Option<i64>>, status: Option<&str>, complexity: Option<i32>, priority: Option<i32>, ) -> Result<Task>

Update a task

Source

pub async fn delete_task(&self, id: i64) -> Result<()>

Delete a task

Source

pub async fn find_tasks( &self, status: Option<&str>, parent_id: Option<Option<i64>>, sort_by: Option<TaskSortBy>, limit: Option<i64>, offset: Option<i64>, ) -> Result<PaginatedTasks>

Find tasks with optional filters, sorting, and pagination

Source

pub async fn get_stats(&self) -> Result<WorkspaceStats>

Get workspace statistics using SQL aggregation (no data loading)

This is much more efficient than loading all tasks just to count them. Used by session restore when there’s no focused task.

Source

pub async fn start_task( &self, id: i64, with_events: bool, ) -> Result<TaskWithEvents>

Start a task (atomic: update status + set current)

Source

pub async fn done_task(&self, is_ai_caller: bool) -> Result<DoneTaskResponse>

Complete the current focused task (atomic: check children + update status + clear current) This command only operates on the current_task_id. Prerequisites: A task must be set as current

§Arguments
  • is_ai_caller - Whether this is called from AI (MCP) or human (CLI/Dashboard). When true and task is human-owned, the operation will fail. Human tasks can only be completed via CLI or Dashboard.
Source

pub async fn spawn_subtask( &self, name: &str, spec: Option<&str>, ) -> Result<SpawnSubtaskResponse>

Create a subtask under the current task and switch to it (atomic operation) Returns error if there is no current task Returns response with subtask info and parent task info

Source

pub async fn pick_next_tasks( &self, max_count: usize, capacity_limit: usize, ) -> Result<Vec<Task>>

Intelligently pick tasks from ‘todo’ and transition them to ‘doing’ Returns tasks that were successfully transitioned

§Arguments
  • max_count - Maximum number of tasks to pick
  • capacity_limit - Maximum total number of tasks allowed in ‘doing’ status
§Logic
  1. Check current ‘doing’ task count
  2. Calculate available capacity
  3. Select tasks from ‘todo’ (prioritized by: priority DESC, complexity ASC)
  4. Transition selected tasks to ‘doing’
Source

pub async fn pick_next(&self) -> Result<PickNextResponse>

Intelligently recommend the next task to work on based on context-aware priority model.

Priority logic:

  1. First priority: Subtasks of the current focused task (depth-first)
  2. Second priority: Top-level tasks (breadth-first)
  3. No recommendation: Return appropriate empty state

This command does NOT modify task status.

Auto Trait Implementations§

§

impl<'a> Freeze for TaskManager<'a>

§

impl<'a> !RefUnwindSafe for TaskManager<'a>

§

impl<'a> Send for TaskManager<'a>

§

impl<'a> Sync for TaskManager<'a>

§

impl<'a> Unpin for TaskManager<'a>

§

impl<'a> !UnwindSafe for TaskManager<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,