Match results still show the highest reported points balance even when cumulative
score has been saved. Select one score presentation for each match: total score
for matches with recorded totals, and the existing balance display for historical
matches without totals.
src/routes/matches/[id]/+page.svelte:34 always selects bestScore with the
heading Highest reported score. The cells at line 163 render that selected
field, so scoreTotal is never displayed.
src/lib/server/fleet/match-history.ts:128 already returns scoreTotal for
each participant alongside bestScore.
src/lib/server/db/player-score-total.ts:9 preserves old records with null
totals. Their balances cannot reconstruct cumulative points earned.
src/routes/matches/[id]/+page.svelte:182 still explains only the balance;
this text must follow the selected score presentation.
Verified against c296769b33392c564d787451844853f31e0c7b80 on 2026-10-12. Production match #1276
has a participant with scoreTotal: 8470 and bestScore: 2760; the rendered page
shows Highest reported score: 2,760, with no Total score column.
Screenshots
Both screenshots use the same disposable synthetic fixture, with totals/balances
staged as 8,470/2,760 and 500/500. The after image is a DOM mockup, not an
implemented application change. Production data and application source were not
modified.
Before:
After (mockup):
Fix
Select the score column at match level based on recorded data, not a date
cutoff. If any participant has a non-null scoreTotal, show Total score
and the participants' scoreTotal values. Zero is a valid recorded total.
If all participants have null/missing totals, preserve Highest reported
score and bestScore for historical/legacy matches. Show exactly one score
column in either case, in the current score column's position.
Handle mixed coverage explicitly: in a match using Total score, show a dash
for a participant without a total. Never substitute a points balance beneath
the Total score heading. Explain that the dash means no total was recorded.
Make the column selection react to match navigation/data updates so moving
between historical and newer matches updates the label, values and explanation.
Update Player results/About these results copy and the match-results guide.
Describe total score as the highest recorded cumulative points earned in this
match; players absent from the final report retain their latest recorded total.
Keep the existing balance explanation only for the historical fallback.
Preserve stored balances and totals, existing historical records, and
leaderboard/profile ranking semantics. Do not backfill totals from balances,
add repeated telemetry snapshots together, or require a schema migration for
this display change.
Add UI regression coverage for totals differing from balances, all-legacy
matches, zero totals, mixed/null totals, participants without stats, and
navigation between score presentations. Assert that newer matches show the
total and no Highest reported score heading, while historical matches retain
their original label and balance.
Run the relevant UI tests, the existing score ingestion/migration/match-detail
tests, npm run check, and the full application suite.
Validation already performed
The existing player-score-total-migration, keyed-telemetry and match-detail
test files pass: 23 tests. This validates storage and historical preservation;
it does not validate the proposed UI behavior. A search through all 135 existing
open and closed issues found no ticket covering this score-display change.
Match results still show the highest reported points balance even when cumulative
score has been saved. Select one score presentation for each match: total score
for matches with recorded totals, and the existing balance display for historical
matches without totals.
- `src/routes/matches/[id]/+page.svelte:34` always selects `bestScore` with the
heading **Highest reported score**. The cells at line 163 render that selected
field, so `scoreTotal` is never displayed.
- `src/lib/server/fleet/match-history.ts:128` already returns `scoreTotal` for
each participant alongside `bestScore`.
- `src/lib/server/db/player-score-total.ts:9` preserves old records with null
totals. Their balances cannot reconstruct cumulative points earned.
- `src/routes/matches/[id]/+page.svelte:182` still explains only the balance;
this text must follow the selected score presentation.
Verified against `c296769b33392c564d787451844853f31e0c7b80` on 2026-10-12. Production [match #1276](https://ec.thewrightserver.net/matches/1276)
has a participant with `scoreTotal: 8470` and `bestScore: 2760`; the rendered page
shows **Highest reported score: 2,760**, with no Total score column.
**Screenshots**
Both screenshots use the same disposable synthetic fixture, with totals/balances
staged as 8,470/2,760 and 500/500. The after image is a DOM mockup, not an
implemented application change. Production data and application source were not
modified.
Before:

After (mockup):

**Fix**
- [x] Select the score column at match level based on recorded data, not a date
cutoff. If any participant has a non-null `scoreTotal`, show **Total score**
and the participants' `scoreTotal` values. Zero is a valid recorded total.
- [x] If all participants have null/missing totals, preserve **Highest reported
score** and `bestScore` for historical/legacy matches. Show exactly one score
column in either case, in the current score column's position.
- [x] Handle mixed coverage explicitly: in a match using Total score, show a dash
for a participant without a total. Never substitute a points balance beneath
the Total score heading. Explain that the dash means no total was recorded.
- [x] Make the column selection react to match navigation/data updates so moving
between historical and newer matches updates the label, values and explanation.
- [x] Update Player results/About these results copy and the match-results guide.
Describe total score as the highest recorded cumulative points earned in this
match; players absent from the final report retain their latest recorded total.
Keep the existing balance explanation only for the historical fallback.
- [x] Preserve stored balances and totals, existing historical records, and
leaderboard/profile ranking semantics. Do not backfill totals from balances,
add repeated telemetry snapshots together, or require a schema migration for
this display change.
- [x] Add UI regression coverage for totals differing from balances, all-legacy
matches, zero totals, mixed/null totals, participants without stats, and
navigation between score presentations. Assert that newer matches show the
total and no Highest reported score heading, while historical matches retain
their original label and balance.
- [x] Run the relevant UI tests, the existing score ingestion/migration/match-detail
tests, `npm run check`, and the full application suite.
**Validation already performed**
The existing `player-score-total-migration`, `keyed-telemetry` and `match-detail`
test files pass: **23 tests**. This validates storage and historical preservation;
it does not validate the proposed UI behavior. A search through all 135 existing
open and closed issues found no ticket covering this score-display change.
Reviewed ffda04f276 against current main 2f52dcb1ef. All eight fix items are done, so I'm closing this.
Checklist
Choose totals from recorded data.src/routes/matches/[id]/+page.svelte:27 selects totals if any participant has a non-null value. Zero qualifies, and no date cutoff is involved.
Preserve the legacy column. The derived column list at :28-39 selects exactly one score field in the original position. All-null/missing totals retain Highest reported score and bestScore.
Handle mixed coverage. Cells at :172-175 render null or missing totals as a dash without substituting balances. The explanation at :191-195 states what that dash means.
React to navigation and data updates. Match, total availability, and columns are derived from page data. The mounted-page regression test navigates legacy → totals → legacy and then refreshes the same match with a zero total, checking labels, cells, and explanations.
Update explanations and documentation. Player results and About these results use the selected score meaning (:126-133,190-202). docs/guides/leaderboard.md:81-89 covers cumulative totals, departed players, mixed coverage, and the historical balance fallback.
Preserve storage and ranking semantics. The fix changes presentation, documentation, and test infrastructure; it adds no migration or ingestion/ranking changes. match-history.ts:127-128 still returns both values, and leaderboard/profile queries continue using best_score.
Add UI regressions. All eight tests in tests/client/ui-match-results.test.ts pass, covering different balances/totals, legacy and missing values, zero, mixed coverage, departed players, participants without stats, empty matches, navigation, and refreshed data. They assert exactly one score column and the matching explanation.
Run required validation.VITEST_MAX_WORKERS=2 npm test passed all 3,055 tests in 227 files, including client UI, score ingestion, score/report migrations, match detail, and migration-memory coverage. npm run check passed with zero errors and zero warnings.
Review notes
Reviewed and tested current main at 2f52dcb; no application source changes were made during review.
The client test project is included in the default full-suite command, so these rendered-component regressions run with the application tests.
Reviewed ffda04f276306d6de07c60c9ad6722a8a9ef9051 against current main 2f52dcb1ef444b2c0a0e0684afea5a9ed269ed1b. All eight fix items are done, so I'm closing this.
**Checklist**
- [x] **Choose totals from recorded data.** `src/routes/matches/[id]/+page.svelte:27` selects totals if any participant has a non-null value. Zero qualifies, and no date cutoff is involved.
- [x] **Preserve the legacy column.** The derived column list at `:28-39` selects exactly one score field in the original position. All-null/missing totals retain Highest reported score and `bestScore`.
- [x] **Handle mixed coverage.** Cells at `:172-175` render null or missing totals as a dash without substituting balances. The explanation at `:191-195` states what that dash means.
- [x] **React to navigation and data updates.** Match, total availability, and columns are derived from page data. The mounted-page regression test navigates legacy → totals → legacy and then refreshes the same match with a zero total, checking labels, cells, and explanations.
- [x] **Update explanations and documentation.** Player results and About these results use the selected score meaning (`:126-133,190-202`). `docs/guides/leaderboard.md:81-89` covers cumulative totals, departed players, mixed coverage, and the historical balance fallback.
- [x] **Preserve storage and ranking semantics.** The fix changes presentation, documentation, and test infrastructure; it adds no migration or ingestion/ranking changes. `match-history.ts:127-128` still returns both values, and leaderboard/profile queries continue using `best_score`.
- [x] **Add UI regressions.** All eight tests in `tests/client/ui-match-results.test.ts` pass, covering different balances/totals, legacy and missing values, zero, mixed coverage, departed players, participants without stats, empty matches, navigation, and refreshed data. They assert exactly one score column and the matching explanation.
- [x] **Run required validation.** `VITEST_MAX_WORKERS=2 npm test` passed all 3,055 tests in 227 files, including client UI, score ingestion, score/report migrations, match detail, and migration-memory coverage. `npm run check` passed with zero errors and zero warnings.
**Review notes**
- Reviewed and tested current main at `2f52dcb`; no application source changes were made during review.
- The client test project is included in the default full-suite command, so these rendered-component regressions run with the application tests.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Match results still show the highest reported points balance even when cumulative
score has been saved. Select one score presentation for each match: total score
for matches with recorded totals, and the existing balance display for historical
matches without totals.
src/routes/matches/[id]/+page.svelte:34always selectsbestScorewith theheading Highest reported score. The cells at line 163 render that selected
field, so
scoreTotalis never displayed.src/lib/server/fleet/match-history.ts:128already returnsscoreTotalforeach participant alongside
bestScore.src/lib/server/db/player-score-total.ts:9preserves old records with nulltotals. Their balances cannot reconstruct cumulative points earned.
src/routes/matches/[id]/+page.svelte:182still explains only the balance;this text must follow the selected score presentation.
Verified against
c296769b33392c564d787451844853f31e0c7b80on 2026-10-12. Production match #1276has a participant with
scoreTotal: 8470andbestScore: 2760; the rendered pageshows Highest reported score: 2,760, with no Total score column.
Screenshots
Both screenshots use the same disposable synthetic fixture, with totals/balances
staged as 8,470/2,760 and 500/500. The after image is a DOM mockup, not an
implemented application change. Production data and application source were not
modified.
Before:

After (mockup):

Fix
cutoff. If any participant has a non-null
scoreTotal, show Total scoreand the participants'
scoreTotalvalues. Zero is a valid recorded total.score and
bestScorefor historical/legacy matches. Show exactly one scorecolumn in either case, in the current score column's position.
for a participant without a total. Never substitute a points balance beneath
the Total score heading. Explain that the dash means no total was recorded.
between historical and newer matches updates the label, values and explanation.
Describe total score as the highest recorded cumulative points earned in this
match; players absent from the final report retain their latest recorded total.
Keep the existing balance explanation only for the historical fallback.
leaderboard/profile ranking semantics. Do not backfill totals from balances,
add repeated telemetry snapshots together, or require a schema migration for
this display change.
matches, zero totals, mixed/null totals, participants without stats, and
navigation between score presentations. Assert that newer matches show the
total and no Highest reported score heading, while historical matches retain
their original label and balance.
tests,
npm run check, and the full application suite.Validation already performed
The existing
player-score-total-migration,keyed-telemetryandmatch-detailtest files pass: 23 tests. This validates storage and historical preservation;
it does not validate the proposed UI behavior. A search through all 135 existing
open and closed issues found no ticket covering this score-display change.
Reviewed
ffda04f276against current main2f52dcb1ef. All eight fix items are done, so I'm closing this.Checklist
src/routes/matches/[id]/+page.svelte:27selects totals if any participant has a non-null value. Zero qualifies, and no date cutoff is involved.:28-39selects exactly one score field in the original position. All-null/missing totals retain Highest reported score andbestScore.:172-175render null or missing totals as a dash without substituting balances. The explanation at:191-195states what that dash means.:126-133,190-202).docs/guides/leaderboard.md:81-89covers cumulative totals, departed players, mixed coverage, and the historical balance fallback.match-history.ts:127-128still returns both values, and leaderboard/profile queries continue usingbest_score.tests/client/ui-match-results.test.tspass, covering different balances/totals, legacy and missing values, zero, mixed coverage, departed players, participants without stats, empty matches, navigation, and refreshed data. They assert exactly one score column and the matching explanation.VITEST_MAX_WORKERS=2 npm testpassed all 3,055 tests in 227 files, including client UI, score ingestion, score/report migrations, match detail, and migration-memory coverage.npm run checkpassed with zero errors and zero warnings.Review notes
2f52dcb; no application source changes were made during review.