# Implementation Proof: quote lifecycle truth and execution explanation Status: open Opened: 2026-04-09 ## Target outcome This turn proves that `unrip` can explain every quote outcome in operator-visible, durable terms instead of forcing the operator to infer meaning from ambiguous labels. The concrete target is the live NEAR Intents BTC/EURe system: - each quote row must expose its current lifecycle state - each non-trade outcome must expose the decisive reason code - execution submission must be distinguishable from strategy approval - blocked, rejected, submitted, failed, and not-filled paths must be visibly different - quote identifiers must be directly usable by operators for tracing and support ## Why this is a meaningful architecture test The current operator surface still fails a core thesis requirement: - the Strategy page shows `Actionable`, which does not tell the operator whether a trade was actually submitted - an operator looking at one quote cannot answer, at a glance, why it did or did not become a trade - quote ids are hidden behind truncation with no direct copy affordance - execution truth exists durably in PostgreSQL, but the UI does not surface the lifecycle coherently That is not just a copy problem. It is an observability gap in the trading product itself. If the system cannot explain a quote outcome precisely, execution is outrunning observability. ## Hypothesis `unrip` becomes more trustworthy if quote handling is modeled and rendered as an explicit lifecycle instead of a single strategy verdict: - strategy evaluation is only one stage in the lifecycle - executor acceptance or rejection must be first-class state - venue submission and downstream outcome must be represented separately - durable reason codes must drive operator labels - forbidden labels that collapse multiple meanings, especially `Actionable`, must be removed The turn passes only if an operator can inspect a quote and immediately understand whether it was filtered, rejected, blocked, submitted, failed, awaiting venue outcome, not filled, or completed, and why. ## Scope - [I021] Quote lifecycle truth and execution explanation: replace ambiguous dashboard verdicts with a per-quote state machine that shows exactly why a quote was filtered, rejected, blocked, submitted, not filled, or executed, with durable reason codes and operator-facing traceability. - Cover the live path from: - raw or normalized quote observation - strategy decision - execute-trade command emission - executor result - solver relay or venue outcome where available - Update the dashboard surfaces that currently expose quote or strategy truth: - Strategy page - any quote or recent-decision tables tied to the active pair - quote-id presentation and operator trace affordances ## Assumptions - The existing durable stores already contain enough information for at least the current live path through strategy decision and executor result. - Some downstream venue-outcome states may still be partially fake or unavailable for older rows; if so, the UI must say that plainly rather than implying more certainty. - The immediate turn should prioritize truthful lifecycle explanation over broader analytics such as markout or long-window outcome attribution. ## Turn-shaping rules - `Actionable` is forbidden as an operator-facing state or label. - Do not add a second analytics product. Stay focused on per-quote lifecycle truth for the live active pair. - Do not invent lifecycle states that cannot be backed by durable repo-owned evidence. - If a state transition is inferred rather than durably observed, the UI must make that distinction explicit. - Prefer a small, explicit state machine over a long list of loosely related badges. ## Non-goals - No new venue integrations. - No broad historical markout analytics turn. - No new execution automation or risk widening. - No redesign of the entire dashboard visual system beyond what is needed to make the quote lifecycle understandable. ## Required operator behavior ### Lifecycle truth For each visible quote or decision row, the operator must be able to identify the current lifecycle state from a bounded set such as: - `Filtered` - `Rejected by strategy` - `Blocked before submit` - `Submission failed` - `Submitted` - `Awaiting venue outcome` - `Not filled` or equivalent final non-fill state, if durable evidence exists - `Completed` or equivalent successful terminal state, if durable evidence exists Exact labels may vary, but they must be specific and mutually meaningful. ### Reason truth Each non-terminal or terminal non-trade state must expose a clear decisive reason, such as: - unsupported pair - below edge threshold - inventory unavailable - executor disarmed - executor paused - submission failed - venue timeout - quote expired If the decisive reason is not known, the surface must say that plainly instead of inventing confidence. ### Traceability For each quote row the operator must be able to access: - quote id in a non-hidden, copyable form - decision id where present - command id where present - execution result where present - pair and direction The operator must be able to reason from a single row without manually cross-correlating multiple pages. ### UI language The UI must not render `Actionable`. Any replacement label must answer a concrete operator question, such as: - did strategy approve this? - was a command emitted? - was the command blocked? - was it submitted? - did it fail? ## Definition of done - `Actionable` is removed from operator-facing dashboard surfaces. - A durable quote lifecycle model exists in repo-owned code and is used by the dashboard. - At least the current live quote path through strategy decision and executor result is rendered coherently per quote. - The operator can tell, from one row, why a recent quote did or did not turn into a submitted trade. - Quote ids are copyable and clearly visible enough for tracing. - Regression tests cover at least: - strategy-approved but executor-disarmed rows - submitted rows - forbidden ambiguous label removal For this turn to close with status `passed`, the specific operator question: `Why did this quote not trade?` must be answerable directly from the dashboard for recent rows without needing manual database inspection. ## Validation evidence required - direct UI or bootstrap evidence that recent rows show explicit lifecycle states instead of `Actionable` - direct evidence that a strategy-approved but executor-disarmed row renders as blocked or rejected with reason - direct evidence that a submitted row renders as submitted - direct evidence that quote ids are directly usable for tracing - automated test evidence for lifecycle derivation and dashboard rendering ## Failure conditions - `Actionable` still appears in the dashboard - the operator still cannot distinguish strategy approval from execution submission - non-trade rows still lack a decisive reason - quote ids remain hidden or non-copyable - lifecycle labels are only cosmetic and not backed by durable repo-owned state ## Current real before this turn - strategy decisions are stored durably - execution results are stored durably - command ids, decision ids, and quote ids already exist in the durable path - the operator dashboard already serves recent decisions and execution-adjacent state ## Deliberately not built by this proof - full venue settlement attribution for all historic trades - generalized quote analytics beyond lifecycle explanation - multi-venue lifecycle harmonization