---
id: STATE-CRM-ACT-002
title: Task status lifecycle
object: DOM-CRM-ACT-003
product_area: crm
module: activities-tasks
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
states:
  - name: open
    meaning: Work is outstanding; creation and reopening choose this status.
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts'
  - name: waiting_for_someone_else
    meaning: Work remains outstanding while another person’s contribution is awaited.
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts'
  - name: deferred
    meaning: Work remains outstanding but has been postponed.
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts'
  - name: completed
    meaning: >-
      The work has finished with completion actor and time recorded; ordinary edits are
      closed.
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts'
  - name: cancelled
    meaning: >-
      The work has been stopped with cancellation actor and time recorded; ordinary edits
      are closed.
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts'
  - name: deleted
    meaning: 'No live task remains, and this module provides no task revision history.'
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts'
transitions:
  - from: open
    to: waiting_for_someone_else
    trigger: An ordinary edit selects another unfinished-work status.
    guard: 'The task is unfinished, updates are unlocked and the read version matches.'
    side_effects:
      - Enabled attention refreshes an overdue item within the task transaction.
    who: A caller authorized to update tasks.
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/unit/services/tasks/lifecycle.spec.js#allows an
      open task to move to any of the three open statuses
  - from: waiting_for_someone_else
    to: deferred
    trigger: An ordinary edit selects another unfinished-work status.
    guard: 'The task is unfinished, updates are unlocked and the read version matches.'
    side_effects:
      - Enabled attention refreshes an overdue item within the task transaction.
    who: A caller authorized to update tasks.
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/unit/services/tasks/lifecycle.spec.js#allows an
      open task to move to any of the three open statuses
  - from: deferred
    to: open
    trigger: An ordinary edit selects another unfinished-work status.
    guard: 'The task is unfinished, updates are unlocked and the read version matches.'
    side_effects:
      - Enabled attention refreshes an overdue item within the task transaction.
    who: A caller authorized to update tasks.
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/unit/services/tasks/lifecycle.spec.js#allows an
      open task to move to any of the three open statuses
  - from: open
    to: completed
    trigger: The dedicated completion action is invoked.
    guard: >-
      Updates are unlocked and the task is unfinished; the public action also requires the
      current read version.
    side_effects:
      - The completion actor and instant are recorded while routing is retained.
      - Enabled attention resolves an overdue item as completed in the same transaction.
    who: >-
      A caller authorized to update tasks, or the workflow service acting through its
      service route.
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/e2e/tasks.e2e.spec.js#completes the task, stamping
      who finished it and when
  - from: open
    to: cancelled
    trigger: The dedicated cancellation action is invoked.
    guard: >-
      Updates are unlocked and the task is unfinished; the public action also requires the
      current read version.
    side_effects:
      - The cancellation actor and instant are recorded while routing is retained.
      - Enabled attention resolves an overdue item as cancelled in the same transaction.
    who: >-
      A caller authorized to update tasks, or the workflow service acting through its
      service route.
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts:closeTask'
  - from: waiting_for_someone_else
    to: completed
    trigger: The dedicated completion action is invoked.
    guard: >-
      Updates are unlocked and the task is unfinished; the public action also requires the
      current read version.
    side_effects:
      - The completion actor and instant are recorded while routing is retained.
      - Enabled attention resolves an overdue item as completed in the same transaction.
    who: >-
      A caller authorized to update tasks, or the workflow service acting through its
      service route.
    provenance: observed
    source: 'services-crm:modules/tasks/services/tasks/lifecycle.ts:taskTransitionRefusal'
  - from: deferred
    to: cancelled
    trigger: The dedicated cancellation action is invoked.
    guard: >-
      Updates are unlocked and the task is unfinished; the public action also requires the
      current read version.
    side_effects:
      - The cancellation actor and instant are recorded while routing is retained.
      - Enabled attention resolves an overdue item as cancelled in the same transaction.
    who: >-
      A caller authorized to update tasks, or the workflow service acting through its
      service route.
    provenance: observed
    source: 'services-crm:modules/tasks/services/tasks/lifecycle.ts:taskTransitionRefusal'
  - from: completed
    to: open
    trigger: The dedicated reopening action is invoked.
    guard: 'The task is closed, updates are unlocked and the required read version matches.'
    side_effects:
      - >-
        Both closing stamp pairs are cleared and the status becomes Open regardless of the
        earlier unfinished status.
      - Enabled attention publishes again if the reopened work is overdue.
    who: A caller authorized to update tasks.
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/integration/services/persistence/tasks.integration.spec.js#reopens
      it as open, whatever status it was in before it closed
  - from: cancelled
    to: open
    trigger: The dedicated reopening action is invoked.
    guard: 'The task is closed, updates are unlocked and the required read version matches.'
    side_effects:
      - >-
        Both closing stamp pairs are cleared and the status becomes Open regardless of the
        earlier unfinished status.
      - Enabled attention publishes again if the reopened work is overdue.
    who: A caller authorized to update tasks.
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts:reopenTask'
  - from: open
    to: deleted
    trigger: A caller requests task deletion.
    guard: Neither supported lock is set; deletion accepts no read version.
    side_effects:
      - >-
        The task row is removed; enabled attention resolves any overdue item within the
        deletion transaction.
    who: A caller authorized to delete tasks; the console supplies no deletion command.
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/e2e/tasks.e2e.spec.js#refuses deleting a task
      locked against deletes
  - from: completed
    to: deleted
    trigger: A caller requests task deletion.
    guard: Neither supported lock is set; deletion accepts no read version.
    side_effects:
      - >-
        The task row is removed; enabled attention resolves any overdue item within the
        deletion transaction.
    who: A caller authorized to delete tasks; the console supplies no deletion command.
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts:deleteTask'
  - from: open
    to: deferred
    trigger: An ordinary edit selects another unfinished-work status.
    guard: 'The task is unfinished, updates are unlocked and the read version matches.'
    side_effects:
      - Enabled attention refreshes an overdue item within the task transaction.
    who: A caller authorized to update tasks.
    provenance: observed
    source: 'services-crm:modules/tasks/services/tasks/lifecycle.ts:taskTransitionRefusal'
  - from: waiting_for_someone_else
    to: open
    trigger: An ordinary edit selects another unfinished-work status.
    guard: 'The task is unfinished, updates are unlocked and the read version matches.'
    side_effects:
      - Enabled attention refreshes an overdue item within the task transaction.
    who: A caller authorized to update tasks.
    provenance: observed
    source: 'services-crm:modules/tasks/services/tasks/lifecycle.ts:taskTransitionRefusal'
  - from: deferred
    to: waiting_for_someone_else
    trigger: An ordinary edit selects another unfinished-work status.
    guard: 'The task is unfinished, updates are unlocked and the read version matches.'
    side_effects:
      - Enabled attention refreshes an overdue item within the task transaction.
    who: A caller authorized to update tasks.
    provenance: observed
    source: 'services-crm:modules/tasks/services/tasks/lifecycle.ts:taskTransitionRefusal'
  - from: waiting_for_someone_else
    to: cancelled
    trigger: The dedicated cancellation action is invoked.
    guard: >-
      Updates are unlocked and the task is unfinished; the public action also requires the
      current read version.
    side_effects:
      - The cancellation actor and instant are recorded while routing is retained.
      - Enabled attention resolves an overdue item as cancelled in the same transaction.
    who: >-
      A caller authorized to update tasks, or the workflow service acting through its
      service route.
    provenance: observed
    source: 'services-crm:modules/tasks/services/tasks/lifecycle.ts:taskTransitionRefusal'
  - from: deferred
    to: completed
    trigger: The dedicated completion action is invoked.
    guard: >-
      Updates are unlocked and the task is unfinished; the public action also requires the
      current read version.
    side_effects:
      - The completion actor and instant are recorded while routing is retained.
      - Enabled attention resolves an overdue item as completed in the same transaction.
    who: >-
      A caller authorized to update tasks, or the workflow service acting through its
      service route.
    provenance: observed
    source: 'services-crm:modules/tasks/services/tasks/lifecycle.ts:taskTransitionRefusal'
  - from: waiting_for_someone_else
    to: deleted
    trigger: A caller requests task deletion.
    guard: Neither supported lock is set; deletion accepts no read version.
    side_effects:
      - >-
        The task row is removed; enabled attention resolves any overdue item within the
        deletion transaction.
    who: A caller authorized to delete tasks; the console supplies no deletion command.
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts:deleteTask'
  - from: deferred
    to: deleted
    trigger: A caller requests task deletion.
    guard: Neither supported lock is set; deletion accepts no read version.
    side_effects:
      - >-
        The task row is removed; enabled attention resolves any overdue item within the
        deletion transaction.
    who: A caller authorized to delete tasks; the console supplies no deletion command.
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts:deleteTask'
  - from: cancelled
    to: deleted
    trigger: A caller requests task deletion.
    guard: Neither supported lock is set; deletion accepts no read version.
    side_effects:
      - >-
        The task row is removed; enabled attention resolves any overdue item within the
        deletion transaction.
    who: A caller authorized to delete tasks; the console supplies no deletion command.
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts:deleteTask'
invalid:
  - from: completed
    to: cancelled
    why: Changing one closed outcome to another requires reopening first.
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts'
  - from: cancelled
    to: completed
    why: >-
      Changing one closed outcome to another requires reopening first; a workflow request
      receives the closed-otherwise refusal.
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts'
  - from: completed
    to: completed
    why: >-
      A public repeat completion is refused. A workflow repeat instead returns a task
      already in the requested status unchanged.
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts'
  - from: open
    to: open
    why: Reopening is limited to work currently Completed or Cancelled.
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts'
  - from: completed
    to: deferred
    why: >-
      A closed task rejects ordinary edits, including requests with unchanged values;
      reopen it before editing.
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts'
  - from: open
    to: completed
    why: >-
      Ordinary edits and creation cannot select a closed status. The service directs
      callers to the appropriate closing action.
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts'
concurrency: >-
  Lifecycle writes lock the task before evaluating its current status. Public actions
  compare the supplied version, so competing completion and cancellation requests cannot
  both commit from the same read. Workflow requests omit that version and return an
  already-satisfied closing request unchanged before applying write restrictions.
