Skip to content

August 2026 Release 3 - #2190

Merged
jmgasper merged 56 commits into
masterfrom
dev
Aug 26, 2026
Merged

August 2026 Release 3#2190
jmgasper merged 56 commits into
masterfrom
dev

Conversation

vas3a and others added 30 commits August 17, 2026 07:42
…board-page

PM-5370 campus leaderboard page
…board-page

PM-5370 - Minor UI updates for campus leaderboard
What was broken
In the work app challenge editor, removing tags from a challenge did not
persist. Clearing the Tags field and saving showed "Challenge saved
successfully", but the removed tags were still present after the save and on
reload.

Root cause
transformFormDataToChallenge() passes the payload through removeEmptyValues(),
which drops empty arrays unless the key is listed in
ALLOW_EMPTY_ARRAY_PAYLOAD_KEYS. Only "groups" and "terms" were listed, so
clearing every tag produced tags: [] which was stripped from the PATCH body.
With no tags key in the request, the challenge API left the stored tags
untouched. Verified against api.topcoder-dev.com that PATCH
/v6/challenges/{id} with {"tags": []} does clear the tags, confirming the
defect is in the UI payload and not in the API.

What was changed
Added "tags" to ALLOW_EMPTY_ARRAY_PAYLOAD_KEYS in
src/apps/work/src/lib/utils/challenge-editor.utils.ts so an empty tags array
is sent to the API and clears the challenge tags, matching the existing
behavior for groups and terms.

Any added/updated tests
Added a unit test in challenge-editor.utils.spec.ts asserting that
transformFormDataToChallenge keeps an empty tags array in the API payload. The
test fails without the fix and passes with it.
…challenge

What was broken
For challenges in 'New' status, the Budget Approve/Reject buttons were not
displayed for TM/Admin users immediately after saving the challenge. The
buttons only appeared after a full page refresh.

Root cause
The budget approval actions in the Work Manager challenge editor are gated on
`hasPersistedPrizeSets`, which was derived from the `challenge` prop. That prop
comes from the page's SWR challenge fetch, which is not revalidated after a
save, so it stays on the pre-save snapshot. Challenges are created in 'New'
status before the Prizes & Billing section is even rendered, so a 'New'
challenge never has persisted prize sets. Entering prizes and saving persists
them (and moves the challenge to Draft), but the stale prop still reported no
persisted prizes, so the approval actions stayed hidden until a refresh
refetched the challenge.

What was changed
- ChallengeEditorForm now tracks the persisted prize sets in local state,
  seeded from the `challenge` prop, kept in sync when that prop changes, and
  advanced with the prize sets returned by challenge-api after a successful
  save. The approval-action gate reads that state, so the Approve/Reject
  buttons render as soon as the save response confirms the prizes were stored.
- Extracted the prize-set check into a documented `hasPrizeSetWithPrizes`
  helper.

Added/updated tests
- Added `shows budget approval actions after saving a new challenge without
  persisted prizes` to ChallengeEditorForm.spec.tsx, which saves a 'New'
  challenge whose fetched snapshot has no prize sets and asserts the
  Approve/Reject Budget buttons appear once the form switches to read-only
  view mode (without the challenge prop being refetched).
- Expanded the ChallengePrizesField test mock so specs can set a placement
  prize on the form.
What was broken
The "Development Stats" win total on the member profile stats page did not
match the sum of the wins shown on the Development subtrack cards. On prod,
sdgun showed 321 wins while the cards summed to 329, and standlove showed
738 wins while the cards summed to 978. The total was correct on first paint
and then changed to the wrong value a few seconds later, once the stats
history request resolved.

Root cause
getTrackSummaryStats aggregates the parent track totals from stats history so
that a challenge appearing under two subtracks is only counted once. A subtrack
card falls back to the aggregate `wins` counter when its history rows carry no
placement data (rating-only rows), but the parent total only counted history
rows with `placement === 1`. Any subtrack that had history without placements
was therefore treated as having zero wins in the total while its card still
displayed the aggregate count, so those wins silently disappeared from the
summary once stats history loaded.

For sdgun, CONTENT_CREATION has a single rating-only history row and 8
aggregate wins, which is exactly the 329 - 321 = 8 difference. For standlove,
ARCHITECTURE (68), DESIGN (147) and DEVELOPMENT (25) are all rating-only and
account for the 978 - 738 = 240 difference.

