Repository navigation
Trading console UI, shared primitives, and frontend tests - #1
Merged
Merged
Conversation
The Horizon 4 trading track (scheduler, guardrails, kill switch, order lifecycle, reconciliation, soak reporting) landed entirely in the API with no UI. 18 of 26 routes had no frontend at all, so the only way to see whether the loop was healthy was curl. The next roadmap step is a paper soak, and a soak you can't watch is a soak you won't watch. Trading console (new tab): - Status strip: broker + live/paper, scheduler cron and next/last run, reconciliation state. An engaged kill switch and a live broker missing the limits the API fails closed on each get a banner, not a pill. - Controls: plan editor, risk limits showing the plan/global merge as `effective`, kill switch, manual tick and cycle triggers. - Live state: positions, orders, intents (including guardrail rejections), soak report, reconciliation drift. Two deliberate safety asymmetries, both tested: engaging the kill switch is one click while releasing requires typing a confirmation phrase, and both order-placing buttons need a confirm step and turn destructive-red when the broker is live. Design primitives: Input/Select/Button/Table/StatusPill/EmptyState, plus lib/chartTheme.ts and lib/metrics.ts. Removes a 9-utility class string copy-pasted across 8 files, chart hex across 6, and metric helpers duplicated between the sweep and walk-forward panels. Also extracts ParamRangeGrid, shared by both forms. Bugs fixed, three found while verifying against a live paper broker: - RunListItem.kind omitted "scheduled_tick", which the scheduler writes to the same runs table; those rows rendered as backtests with a click handler that silently did nothing. - Share quantities were rounded to whole numbers. The loop sizes by cash, so a real position is 32.37188786847498 shares, displayed as "32". - The ledger stores strategy as a JSON blob, rendered raw in table cells. - useTradeConsole used Promise.all, so one failing endpoint blanked the whole console including the kill switch. Now degrades per-call. - Every asset row emitted id="strategy-select", so labels focused the wrong control. Tests: vitest + testing-library, 107 tests, added to the CI frontend job. Housekeeping: untrack tsbuildinfo and the generated vite.config.js/.d.ts (tsc -b rewrites them every build, so they added churn to every commit); bump postcss to clear a pre-existing advisory. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ggange
added a commit
that referenced
this pull request
Aug 13, 2026
Trading console UI, shared primitives, and frontend tests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The Horizon 4 trading track — scheduler, risk guardrails, kill switch, order lifecycle, reconciliation, soak reporting — landed entirely in the API with no UI. 18 of 26 routes had no frontend at all, so the only way to see whether the loop was healthy (is the kill switch engaged? did the 16:30 cron fire? is the ledger drifting from the venue?) was curl.
The next roadmap step is a paper soak. A soak you can't watch is a soak you won't watch.
What's in it
Trading console — a fourth tab wiring every
/trade/*route:StrategyPicker), risk limits showing the plan/global merge aseffectiveso it's visible rather than guessed, kill switch, manual tick and cycle triggers.Two deliberate safety asymmetries, both covered by tests and exercised in a browser:
RELEASE. Stopping should never be harder than starting, and releasing is the direction that re-arms capital.Design primitives —
Input/Select/Button/Table/StatusPill/EmptyState, pluslib/chartTheme.tsandlib/metrics.ts. Removes a 9-utility class string copy-pasted across 8 files, chart hex across 6, and metric helpers duplicated between the sweep and walk-forward panels. Also extractsParamRangeGrid, shared by both forms.Bugs fixed
Three of these only surfaced while verifying against a live
paper_simbroker:RunListItem.kindomitted"scheduled_tick"runstable; they rendered as backtests with a click handler that silently did nothing32.37188786847498shares — displayed as "32"strategystored as a JSON blob{"period": 5, "type": "rsi"}in table cellsuseTradeConsoleusedPromise.allid="strategy-select"Tests
Vitest + Testing Library — 107 tests across 12 files, added to the existing CI frontend job. Coverage is weighted toward where a bug is expensive: the confirmation gates, the limits merge, the safety banners, API error decoding, and
buildRequest()(previously untested).Verification
Beyond the suite, this was run end-to-end against a live backend on
paper_sim:max_position_valuelowered → intent rejected with the guardrail reason surfaced in the UIHousekeeping
Untracks
tsconfig*.tsbuildinfoand the generatedvite.config.js/.d.ts—tsc -brewrites them on every build, so they added unrelated churn to every commit. Bumpspostcssto clear a pre-existing high-severity advisory (npm auditnow clean).Known, not addressed
🤖 Generated with Claude Code