Skip to content

feat(clmm): manage_clmm tool to recover orphaned LP positions; bin_count on get_pool_info - #204

Open
fengtality wants to merge 13 commits into
mainfrom
feat/lp-close-retry-ownership
Open

feat(clmm): manage_clmm tool to recover orphaned LP positions; bin_count on get_pool_info#204
fengtality wants to merge 13 commits into
mainfrom
feat/lp-close-retry-ownership

Conversation

@fengtality

@fengtality fengtality commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Condor-side of the gateway#678 retry-ownership work, plus the CLMM bin_count wiring, and it absorbs the Derive Options Trader agent rename from the now-closed #202 (see below). Canonical design: docs/retry-architecture.md (in the gateway PR). Agents drive executors through manage_executors, where no controller exists to react to a stranded position — and the tick-prompt summary was RUNNING-only, so a terminal executor still holding a live on-chain position was invisible to the agent.

Orphaned positions

  • ExecutorsProvider: surfaces terminal executors that still own a position (involuntary POSITION_HOLD with hold_reason, the injected orphaned_position flag, or legacy FAILED-with-position) as a reason-aware 🚨 ORPHANED POSITION line with explicit recovery guidance — a fresh lp_executor cannot adopt an existing position and would mint a second one. Also exposed as orphaned_executors in provider data.
  • manage_executors: new orphaned (list recovery candidates) and resolve_orphan (mark recovered) actions wired to the new API endpoints.
  • resolve_orphan without executor_id now returns a required-input error pointing at action="orphaned". It previously fell through get_flow_stage() to show_schema/list_types, so an agent's recovery request was silently answered with executor-type listings.
  • Stop handling: the already_terminated payload (close_type, position address, orphan warning) is surfaced in both the MCP tool result and the Telegram stop menu instead of being treated as a plain stop.
  • guides/lp_executor.md: close-exhaustion terminates as an involuntary POSITION_HOLD (hold_reason: close_retries_exhausted); FAILED means nothing-left-on-chain; orphan recovery flow documented, including that the lp_rebalancer halt is in-memory and clears on controller restart — so restart is the acknowledgment step after resolving.

manage_clmm — the tool that closes an orphan

The lifecycle above could flag an orphan but not clear it. Every warning said to close the position "via the gateway tools" — an instruction with no implementing tool. An agent following it found that manage_executors(action="stop") is a no-op (the executor has already terminated, which is the correct contract), manage_amm handles AMMs only, and explore_dex_pools is read-only. The position stayed open.

  • New manage_clmm tool, mirroring manage_amm: progressive-disclosure guide, per-action validation, dispatch to client.gateway_clmm.*. Actions: position_info, open, add_liquidity, remove_liquidity, close, collect_fees. Pool discovery stays in explore_dex_pools rather than being duplicated.
  • Two details decide whether a recovery call works, both test-pinned: an orphan records its DEX as lp_provider: "orca/clmm" while Gateway routes on the bare "orca", so the connector is normalised; and an lp_executor position is absent from the API database, so close must forward pool_address or the API returns 400.
  • The orphan listing now emits the concrete call, built from the record's own fields — including that connector_name holds the network, not the DEX, which is the easiest way to hand-build a dead call. Records awaiting reconciliation emit no call, so a close is never suggested with an unknown position address.
  • All four dead-end warnings (tick prompt, Telegram stop menu, manage_executors docstring, orphan listing) now name manage_clmm and state that stopping will not close the position.

CLMM bin_count

manage_gateway_clmm(action="get_pool_info", bin_count=N) requests the per-tick liquidity distribution around the active price. Meteora always returns its bins; orca, raydium, uniswap and pancakeswap compute them on request, so the default of 0 keeps pool-info cheap. Requires hummingbot-api-client 1.5.8 (pinned here) for the typed parameter.

Absorbs #202 (Derive Options Trader)

#202 renamed the smart_money_flow agent to derive_options_trader, added the options_flow routine and options_oracle_operator strategy, and moved both strategies off the opencode custom endpoint onto claude-acp:sonnet. It was branched from main before #203, so it missed two gates #203 adds — and its own CI stayed green because those gates don't exist on its base. Merging it here rather than after would have turned main red on merge.

#202 is closed with a comment pointing here.

Dependency: requires the unreleased client 1.5.8

