Skip to content

feat(phoenix): add Eternal state preparation - #9

Open
92Infinitus92 wants to merge 6 commits into
feat/scenarios/phoenix-eternalfrom
feat/phoenix-eternal-integrated
Open

92Infinitus92 wants to merge 6 commits into
feat/scenarios/phoenix-eternalfrom
feat/phoenix-eternal-integrated

Conversation

@92Infinitus92

@92Infinitus92 92Infinitus92 commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Adds declarative state preparation for Phoenix Eternal:

  • trader collateral stress
  • direct mark-price shock
  • spot/perp reference-price divergence
  • two-stage liquidation cascade scenarios
  • live market discovery and account validation
  • HTTP and MCP scenario builders
  • pinned BTC and SOL behavioral fixtures

The implementation prepares protocol state only. It does not
build or execute trading or liquidation transactions.

Verification

  • Phoenix unit and materialization tests
  • CLI endpoint tests
  • MCP tool tests
  • Rust formatting and compilation
  • Clippy
  • pinned Phoenix Eternal and Hawkeye behavioral verification
  • real orderbook transaction against the pinned fixture

Stacking

This PR is stacked on feat/pump-protocol.

Once the Pump PR is merged into develop, this branch will be rebased and retargeted to develop.

Greptile Summary

The PR adds declarative Phoenix Eternal state preparation, including collateral, market-price, divergence, and liquidation-cascade scenario builders.

  • Registers Phoenix Eternal scenario templates and protocol support.
  • Adds typed Phoenix account materialization and collateral-index synchronization.
  • Exposes Phoenix discovery and scenario-building through MCP.
  • Adds pinned behavioral fixtures and materialization tests.

Confidence Score: 4/5

The PR is not yet safe to merge because MCP scenario staging still ignores the Studio server’s configured interface and port.

The embedded MCP service receives no runtime scenario API endpoint, and stage_scenario continues posting to fixed IPv4 loopback port 18488; this leaves the previously reported non-default-port, non-loopback, and IPv6-only listener failures outstanding.

Files Needing Attention: crates/mcp/src/surfpool/mod.rs, crates/cli/src/http/mod.rs

Important Files Changed

Filename Overview
crates/core/src/scenarios/protocols/phoenix-eternal/v1/state_builder.rs Builds and validates Phoenix Eternal market and collateral scenario state.
crates/core/src/surfnet/svm.rs Adds Phoenix-specific account materialization, typed price forging, collateral-index synchronization, and same-slot patch preservation.
crates/mcp/src/surfpool/mod.rs Adds Phoenix MCP builders and account discovery while the previously reported runtime Studio-endpoint propagation problem remains.
crates/types/src/scenarios.rs Extends scenario-facing types required by the Phoenix builders and templates.

Sequence Diagram

sequenceDiagram
    participant Client
    participant MCP as Phoenix MCP Builder
    participant Surfnet as Surfnet RPC
    participant API as Scenario API
    Client->>MCP: Build Phoenix scenario
    MCP->>Surfnet: Read live market/trader accounts
    Surfnet-->>MCP: Account state
    MCP->>MCP: Validate and construct overrides
    MCP->>API: POST /v1/scenarios
    API-->>MCP: Scenario id
    MCP-->>Client: Studio editor URL
Loading

Reviews (23): Last reviewed commit: "refactor(phoenix): trim duplicate tests ..." | Re-trigger Greptile

@92Infinitus92 92Infinitus92 self-assigned this Aug 20, 2026
Comment thread crates/core/src/surfnet/svm.rs Outdated
@github-actions

Copy link
Copy Markdown
  • P1 — crates/core/src/surfnet/svm.rs:2806: Each Phoenix override refreshes and reinstalls the remote PerpAssetMap. Multiple same-slot overrides targeting that map therefore erase earlier patches. Refresh shared accounts once per materialization batch, or preserve already-modified target accounts.

  • P1 — crates/mcp/src/surfpool/mod.rs:1116: Phoenix MCP builders hard-code port 18488, while --studio-port is configurable. All builders fail when the studio uses another port. Pass the configured studio address into the MCP server instead of using the constant.

@github-actions

