cd /news/ai-agents/when-cleanup-resets-the-retry-budget · home topics ai-agents article
[ARTICLE · art-125391] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=· neutral

When Cleanup Resets the Retry Budget

An engineer's experiment on Orca, a desktop tool for organizing terminals and agent work, traced a runaway remount bug to a cleanup predicate that consulted the wrong index: terminal rows and unified UI tabs live in separate indexes, so a tab could appear present to the remount path but absent to the cleanup path, erasing its recovery history and resetting the retry budget. In fixture tests, a divergent index produced 200 remounts on the base revision versus 1 on the proposed fix, while a 16-second-spaced schedule yielded 10 versus 3. The proposed patch makes both the remount eligibility check and the disposal check rely on the same terminal-row lookup rather than lowering the retry cap.

by read4 min views3 publishedSep 10, 2026

A retry limiter can record an attempt correctly and still lose control before the next call. An Orca recovery-module experiment exposed the reason: display cleanup erased a terminal's recovery history while that terminal remained eligible for another remount. The useful review target is the cleanup predicate.

Adapted from the complete English research article. Orca is a desktop tool for organizing terminals and Agent work. PR #19745 describes a Windows crash in which eight tabs reportedly remounted 8,878 times in roughly 122.4 seconds. We did not obtain the original crash bundle; those numbers are the author's incident report, not our measurements.

The public code exposes a mechanism worth testing. Terminal rows live in one index, while unified UI tabs live in another. They usually correspond but can diverge.

Remounting consults the terminal-row index. The old budget-release path consulted the unified UI index instead. The same tab could consequently receive two incompatible answers: it existed for the function performing a remount, but appeared absent to the cleanup function deciding whether to erase its recovery history.

Each lookup returned a definite answer. Their combination allowed recovery to discard the evidence of its own activity.

We pinned the base and proposed head revisions and loaded the complete recovery and lookup modules. The original budget calculation, instance disposal, remount and generation-update logic remained intact. We supplied fixtures for store plumbing, time, timers, PTY and logging. We did not start Electron or reproduce graphics-memory exhaustion.

Each cycle registered an instance, requested recovery and unregistered it. We then made the UI index miss a tab whose terminal row remained present. Two request schedules tested different constraints: 10 milliseconds between calls for the cooldown, and 16 seconds to move past the cooldown while remaining inside the cumulative budget window.

Scenario Requests Base remounts Proposed-head remounts
Both indexes agree; 10ms spacing 200 1 1
Terminal row present, UI entry absent; 10ms spacing 200 200 1
Same divergence; 16s spacing 10 10 3

Both rounds agreed. The first row shows that the old limiter was not universally ineffective. It worked when disposal could still see the tab. The second demonstrates history being reset under index divergence. The third separates the cumulative cap from the cooldown: even with requests spaced apart, the old code never retained enough history to reach its limit.

These counts describe successful remounts in the fixture's in-memory store, not production crashes.

The proposed fix does not lower the cap or introduce a second limiter. It makes the question “can this terminal still be remounted?” and the question “has this terminal gone away?” rely on the same terminal-row lookup.

Replacing a display instance does not end the lifetime of the terminal object that owns the recovery budget. If that object can still produce another recovery effect, a missing entry in a different UI projection should not erase the history constraining it.

This is a bounded correction. The two indexes can still disagree elsewhere. The patch chooses the appropriate source of identity for this budget; it does not establish system-wide index consistency.

Merely proving that a storm stops is insufficient: disabling every recovery would also satisfy that test. We retained three controls.

Control Result on both revisions
Fixture removes the terminal row, disposes the instance, then recreates the same ID Two requests produce two remounts
Requests at 0, 16, 32, 48 and 300.001 seconds First three accepted, fourth constrained, final request accepted: four remounts
Replay the old generation after one successful recovery Two requests produce one remount

The close control mutates the fixture's terminal rows; it is not a real UI close action. It checks the budget-release branch. The expiry control checks that the cap does not become permanent, while the stale-generation control checks that delayed requests cannot continue acting on a replaced display instance.

Together, these controls distinguish preserving necessary history from freezing recovery altogether.

The tempting response to a recovery storm is another limit. This case suggests inspecting the existing limit's release conditions first. Who can erase its history? Does that decision rely on the object performing the action, or on a UI projection or cache that can temporarily lose sight of it?

The same question applies to retry counts, failure lockouts and spending budgets. An accurate timestamp is ineffective if the action's own cleanup path deletes it before the next admission decision.

Not every budget needs permanent persistence. Its lifetime does, however, need to cover the object it constrains, and its release predicate needs to agree with the execution predicate. The disappearance of a UI instance does not necessarily end a backing object's history.

The reusable finding is simple: a protection mechanism must both record an action correctly and preserve that record until the next decision that depends on it. Cleanup deserves the same scrutiny as admission.

Test both the admission path and every history-deletion path. Keep controls for real object disposal, window expiry and stale requests so that stopping a storm does not silently disable valid recovery.

Full English edition · 中文版本 · Methods and saved observations

── more in #ai-agents 4 stories · sorted by recency
── more on @orca 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/when-cleanup-resets-…] indexed:0 read:4min 2026-09-10 ·