What was changed
- src/apps/profiles/src/hooks/useFetchActiveTracks.tsx: added a
  `hasPlacementHistory` helper and split the history summaries into
  placement-bearing rows and rating-only rows. Placement-bearing rows keep the
  existing de-duplicated unique-history win count, while rating-only rows now
  contribute their aggregate wins to the parent total, the same way subtracks
  with no history at all already did. The `historyStatsWins` fallback is now
  computed from placement-bearing summaries only so those wins are not counted
  twice, and its `Math.max` is seeded with 0 to avoid `-Infinity`.
- Challenge and submission totals are untouched; only the win aggregation
  changed.

Any added/updated tests
- src/apps/profiles/src/hooks/useFetchActiveTracks.spec.tsx: new
  `getTrackSummaryStats` suite with two cases, modeled on the sdgun payload:
  one asserting the Development total equals the sum of the subtrack card wins
  when a subtrack has rating-only history (fails with 77 vs 85 before this
  change), and one asserting aggregate wins are preserved when no subtrack
  history has placements.
- Verified against the live prod payloads for both members reported in the
  ticket: Development totals now come out as 329 for sdgun and 978 for
  standlove, matching the sum of the subtrack cards in both cases, with
  challenge and submission totals unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…board-page

Make campus leaderboard profile name clickable
…s-tooltip

Fixes for general statistics tooltip
What was broken
Work Manager rendered the design Submission limit control with no option selected,
so a saved Unlimited or Limited value was invisible on the challenge view page and
after saving a draft, even though the value was stored in challenge metadata.
Copilots could also still raise or lower the limit after members had uploaded
submissions, and the Review application does not retroactively create scorecards
for submissions that a later limit would have allowed.

Root cause
The radio selection and the count are display-only form fields that are not part of
the persisted challenge payload. The editor resets the form when challenge data
arrives and after each save, which drops both fields. The seeding effect only ran
while those fields were undefined and its dependencies did not change when a reset
cleared them, so the fields were never re-seeded and the radio group rendered with
no selection. Nothing in the editor tied the control to existing submissions.

What was changed
The submission-limit selection and count are now re-seeded from the current
challenge metadata whenever they do not match it, so the persisted limit stays
visible after the challenge loads and after a draft save. The mode and count become
read-only, with an explanatory hint, once the challenge has at least one contest or
checkpoint submission. Challenge form data now carries numOfCheckpointSubmissions
alongside numOfSubmissions so two-round design challenges lock on checkpoint
uploads too, and FormRadioGroup accepts the optional hint already supported by
FormFieldWrapper.

Any added/updated tests
Added MaximumSubmissionsField coverage for restoring the persisted limit after a
form reset, replacing a stale selection with the persisted metadata, locking on a
contest submission, locking on a checkpoint submission, and staying editable while
no submission exists. Added a challenge-editor utils test that
numOfCheckpointSubmissions is kept in form data.
What was broken

In the Admin advanced review configuration for Design challenges, the
Checkpoint Review, Review, and Approval "Member N" selectors were rendered with
the red required asterisk, and closed-opportunity validation refused to save or
launch until a member was picked for each of them. Those assignments are no
longer something an admin has to make, because the selected copilot is assigned
to those private phases automatically.

Root cause

PM-5755 made the editor assign the selected copilot to the Design Checkpoint
Review, Review, and Approval reviewer rows during save, but the reviewer
assignment exception was never widened past Screening and Checkpoint Screening.
`isScreenerAssignmentOptional` therefore still reported those Design review
phases as requiring an up-front member, which drove both the `required` flag on
the member autocomplete and the closed-opportunity slot validation in the yup
schema and the draft-save reviewer check.

What was changed

Renamed `isScreenerAssignmentOptional` to `isReviewerAssignmentOptional` and
gave it an `isDesignChallenge` argument that also treats Checkpoint Review,
Review, and Approval as deferrable, matching the phases the copilot is assigned
to during save. HumanReviewTab passes that flag when the selected track is
Design and the selected type is Challenge, so the advanced view no longer marks
those member fields required. The challenge editor schema reads the same flag
from a new resolver validation context supplied by ChallengeEditorForm, which
also re-triggers reviewer validation when the track or type selection changes,
and the draft-save reviewer check receives it through its existing options
object. Every other track, challenge type, and reviewer phase keeps the
previous required behavior. The ChallengeEditorPage README was updated to match.

Any added/updated tests