Copy link
Copy Markdown
  • [P1] crates/mcp/src/surfpool/mod.rs:1116: All new Phoenix MCP builders post to the compile-time default port. When --studio-port is configured, requests go to the wrong server and generated editor URLs are also invalid. Pass the runtime Studio address into Surfpool and use it for endpoints and URLs.

Comment thread crates/core/src/surfnet/svm.rs Outdated
@92Infinitus92

Copy link
Copy Markdown
Collaborator Author

@greptileai

@github-actions

Copy link
Copy Markdown
  • High – Phoenix overrides silently use stale state when refresh fails (svm.rs): Missing graph accounts or RPC errors only emit warnings; materialization then patches whatever account is already in the SVM and returns success. This defeats fetchBeforeUse, can produce an invalid Phoenix graph, and consumes the scheduled override without retry. Return an error—or skip/requeue the override—when the required refresh is incomplete.

@github-actions

Copy link
Copy Markdown
  • [P1] Make cascade registration/materialization atomic — svm.rs:2733: overrides are removed before fallible Phoenix refresh/patching. If slot-0 collateral preparation fails, the RPC returns an error but the slot-1 mark shock remains scheduled, so a “failed” cascade can later execute only its destructive second stage. Restore/cancel all scenario overrides on failure, or validate/materialize before committing future stages.

@92Infinitus92
92Infinitus92 force-pushed the feat/phoenix-eternal-integrated branch from fdd0f55 to ecdbc0c Compare August 31, 2026 05:15
@92Infinitus92
92Infinitus92 changed the base branch from feat/pump-protocol to fix/pump-local-first-scenario-creation August 31, 2026 05:15
@92Infinitus92

Copy link
Copy Markdown
Collaborator Author

@greptileai

