Effort
| Delivery boundary |
P50 |
P90 |
Substantive files |
Direct UserDirectedWork, user_intervention, and Return to Work |
2,500 review lines |
4,300 review lines |
18–29 |
Delivery contract
Dependency and single goal
Strictly stack on PR 7 and deliver only the direct source from the Member page. Reuse lifecycle, flat snapshot, Turn context/FIFO, Task gates, lease handoff, Archive fence, and Writer resolution. Leave Group mention and peer Inbox to PR 9.
State after merge
With the rollout gate enabled, the user can use a Member's direct page in Working/Idle/Paused to ask questions, edit files, run commands/tests, and use approved tools. A normal Member cannot change the formal graph; an additional Writer may use PR 7's graph-admin Tool. When the Member is busy with TaskExecution, a direct message creates visible user_intervention, yields the old execution at a safe point, and runs UserDirectedWork in the same runtime slot without opening a second lane. Intervention does not disappear because of TTL, page close, Stop, or restart. Only the user's Return to Work consumes it.
develop paths that must be replaced
state/commands/session/message/send.rs currently auto-resumes a Paused Team and injects busy-Member direct input as TaskExecution steering. agent_member_interventions.rs currently has TTL/startup cleanup. org_tasks/intervention.rs currently polls every 500 ms for up to 90 seconds and blanket-drains Inbox on Return. The independent agent_org_send_user_message_to_member/enter-intervention command is still a second send path. Replace these semantics on the Agent Org branch while preserving ordinary SDE steering, Queue, and Stop.
Implementation steps and authoritative entry points
- Freeze the production send chain as
useUserIntentSubmit → SessionService.sendMessage → agent_send_message → typed Agent Org direct dispatcher. The frontend carries the existing stable turnIntentId and source EventStore user event; the backend verifies both belong to the target canonical Member Session. Delete the independent command or reduce it to a stateless thin adapter over the same dispatcher.
- One IMMEDIATE transaction validates Team, Member, source, and queue cap; writes
UserDirectedWork{source=DirectMember} context, FIFO sequence, and receipt; and, when TaskExecution is active, writes the intervention chain and unique original-Task continuation receipt. Only after commit request yield from the old execution.
- The old runtime must execute
release_if_current against lease/generation before the direct Turn can take the same slot. Suspend timeout shows waiting/yield_timeout only and never opens a second runtime.
- The UserDirectedWork finalizer first writes assistant output with exact
reply_to_event_id to EventStore, then terminates the Turn, releases runtime, and kicks FIFO. It never calls Task complete/fail/requeue hooks and does not block formal Quiescence merely because the participant is a Writer.
- Return uses a stable request ID to atomically consume the same receipt. In
Working, if the original Task remains open with the same owner, it creates at most one continuation. In Paused/Idle, it only clears intervention. If the Task is terminal, cancelled, or reassigned, record no_longer_needed. Delete the 500 ms/90-second poll and blanket Inbox drain.
- Member page and Overview show yielding,
user_intervention, side quest, and Return. Stop stops only the current UserDirectedWork and preserves intervention. Remove TTL countdown/expiry timers and make clear that off-board side quests do not automatically enter the Task board.
Primary files and entry points
src-tauri/crates/agent-core/src/core/coordination/agent_member_interventions.rs
src-tauri/crates/agent-core/src/core/coordination/agent_org_user_directed_work/*
src-tauri/crates/agent-core/src/state/commands/session/{message/send.rs,org_tasks/intervention.rs}
src-tauri/crates/agent-core/src/core/session/scheduler.rs
src-tauri/crates/agent-core/src/{lifecycle.rs,init/tool_assembly.rs}
src/api/tauri/agent/orgTasks.ts
src/engines/ChatPanel/hooks/useWorkspaceChat/useUserIntentSubmit.ts
src/engines/ChatPanel/InputArea/components/{useAgentOrgIntervention,AgentOrgInterventionPinBar,AgentOrgOverviewPanel}.tsx*
Scope boundaries
Do not add Task waiting_for_user, modify the original Task's status/owner/dependencies, classify direct input as TaskExecution small steering, automatically Return on TTL/Stop, resume a cancelled/reassigned Task, add TaskExecution revocation, open a second runtime, or add Coordinator TaskExecution.
Failure scenarios that must be rejected or remain no-ops
- Receipt failure still yields or starts work.
- Yield timeout opens a second runtime.
- A crash after old-lease release but before FIFO kick loses the Turn.
- TTL, page close, or startup automatically Returns.
- Duplicate direct input suspends twice.
- Duplicate Return creates two continuations.
- Stopping UserDirectedWork cancels a formal Task.
- Return in
Paused/Idle resumes formal work automatically.
- A cancelled/reassigned original Task still receives a continuation.
- A normal Member mutates the formal graph.
- A started UserDirectedWork crash automatically replays file/external side effects.
- Archived, CLI, or noncanonical targets start a Provider.
Acceptance and handoff
Verify the Working/Idle/Paused direct matrix; real file edit, shell, and test production paths; normal-Member three-layer graph denial and Writer allow; suspend timeout, restart, duplicate direct, and duplicate Return; intervention survives Stop, page close, and elapsed time; per-Member runtime count is always ≤ 1; suspend P90 ≤ 5 seconds and hard wait ≤ 10 seconds; runtime release after terminal UserDirectedWork P50 ≤ 1 second and P90 ≤ 5 seconds; and ordinary SDE steering/Queue/Stop regression. After merge, PR 9 may add source adapters only to enqueue_user_directed_work(canonical member, stable turn id, typed source, root authority, optional intervention handoff) and must not copy scheduler/finalizer logic.
Plain-language contract
Dependency
PRs 1–7.
How it works
Connect generic direct send to the one typed UserDirectedWork dispatcher. An idle Member enters its FIFO. If the Member is busy with TaskExecution, first persist the intervention/continuation receipt, then let the old lease exit at a safe point, and finally run UserDirectedWork in the same runtime slot. The reply lands in EventStore with the exact reply ID before the Turn ends and runtime releases. Return uses a stable request and creates one continuation only when the Team is Working and the original Task is still valid.
State after merge
In Working/Idle/Paused, the user can chat directly with a Member, modify files, and run commands/tests. Busy direct work shows that the Member “was called away by the user” and never opens a second runtime. Intervention does not disappear because of TTL, page close, Stop, or restart; only Return clears it.
Boundaries
Do not treat direct input as “small steering,” add a Task waiting state, let a normal Member modify the graph, automatically Return on TTL/Stop, or resume cancelled/reassigned work. Group and peer Inbox remain closed.
How to test
Verify real file/shell/test paths, normal-Member denial and Writer allow, suspend timeout/restart/duplicate Return, intervention surviving Stop/page close/time, per-Member runtime ≤ 1, release P50 ≤ 1 second/P90 ≤ 5 seconds, and ordinary SDE steering/Queue/Stop regression.
Effort
user_intervention, and Return to WorkDelivery contract
Dependency and single goal
Strictly stack on PR 7 and deliver only the direct source from the Member page. Reuse lifecycle, flat snapshot, Turn context/FIFO, Task gates, lease handoff, Archive fence, and Writer resolution. Leave Group mention and peer Inbox to PR 9.
State after merge
With the rollout gate enabled, the user can use a Member's direct page in
Working/Idle/Pausedto ask questions, edit files, run commands/tests, and use approved tools. A normal Member cannot change the formal graph; an additional Writer may use PR 7's graph-admin Tool. When the Member is busy with TaskExecution, a direct message creates visibleuser_intervention, yields the old execution at a safe point, and runs UserDirectedWork in the same runtime slot without opening a second lane. Intervention does not disappear because of TTL, page close, Stop, or restart. Only the user's Return to Work consumes it.developpaths that must be replacedstate/commands/session/message/send.rscurrently auto-resumes a Paused Team and injects busy-Member direct input as TaskExecution steering.agent_member_interventions.rscurrently has TTL/startup cleanup.org_tasks/intervention.rscurrently polls every 500 ms for up to 90 seconds and blanket-drains Inbox on Return. The independentagent_org_send_user_message_to_member/enter-intervention command is still a second send path. Replace these semantics on the Agent Org branch while preserving ordinary SDE steering, Queue, and Stop.Implementation steps and authoritative entry points
useUserIntentSubmit → SessionService.sendMessage → agent_send_message → typed Agent Org direct dispatcher. The frontend carries the existing stableturnIntentIdand source EventStore user event; the backend verifies both belong to the target canonical Member Session. Delete the independent command or reduce it to a stateless thin adapter over the same dispatcher.UserDirectedWork{source=DirectMember}context, FIFO sequence, and receipt; and, when TaskExecution is active, writes the intervention chain and unique original-Task continuation receipt. Only after commit request yield from the old execution.release_if_currentagainst lease/generation before the direct Turn can take the same slot. Suspend timeout showswaiting/yield_timeoutonly and never opens a second runtime.reply_to_event_idto EventStore, then terminates the Turn, releases runtime, and kicks FIFO. It never calls Task complete/fail/requeue hooks and does not block formal Quiescence merely because the participant is a Writer.Working, if the original Task remains open with the same owner, it creates at most one continuation. InPaused/Idle, it only clears intervention. If the Task is terminal, cancelled, or reassigned, recordno_longer_needed. Delete the 500 ms/90-second poll and blanket Inbox drain.user_intervention, side quest, and Return. Stop stops only the current UserDirectedWork and preserves intervention. Remove TTL countdown/expiry timers and make clear that off-board side quests do not automatically enter the Task board.Primary files and entry points
Scope boundaries
Do not add Task
waiting_for_user, modify the original Task's status/owner/dependencies, classify direct input as TaskExecution small steering, automatically Return on TTL/Stop, resume a cancelled/reassigned Task, add TaskExecution revocation, open a second runtime, or add Coordinator TaskExecution.Failure scenarios that must be rejected or remain no-ops
Paused/Idleresumes formal work automatically.Acceptance and handoff
Verify the Working/Idle/Paused direct matrix; real file edit, shell, and test production paths; normal-Member three-layer graph denial and Writer allow; suspend timeout, restart, duplicate direct, and duplicate Return; intervention survives Stop, page close, and elapsed time; per-Member runtime count is always ≤ 1; suspend P90 ≤ 5 seconds and hard wait ≤ 10 seconds; runtime release after terminal UserDirectedWork P50 ≤ 1 second and P90 ≤ 5 seconds; and ordinary SDE steering/Queue/Stop regression. After merge, PR 9 may add source adapters only to
enqueue_user_directed_work(canonical member, stable turn id, typed source, root authority, optional intervention handoff)and must not copy scheduler/finalizer logic.Plain-language contract
Dependency
PRs 1–7.
How it works
Connect generic direct send to the one typed UserDirectedWork dispatcher. An idle Member enters its FIFO. If the Member is busy with TaskExecution, first persist the intervention/continuation receipt, then let the old lease exit at a safe point, and finally run UserDirectedWork in the same runtime slot. The reply lands in EventStore with the exact reply ID before the Turn ends and runtime releases. Return uses a stable request and creates one continuation only when the Team is Working and the original Task is still valid.
State after merge
In
Working/Idle/Paused, the user can chat directly with a Member, modify files, and run commands/tests. Busy direct work shows that the Member “was called away by the user” and never opens a second runtime. Intervention does not disappear because of TTL, page close, Stop, or restart; only Return clears it.Boundaries
Do not treat direct input as “small steering,” add a Task waiting state, let a normal Member modify the graph, automatically Return on TTL/Stop, or resume cancelled/reassigned work. Group and peer Inbox remain closed.
How to test
Verify real file/shell/test paths, normal-Member denial and Writer allow, suspend timeout/restart/duplicate Return, intervention surviving Stop/page close/time, per-Member runtime ≤ 1, release P50 ≤ 1 second/P90 ≤ 5 seconds, and ordinary SDE steering/Queue/Stop regression.