Repository navigation
Description
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.
Written-by: FlyBot Dev-3
Claimed-by: FlyBot Lead
Claim-Id: 01e37876ef3a4ab49748c04ae6b52229
Branch: dev/3-workflow-stop-retry
Base: 16d1645
plugins/workflow: a Store/Reset whose Bot release fails freezes the run (paused + releasePending, #1476) and no longer has any way out on its own — the frozen run holds a maxConcurrent slot until the owner presses Stop again.
Steps to reproduce
- A workflow with two nodes; run a task so one node is in flight and one run Bot exists.
- Make the host refuse to remove that Bot (in the test this is one
releasehook that throws). - Press Stop on that run.
reset({ runId })releases what it can, keeps the failed id, and callshold():run.paused = true,run.releasePending = true. - Do nothing else — do not press Stop again.
Expected: the run's step deadline (45 minutes by default) is the bounded wait the subsystem doc promises, so the lane gets its slot back: its Bot is released again and the run ends, reading paused-expired in the Runs tab.
Actual: the lane stays at its maxConcurrent limit forever. hold() writes those two flags without calling syncTimers(), so the deadline of the node the run was on is still armed; when it fires, expireStep() returns at if (… || run.paused === true) return — the timer is already deleted at that point, nothing re-arms it, and nothing retries the release. docs/subsystems/workflow.md:41 states the contract this breaks: "a step still unanswered after its workflow's stepTimeoutMinutes (45 minutes by default) fails the run and releases its Bots (#1530, #1580)" — one hold() and the workflow can queue tasks that never start.
Scope
plugins/workflow/src/service.js: the deadline of a run frozen by a failed Stop retries the release; when it succeeds the run is ended with failure.code: 'paused-expired' and archived (slot freed, lane.history row, one stage line), and when it still fails the deadline is armed again with the id that would not go still named. No change to resume(), to releasePending's meaning, or to what the panel draws; an owner's own Pause is untouched (its deadline is cleared as before, so it is still never timed out). One test file, plugins/workflow/test/stop-retry-deadline.test.js and one changelog.d fragment; docs/subsystems/workflow.md is unchanged because it already promises this contract, so the branch carries a Docs-not-needed: line.
Duplicate check
No existing issue covers this: #1476 introduced paused/releasePending and the Keep-the-Bot rule (it is about the flags, not about the timer), #1530/#1580 introduced the step deadline and its bounded hand-off (their tests cover an unanswered step and an owner Pause, and deadline.test.js pins "a paused run holds no timer" for the owner's Pause — the failed-Stop run is the case neither covers), and #2426/#2423 are the label fix on the same frozen run (Pause/Running drawn instead of Paused), a different symptom in plugins/workflow/client.js.
Activity
workflow: a Stop that cannot release its Bot ends at the deadline, no…