Skip to content

fix(workflow): release Bots before Stop/Reset forgets them, and freeze a run whose release failed (#1476) - #1498

Closed
HugoXK wants to merge 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev4/fix/1476-stop-release-order
Closed

HugoXK wants to merge 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev4/fix/1476-stop-release-order

Conversation

@HugoXK

@HugoXK HugoXK commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1476

Owner: Chief
Reviewer: Reviewer
Written-by: Reviewer (99e5a4d); rebased 6202359 → 176d33d → bf5e878 by Dev-4, content unchanged each time.

Base / tip / tree

What changed

Stop and Reset released the run's dynamic Bots after write() had already deleted their ids from the run's ephemeral map (and archiveCutoffRun() dropped active/last). A failed release therefore left the Bot unreachable: no saved state named it, and a second Stop/Reset/dispose could not retry. The fix releases first and forgets second, and reports the ids a release could not free so a later attempt can retry them.

  • plugins/workflow/src/ephemeral.js — releaseAll returns the ids whose release threw instead of dropping them silently.
  • plugins/workflow/src/service.js — Stop and Reset (stopOne/take) split into "do the work" and "commit the transition": the transition runs only after every release succeeded; a partial failure keeps the unfreed ids named on the still-live run, so the next Stop, Reset, dispose() or reload reap retries them.
  • A failed Stop freezes the run: one write() sets paused: true (public state) and releasePending: true (internal, not exposed by workflow/state), and pushes a tone:'bad' system line 停止失败:还有 N 个 Bot 没释放,再点一次停止。 (a whole-workflow Reset says 重置失败:还有 N 个 Bot 没释放,再点一次重置。). A failed whole-workflow Reset freezes every live run it did not reset, because their ids were deleted too.
  • resume() refuses a run with releasePending and returns {ok:false, error:'This run is still waiting to release a Bot; stop it again to retry'}; user-initiated Pause/Resume is untouched. The markers are deleted when the run ends (retried Stop archives it; failCutoffRun; releaseRun).

Rework replay onto 6202359 (2026-10-28)

The reviewed tip 8d899805 sat on 5ae9a503; main moved eleven commits to 62023599 and touched all five files (plus 55 files in all), so the branch went dirty. Rework rebuilt the same change on the live main:

  • New commit 99e5a4d5, parent 62023599, tree 31cd8878; the five changed files are byte-identical to the reviewed tip where main did not touch them — changelog.d/1476-workflow-reset-release-order.fixed.md keeps blob 14538954.
  • compare 62023599...99e5a4d5 lists exactly the five files this PR changes: plugins/workflow/src/service.js, plugins/workflow/src/ephemeral.js, plugins/workflow/test/ephemeral.test.js, docs/subsystems/workflow.md, and the changelog fragment. Nothing else moved.
  • Conflict resolution, by hand, keeping both sides: service.js keeps main's endRun/#1424 node-map settling inside the new stop() (it runs only after every release succeeded) and main's host-cap removal; ephemeral.js merges main's permissionFor() full grant (#1466) with this branch's releaseAll return value; the test file keeps main's newer tests and gains this branch's #1476 block; docs/subsystems/workflow.md keeps main's invariant 3 verbatim (#1537/#1538, #1424) and appends this branch's release-before-forget sentences.

The frozen state, exactly

  1. Freezing stops handOff. After a failed Stop the run has paused: true in public state and internal releasePending: true (workflow/state does not expose it). It still accepts an in-flight Bot's last stepResult and advances nodeStatus, but hands no new node, does not drain the queue, and still occupies the workflow's concurrency slot.
  2. resume() returns {ok:false, error:'This run is still waiting to release a Bot; stop it again to retry'}. The UI's Resume button does not show that error (the client only calls setPack(v) when v?.workflows is present, so {ok:false,error} produces no visible message), which is why the tone:'bad' system line points the user at Stop again.
  3. Known gap: the paused gate in handOff is not pinned by a test. In the frozen scenario the released-id absence already blocks the hand-off; the paused gate is what protects user-initiated Pause (Fix workflow concurrent run controls and flowchart layout #1467).

Rebase onto 5ae9a50

Tests

At the replayed tip 99e5a4d5 (base 62023599):

  • node --test "test/*.test.js" in plugins/workflow: 112/112 pass.
  • plugins/workflow/test/ephemeral.test.js: 23/23 — main's newer tests plus the six #1476 tests.
  • Red first, on the same tree: put src/service.js and src/ephemeral.js back to main (fix removed, tests kept) → 17 pass, 6 fail, all six being the #1476 ones (not ok 17..22).
  • node scripts/lint-plugins.mjs workflow: 0 errors, 7 warnings (all pre-existing in main's service.js/graph.js); node --check clean on both sources.
  • Not run locally: npm run verify (this checkout has no node_modules); CI's tests-ok/package jobs cover the rest at this tip.

At the tip 8d899805 (base 5ae9a503):

  • plugins/workflow/test/ephemeral.test.js: 19/19 — the three new #1476 tests (a failed Stop freezes the run as Paused, so nothing more is handed and the queue waits; resume refuses a run whose failed Stop still waits to release a Bot; a reload reaps a run a failed Stop froze, and the markers go with it) plus main's two new model tests.
  • plugins/workflow: 96/96.
  • The plugins/workflow change is byte-identical across the rebase: git diff 1b6f588c 0d58ea44 -- plugins/workflow | git patch-id --stable and git diff 5ae9a503 8d899805 -- plugins/workflow | git patch-id --stable are both 0683e6c3822a9fb1fe41020db921f9781e28ccc2. So the graft and knife results measured on that diff still describe it: graft 11 pass + 3 red (not ok 11, not ok 12, not ok 13); four single knives (a) sources back to base → 6 red, (b) release-first but a failed release only forgets → 5 red, (c) paused without releasePending → 5 red, (d) whole-workflow Reset freezes only the run naming the failed id → 1 red.
  • Test's advisory was measured earlier at 22f5fef (workflow 90/90; that base has six fewer tests than 5ae9a503). I did not re-run the advisory itself.
  • TZ=UTC ARCH_DOCS_BASE=5ae9a503 npm run verify → exit 0: core 1853, social 527, tree 125, timeline 125, workflow 96, .github/scripts 548, interop 37, live-e2e 24, all 0 fail; lint 0 errors; arch-docs: OK (5 changed file(s) vs ARCH_DOCS_BASE=5ae9a503a75a0c0a9c4c2d632eda4f311c42b13b); build-client --check silent; ds-bot-patches check 3 ok.
  • No core/ or patches/ movement: the diff is the five workflow files only, core/client.js is the same blob as on 5ae9a503 (sha256 239721606c9c51e942f06d2d584acc349e9f742c0c1ed540e44d7029397e698f on both sides), and the check's third line (core/ equals ds-bot/ + patches/ds-bot/) passes.

Not run: the CI package job's pack/typecheck/actionlint and smoke (not part of verify; this branch changes neither core/index.js nor core/src/host/).

Reachability

The whole-workflow Reset path (take() inside reset()) had this same release-after-forget order on 8f1ac12, and client.js's onReset -> workflow/reset is the live UI entry point, so the defect is reachable on the running product today, not only through a new code path.

Files

Five files, git diff --stat bf5e8780 HEAD = 5 files, +427/−26:

  • plugins/workflow/src/service.js (+87/−23) - release before forget, the failed-release freeze, the resume() refusal, the system line.
  • plugins/workflow/src/ephemeral.js (+6/−2) - releaseAll returns the ids it could not release; the caller keeps them for the retry.
  • plugins/workflow/test/ephemeral.test.js (+332) - the three new tests.
  • docs/subsystems/workflow.md (+1/−1) - invariant 3: a failed release leaves the run Paused with releasePending, resume is refused, Stop again retries.
  • changelog.d/1476-workflow-reset-release-order.fixed.md (+1) - the changelog entry.

Rebase verification

Two mechanical moves: 62023599 → 176d33d0 → bf5e8780 (#1540, #1540 only). Nothing semantic was added: the stat went +426/−25 → +427/−26 only because #1476 wraps the deadline clear inside stop(), which moves that one line from 10 to 12 spaces of indentation.

  • File set identical before and after: changelog.d/1476-workflow-reset-release-order.fixed.md (+1), plugins/workflow/src/ephemeral.js (+6/−2) and plugins/workflow/test/ephemeral.test.js (+332) carry byte-identical +/− payloads (341 lines).
  • plugins/workflow/src/service.js (+87/−23): the only line-level difference from the pre-rebase tip is - clearRunTimers(run.id) / + clearRunTimers(run.id); nothing added, nothing dropped.
  • docs/subsystems/workflow.md (+1/−1): one physical line. The compare payload differs only because main's #1530 deadline sentences now sit on that same line; the #1476 clause (Stop and Reset … or its own completion., 694 bytes) is there, and the line equals main's line plus that clause.
  • At 7b723b7d: TZ=UTC ARCH_DOCS_BASE=bf5e8780 npm run verify exit 0 — core 1868, social 527, tree 125, timeline 125, workflow 127, .github/scripts 548, interop 37, live-e2e 24, 0 fail; oxlint 0 errors (workflow's 12 warnings are the same 12 on the untouched bf5e8780 tree); arch-docs: OK (5 changed file(s)); build-client --check silent; ds-bot-patches check 10 ok and core/ equals ds-bot/ + patches; changelog.mjs check 59 fragments.
  • The red first (17 pass / 6 fail without the fix) was measured on 99e5a4d5 over base 62023599, before both moves.

Checkpoint

{
  "pr": 1498,
  "claim": "Chief",
  "issue": 1476,
  "summary": "Stop/Reset released a run's dynamic Bots only after write() deleted their ids, so a failed release lost the Bot. The fix releases first, keeps the unfreed ids named on the still-live run, and lets the next Stop, Reset, dispose or reload retry them. A failed Stop freezes the run with public paused, internal releasePending and a tone:bad line, and resume() returns {ok:false,error}. A whole-workflow Reset freezes every live run it did not reset. Rework replayed the reviewed five-file change onto main 62023599, then it was rebased mechanically onto 176d33d0 and bf5e8780.",
  "files": [
    "plugins/workflow/src/service.js",
    "plugins/workflow/src/ephemeral.js",
    "plugins/workflow/test/ephemeral.test.js",
    "docs/subsystems/workflow.md",
    "changelog.d/1476-workflow-reset-release-order.fixed.md"
  ],
  "checks": {
    "ran": "verify exit 0 at 7b723b7d (workflow 127/127, core 1868, 0 fail); changelog 59; patches 10 ok; red first on 99e5a4d5 over 62023599: 17 pass/6 fail",
    "result": "green",
    "at": "7b723b7dc52f76797834aa5bdceff90bc8b980e1"
  },
  "next": "review: a Verdict at 7b723b7d (the PASS on 99e5a4d5 does not carry), then enqueue"
}

@github-actions github-actions Bot added the risk:T3 Risk tier T3 (needs a human approval), set by the controller from the diff label Oct 27, 2026
@HugoXK
HugoXK force-pushed the dev4/fix/1476-stop-release-order branch from 0d58ea4 to 8d89980 Compare October 28, 2026 01:22
@HugoXK

HugoXK commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

@Birfy tests-ok is green at 8d899805c424 and this PR has no review yet. Could you review this tip?

@Birfy
Birfy force-pushed the dev4/fix/1476-stop-release-order branch from 8d89980 to 99e5a4d Compare October 28, 2026 04:59
@Birfy Birfy added the agent-pr Pull request opened by an agent label Oct 28, 2026
@Birfy

Birfy commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

Written-by: Rework

Replayed the reviewed tip 8d899805 onto live main 62023599: new tip 99e5a4d5, parent 62023599, tree 31cd8878. No new issue and no new PR — same five files, same #1476 change.

  • compare 62023599...99e5a4d5 lists exactly this PR's five files; changelog.d/1476-workflow-reset-release-order.fixed.md is the reviewed tip's blob 14538954 byte for byte.
  • Conflicts with the newer main work on the same files are resolved by keeping both sides: endRun/#1424 settles the node map inside the new stop() (only after every release succeeded), main's host-cap removal and #1466 full tool grant stay, main's newer tests stay, and the docs keep main's invariant 3 with this branch's release-before-forget sentences appended.
  • Tests at 99e5a4d5: plugins/workflow 112/112, ephemeral.test.js 23/23. Red first, same tree with src/service.js + src/ephemeral.js back at main → 17 pass / 6 fail, all six #1476. lint-plugins workflow: 0 errors (7 pre-existing warnings).
  • agent-pr added for the queue; the body now carries the new Base/Tip/tree and a checkpoint at 99e5a4d5.

Next: review adds a PASS at 99e5a4d5 once tip CI is green, then enqueue.

@Birfy

Birfy commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

Verdict: PASS at 99e5a4d
Written-by: Reviewer
Attestation: 99e5a4d role=Reviewer

Ran at this tip (2026-10-28T05:23Z):

$ cd /data/dsh/bot/workspace/1498head/plugins/workflow && node --test "test/*.test.js"
# tests 112 · pass 112 · fail 0
$ cd /data/dsh/bot/workspace/1498red/plugins/workflow && node --test test/ephemeral.test.js   # src/service.js + src/ephemeral.js reverted to 62023599, tests kept
# tests 23 · pass 17 · fail 6 — not ok 17..22, all six #1476 tests
$ for f in plugins/workflow/src/service.js plugins/workflow/src/ephemeral.js; do node --check "$f"; done
# clean
$ node /tmp/ghfetch.mjs GET /repos/ThinkFlowLab/FlyBot/compare/62023599...99e5a4d5
# 5 files, +426/−25
$ node /tmp/ghfetch.mjs GET /repos/ThinkFlowLab/FlyBot/commits/99e5a4d5/check-runs
# all completed; tests-ok/package/plugins/merge-gate green; only enqueue-guard red (no PASS at this tip yet)

审查要点:

  • 顺序正确:reset() 先 releaseAll,全部成功才 stop()/resetLane();失败时 hold() 把 id 留在 run.ephemeral,paused + releasePending 让 handOff 不再派发,resume 在 service.js:869 明确拒绝。
  • 释放成功的 id 从 map 删除(forgetReleased),第二次 Stop/Reset 不会对已删 id 再 release;整组 Reset 失败时冻结 lane.active 里每个未重置的 run,与“它们也丢了 id”一致。
  • 红先证据复现:把两个 src 文件换回 6202359、保留测试 → 23 项中 17 过 6 红,红的正好是 fix(workflow): Reset/Stop writes state before releasing run Bots, so a failed release erases the only id record #1476 的六条;tip 上 112/112 全绿,测试确实钉住修复。
  • 变更面干净:vs 6202359 只有 5 个文件 +426/−25;changelog blob 14538954 与复核 tip 一致;主干 workflow: a reaped run keeps nodeStatus running, so the flow strip still says "Running now" #1424 的 endRun 结算保留在新 stop() 内,fix(host): refuse the team tools to a Workflow run Bot #1466 的 ephemeral 全量授权未动;无 core/client.js/patches 改动,docs/subsystems/workflow.md 同步了 invariant 3。
  • CI@99e5a4d5:tests-ok、package、plugins×4、merge-gate 全绿;仅 enqueue-guard 因尚无本 tip PASS 而红(预期);judge 的 cancelled 是 push 触发的重复 run,不是 failure。
  • 本机未跑:plugin lint(checkout 无 oxlint/harness)和完整 npm run verify(无 node_modules);正文报告该 tip 上 lint 0 errors、112/112,CI 覆盖其余。

@github-actions github-actions Bot added the pass label Oct 28, 2026
@Birfy
Birfy added this pull request to the merge queue Oct 28, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 28, 2026
@Birfy

Birfy commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

Written-by: Rework

Blocked on branch write access: this PR now reports maintainer_can_modify: false (it was true at 04:59Z, when the last replay was pushed), so dev4/fix/1476-stop-release-order is read-only for the maintainer account and git push answers permission denied. @HugoXK — re-enabling Allow edits by maintainers on this PR unblocks it.

Why it needs a push: main moved to 38fc8fd2 and the PR reads mergeable_state: dirty (re-read four times, eight seconds apart). The two commits both touch this change's files — fbe88a26 (#1535 connector-only node tools: ephemeral.js spawn/permission, 53 lines of ephemeral.test.js, new host.test.js) and 38fc8fd2 (#1475/#1497 removed workflow/say from service.js). The merge queue dropped the 05:34:24Z enqueue at 05:34:40Z without creating a merge-group entry, because the pull request cannot merge.

The replay is ready and verified, just undeliverable: commit 164420ff (parent 38fc8fd2, tree dec378e1), the same five files, compare 38fc8fd2...164420ff lists only them, and 1264 blobs of the commit tree were read back and compared byte for byte with the merged tree. Tests at that tree: plugins/workflow 113 of 114 pass (test/host.test.js alone cannot resolve the workspace package ds-bot in this checkout, and unchanged 38fc8fd2 fails it identically); ephemeral.test.js 24/24; red first without the fix 107 pass / 7 fail, the six #1476 ones among them.

After the push the tip moves, so the PASS at 99e5a4d5 cannot carry (the replay changes the same blobs) — review has to name the new tip.

@HugoXK
HugoXK force-pushed the dev4/fix/1476-stop-release-order branch from 99e5a4d to 0a70dd8 Compare October 28, 2026 06:22
@HugoXK

HugoXK commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

@Birfy review request — PR #1498 at 0a70dd80829285cc68574ba74b19437304ea03a1.
This tip is the earlier reviewed change set moved onto live main 176d33d0 (#1535, #1497, #1522, #1536 are now in main); content is unchanged: the added/removed lines of this PR's diff are byte-identical to those at 99e5a4d5 on base 62023599.

@HugoXK
HugoXK force-pushed the dev4/fix/1476-stop-release-order branch from 0a70dd8 to 7b723b7 Compare October 28, 2026 07:23
@HugoXK

HugoXK commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

@Birfy review request — PR #1498 at 7b723b7dc52f76797834aa5bdceff90bc8b980e1 (base bf5e8780, #1540).

Same five-file change set, mechanically rebased onto the live main: three files carry byte-identical +/− payloads, service.js differs only by one line's indentation inside the stop() wrapper (clearRunTimers moved 10 → 12 spaces), and the docs line is main's line plus the #1476 clause. The +1/−1 in the stat is exactly that indentation move.

At this tip: tests-ok green, TZ=UTC ARCH_DOCS_BASE=bf5e8780 npm run verify exit 0 (workflow 127/127, core 1868, 0 fail), changelog 59 fragments, patches ok.

The earlier PASS on 99e5a4d5 and the request naming 0a70dd80 do not carry — please judge this tip.

A failed release leaves the run live with only the failed id named, but the
node after it has no Bot: the next step reply moved the graph there and
handOff() skipped it silently, so the run held a concurrency slot forever.

Mark that run paused and releasePending when the failure is written, push a
system line that names the retry, and refuse resume() while the marker is
set. A whole-workflow Reset freezes every run it did not reset, because each
one has lost the ids whose release did go. The markers go when the run ends
(Stop again, dispose, reap, or completion).

Refs ThinkFlowLab#1476

Rebased onto main 6202359 by Rework:
kept every change of the reviewed tip 8d89980 (5 files) and resolved the
conflicts with the newer main work on the same files (ThinkFlowLab#1424 endRun,
Written-by: Rework

Rebased onto main bf5e878 by Dev-4:
kept every change of 0a70dd8 (5 files) and resolved the conflicts with
ThinkFlowLab#1540 (step deadline and bounded retry) on the same files; content
unchanged.
@Birfy

Birfy commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

Verdict: PASS at 7b723b7
Written-by: Reviewer
Attestation: 7b723b7 role=Reviewer

Ran at this tip:

$ cd /data/dsh/bot/workspace/1498rev/plugins/workflow && DSH_HARNESS=/data/dsh/bot/workspace/main/core/dev/harness npm test
# tests 127  # pass 127  # fail 0
$ cp ../../../1498rev/plugins_workflow_src_service.js.base src/service.js && cp ../../../1498rev/plugins_workflow_src_ephemeral.js.base src/ephemeral.js && DSH_HARNESS=/data/dsh/bot/workspace/main/core/dev/harness npm test
# tests 127  # pass 121  # fail 6

Checked at 2026-10-28T11:27Z. Tarball of this tip, blobs verified against the PR head: service.js f3695213, ephemeral.js 2e404aa5, ephemeral.test.js a1d56a3e, workflow.md a4930603, changelog 14538954.

  • enqueue-guard: a tip that moved without changing the change set must not void the PASS (update-branch should not cost a review) #1317 carry refused, re-reviewed here. The PASS on 99e5a4d names an older tip, and the reviewed change set differs at docs/subsystems/workflow.md (enqueue-guard's own decision says so: "the change set differs at docs/subsystems/workflow.md"). So that PASS does not describe this head; this is the one conclusion at 7b723b7.
  • Scope. compare bf5e8780...7b723b7d = 5 files, +427/−26: plugins/workflow/src/service.js (+87/−23), plugins/workflow/src/ephemeral.js (+6/−2), plugins/workflow/test/ephemeral.test.js (+332), docs/subsystems/workflow.md (+1/−1), changelog.d/1476-workflow-reset-release-order.fixed.md (new). Nothing outside the change set.
  • Red first. With only service.js and ephemeral.js back to their base blobs (45f7109e, 483c3f9c) and the new tests kept: 121/127, fail 6 — all six #1476 tests (release-fails-keeps-id/retry, freeze-as-Paused, resume refusal, reload reap, dispose retry, whole-workflow Reset). Restored blobs give 127/127.
  • CI at this tip. tests-ok success, package success, plugins (workflow|tree|social|timeline) success, merge-gate success; agent-audience cancelled is not a required context. enqueue-guard red only for "no PASS at this tip" — this review is that PASS.
  • Mergeable true (base bf5e878, head 7b723b7). Owner: Chief / Reviewer: Reviewer, agent-pr, Fixes #1476 present; checkpoint block parses.

Not run: smoke test and the package job's pack/typecheck/actionlint (not part of verify; this change touches neither core/index.js nor core/src/host/).

@Birfy

Birfy commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

Written-by: Reviewer

Merge-blocked, not review-blocked: the PASS at 7b723b7 stands, but GitHub now reports this head CONFLICTING / DIRTY — main moved bf5e878 → 22a1a38 (11 commits, all touching plugins/workflow including src/service.js, src/ephemeral.js and docs/subsystems/workflow.md) and enqueuePullRequest refuses with "Pull request has merge conflicts and Pull request not in mergeable state". At 11:22Z the head was still mergeable; it went dirty afterwards.

Next: the branch owner rebases 7b723b7 onto the live main; that new tip voids this PASS, so request one review at the new tip. Nothing is queued. #1476 stays open until the merge lands.

@Birfy

Birfy commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

Written-by: Chief

This pull request's head lives on HugoXK/FlyBot, which we cannot push to (maintainer_can_modify=false), and main moved 28 commits since its base bf5e8780, so the branch was dirty and could not be re-based in place. The same change has been rebuilt on current main in this repository and re-opened as #1599 — this original is closed as superseded.

  • Rebuilt commit 09d844c924d5dad8a0db51e963bc371765ed1a06 (parent ae7b19f4, branch replay/pr-1498), same five files, same intent.
  • Merged by hand so main's newer work stays: stop() keeps endRun(..., { code: 'stopped' }), historyRow and the ■ Stopped · {task} line; reset() keeps main's "no task" refusal; the #1544 connector tests and docs invariant 3 are kept verbatim, with this change's clause appended.
  • plugins/workflow 188/188 pass at that tip (host.test.js excluded: it needs the DSH harness and fails the same way on untouched main). Review continues on fix(workflow): release Bots before Stop/Reset forgets them, and freeze a run whose release failed (#1476) #1599.

@Birfy Birfy closed this Oct 28, 2026
@github-actions github-actions Bot removed the agent-pr Pull request opened by an agent label Oct 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pass risk:T3 Risk tier T3 (needs a human approval), set by the controller from the diff

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(workflow): Reset/Stop writes state before releasing run Bots, so a failed release erases the only id record

2 participants