invariants:
  - INV-DOM-CRM-ACT-003-02
  - INV-DOM-CRM-ACT-003-10
  - INV-DOM-CRM-ACT-003-12
evidence:
  - >-
    services-crm at a8d1364f: modules/tasks/services/tasks/lifecycle.ts (the transition
    table); services/persistence/tasks.ts (closeTask, updateTask, deleteTask,
    CLOSING_OUTCOMES); db/tasks.table.ts (tasks_completion_check,
    tasks_cancellation_check); docs/migrations/task-management/README.md §4;
    docs/milestones/CRM-M8-activities-and-tasks.md (D-52).
  - >-
    react-console at baf6dae3: lib/api/tasks.ts (transition sends the version read);
    components/tasks/task-detail-sheet.tsx (closed tasks disable every field).
---

# Task Status Lifecycle

## The Lifecycle

```mermaid
stateDiagram-v2
  open --> waiting_for_someone_else: save progress
  waiting_for_someone_else --> deferred: save progress
  deferred --> open: save progress
  open --> completed: close
  open --> cancelled: close
  waiting_for_someone_else --> completed: close
  deferred --> cancelled: close
  completed --> open: reopen
  cancelled --> open: reopen
  open --> deleted: remove
  completed --> deleted: remove
  open --> deferred: save progress
  waiting_for_someone_else --> open: save progress
  deferred --> waiting_for_someone_else: save progress
  waiting_for_someone_else --> cancelled: close
  deferred --> completed: close
  waiting_for_someone_else --> deleted: remove
  deferred --> deleted: remove
  cancelled --> deleted: remove
```

Open, Waiting for someone else and Deferred all represent unfinished work. Completed and Cancelled close ordinary editing. Deleted is an explanatory absence state rather than a stored status.

## Transitions Explained

The structured rows cover all directed moves among the three unfinished statuses, closing from each, reopening from either closed status, and deletion from every persisted status. Reopening always chooses Open rather than restoring the preceding status. Closing retains the holder and queue.

## What Cannot Happen

A patch cannot substitute for a closing action. Work must be reopened before changing its closed outcome or editing its fields. The workflow service’s already-satisfied requests have a repeat contract that differs from the public console actions.

## Concurrency and Timing

A locked read decides the lifecycle change. Public version checks detect stale requests; workflow requests use serialization and current-state repeat handling. Enabled attention participates in the same transaction and can therefore prevent the task write from committing.