pyproject.toml required ==1.5.8 while uv.lock still resolved 1.5.6, so every uv run --frozen silently re-synced the venv back down. That downgrade is not cosmetic — 1.5.6 has no pool_address on close_position, so manage_clmm's close died with:

TypeError: close_position() got an unexpected keyword argument 'pool_address'

The tool's unit tests stub the client object, so they passed throughout; only a live call surfaced it. The lock now names 1.5.8. Its sdist/wheel hashes are absent because 1.5.8 is not on PyPI yet — a plain uv lock fills them in once hummingbot/hummingbot-api-client#25 merges and releases, and uv lock --check accepts the entry as consistent with pyproject.toml meanwhile.

Until that release uv run --frozen fails loudly (can't be installed because it doesn't have a source distribution or wheel), which is the honest state of the dependency and strictly better than silently running against a client that cannot satisfy the tool. To work locally before the release:

uv pip install --python .venv/bin/python ../hummingbot-api-client
uv run --no-sync python -m pytest tests/

This PR merges last — after #203, then after hummingbot/hummingbot-api-client#25 is released.

Companion PRs

Based on #203

This PR targets feat/trade-panel-dex (#203), not main, since #203 merges first. It has been rebased onto that branch, so the diff here is only this branch's own commits (16 files) rather than 330.

Conflicts resolved during the rebase:

  • tools/gateway_clmm.pyFeat/trade panel dex #203's plain get_pool_info call vs. this branch's bin_count. Resolved to the typed bin_count= call in Feat/trade panel dex #203's formatting; the intermediate _get passthrough commit is superseded later in the series.
  • formatters/__init__.pyFeat/trade panel dex #203 reformatted imports and moved the gateway block below executors; format_clmm_result added to the relocated block.
  • schemas.pyFeat/trade panel dex #203 reflowed the AMMRequest tail to multi-line; kept their formatting and appended CLMMRequest after it.
  • uv.lockFeat/trade panel dex #203 bumps the client to the published 1.5.7, this branch needs 1.5.8 (see below); resolved to 1.5.8.

#203 also adds a CI gate (black --check ., isort --check .) that main does not have, so a formatting-only commit runs the locked tools (black 26.1.0, isort 8.0.1) over this branch's files.

The liquidity depth column in #203 shows bins only for Meteora until fetch_liquidity_bins passes bin_count — details and the one-line change are in a comment on that PR.

Merge order

  1. Feat/trade panel dex #203 — the base of this branch
  2. feat(clmm): bin_count, CLMM liquidity methods, and orphan-closable positions (1.5.8) hummingbot-api-client#25 — released to PyPI as 1.5.8
  3. this PR

Until step 2, uv sync here cannot install (hummingbot-api-client==1.5.8 is not yet on PyPI), so CI will be red at the dependency step. Lint/test failures inherited from the base branch are being addressed in #203; all 12 Python files in this PR pass black and isort under the locked versions.

Validation

2268 tests pass on the rebased branch (uv run --no-sync against a locally built 1.5.8), including 24 covering manage_clmm dispatch/validation and the exact recovery call the orphan listing emits, plus the resolve_orphan required-input contract. One unrelated test, test_agents.py::test_numeric_credentials_reach_the_subprocess_as_strings, fails identically on the bare feat/trade-panel-dex base. Validated live on mainnet with the companion branches deployed: forced close-failure cascade → 🚨 orphan surfaced in the tick prompt → already_terminated on re-stop → recovery → resolve_orphan cleared it. bin_count=4 returns populated bins for orca and raydium through the MCP tool; bin_count=0 returns none.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Mt84XBEMVxbbyMG8fDxDKj

@greptile-apps

greptile-apps Bot commented Aug 13, 2026

Copy link
Copy Markdown

Greptile Summary

The PR adds CLMM orphan-position recovery, exposes orphan lifecycle information through executor tooling, wires bin_count into CLMM pool information, and incorporates the Derive Options Trader rename and strategy additions.

  • Adds manage_clmm operations and concrete orphan-recovery instructions.
  • Adds orphan listing and resolution actions to executor management.
  • Adds CLMM liquidity-bin configuration and updates the API client dependency.
  • Replaces Smart Money Flow with the Derive Options Trader agent and options-based routines.

Confidence Score: 5/5

The PR appears safe to merge after its explicitly documented dependency release prerequisite is satisfied.

No blocking failure remains; the previously reported resolve_orphan fallthrough is fixed by unconditional action routing and an explicit missing-ID response.

Important Files Changed

Filename Overview
mcp_servers/hummingbot_api/schemas.py Adds unconditional routing for orphan actions, explicit CLMM request fields, and the tested fix for missing resolve_orphan IDs.
mcp_servers/hummingbot_api/tools/executors.py Adds orphan discovery and resolution flows while surfacing already-terminated executor state and recovery guidance.
mcp_servers/hummingbot_api/tools/gateway_clmm.py Adds direct CLMM position-management dispatch, validation, connector normalization, and pool-address forwarding.
condor/agents/providers/executors.py Exposes terminal executors that may retain on-chain positions and provides reason-aware recovery instructions.
agents/derive_options_trader/routines/options_flow.py Introduces the Derive options signal routine used by the renamed trading agent.
uv.lock Updates the locked API client requirement to the acknowledged unreleased 1.5.8 dependency.

Sequence Diagram

sequenceDiagram
    participant Agent
    participant Executors as manage_executors
    participant CLMM as manage_clmm
    participant Gateway
    Agent->>Executors: "action="orphaned""
    Executors-->>Agent: position, pool, connector, network
    Agent->>CLMM: "action="close" with position and pool"
    CLMM->>Gateway: close_position(...)
    Gateway-->>CLMM: close result
    CLMM-->>Agent: position closed
    Agent->>Executors: "action="resolve_orphan", executor_id"
    Executors-->>Agent: orphan marked recovered
Loading

Reviews (13): Last reviewed commit: "test(agents): teach the numeric-credenti..." | Re-trigger Greptile

Comment thread mcp_servers/hummingbot_api/schemas.py Outdated
fengtality added a commit that referenced this pull request Aug 13, 2026
… error

Greptile P1 on #204: get_flow_stage() required executor_id for the
resolve_orphan action, so a call missing the id silently fell through to
show_schema/list_types and the recovery request was ignored. The action now
always routes to resolve_orphan and the tool returns an explicit error
pointing at action="orphaned" to find candidates.

Also documents in the LP executor guide that resolve_orphan updates the API
database only — an lp_rebalancer controller's in-memory orphan halt clears
on controller restart, so restart after resolving.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Aug 13, 2026

Copy link
Copy Markdown

Want your agent to iterate on Greptile's feedback? Try greploops.

@fengtality fengtality changed the title feat(executors): surface orphaned LP positions to agents — tick-prompt warnings, orphaned/resolve_orphan actions feat(clmm): surface orphaned LP positions to agents; bin_count on get_pool_info Aug 13, 2026
@rapcmia

rapcmia commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Test update:
image

  • Build local hbot-lib image using hbot/8424
  • Integrate the local hbot-lib to HAPI/217 and build local images including GW/679
  • Integrate HAPI-client/25 on local v1.5.8 and setup with condor/204
  • Deploy HAPI/217 make setup; make deploy successfully
  • Install and run condor/204 make install; make run ok
  • Successfully deploy webUI

Local hummingbot-api-client v1.5.8 integration ✅

  • Condor started with the local Hummingbot API client version 1.5.8 and connected successfully to the local Hummingbot service.
  • Read-only pool lookups worked for Orca, Meteora DAMM v2, and Meteora DLMM. The returned information included prices, fees, reserves, and liquidity details.
  • The Meteora DAMM v2 pool-info tool returned the expected price, reserves, and fee data.
  • A Meteora DLMM lookup accepted bin_count=20 and returned 141 liquidity-bin entries around the active price.
  • Meteora returns its available bins, so this is expected and is not limited to 20 entries.

Test still in progress

@rapcmia

rapcmia commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Test update:

  • Condor used the local API client successfully and read Orca and Meteora pool information. ✅
  • Empty orphan checks, missing recovery selection, and repeat stops on ended executors behaved safely. ✅
  • A real Orca position that could not close was clearly shown as an orphaned position instead of disappearing. ✅
  • Condor showed the orphan warning and affected position ✅
    #### Test scenario
      - Opened LP excutor on Orca
      - Transferred all SOL balance to USDC until it is flat 0
      - Asked agent to close the position
      - Retries until 10/10 occurred 
    
    #### live orphan state is now confirmed.
    curl -sS -u admin1:admin2 -H 'Content-Type: application/json' \
      -X POST http://localhost:8000/executors/search \
      -d '{"executor_types":["lp_executor"]}' | jq
    
    {
      "executor_id": "36Xg…bcMn",
      "status": "TERMINATED",
      "close_type": "POSITION_HOLD",
      "position_address": "8i1u…sUhA",
      "current_retries": 11,
      "max_retries_reached": true,
      "hold_reason": "close_retries_exhausted"
    }
    
    curl -sS -u admin1:admin2 \
      http://localhost:8000/executors/positions/orphaned | jq
    
    {
      "count": 1,
      "orphans": [{
        "executor_id": "36Xg…bcMn",
        "close_type": "POSITION_HOLD",
        "position_address": "8i1u…sUhA",
        "hold_reason": "close_retries_exhausted"
      }]
    }
    
  • The close process retried with increasing delays before stopping and leaving the position visible. ✅
    • It waited longer between attempts: 2, 4, 8, 16, then 30 seconds.
    • After the normal limit of 10 retries, the next failed attempt stopped the
      executor but kept the open position visible for recovery.
  • Marking an orphan as recovered removed it from the warning and recovery list. ✅
    • From the test i did (resolved_orphan), it seems it was a acknowledgement and did not close the position (using tools or gateway route) using Orca and meteora ❗

Test CLMM bin_count

image
  • Orca and Raydium pool lookups both returned no bins with bin_count=0 and exactly 20 bins with bin_count=20.
  • Meteora accepted the value but returned all 141 populated bins for both requests. This is its expected connector behavior, it does not limit bins.
  • All checks used the normal read-only pool lookup. No positions, trades, or funds were changed.

@rapcmia

rapcmia commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Test update:

  • Setup a orphaned lp_executor
    curl -sS --max-time 15 -u "$HBOT_API_USER:$HBOT_API_PASSWORD" \
      http://localhost:8000/executors/positions/orphaned | jq
    
    {
      "count": 1,
      "orphans": [
        {
          "executor_id": "HJJUFaSZdThCH6rRv5agcVCZ4widziThm1aRdh2LtcTW",
          "executor_type": "lp_executor",
          "connector_name": "solana-mainnet-beta",
          "trading_pair": "SOL-USDC",
          "close_type": "POSITION_HOLD",
          "position_address": "H4vD69DsraHjHyKvRwRPHVGe2aJkvAUaNK5tMif2CiNw",
          "hold_reason": "close_retries_exhausted",
          "needs_onchain_reconciliation": false
        }
      ]
    }
    

Test orphan recovery acknolwedgement

  • The orphan warning tells the agent to close the position using gateway tools, then call resolve_orphan.
  • For Meteora DLMM or Orca Whirlpool LP-executor positions, the currently exposed MCP tools cannot close the on-chain CLMM position:
    • manage_executors(action="stop") is a no-op because the executor is already terminated.
    • manage_amm(action="remove_liquidity") does not support these CLMM position types. Its Meteora support is for DAMM v2; Orca is unsupported.
    • explore_dex_pools is read-only.
  • The underlying Gateway API has a CLMM close endpoint, but no MCP tool currently exposes it.

Telegram stop handling for an already-terminated orphan

Stop executor HJJUFaSZdThCH6rRv5agcVCZ4widziThm1aRdh2LtcTW.


✅ mcp.condor.consult (19s)

I’ll submit the stop request only for that executor.Stop request completed as a no-op: the executor was already TERMINATED with POSITION_HOLD.

No LP position or orphan record was changed.
  • It accepted the stop request.
  • It correctly treated it as a no-op.
  • The executor remained terminated.
  • No LP position or orphan record was changed.

@fengtality fengtality changed the title feat(clmm): surface orphaned LP positions to agents; bin_count on get_pool_info feat(clmm): manage_clmm tool to recover orphaned LP positions; bin_count on get_pool_info Aug 17, 2026
fengtality added a commit that referenced this pull request Aug 17, 2026
… error

Greptile P1 on #204: get_flow_stage() required executor_id for the
resolve_orphan action, so a call missing the id silently fell through to
show_schema/list_types and the recovery request was ignored. The action now
always routes to resolve_orphan and the tool returns an explicit error
pointing at action="orphaned" to find candidates.

Also documents in the LP executor guide that resolve_orphan updates the API
database only — an lp_rebalancer controller's in-memory orphan halt clears
on controller restart, so restart after resolving.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@fengtality
fengtality force-pushed the feat/lp-close-retry-ownership branch from add49f5 to 02c8d94 Compare August 17, 2026 17:54
@fengtality
fengtality changed the base branch from main to feat/trade-panel-dex August 17, 2026 17:55
@fengtality

Copy link
Copy Markdown
Contributor Author

@greptile-apps

@fengtality
fengtality changed the base branch from feat/trade-panel-dex to main August 18, 2026 18:35
fengtality and others added 10 commits August 18, 2026 11:36
…t warnings, orphaned/resolve_orphan actions

Condor-side of the gateway#678 retry-ownership work (canonical design:
docs/retry-architecture.md in the companion gateway PR). Agents drive
executors through manage_executors, where no controller exists to react
to a stranded position — and the tick-prompt summary was RUNNING-only, so
a terminal executor holding a live on-chain position was invisible:

- ExecutorsProvider surfaces terminal executors that still own a position
  (involuntary POSITION_HOLD with hold_reason, the injected
  orphaned_position flag, or legacy FAILED-with-position) as a
  reason-aware ORPHANED POSITION warning with explicit recovery guidance:
  close via the gateway tools by position address — a fresh lp_executor
  CANNOT adopt an existing position and would mint a second one — then
  mark recovered. Also exposed as orphaned_executors in provider data.
- manage_executors gains orphaned (list recovery candidates) and
  resolve_orphan (mark recovered) actions wired to the new API endpoints.
- stop handler surfaces the already_terminated payload (close_type,
  position_address, orphan warning) instead of treating it as a plain
  stop; Telegram stop menu shows the same.
- guides/lp_executor.md: close-exhaustion now terminates as an
  involuntary POSITION_HOLD (hold_reason=close_retries_exhausted), FAILED
  means nothing-left-on-chain, and the orphan recovery flow.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HahKfEY9rvKnZijrzUAFSq
… error

Greptile P1 on #204: get_flow_stage() required executor_id for the
resolve_orphan action, so a call missing the id silently fell through to
show_schema/list_types and the recovery request was ignored. The action now
always routes to resolve_orphan and the tool returns an explicit error
pointing at action="orphaned" to find candidates.