@92Infinitus92
92Infinitus92 force-pushed the feat/phoenix-eternal-integrated branch 2 times, most recently from bfecef3 to eb85f90 Compare August 31, 2026 06:21
Comment thread crates/cli/src/http/mod.rs Outdated
@92Infinitus92
92Infinitus92 force-pushed the feat/phoenix-eternal-integrated branch from eb85f90 to 6f4a50f Compare August 31, 2026 06:29
Comment thread crates/cli/src/http/mod.rs Outdated
@92Infinitus92
92Infinitus92 force-pushed the feat/phoenix-eternal-integrated branch from 6f4a50f to ca1c453 Compare August 31, 2026 06:38
Comment thread crates/cli/src/http/mod.rs Outdated
@92Infinitus92
92Infinitus92 force-pushed the feat/phoenix-eternal-integrated branch from ca1c453 to 6f864e5 Compare August 31, 2026 06:45
Comment thread crates/mcp/src/surfpool/mod.rs Outdated
Comment on lines +179 to +184
pub fn new() -> Self {
let local = format!(
"http://127.0.0.1:{}",
CHANGE_TO_DEFAULT_STUDIO_PORT_ONCE_SUPERVISOR_MERGED
);
Self::with_urls(local.clone(), local)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Standalone staging ignores configured port

When standalone surfpool mcp is used with a Studio server on a non-default --studio-port, Surfpool::new() still targets 127.0.0.1:18488, causing Phoenix scenario staging to post to the wrong server and fail.

Knowledge Base Used: MCP server integration

Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/mcp/src/surfpool/mod.rs
Line: 179-184

Comment:
**Standalone staging ignores configured port**

When standalone `surfpool mcp` is used with a Studio server on a non-default `--studio-port`, `Surfpool::new()` still targets `127.0.0.1:18488`, causing Phoenix scenario staging to post to the wrong server and fail.

**Knowledge Base Used:** [MCP server integration](https://app.greptile.com/limechain/-/custom-context/knowledge-base/limechain/surfpool/-/docs/mcp-server.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code Fix in Codex Fix in Cursor

Comment thread crates/cli/src/http/mod.rs Outdated
@92Infinitus92
92Infinitus92 force-pushed the feat/phoenix-eternal-integrated branch from 6f864e5 to 9cf8066 Compare August 31, 2026 06:59
@92Infinitus92

92Infinitus92 commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator Author

@greptileai This axis is intentionally reverted to the established team convention: the MCP tools use the shared default-port constant inline, exactly as the pump tool on the base branch does. The constant's own name (CHANGE_TO_DEFAULT_STUDIO_PORT_ONCE_SUPERVISOR_MERGED) is the tracked follow-up — runtime addresses arrive with the supervisor work, for every tool at once, rather than piecemeal per PR. A non-default Studio port is not a supported configuration today anyway: the dashboard's own /config fetch breaks on it, independent of MCP. Standalone surfpool mcp has no configuration channel at all (the command takes no flags), so the constant is that mode's contract by construction. So please check your score as I believe is unproper 4/5

@greptile-apps

greptile-apps Bot commented Aug 31, 2026

Copy link
Copy Markdown

That context is valid. Given the current contract, the inline CHANGE_TO_DEFAULT_STUDIO_PORT_ONCE_SUPERVISOR_MERGED usage is intentional and consistent with the existing Pump MCP tool; a non-default Studio listener is not a supported configuration today, and runtime endpoint plumbing is deliberately deferred to the supervisor work. I’m withdrawing this finding for the current PR rather than treating the fixed default port as a merge blocker.

@92Infinitus92
92Infinitus92 force-pushed the feat/phoenix-eternal-integrated branch from 9cf8066 to 989d4bd Compare September 2, 2026 07:07
@92Infinitus92
92Infinitus92 changed the base branch from fix/pump-local-first-scenario-creation to develop September 2, 2026 07:07
@92Infinitus92
92Infinitus92 force-pushed the feat/phoenix-eternal-integrated branch 2 times, most recently from 1d5ce77 to cd94ac3 Compare September 8, 2026 05:58
@failfmi
failfmi changed the base branch from develop to feat/scenarios/phoenix-eternal September 9, 2026 11:39
…lateral

Move collateral, direct-mark, and reference scenarios onto the generic IDL
override path and drop the bespoke forge for the parts the IDL can name.
Fetch the market catalog live via list_phoenix_markets instead of hardcoding
it. Write a hot trader's effective collateral into GlobalTraderIndex, where
the risk engine actually reads it, not the stale copy in the Trader account.
Remove the dead cascade example and editor schema and trim the builder.
…tion

A Phoenix override with a bad value returned an error out of
materialize_overrides_for_slot, which the block-production runloop
turned into a simnet abort. Every Phoenix branch now warns with the
override id and continues, like the shared IDL path.

- dispatch the PerpAssetMap writer on the account discriminant, so the
  other Phoenix account types keep the generic IDL path
- fill the fork gap once for GlobalConfig and the trader index instead
  of refetching per override
- log the skipped same-slot refresh at warn
- validate dynamic_ref values in create_scenario and say which tool
  resolves them
- assert the templates' PerpAssetMap address against GlobalConfig in
  the live suite; keep every retry error in the live fetch helper
@92Infinitus92
92Infinitus92 force-pushed the feat/phoenix-eternal-integrated branch from e5c5bcc to 204c28a Compare September 9, 2026 11:48
Only traderState.quoteLotCollateral is mirrored into the GlobalTraderIndex, so any other TraderState
write on a hot Trader is now refused at scenario creation and skipped at Play. Every Trader override
checks the embedded header key at Play, not just the hot ones. The index and GlobalConfig stay
local-first: a refresh of one Trader must not reinstall the shared index over mirrors that earlier
scenarios prepared.
No behavior change. The PR shrinks by about 600 lines:

- live tests: drop the three synthetic materialize_* copies of the unit
  tests and the duplicate second-market block; one phoenix_market_scenario
  helper replaces the three scenario builders
- collateral: one table-driven index lookup test, cold-trader Play test
  covers the happy path and the mismatched key, duplicate builder and
  header tests removed, one parse_quote_lot_collateral for both callers
- state_builder: forge dispatch matches on the sorted key set, the owner
  check runs once, unique_subslice_offset is a windows scan, the patch and
  forge test pairs are merged
- mcp: list_phoenix_markets uses a fallible inner function; the two
  staging rejection tests become one table
- README: one verification section instead of three overlapping ones
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.

1 participant