Skip to content

feat(agent-org): [5/10] add durable Pause and Resume handoff #760

Description

@ShiboSheng

Effort

Delivery boundary P50 P90 Substantive files
Pause/Resume fence, handoff receipts, and continuation 1,700 review lines 3,200 review lines 14–22

Delivery contract

Dependency and single goal

Stack on PR 4 and add only one lifecycle capability: temporarily stop and continue formal work. Reuse PR 1 generation/state ownership, PR 3 typed formal Turn/FIFO/runtime identity, and PR 4 terminal/owner legality.

State after merge

When the user clicks Pause, the Team first persists a Paused fence. New formal Task graph mutations, TaskExecution, and formal Inbox claim/Wake are rejected immediately. Formal Turns already running yield their runtimes in parallel and within a bound. Resume consumes only the active pause episode, returns the Team to Working, and creates at most one FIFO continuation for each still-valid piece of formal work. Refresh, restart, and duplicate clicks do not bump generation twice or resume work twice. Team and history remain readable while paused. UserDirectedWork introduced in PR 8 and later will be permitted, but this PR does not open it early.

Implementation steps and authoritative entry points

  1. Pause carries a stable request ID and writes status=paused, a new generation, an episode receipt, and child handoff receipts for every queued/running formal Turn in one transaction.
  2. After commit, one runtime teardown owner requests yield from active formal Turns in parallel. Release uses session_id + original_runtime_lease_id + original_turn_generation through release_if_current; an old lease cannot remove a new runtime.
  3. A timeout records draining/SLO failure only. It cannot open a second runtime or undo the committed Paused fence.
  4. Resume consumes only the current active episode. One transaction writes the resume generation and at most one continuation receipt per original formal Turn. Work that PR 4 considers terminal, cancelled, reassigned, or owner-mismatched does not resume.
  5. Continuations enter PR 3's same Member FIFO. Overview immediately shows Paused/draining/Resume from the durable fence instead of waiting for every Provider to stop before changing the UI.
  6. Remove the develop resume_paused_run_for_user_message auto-resume behavior. The Pause selector captures only Coordinator/TaskExecution formal Turns and cannot put current or future UserDirectedWork into handoff receipts.

Primary files and entry points

state/commands/session/org_tasks/lifecycle.rs, agent_org_runs/{store,worker}.rs, pause episode/child receipt persistence, runtime lease/release ownership, AgentOrgOverviewPanel.tsx, and the Tauri lifecycle wire.

Scope boundaries

Pause accepts only Working; Idle already has no formal work to pause. Pause is not Cancel and does not alter Task status or goal. Resume is not a new batch and creates no new Task. Do not add a waiting_for_user Task state, a TaskExecution revocation subsystem, a requirement to wait for the old lease before showing Paused, or direct intervention/Return.

Failure scenarios that must be rejected or remain no-ops

  • Duplicate Pause/Resume bumps generation twice.
  • An old lease removes a new runtime.
  • A Paused Turn mutates the formal graph across Resume.
  • A timeout opens a second runtime.
  • Cancelled or reassigned work is resumed by a continuation.
  • Restart reconstructs the episode from memory.
  • Pause partially commits without handoff receipts.

Acceptance and handoff

Verify episode/child-receipt transaction fault injection, duplicate/restart/lease races, fence P90 ≤ 250 ms with 10 active runtimes, parallel yield, whole-Team draining ≤ 10 seconds, and no frontend poll/Wake while Paused. After merge, PR 6 reuses the “durable fence first, bounded teardown second” primitive for irreversible Archive. PR 8 reuses the child-handoff/lease contract for a single-Member intervention but cannot reuse Team Resume semantics.

Plain-language contract

Dependency

PRs 1–4, especially PR 3 Turn/FIFO and PR 4 Task legality.

How it works

Pause accepts only Working. One transaction first writes the Paused fence, generation, episode receipt, and child receipts for every queued/running formal Turn. After commit, request those formal Turns to yield their runtimes in parallel. Resume consumes only the current episode and creates at most one new FIFO continuation for each still-valid work item. Remove the old path where an ordinary message automatically resumes the Team.

State after merge

Paused immediately blocks new formal graph mutations, TaskExecution, and formal Wake. Refresh, restart, and duplicate clicks cannot pause or resume twice. UserDirectedWork remains closed, but Pause already targets only formal Turns so future side quests will not be stopped accidentally.

Boundaries

Pause is not Cancel and does not change Task status. Do not add Task paused/waiting states, execution revocation, or a second runtime.

How to test

Use episode/child-receipt fault injection, duplicate/restart/lease races, 10 formal runtimes yielding in parallel, fence P90 ≤ 250 ms, whole-Team drain ≤ 10 seconds, and zero Paused poll/formal Wake.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Effort: HighUXImprovements to user experience, workflow smoothnessenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions