#92285: fix: reconcile orphaned managed flows when all child tasks are terminal#92301
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed June 15, 2026, 2:45 PM ET / 18:45 UTC. Summary PR surface: Source +57, Other +172. Total +229 across 3 files. Reproducibility: yes. at source level: the linked issue provides consistent parent task, backing CLI child, Review metrics: 1 noteworthy metric.
Stored data model Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Retarget or replace this branch with task-registry reconciliation that terminalizes the stale parent subagent task from its scoped terminal CLI child, lets existing Do we have a high-confidence way to reproduce the issue? Yes, at source level: the linked issue provides consistent parent task, backing CLI child, Is this the best way to solve the issue? No. This branch is a plausible managed-flow cleanup, but the narrow maintainable fix is to reconcile the stale parent subagent task from its scoped backing CLI child and rely on existing Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against c40db057da33. Label changesLabel justifications:
Evidence reviewedPR surface: Source +57, Other +172. Total +229 across 3 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
…asks are terminal When a subagent backing session becomes lost, the child task transitions to lost but the parent managed TaskFlow remains running indefinitely because no mechanism exists to reconcile a managed flow whose all linked tasks are terminal (without a cancel request). This adds a new reconciliation rule: a managed flow in running/queued status with at least one child task and zero active (queued/running) child tasks is reconciled to "lost" during task-flow registry maintenance (both preview and apply modes). Cancel-requested flows continue to be handled by the existing shouldFinalizeCancelledFlow path. Closes openclaw#92285
resolveProviderIndexIdentities() returns MemoryIndexProviderIdentity[], and noUncheckedIndexedAccess is not enabled, so array[0] does not include undefined in the type. The ! assertion is a no-op that oxlint flags as no-unnecessary-type-assertion.
332f8fb to
159e010
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
Thanks @Pandah97 for working on this. I am closing this PR as superseded by #92454 because both PRs are trying to resolve the stale-running task/TaskFlow report from #92285, and #92454 is the surviving canonical path with the narrower task-registry fix and regression tests. Clownfish is keeping the canonical review thread at #92454 tied to the original issue at #92285 so validation and follow-up stay in one place. Your work in #92301 remains part of the source PR context, and attribution/credit should be preserved if maintainers carry any of this approach forward. If this PR covers a distinct reproduction path that #92454 does not handle, please reply and we can reopen or split that back out. |
"## Summary\n\nAdd a new reconciliation rule in task-flow registry maintenance that transitions a managed TaskFlow to "lost" when all its linked child tasks are terminal (but no cancel was requested). This prevents parent orchestration flows from remaining permanently stale_running after a child subagent session is lost.\n\n## Root Cause\n\nWhen a subagent backing session becomes lost, the child task is correctly marked as "lost" by the task registry lifecycle listener. The child's task_mirrored flow is also synced to "lost" via
syncFlowFromTaskResult(). However, the parent's managed TaskFlow (the orchestrator flow) stays "running" indefinitely because:\n\n1. Managed flows don't auto-sync from child task status changes\n2. The existingshouldFinalizeCancelledFlow()only applies whencancelRequestedAtis set\n3. No reconciliation mechanism existed for the "all children terminal, flow still running" state\n\n## Real behavior proof\n\nBehavior or issue addressed: Reconcile orphaned managed TaskFlows to "lost" when all child tasks are terminal during task-flow registry maintenance, preventing parent orchestration flows from remaining permanently stale_running after backing session loss.\n\nReal environment tested: Linux 4.19.112, Node.js via tsx, openclaw workspace importing the production task-flow maintenance modules.\n\nExact steps or command run after this patch:\n\n$ npx tsx scripts/repro-92285.mts\n\n=== Test 1: Orphaned managed flow reconciliation ===\n Flow created: {\"id\":\"167a51d6-7370-4eb7-9c56-d9b4e389acb4\",\"status\":\"running\",\"syncMode\":\"managed\"}\n Child task created: {\"id\":\"09c62b03-9132-49a2-b478-894b3c2e40c0\",\"status\":\"running\",\"flowId\":\"167a51d6-7370-4eb7-9c56-d9b4e389acb4\"}\n Preview (child alive): {\"reconciled\":0,\"pruned\":0}\n Child marked lost: {\"id\":\"09c62b03-9132-49a2-b478-894b3c2e40c0\",\"status\":\"lost\"}\n Maintenance summary: {\"reconciled\":1,\"pruned\":0}\n Flow after maintenance: {\"id\":\"167a51d6-7370-4eb7-9c56-d9b4e389acb4\",\"status\":\"lost\"}\n\n=== Test 2: Running flow with no tasks is not touched ===\n Flow created (no tasks): {\"id\":\"9e53f7d2-28f3-41fa-a350-2886dfaaa4d3\",\"status\":\"running\"}\n Maintenance summary: {\"reconciled\":0,\"pruned\":0}\n Flow after maintenance: {\"id\":\"9e53f7d2-28f3-41fa-a350-2886dfaaa4d3\",\"status\":\"running\"}\n\n=== Test 3: Queued managed flow with terminal child ===\n Flow created (queued): {\"id\":\"465ea5a1-3a61-4324-9127-7d760f2176f8\",\"status\":\"queued\"}\n Child task created: {\"id\":\"91aeeeeb-32ff-4347-8240-d2d3b22b3652\",\"status\":\"running\"}\n Maintenance summary: {\"reconciled\":1,\"pruned\":0}\n Flow after maintenance: {\"id\":\"465ea5a1-3a61-4324-9127-7d760f2176f8\",\"status\":\"lost\"}\n\n=== Test 4: Cancel-requested flow still finalizes as cancelled ===\n Flow created (cancel requested): {\"id\":\"93c84313-deaa-49bb-bf6b-378f3ed213fc\",\"status\":\"running\"}\n Maintenance summary: {\"reconciled\":1,\"pruned\":0}\n Flow after maintenance: {\"id\":\"93c84313-deaa-49bb-bf6b-378f3ed213fc\",\"status\":\"cancelled\"}\n\n=== Results ===\nTest 1 (orphaned managed flow \u2192 lost): PASS\nTest 2 (empty managed flow untouched): PASS\nTest 3 (queued flow with dead child \u2192 lost): PASS\nTest 4 (cancel-requested flow \u2192 cancelled): PASS\n\n\nEvidence after fix:\n\n$ pnpm vitest run src/tasks/task-flow-registry.maintenance.test.ts\n\n RUN v4.1.7\n\n Test Files 1 passed (1)\n Tests 5 passed (5)\n Start at 09:04:56\n Duration 10.45s (transform 4.05s, setup 0ms, import 7.20s, tests 2.99s, environment 0ms)\n\n[test] passed 1 Vitest shard in 21.16s\n\n\nObserved result after fix: The repro script confirms orphaned managed flows transition to "lost" when all child tasks are terminal. Queued flows are also handled. Cancel-requested flows still finalize as "cancelled" (existing behavior preserved). Running flows with no child tasks are left untouched.\n\nWhat was not tested: Integration with specific task orchestration plugins; real task-flow execution lifecycle (the fix operates at the registry maintenance layer before plugin-specific hooks fire).\n\n## Regression Test Plan\n\n- [x]pnpm vitest run src/tasks/task-flow-registry.maintenance.test.ts\u2014 5 passed\n- [x]pnpm vitest run src/tasks/task-flow-registry.test.ts\u2014 passes\n- [x] Reproducer script confirms 4/4 scenarios\n- [x] Cancel-requested flow still finalizes as cancelled (regression preserved)\n- [x] Empty managed flow (no child tasks) left untouched\n"