103: EMC Perps: propagate Phoenix TWAP warnings through the tree to Perpetual Contracts

This commit is contained in:
2026-10-26 06:38:53 +01:00
parent e71a8daa8d
commit cfb49ed896
22 changed files with 797 additions and 7696 deletions
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-10-26
@@ -0,0 +1,31 @@
# Design
## Context
See proposal.md for motivation. The adapter currently reads TWAP only when positions exist, and its decoder returns only a position-keyed map. Immutable account/snapshot records and identity-based JavaFX reconciliation already support retained observations.
## Goals / Non-Goals
**Goals:** Preserve eligible orders independently of matching, render actionable reasons with exact ownership, and summarize distinct orders through collapsed trees.
**Non-Goals:** Order cancellation, predicting execution failure, new polling or notifications, changes to capital or liquidation calculations.
## Decisions
- Return matched TWAPs and account-owned warning observations from decoding. Warning data holds TWAP address/order sequence, asset/subaccount identity, raw counters/fills, typed reason, optional matched position symbol and original receipt time. Keep compatible constructors for public records. A generic untyped UI message or synthetic position would lose ownership and distort totals.
- Read TWAP after trader state for every existing account. Fetch metadata for held positions or eligible filled outstanding orders; never request marks for warning-only markets. Empty unregistered authorities need no TWAP/market reads. Continue strict schema, counters, duplicate and identity validation, including orders that are ultimately hidden.
- Missing market and missing open position produce account-owned warnings. A matched order whose next execution estimate is unavailable keeps its progressbar plus a timing warning: this states unavailable timing, not a stopped order. Zero fills and zero remaining children stay invisible. Do not treat absence of optional USD valuation alone as a warning.
- Map matched warnings to positions, unmatched Cross warnings to their real Cross group (including zero-capital accounts), and propagate all through venue/wallet/root. An unmatched isolated order with no reliable position remains on Phoenix with its true isolated subaccount in the tooltip; inventing a Cross owner would violate identity. Existing risk reads also cover newly visible warning-only Cross accounts.
- Format warnings only in EMC. Build summaries from underlying observations, keyed by wallet plus account/order identity, rather than counting child indicators. Render an amber vector triangle with a readable label, retained/stale qualifier and detailed source tooltip. Five minutes is the same observation-age cutoff as existing risk; it is not an execution deadline. Existing three-second polling reevaluates age without moving source timestamps or rebuilding retained rows.
- A successful observation replaces warning lists; failures retain the complete prior venue. Consumer read failures qualify all visible summaries. Normal TWAP bars and Risk remain separate.
## Risks / Trade-offs
- Extra reads for registered empty accounts → reuse shared pacing/cooldown; fetch metadata only if needed and no extra marks.
- Missing metadata prevents quantities and symbols → show raw asset ID/lots and explicitly unknown values.
- Nonatomic state/TWAP reads can temporarily report no matching position → describe only the observed mismatch and let the next successful read reconcile it.
- Aggregation could duplicate orders or hide stale sources → distinct identity keys, per-source times/status, multi-wallet and collapsed-tree checks.
## Migration Plan
Build and verify locally with temporary harnesses and JavaFX images. Update the three main specs and meaningful docs after implementation. Deployment remains a separate owner action; no commits, pushes or Hub restart. Reverting these source changes restores prior presentation without changing orders.
@@ -0,0 +1,28 @@
# Proposal
## Why
Issue #103 addresses a real Phoenix order with fills and remaining children that disappears from EMC because its market metadata is missing. Retaining and propagating a concise warning protects Evelyn's account oversight without introducing trading actions.
## What Changes
- Preserve eligible unresolved TWAPs as immutable account-owned warning observations, including orders without open positions.
- Show a small amber triangle and short description on the owning position or Cross account, with distinct-order summaries on every ancestor through Perpetual Contracts regardless of expansion state.
- Preserve original times and failure/freshness qualifications; clear resolved warnings on successful reads. Continue hiding zero-fill and completed orders.
- Keep normal TWAP progress, valuations and margin risk independent. Update meaningful documentation and verify with temporary fixtures and JavaFX previews.
## Capabilities
### New Capabilities
None.
### Modified Capabilities
- `phoenix-perps-service`: discover TWAPs for empty existing accounts and retain unresolved filled orders without weakening identity validation.
- `evelyn-perps-service`: preserve warning ownership, including warning-only Cross accounts, through immutable snapshots and retained failures.
- `evelyn-perps-overview`: display and aggregate accessible TWAP warnings through the complete tree, including collapsed branches.
## Impact
Phoenix account and Evelyn snapshot records gain warning lists with compatible constructors. The decoder, reader, mapping and Perps table change; no new dependencies or transaction operations. Repository docs and the shared Evelyn overview change under the owner's explicit documentation instruction. No commits, pushes, Hub restart or deployment.
@@ -0,0 +1,76 @@
## MODIFIED Requirements
### Requirement: Perps overview displays a collapsible position hierarchy
The Perps tab SHALL display Position, Risk, Direction, Margin, Collateral, Leverage, Exposure, Value, uPnL and TWAP beneath the visible Perpetual Contracts root. Isolated hierarchy SHALL be wallet → venue → position; each Phoenix Cross account SHALL add a Cross group above its positions. Groups SHALL show applicable totals and risk summaries, leave direction/aggregate ratios blank, show TWAP warnings when applicable, and be expanded by default.
#### Scenario: Open either environment's Perps tab
- **WHEN** the owner opens Perps in Production or Test
- **THEN** all ten columns and the account-aware hierarchy are available with Risk near the position name
#### Scenario: Collapse and expand groups
- **WHEN** the owner collapses a wallet, venue or Cross account
- **THEN** the group still shows its worst known risk and incomplete-observation counts without changing totals
### Requirement: TWAP cells show execution progress and snapshot duration
Matching filled Phoenix TWAPs SHALL show a progressbar using executed/total child counts and an overlaid estimated duration to the next child in unbounded hours, minutes and seconds. Cells with no eligible progress or warning SHALL be empty. Matched timing warnings SHALL coexist with their progressbar. Updates SHALL follow existing snapshots without a live timer. Failed retained observations SHALL be labeled retained; due or unknown schedules SHALL not show negative or wrapped times or imply execution.
#### Scenario: Long interval
- **WHEN** the snapshot's estimated wait is 28 hours 32 minutes 10 seconds, or 128 hours 32 minutes 10 seconds
- **THEN** the text is approximately 28:32:10 or 128:32:10 respectively
#### Scenario: Failed or due observation
- **WHEN** the venue read fails or the latest observed next slot is already due
- **THEN** the cell communicates retained or awaiting-update status without advancing progress
### Requirement: Venue visibility follows available child rows
EMC SHALL hide venue rows with neither positions, Cross accounts nor TWAP warnings and show them when children reappear. Funded empty Cross accounts and accounts with eligible TWAP warnings SHALL keep their venue visible. Unmatched isolated warnings SHALL remain on the venue with true subaccount identity, never on an invented Cross parent. Hidden venues SHALL remain in snapshots and totals, with read status available in wallet tooltips. Unknown scopes SHALL NOT become zero totals; failed reads SHALL preserve last-success totals. Wallet rows and the root SHALL remain visible.
#### Scenario: Empty venue
- **WHEN** Jupiter or Phoenix has no positions, Cross accounts or TWAP warnings
- **THEN** its heading is absent from that wallet's displayed children
- **AND** a successful empty scope still contributes zero to totals
#### Scenario: Funded Cross account without positions
- **WHEN** Phoenix returns a Cross account with capital but no open positions
- **THEN** Phoenix and its Cross account remain visible with that capital counted once
#### Scenario: Positions disappear and return
- **WHEN** a venue loses its last child and later returns a position
- **THEN** its heading disappears and reappears with the correct child
- **AND** unrelated retained rows keep their selection and expansion state
#### Scenario: Hidden scope has not been read successfully
- **WHEN** a childless venue has never been read successfully and its first read is pending or failed
- **THEN** the heading is hidden and its read status is available on the wallet tooltip
- **AND** required totals remain unavailable rather than reporting zero
### Requirement: Polling preserves Perps view state
The Perps table SHALL retain matching wallet, venue and position identities across snapshots. Repeated unchanged snapshots SHALL leave retained rows, expansion, selection and formatting untouched except when risk or TWAP-warning freshness changes, without flicker or table rebuild. New groups SHALL be expanded by default, and added or removed positions SHALL be reconciled by identity without resetting retained groups.
#### Scenario: Poll unchanged positions
- **WHEN** a user collapses a group or selects a position and repeated snapshots are unchanged
- **THEN** the same rows remain with the same expansion and selection
- **AND** only a changed risk or TWAP-warning freshness indication requires a row-value update
## ADDED Requirements
### Requirement: TWAP warnings propagate through every ancestor
EMC SHALL show an amber warning triangle and concise text at the owning position or Cross group and on every actual ancestor through Perpetual Contracts. Summaries SHALL count each distinct order once per scope independently of expansion state. Unfilled and completed orders SHALL remain invisible. Risk and capital totals SHALL remain independent.
#### Scenario: Collapsed Cross branch
- **WHEN** a filled outstanding Cross order has missing market metadata and Cross or Phoenix is collapsed
- **THEN** Cross, Phoenix, wallet and Perpetual Contracts still carry the warning
- **AND** each summary counts that order once
#### Scenario: Position and multiple wallets
- **WHEN** a position warning and an unmatched Cross warning affect different wallets
- **THEN** each follows only its actual ancestors and the root counts two orders
- **AND** clearing one warning leaves the other and its ancestor summaries intact
### Requirement: Warning details preserve reason and freshness
Warning tooltips SHALL identify wallet/account/position, reason, TWAP address, asset/subaccount IDs, raw progress/fills and original observation time. Unknown metadata SHALL remain unknown without unsupported cancellation/delisting/stoppage claims. Failure retention, future timestamps and the existing five-minute observation-age cutoff SHALL qualify all affected summaries.
#### Scenario: Retained or aged warning
- **WHEN** a warned venue or consumer read fails, or its original observation becomes five minutes old
- **THEN** source and inherited warnings remain visible with retained/stale qualification and original times
- **AND** existing UI polling updates age without additional venue reads or resetting selection and expansion
@@ -0,0 +1,24 @@
## MODIFIED Requirements
### Requirement: TWAP observations belong to existing filled positions
The service SHALL publish immutable TWAP observations on matching existing Phoenix positions whose order has a positive actual fill and remaining executions, and account-owned warnings for eligible unresolved orders. It SHALL preserve counters, quantities, nullable price and observation/estimated times without UI formatting. No new position SHALL be synthesized. TWAP errors SHALL retain the complete prior venue observation with failure status. Polling frequency SHALL remain unchanged.
#### Scenario: Unfilled order or no position
- **WHEN** an active TWAP has no actual fills or no matching open position
- **THEN** a zero-fill order is absent from every overview row and cannot create a visible venue
- **AND** an eligible filled outstanding order without a position is preserved as a warning on its actual account scope
#### Scenario: TWAP read fails
- **WHEN** the TWAP read fails after a successful venue observation
- **THEN** prior positions, TWAP observations and original timestamps remain with failed venue status
- **AND** other venues and wallets continue refreshing
#### Scenario: Filled order without position
- **WHEN** a filled outstanding order cannot match an open position
- **THEN** its warning retains the real account identity and Cross accounts remain present even without capital or positions
- **AND** warning-only data does not synthesize positions or valuations
#### Scenario: Warning recovery and retention
- **WHEN** a successful observation resolves or removes a warned order
- **THEN** its warning is cleared while unrelated warnings remain
- **AND** failed reads instead retain warnings and their original times
@@ -0,0 +1,52 @@
## MODIFIED Requirements
### Requirement: Read failures cannot masquerade as empty portfolios
HTTP, authentication, malformed schema, identity mismatch and numeric conversion errors SHALL fail the read. Requests SHALL have bounded timeouts. Only a valid response with no nonzero positions SHALL produce an empty result. Present mark prices SHALL be positive and finite; an explicitly absent mark SHALL preserve positions and quantities with unavailable price-dependent valuations.
#### Scenario: Missing mark price
- **WHEN** a valid mark response has no mark price for a held position
- **THEN** the position and its TWAP quantities remain present with unknown USD valuations
- **AND** affected aggregate valuations remain unknown
#### Scenario: Rejected access or invalid price
- **WHEN** an HTTP request is rejected or a present mark price is invalid
- **THEN** the read fails instead of returning an empty or partial portfolio
#### Scenario: Empty account
- **WHEN** a valid trader snapshot has no subaccounts
- **THEN** an empty result is returned without market-price or TWAP requests; existing empty subaccounts still receive TWAP discovery
#### Scenario: Public API rate limit
- **WHEN** the shared adapter issues requests for PROD and TEST
- **THEN** request starts SHALL be spaced at least one second apart
- **AND** HTTP 429 SHALL fail the lookup and establish a shared cooldown from Retry-After (seconds or HTTP date, 60 seconds fallback)
- **AND** lookups during cooldown SHALL fail without external calls, with no immediate retry
### Requirement: Read precise TWAP snapshots for held markets
The reader SHALL read official TWAP snapshots through its existing paced transport and associate orders by authority, PDA, subaccount and market identity. Only orders with actual fills and remaining children SHALL be exposed. Matched orders SHALL retain position progress; valid unresolved orders SHALL retain account-owned warnings with identity, raw counters/fills and original observation time. Existing accounts without positions SHALL receive TWAP discovery. Quantities SHALL use exact lot conversion and explicit/legacy dust semantics. Unavailable size inputs SHALL remain unknown. Existing mark prices SHALL be reused without Ticker reads.
#### Scenario: Explicit and legacy dust
- **WHEN** total children are 5, regular size 10 lots and explicit dust count/size are 2/3
- **THEN** total size is 36 lots and the fourth child is 3 lots
- **AND** legacy zero dust count with size 3 instead represents four regular children and a final 3-lot child
#### Scenario: Identity mismatch or unfilled order
- **WHEN** authority/PDA/subaccount/asset identities disagree or an order has no fills
- **THEN** disagreement fails the read, while a valid unfilled order is absent from all TWAP data and warnings
#### Scenario: Missing market or missing position
- **WHEN** a filled outstanding order has missing market metadata or no matching open position
- **THEN** a warning preserves its identity and raw progress without inventing a symbol, conversion, price or execution status
- **AND** healthy positions and account risk remain available
#### Scenario: Existing empty account
- **WHEN** an account has no held positions but has a filled outstanding TWAP
- **THEN** TWAP discovery returns its warning without fetching market prices or creating positions
#### Scenario: Completed order
- **WHEN** an order has no remaining children
- **THEN** it is absent from active TWAP data and warnings
#### Scenario: Matched order with unavailable timing
- **WHEN** an otherwise valid matched filled order has no usable future next-execution estimate
- **THEN** its progress remains available with a timing warning that does not assert execution has stopped
@@ -0,0 +1,19 @@
# Tasks
## 1. Phoenix warning observations
- [x] 1.1 Preserve eligible unmatched orders and matched timing warnings with strict identities/counters and original times; verify missing metadata, zero-fill/completed suppression and known-market matching with temporary fixtures.
- [x] 1.2 Discover TWAPs for existing empty accounts with existing transport safeguards and document changed reads in docs/PhoenixPerps.md; verify empty-account request paths and HTTP failure behavior.
## 2. Snapshot ownership
- [x] 2.1 Map warnings onto positions, real Cross accounts and isolated venue fallbacks without valuation changes, preserving them on failures; verify immutable lists, warning-only accounts, identity and recovery with temporary fixtures and document the snapshot behavior.
## 3. Tree presentation
- [x] 3.1 Render the amber warning icon, concise descriptions and detailed tooltips with retained/stale source information; verify actual JavaFX cells, normal bars, Risk and row backgrounds in a preview.
- [x] 3.2 Propagate distinct warnings through every actual ancestor to Perpetual Contracts independently of collapse state; verify multiple wallets, clearing and stable selection/expansion, and update docs/Evelyn.md plus the shared Evelyn overview.
## 4. Integration verification
- [x] 4.1 Run the normal build and integrated temporary fixture/JavaFX checks, inspect a paced read-only live observation if available, validate/sync affected OpenSpec specs and record evidence in verification.md; confirm no commits, pushes or runtime changes.
@@ -0,0 +1,39 @@
# Verification — issue #103
Verified locally on 2026-10-26. No commits, pushes, Hub restart, deployment, signing or order changes.
## Delivered behavior
- The Phoenix decoder preserves filled outstanding orders with missing market metadata or no matching open position as typed immutable warnings. It also preserves matched progress with a timing warning when the next execution cannot be estimated.
- TWAP discovery includes existing empty accounts. Metadata is conditional and warning-only markets cause no mark-price calls. Existing request pacing, timeout and shared 429 cooldown remain in use.
- Warnings map to their real position or Cross account. Empty warning-only Cross accounts remain visible without invented positions or capital. Unmatched isolated orders remain on Phoenix with their real subaccount identity.
- Amber vector triangles and concise text appear in TWAP cells. Distinct source orders propagate through every actual ancestor to Perpetual Contracts, independently of expansion. Successful recovery clears only resolved orders; failures and five-minute/future-date staleness remain qualified at every level.
- Detail tooltips preserve raw counters, IDs and original receipt times. They have bounded scrollable content and remain available while moving between their owner cell and details. Risk and existing normal TWAP bars remain independent.
- Updated docs/Evelyn.md, docs/PhoenixPerps.md and the shared r35157_docs/projects/evelyn/README.md; removed obsolete matching/discovery/group-cell claims. The three affected main OpenSpec specifications are synced. No permanent tests or dependencies were added.
## Checks
- `JAVA_HOME=/usr/local/software/java/jfx-25 ./gradlew build`: successful; 42 existing tests, no failures/errors/skips.
- `/tmp/Issue103Check.java`: 32 focused assertions passed. Covers the captured real asset-97 response; missing markets; matching and unmatched positions; hidden zero-fill/completed orders; identity/duplicate/counter rejection; immutable lists; correct Cross/isolated mapping; warning-only empty accounts without mark requests; unchanged monetary totals; failure retention/recovery; and 429 cooldown. Uses local HTTP fixtures and the actual decoder/adapter/service.
- `/tmp/Issue102Check.java`: all 68 existing temporary risk checks still pass, including exact boundaries, account scope and retained/future observations.
- `/tmp/Issue103Preview.java`: 82 JavaFX assertions passed. This is an assertion count, including repeated checks of recycled empty cells, not 82 distinct user scenarios. Checks actual warning graphics, source and ancestor counts over two wallets, collapsed Cross/Phoenix/wallet/root nodes, normal 28-hour progress, timing warning plus bar, margin-risk independence, direction backgrounds, accessible text, tooltip content/scrolling/leave behavior, snapshot failures, five-minute aging, recovery, row identity/selection, warning-only Cross, empty venue hiding and horizontal scrolling.
- Rendered JavaFX images inspected in `/tmp/issue103-check/`: `twap-warnings-expanded.png`, `twap-warnings-collapsed.png`, `twap-warning-tooltip.png`, `twap-warning-tooltip-bottom.png`, `twap-warnings-stale.png`, `twap-warning-empty-cross.png`, `twap-warnings-small-window.png`. Long tooltip height and contrast were corrected during inspection. TWAP was scrolled into the viewport before final visual checks.
- Strict validation passes for change `103-perps-twap-warnings` and specifications `phoenix-perps-service`, `evelyn-perps-service` and `evelyn-perps-overview`. Existing long modified requirement paragraphs produce informational length hints only.
- Changed working-tree and change-specific staged whitespace checks pass; 24 local documentation file links resolve. Pre-existing staged/deleted OpenSpec artifacts for #97 and #99 were left untouched.
## Read-only live observation
`/tmp/Issue103Live.java` used the actual default paced Phoenix adapter and local PDA derivation against the owner's reported wallet. One lookup ran from **2026-10-26 05:25:26 to 05:25:38 UTC**. It returned one account with eight held positions and one warning:
```text
PDA/subaccount: 0/0
Asset ID: 97
Reason: MARKET_UNAVAILABLE
Progress: 34/346
Remaining: 312
Original TWAP receipt: 2026-10-26T05:25:28.553550180Z
Mapped Cross warnings: 1
Venue fallback warnings: 0
```
The order's market identity and execution status remain unresolved; this verification does not claim cancellation, delisting or stopped execution. It confirms local reader/mapping behavior, not deployment to the running Hub. Live reads are separate observations, not an atomic portfolio snapshot.
+27 -6
View File
@@ -7,7 +7,7 @@ Let the owner inspect Evelyn perpetual positions grouped by wallet and venue in
## Requirements
### Requirement: Perps overview displays a collapsible position hierarchy
The Perps tab SHALL display Position, Risk, Direction, Margin, Collateral, Leverage, Exposure, Value, uPnL and TWAP beneath the visible Perpetual Contracts root. Isolated hierarchy SHALL be wallet → venue → position; each Phoenix Cross account SHALL add a Cross group above its positions. Groups SHALL show applicable totals and risk summaries, leave direction/aggregate ratios and TWAP blank, and be expanded by default.
The Perps tab SHALL display Position, Risk, Direction, Margin, Collateral, Leverage, Exposure, Value, uPnL and TWAP beneath the visible Perpetual Contracts root. Isolated hierarchy SHALL be wallet → venue → position; each Phoenix Cross account SHALL add a Cross group above its positions. Groups SHALL show applicable totals and risk summaries, leave direction/aggregate ratios blank, show TWAP warnings when applicable, and be expanded by default.
#### Scenario: Open either environment's Perps tab
- **WHEN** the owner opens Perps in Production or Test
@@ -35,12 +35,12 @@ EMC SHALL request the current Perps snapshot from each environment's own service
- **AND** a failure reading one service does not prevent attempting the other service
### Requirement: Polling preserves Perps view state
The Perps table SHALL retain matching wallet, venue and position identities across snapshots. Repeated unchanged snapshots SHALL leave retained rows, expansion, selection and formatting untouched except when risk freshness changes, without flicker or table rebuild. New groups SHALL be expanded by default, and added or removed positions SHALL be reconciled by identity without resetting retained groups.
The Perps table SHALL retain matching wallet, venue and position identities across snapshots. Repeated unchanged snapshots SHALL leave retained rows, expansion, selection and formatting untouched except when risk or TWAP-warning freshness changes, without flicker or table rebuild. New groups SHALL be expanded by default, and added or removed positions SHALL be reconciled by identity without resetting retained groups.
#### Scenario: Poll unchanged positions
- **WHEN** a user collapses a group or selects a position and repeated snapshots are unchanged
- **THEN** the same rows remain with the same expansion and selection
- **AND** only a changed risk freshness indication requires a row-value update
- **AND** only a changed risk or TWAP-warning freshness indication requires a row-value update
### Requirement: Jupiter positions communicate direction and USD size
Positions SHALL show readable Long/Short direction and Isolated/Cross margin text. USD amounts SHALL use grouping and two decimals; leverage SHALL use a multiplication sign. Signed uPnL SHALL be green for positive, red for negative and neutral for rounded zero without negative zero. Existing faint direction backgrounds SHALL remain; groups SHALL have distinct weight and no direction color. Numeric columns SHALL be right-aligned with useful widths and tooltips.
@@ -70,10 +70,10 @@ Tooltips SHALL explain isolated collateral, exposure-based leverage, collateral-
- **AND** no position-only metric is labeled account utilization
### Requirement: Venue visibility follows available child rows
EMC SHALL hide venue rows with neither positions nor Cross accounts and show them when children reappear. Funded empty Cross accounts SHALL keep their venue visible. Hidden venues SHALL remain in snapshots and totals, with read status available in wallet tooltips. Unknown scopes SHALL NOT become zero totals; failed reads SHALL preserve last-success totals. Wallet rows and the root SHALL remain visible.
EMC SHALL hide venue rows with neither positions, Cross accounts nor TWAP warnings and show them when children reappear. Funded empty Cross accounts and accounts with eligible TWAP warnings SHALL keep their venue visible. Unmatched isolated warnings SHALL remain on the venue with true subaccount identity, never on an invented Cross parent. Hidden venues SHALL remain in snapshots and totals, with read status available in wallet tooltips. Unknown scopes SHALL NOT become zero totals; failed reads SHALL preserve last-success totals. Wallet rows and the root SHALL remain visible.
#### Scenario: Empty venue
- **WHEN** Jupiter or Phoenix has no positions and no Cross accounts
- **WHEN** Jupiter or Phoenix has no positions, Cross accounts or TWAP warnings
- **THEN** its heading is absent from that wallet's displayed children
- **AND** a successful empty scope still contributes zero to totals
@@ -92,7 +92,7 @@ EMC SHALL hide venue rows with neither positions nor Cross accounts and show the
- **AND** required totals remain unavailable rather than reporting zero
### Requirement: TWAP cells show execution progress and snapshot duration
Matching filled Phoenix TWAPs SHALL show a progressbar using executed/total child counts and an overlaid estimated duration to the next child in unbounded hours, minutes and seconds. Other cells SHALL be empty. Updates SHALL follow existing snapshots without a live timer. Failed retained observations SHALL be labeled retained; due or unknown schedules SHALL not show negative or wrapped times or imply execution.
Matching filled Phoenix TWAPs SHALL show a progressbar using executed/total child counts and an overlaid estimated duration to the next child in unbounded hours, minutes and seconds. Cells with no eligible progress or warning SHALL be empty. Matched timing warnings SHALL coexist with their progressbar. Updates SHALL follow existing snapshots without a live timer. Failed retained observations SHALL be labeled retained; due or unknown schedules SHALL not show negative or wrapped times or imply execution.
#### Scenario: Long interval
- **WHEN** the snapshot's estimated wait is 28 hours 32 minutes 10 seconds, or 128 hours 32 minutes 10 seconds
@@ -126,3 +126,24 @@ EMC SHALL mark risk stale after five minutes from its original observation, on r
#### Scenario: Retained critical risk
- **WHEN** a previously critical observation fails to refresh
- **THEN** its critical state and original time remain visible with stale/retained indication
### Requirement: TWAP warnings propagate through every ancestor
EMC SHALL show an amber warning triangle and concise text at the owning position or Cross group and on every actual ancestor through Perpetual Contracts. Summaries SHALL count each distinct order once per scope independently of expansion state. Unfilled and completed orders SHALL remain invisible. Risk and capital totals SHALL remain independent.
#### Scenario: Collapsed Cross branch
- **WHEN** a filled outstanding Cross order has missing market metadata and Cross or Phoenix is collapsed
- **THEN** Cross, Phoenix, wallet and Perpetual Contracts still carry the warning
- **AND** each summary counts that order once
#### Scenario: Position and multiple wallets
- **WHEN** a position warning and an unmatched Cross warning affect different wallets
- **THEN** each follows only its actual ancestors and the root counts two orders
- **AND** clearing one warning leaves the other and its ancestor summaries intact
### Requirement: Warning details preserve reason and freshness
Warning tooltips SHALL identify wallet/account/position, reason, TWAP address, asset/subaccount IDs, raw progress/fills and original observation time. Unknown metadata SHALL remain unknown without unsupported cancellation/delisting/stoppage claims. Failure retention, future timestamps and the existing five-minute observation-age cutoff SHALL qualify all affected summaries.
#### Scenario: Retained or aged warning
- **WHEN** a warned venue or consumer read fails, or its original observation becomes five minutes old
- **THEN** source and inherited warnings remain visible with retained/stale qualification and original times
- **AND** existing UI polling updates age without additional venue reads or resetting selection and expansion
+14 -3
View File
@@ -85,17 +85,28 @@ Each venue SHALL carry its last-success time and whether the latest attempt fail
- **THEN** its previous observations remain available with their original success time and failure indication
### Requirement: TWAP observations belong to existing filled positions
The service SHALL publish immutable TWAP observations only on matching existing Phoenix positions whose order has a positive actual fill and remaining executions. It SHALL preserve counters, quantities, nullable price and observation/estimated times without UI formatting. No new position SHALL be synthesized. TWAP errors SHALL retain the complete prior venue observation with failure status. Polling frequency SHALL remain unchanged.
The service SHALL publish immutable TWAP observations on matching existing Phoenix positions whose order has a positive actual fill and remaining executions, and account-owned warnings for eligible unresolved orders. It SHALL preserve counters, quantities, nullable price and observation/estimated times without UI formatting. No new position SHALL be synthesized. TWAP errors SHALL retain the complete prior venue observation with failure status. Polling frequency SHALL remain unchanged.
#### Scenario: Unfilled order or no position
- **WHEN** an active TWAP has no actual fills or has no matching open position
- **THEN** it is absent from every overview row and cannot create a visible venue
- **WHEN** an active TWAP has no actual fills or no matching open position
- **THEN** a zero-fill order is absent from every overview row and cannot create a visible venue
- **AND** an eligible filled outstanding order without a position is preserved as a warning on its actual account scope
#### Scenario: TWAP read fails
- **WHEN** the TWAP read fails after a successful venue observation
- **THEN** prior positions, TWAP observations and original timestamps remain with failed venue status
- **AND** other venues and wallets continue refreshing
#### Scenario: Filled order without position
- **WHEN** a filled outstanding order cannot match an open position
- **THEN** its warning retains the real account identity and Cross accounts remain present even without capital or positions
- **AND** warning-only data does not synthesize positions or valuations
#### Scenario: Warning recovery and retention
- **WHEN** a successful observation resolves or removes a warned order
- **THEN** its warning is cleared while unrelated warnings remain
- **AND** failed reads instead retain warnings and their original times
### Requirement: Risk observations preserve scope and exact meaning
Snapshots SHALL preserve isolated risk prices and Cross account tiers/thresholds with original observation times. Signed price distance SHALL use the current venue reference as denominator and preserve boundary crossing. Cross MM utilization SHALL use effective collateral, with nonpositive denominators unavailable. Group risk SHALL count each isolated position and shared account once and retain worst known severity plus unknown/stale counts without averaging.
+21 -4
View File
@@ -33,8 +33,8 @@ HTTP, authentication, malformed schema, identity mismatch and numeric conversion
- **THEN** the read fails instead of returning an empty or partial portfolio
#### Scenario: Empty account
- **WHEN** a valid trader snapshot has no subaccounts or no nonzero positions
- **THEN** an empty result is returned without market-price or TWAP requests
- **WHEN** a valid trader snapshot has no subaccounts
- **THEN** an empty result is returned without market-price or TWAP requests; existing empty subaccounts still receive TWAP discovery
#### Scenario: Public API rate limit
- **WHEN** the shared adapter issues requests for PROD and TEST
@@ -62,7 +62,7 @@ Equity SHALL include collateral, undiscounted price PnL and signed unsettled fun
- **AND** effective Cross leverage uses 103 USD as its denominator
### Requirement: Read precise TWAP snapshots for held markets
The reader SHALL read official TWAP snapshots through its existing paced transport and associate orders by authority, PDA, subaccount and market identity. Only orders with actual fills and remaining children on an existing position SHALL be exposed. Quantities SHALL use exact lot conversion and explicit/legacy dust semantics. Unavailable size inputs SHALL remain unknown. Existing mark prices SHALL be reused without Ticker reads.
The reader SHALL read official TWAP snapshots through its existing paced transport and associate orders by authority, PDA, subaccount and market identity. Only orders with actual fills and remaining children SHALL be exposed. Matched orders SHALL retain position progress; valid unresolved orders SHALL retain account-owned warnings with identity, raw counters/fills and original observation time. Existing accounts without positions SHALL receive TWAP discovery. Quantities SHALL use exact lot conversion and explicit/legacy dust semantics. Unavailable size inputs SHALL remain unknown. Existing mark prices SHALL be reused without Ticker reads.
#### Scenario: Explicit and legacy dust
- **WHEN** total children are 5, regular size 10 lots and explicit dust count/size are 2/3
@@ -71,7 +71,24 @@ The reader SHALL read official TWAP snapshots through its existing paced transpo
#### Scenario: Identity mismatch or unfilled order
- **WHEN** authority/PDA/subaccount/asset identities disagree or an order has no fills
- **THEN** disagreement fails the read, while a valid unfilled order is absent from returned positions' TWAP data
- **THEN** disagreement fails the read, while a valid unfilled order is absent from all TWAP data and warnings
#### Scenario: Missing market or missing position
- **WHEN** a filled outstanding order has missing market metadata or no matching open position
- **THEN** a warning preserves its identity and raw progress without inventing a symbol, conversion, price or execution status
- **AND** healthy positions and account risk remain available
#### Scenario: Existing empty account
- **WHEN** an account has no held positions but has a filled outstanding TWAP
- **THEN** TWAP discovery returns its warning without fetching market prices or creating positions
#### Scenario: Completed order
- **WHEN** an order has no remaining children
- **THEN** it is absent from active TWAP data and warnings
#### Scenario: Matched order with unavailable timing
- **WHEN** an otherwise valid matched filled order has no usable future next-execution estimate
- **THEN** its progress remains available with a timing warning that does not assert execution has stopped
### Requirement: TWAP time estimates disclose their slot assumption
The reader SHALL estimate future execution times from snapshot slot, due slot and cooldown using a documented nominal slot duration and response observation time. Completion SHALL derive from remaining executions, never expiry. Already-due schedules, invalidated completion schedules and unrepresentable estimates SHALL remain unavailable instead of predicting fills.