- Add IDashboardSummaryService/DashboardSummaryService: real event/snapshot/
anomaly counts, top-5 signals, and per-stage pipeline health from worker state.
- Home: replace hard-coded zeros + placeholder feed with live data, a clickable
signal feed, and a first-run empty state with a Settings CTA.
- MainLayout: add an appbar capture-status pill (Capturing/Paused) bound to the
poller toggles, refreshed via IOptionsMonitor.OnChange.
- MyBets: success snackbar on bet submit. Backtest: surface a Cancel button
while a run is in flight.
- Add en/ru localization for all new strings; register IOptionsMonitor<WorkerOptions>
in the bUnit test context for layout-rendering tests.
- Add IEventRepository/IResultRepository.GetManyAsync to kill N+1 lookups at
6 sites (backtest, outcome eval, both bet-journal paths, anomaly browsing,
results selection); guarded by a Received(1).GetManyAsync test.
- Add EventRepository.QueryAsync to push date+sport filtering to SQL (was
load-whole-range-then-filter); search/sort stay in-memory for Cyrillic order.
- Add AnomalyRepository.CountSinceAsync (unread badge) + ListByDateRangeAsync
(feed date filter); add Event/Snapshot count methods for the dashboard.
- Add composite indexes IX_Snapshots_EventCode_CapturedAt and
_EventCode_Source_CapturedAt via a new migration + model snapshot.
- Introduce SqliteDateText as the single source of the O-format date encoding
shared by Mapping (read/write) and the repositories' range predicates.
- Fix LiveOddsPoller cadence drift (budget sleep against cycle time); make
DetectAnomalies dedup O(1) per event; add Event.Title to dedup the title join.
Tests adapted to the batched GetManyAsync via a TestFixtures bridge.
* Pages/Results/ResultsList.razor — completed-events list with date range,
sport/winner filter, search, footer count.
* Pages/Results/ResultsLoader.razor — driver page with two modes (load all
in range / load selected events), live progress reporting via
IProgress<PullResultsProgress>, summary line, cancellable.
* Replaces the Phase 5 Pages/Results.razor placeholder.
Service layer:
* IResultsBrowsingService + ResultsBrowsingService (Scoped, mirrors the
Event/Anomaly browsing-service pattern). Reads IResultRepository +
IEventRepository, projects to immutable view-model records.
* UiServicesExtensions: registers ResultsBrowsingService; also fixes an
unrelated localization resolver bug (drop ResourcesPath since
SharedResource lives in the Marathon.UI.Resources namespace already).
Localization:
* 41 new Results.* keys (RU+EN parity) covering both pages, filter chips,
loader modes, progress states, and footer copy.
Tests:
* ResultsListTests + ResultsLoaderTests — 22 new bUnit tests covering
filter narrowing, mode switching, progress aggregation, and empty
states.
* FakeResultsBrowsingService support type for tests.
* MarathonTestContext registers the fake; TestData adds factories for
EventResult/EventResultListItem.
Creates the 9-project .NET 8 solution (5 src + 4 test) with Marathon.Domain
fully implemented: value objects (SportCode, EventId, OddsRate, OddsValue,
BetScope hierarchy), enums (Side, BetType, OddsSource, AnomalyKind), and
entities (Sport, Country, League, Event, Bet, OddsSnapshot, EventResult,
Anomaly) with all invariants enforced in constructors. 96 domain tests pass
(FluentAssertions + xUnit). Directory.Build.props and Directory.Packages.props
centralise build settings and NuGet versions. Both Marathon.sln and Marathon.slnx
are committed; dotnet build Marathon.sln succeeds with 0 warnings/errors.