Also documents in the LP executor guide that resolve_orphan updates the API
database only — an lp_rebalancer controller's in-memory orphan halt clears
on controller restart, so restart after resolving.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Regression cover for d8012bd: a resolve_orphan call with no executor_id must
route to the resolve_orphan stage and return an actionable error, rather than
falling through get_flow_stage() to show_schema/list_types and answering a
recovery request with executor-type listings.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Agents can now request the per-tick liquidity distribution around the active
price via manage_gateway_clmm(action="get_pool_info", bin_count=N), which the
companion API forwards to Gateway. Meteora always returns its bins; orca,
raydium, uniswap and pancakeswap compute them on request, so the default of 0
keeps pool-info cheap.

The client library's get_pool_info has no bin_count parameter, so requests
with bins go straight to the endpoint — the same passthrough the executors
tools use for newer routes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1.5.8 adds bin_count to gateway_clmm.get_pool_info, so the tool calls the
typed client method instead of reaching past it to the endpoint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The orphan warning told the agent to "close the position via the gateway tools
(remove liquidity by position address)" — an instruction with no implementing
tool. Following it, an agent found that manage_executors(action="stop") is a
no-op (the executor has already terminated, which is the correct contract),
manage_amm handles AMMs only, and explore_dex_pools is read-only. The position
stayed open and the recovery loop dead-ended.

Adds manage_clmm, mirroring manage_amm: progressive-disclosure guide, per-action
validation, dispatch to client.gateway_clmm.*. Actions: position_info, open,
add_liquidity, remove_liquidity, close, collect_fees. Pool discovery stays in
explore_dex_pools rather than being duplicated.

Two details decide whether a recovery call actually works, and both are covered
by tests:

- an orphan records its DEX as lp_provider "orca/clmm" while Gateway routes on
  the bare "orca", so the connector is normalised
- an lp_executor position is not in the API database, so close must forward
  pool_address or the API returns 400

The orphan listing now emits the concrete call rather than prose, built from the
record's own fields — including that connector_name holds the network, not the
DEX, which is the easiest way to construct a dead call by hand. Records still
awaiting reconciliation emit no call, so no close is ever suggested with an
unknown position address.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mt84XBEMVxbbyMG8fDxDKj
Four places told the agent (or the Telegram user) to close an orphaned position
"via the gateway tools" — the tick-prompt warning, the Telegram stop menu, the
manage_executors docstring, and the orphan listing. None named a tool that could
do it, and the nearest guess, stopping the executor, is a no-op because it has
already terminated.

All four now name manage_clmm(action="close") and say plainly that stopping will
not close the position.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mt84XBEMVxbbyMG8fDxDKj
pyproject already required ==1.5.8, but uv.lock still resolved 1.5.6, so every
`uv run --frozen` silently re-synced the venv back down. That downgrade is not
cosmetic: 1.5.6 has no pool_address on close_position and no add/remove
liquidity, so manage_clmm's close died with

    TypeError: close_position() got an unexpected keyword argument 'pool_address'