Added a reviewer.utils unit spec covering the screening exception, the new
Design copilot phase exception, and the unchanged required cases for other
tracks, AI reviewer rows, and unknown phases. Added schema coverage for
accepting unassigned Design Review and Approval rows with the design validation
context and for still rejecting them without it. Added a HumanReviewTab test
asserting the Design Challenge Checkpoint Review, Review, and Approval member
fields render as optional, and a ChallengeEditorForm test that launches a Design
draft whose copilot-assigned review rows have no member.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…board-page

PM-5370 - show placement for 2nd and 3rd place
PM-5758: show and lock the design submission limit in Work Manager
PM-5562: Count rating-only history subtrack wins in track totals
PM-5165: show budget approve/reject actions right after saving a New challenge
PM-5896: keep empty tags array in challenge update payload
PM-5913: Drop the required marker from Design review member fields
vas3a and others added 26 commits August 21, 2026 08:36
…board-page

Fixes to campus leaderboard UI
…opilots

PM-5954 - show actions in review tab for copilots & reviewers
What was broken
The previous PM-5562 follow-up made Development totals include aggregate wins
for subtracks whose history had no placement data. QA still found that the
profile totals for pops and wleite showed 76 instead of 152 and 2 instead of
36.

Root cause
Legacy Marathon Match history is partial but contains placement fields. The
shared subtrack summary therefore treated those incomplete rows as the source
of truth and replaced 76 and 34 valid aggregate wins with zero placement wins.
The prior fix only covered histories with no placement fields at all.

What was changed
Keep an explicit aggregate wins value authoritative for Marathon Match while
retaining placement-derived wins for modern tracks. This preserves the earlier
Development deduplication and rating-only history fixes.

Any added/updated tests
Added a regression case modeled on the pops payload, proving that 76 aggregate
Marathon Match wins survive a partial placement history with no first-place
rows. The existing placement-history and Development aggregation tests remain
passing.
PM-4699 Add bubble skill statistics UI with mock data
PM-5562: Preserve aggregate Marathon Match wins
Integrate UI with skill statistics api
…board-page_fixes

PM-5939 -  campus leaderboard UI
PM-5964 Alignment issue in profile section
What was broken
In Work Manager a copilot could select "Limited" for the design submission limit,
leave the "Limit count" textbox empty, and still save or autosave the challenge.
No error was shown, and the challenge was persisted with limit metadata that
declares a limit but carries no number, which no downstream application can enforce.

Root cause
The submission-limit radio selection and the count are display-only form fields that
are serialized into the legacy submissionLimit challenge metadata entry. Nothing in
the challenge editor schema validated that entry, so an empty count produced no
validation error, formState.isValid stayed true, and both manual save and autosave
accepted the incomplete value.

What was changed
The parsing and serialization of the submissionLimit metadata contract moved into a
shared submission-limit utility so the editor field and the validation schema read
the same value. The challenge editor schema now rejects limit metadata that declares
a limit without a count of at least 1, and reports the message on the visible
submissionLimitCount field so the error renders under "Limit count" and in the save
footer. Saving, autosaving, and launching are blocked until a count is entered.

The rule only applies while the control is editable. The challenge editor publishes
an isSubmissionLimitConfigurable flag on the existing yup validation context, which
is true only for Design submission settings that have no uploaded contest or
checkpoint submissions. That keeps non-Design challenges, and challenges whose limit
is already locked by member submissions, saveable. The field revalidates itself after
each mode or count change so the error tracks the value that would be saved.

Any added/updated tests
Added submission-limit utility tests for detecting a limited setting with a missing
or zero count and for the contest/checkpoint submission check. Added challenge editor
schema tests that a limited setting without a count is rejected on the
submissionLimitCount path, that a zero count is rejected, that a valid count and an
unlimited setting pass, and that the rule is skipped when the limit is not
configurable. Added MaximumSubmissionsField tests that saving is blocked while the
count is empty and succeeds once a count is entered. Five of the new tests fail
against the unchanged source.
…ate-submissions

PM-5727 - UI for duplicate submisisons in work app & review app
PM-5758: require a count when design submissions are limited
…bile-ui

Campus leaderboard mobile UI Fixes
…bile-ui

PM-5886 - campus leaderboard UI updates
@jmgasper
jmgasper requested a review from kkartunov as a code owner August 26, 2026 03:35
Comment on lines +363 to +364
link.getAttribute('href')
?.startsWith('https://review.example.test'),
@jmgasper
jmgasper merged commit 0ff1b66 into master Aug 26, 2026
8 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants