fix(agents): refuse a plain stop that would orphan on-chain positions - #184
Open
fengtality wants to merge 1 commit into
Open
fix(agents): refuse a plain stop that would orphan on-chain positions#184fengtality wants to merge 1 commit into
fengtality wants to merge 1 commit into
Conversation
Stopping a strategy that still holds open positions silently stranded them. `engine.stop()` cleans up executor tracking (executors land in SYSTEM_CLEANUP) while the on-chain position stays live, so the normal `stop_executor(keep_position=False)` close path can no longer reach it. Recovery means going around the executor layer entirely. This is only wrong for agents whose shutdown policy declares `on_kill_switch: flatten_all` -- those are saying their positions are risk to close, not spot to keep. For them a plain stop is almost always a mistake; `shutdown` is the operation that winds down per shutdown.md. Guard `/stop` for exactly that case: 409 with the open executors and positions named, pointing at `shutdown`, with `force=true` as the explicit override. Other policies (keep_all, keep_spot_close_perp) are untouched, as is stopping an agent that holds nothing. `open_risk()` reuses the winddown's own executor/position lookups so the guard and the shutdown path cannot disagree about what "open" means. In the all-instances branch every engine is guarded before any is stopped, so a 409 can't leave half the instances down. Verified against the failure it fixes. Before, stopping the LP agent with two live positions succeeded and left both as SYSTEM_CLEANUP with ~$25 stranded on-chain and no alert. After, the same stop returns 409 naming the open position, and `shutdown` attempts the flatten and raises its stranded-position alert when a swap fails -- no silent orphan. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0154EUNSY4ocqsWPKZWgwBJn
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Split out of #162 (unrelated to the LP agent content there).
Problem
engine.stop()tears down executor tracking — executors land inSYSTEM_CLEANUP— while any on-chain position stays live. Once tracking is gone,stop_executor(keep_position=false)can't reach the position, so recovery means going around the executor layer entirely.Hit for real: stopping an LP agent with two live CLMM positions succeeded, marked both
SYSTEM_CLEANUP, and left ~$25 open on-chain with no alert. Found by accident.Fix
Only applies to agents declaring
on_kill_switch: flatten_all— for them, positions are risk to close, never spot to keep.keep_allandkeep_spot_close_perpare untouched, as is stopping an agent holding nothing.condor/agents/shutdown.py—open_risk(engine)reuses the winddown's own lookups so the guard and shutdown can't disagree about what "open" means.condor/web/routes/agents.py—_guard_stop_orphaning()raises 409 naming what's open;force=trueoverrides. In the all-instances branch every engine is guarded before any is stopped, so a 409 can't leave half stopped.stopw/ open riskSYSTEM_CLEANUP×2🤖 Generated with Claude Code