The lock now names 1.5.8. Its sdist/wheel hashes are absent because 1.5.8 is not
published yet — they get filled in by a plain `uv lock` once hummingbot-api-client#25
merges and releases. `uv lock --check` accepts the entry as consistent with
pyproject in the meantime.

Until that release, `uv run --frozen` fails loudly:

    Distribution `hummingbot-api-client==1.5.8` can't be installed because it
    doesn't have a source distribution or wheel for the current platform

which is the honest state of the dependency, and better than silently running
against a client that cannot satisfy the tool. To work locally before the
release, install the client from source and skip the re-sync:

    uv pip install --python .venv/bin/python ../hummingbot-api-client
    uv run --no-sync python -m pytest tests/

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mt84XBEMVxbbyMG8fDxDKj
Rebasing onto #203 moves this branch onto a base that enforces
`black --check .` and `isort --check .` in CI, which main did not. The code was
written to match the surrounding pre-reformat style, so it needs a pass with the
locked tools (black 26.1.0, isort 8.0.1).

Formatting only — no behaviour change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mt84XBEMVxbbyMG8fDxDKj
Last agent still on `claude-acp:opus`; every other claude-acp agent already
runs sonnet, so this makes the default uniform across the agent set.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mt84XBEMVxbbyMG8fDxDKj
fengtality and others added 3 commits August 18, 2026 11:39
- Agent identity is now options-first: the Derive options positioning read
  (25D risk reversal, put/call OI, IV term structure, net GEX) is the core
  signal, with the options_flow routine and Derive public API reference
  documented at agent level.
- The smart-money capital-flow content (cross-market regime + Solana
  on-chain pulse) moves out of AGENT.md into a renamed smart_money_flow
  strategy (was derive_flow_trader), which now also reads options_flow
  each tick as a confirmation/sizing input and tie-breaker.
- Add options_flow routine and options_oracle_operator strategy; set both
  strategies to a 5-minute cadence and agent_key claude-acp:sonnet.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- `options_flow.py` failed `black --check` and `isort --check`, which #203's CI
  enforces repo-wide. Formatting only.
- `options_flow.py` line 433 wrote a Markdown underscore escape as `\_` inside a
  non-raw string. Python does not recognise `\_`, so it kept the two characters
  but raised SyntaxWarning (an error in a future version). Doubled to `\\_`:
  identical rendered output, no warning.

The GeckoTerminal rate-gate guard needed no fix here. #202 only *renamed*
`onchain_flow.py`; #203 had already rewritten that file to call
`pool_data.gecko_request`, so the merge took the rename with the rate-gated
content and `test_nobody_hand_builds_a_geckoterminal_url` passes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mt84XBEMVxbbyMG8fDxDKj
…redicate

build_mcp_servers_for_session now holds every server candidate to
has_server_access(user_id, name) before its credentials go into the
subprocess env. The _NumericPasswordServer stub predates that check, so
the test died on AttributeError instead of exercising the str-coercion
it pins. Grant the stub unconditional access — the test's subject is
credential stringification, not authorization.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0166iQoxKce23GkUwuQJxdkr
@fengtality
fengtality force-pushed the feat/lp-close-retry-ownership branch from 02684d5 to 3d9f2ef Compare August 18, 2026 18:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants