unrip/archive/implementation/20260409T160740Z-quote-lifecycle-truth-and-execution-explanation-proof.md
philipp bd72e355b1 Archive implementation turn: quote lifecycle truth and execution explanation
Proof: Preserve the completed implementation turn and record its outcome in the tracked archive.
Assumptions: The archived files capture the relevant planning state for the completed turn.
Still fake: Archiving does not validate the work by itself; external evidence still governs whether the result is trustworthy.
2026-04-09 18:07:40 +02:00

200 lines
9.7 KiB
Markdown

# 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
- operator-facing labels must not overclaim beyond the durable evidence actually stored
## 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.
The immediate trigger for this turn is a real semantic failure:
- the dashboard treated `trade_execution_results.status = submitted` as a successful trade
- recent submitted quote terms were rendered as if they were realized asset deltas
- tests passed because that wrong assumption had been encoded into the test suite itself
This turn must therefore fix both the UI and the conditions that allowed the mistake through.
## 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.
- The prevention strategy must be implemented in repo code and tests rather than left to reviewer judgment alone.
## Turn-shaping rules
- `Actionable` is forbidden as an operator-facing state or label.
- Operator-facing labels must not overstate event certainty.
- Terms such as `trade`, `success`, `filled`, `completed`, `profit`, and `asset delta` are forbidden unless backed by a durable event explicitly representing that fact.
- 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.
The repo must adopt a hard evidence-state vocabulary for this turn. At minimum:
- `observed`
- `evaluated`
- `command_emitted`
- `rejected`
- `blocked`
- `submitted`
- `failed`
- `awaiting_outcome`
- `completed`
No operator surface may collapse these into softer or stronger claims.
### 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?
### Semantic invariants
The implementation and tests must enforce at least these invariants:
- `submitted` is not `completed`
- `submitted` is not a realized asset delta
- executor-side blocking is not strategy rejection
- stronger labels must not be rendered from weaker evidence
These invariants are proof-critical, not optional cleanup.
## 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.
- overloaded backend and UI names that imply stronger certainty than the evidence supports are removed or renamed
- Regression tests cover at least:
- strategy-approved but executor-disarmed rows
- submitted rows
- forbidden ambiguous label removal
- forbidden semantic overclaims such as treating `submitted` as `completed`
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
- automated test evidence for negative semantic invariants, especially `submitted != completed`
## 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
- the repo still uses `trade` or `asset delta` language for mere submission evidence
- tests still encode the old overclaiming semantics
## 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
## Prevention requirements for this proof
- Add a truth-review checklist to the implementation work:
- what exact durable table or event backs this label?
- what is the strongest claim the evidence supports?
- what would make this wording false?
- what negative regression test prevents that overclaim from returning?
- Separate lifecycle derivation from summary metrics so summaries are computed from lifecycle states rather than raw convenience queries.