fix(FN-5256): await disposal across task:moved-away and task:deleted
Close the last fire-and-forget gap from the previous fixes: the task:moved (away from in-progress) and task:deleted listeners no longer call the synchronous fire-and-forget `abortInFlightTaskWork`. Instead they track an awaited disposal promise per task in `pendingTaskDisposals`. The task:moved (to in-progress) dispatch path awaits any in-flight disposal for the same task before calling `execute()`, so a fast bounce (in-progress → todo → in-progress) no longer races the conflict-cleanup path against a still-live shell. `awaitAbortInFlightTaskWork` now claims each session surface (activeSessions, activeStepExecutors, activeWorkflowStepSessions, activeSubagentSessions) synchronously before awaiting any async abort. This lets concurrent disposal calls for the same task dedupe naturally — the second call finds the maps empty and no-ops, preserving the existing single-abort/single-dispose contract that the soft-delete and user-cancel tests assert. Adds a regression test in executor-user-cancel covering the re-dispatch ordering: an immediate task:moved-to-in-progress that follows a still-running task:moved-away must wait for abort to complete before execute() runs. The legacy `abortInFlightTaskWork` is removed (no callers). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,3 +9,5 @@ fix(FN-5256): harden three independent code paths that were losing live task wor
|
||||
- Pause-before-park now synchronously awaits agent/step/workflow session disposal via a new `awaitAbortInFlightTaskWork` method, so by the time `parkTaskAfterWorkflowStepPause` calls `moveTask("todo")` the spawned shells are already reaped and any fast re-dispatch sees a clean slate. The user-initiated pause handler on `task:updated` was collapsed onto the same await path for the same reason.
|
||||
|
||||
- Self-healing `reconcileTaskWorktreeMetadata` now normalizes both sides via `realpathSync` (with ENOENT fallback) before comparing the task worktree against the registered set, fixing the macOS `/private/var/...` false-stale flag. It additionally refuses to clear `worktree`/`branch` metadata for in-progress or in-review tasks — those go through `task:auto-recover-worktree-metadata-skipped-active` audit events and leave executor-level recovery in charge.
|
||||
|
||||
- The `task:moved`-away and `task:deleted` listeners now track an awaited disposal promise per task. A re-dispatch (`task:moved` → in-progress) awaits any in-flight disposal for the same task before calling `execute()`, so a fast bounce (in-progress → todo → in-progress) can no longer race the conflict-cleanup path against a still-live shell. `awaitAbortInFlightTaskWork` claims each session surface synchronously before awaiting its abort, so concurrent disposal calls dedupe naturally and the legacy fire-and-forget `abortInFlightTaskWork` has been removed.
|
||||
|
||||
Reference in New Issue
Block a user