v1.5.0: Social & Retention — contracts, leaderboards, achievements, daily streak - #4
Merged
Conversation
Expands §6 of the master expansion spec into an implementable design: daily contracts board, global leaderboards, achievements/badges, and the daily streak. Records the four owner-resolved design forks (single Social tab, rate-scaled contract targets, explicit streak claim with missed-day reset, admin-tunable `social` config section). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Twelve TDD tasks from the design spec: day-cycle helpers and the social config section, canonical state additions, the four shared modules (daily/contracts/streak/achievements), the two reducer actions plus the automatic achievement sweep, load-path rollover, the leaderboard service and route, three client tasks, and release prep. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…unlocks Two pre-existing event tests needed updating: one asserted a successful result with toEqual (now also carries unlockedAchievements), and two built a bare runtime-fields-only config that the sweep's goalCtx call can't read. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…banner Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…treak Adds the e2e smoke suite, README/CHANGELOG entries, and the version bump. The e2e suite caught a real bug before it shipped: the global leaderboards are served from a ~60s cache, so opting out left a player visible for up to a minute. The per-event board has always been immediate (v1.4's "hard requirement 1"), so the route now invalidates the cache on opt-out, with a unit regression test pinning it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
NeverEndingCode
marked this pull request as ready for review
August 1, 2026 04:41
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.
Implements v1.5, the final phase of the v1.2–v1.5 expansion. Spec and 12-task plan are in the first two commits; the remaining ten are the implementation, one per task.
What's in it
social.*tunables — all the numbers above are Balancing-tab editable and event-overlayable.Design points worth a look
dateKey, which is what guarantees client and server agree without a sync step. Targets and baselines are stored — a rate-scaled target recomputed on every read would recede as fast as the player approached it.tests/contracts.test.jsand the e2e suite both pin this.applyAction), and afterevaluate()on the load path. The second is what catches lifetime-FLOPS thresholds crossed while a player was offline, which no action touches.A real bug the e2e suite caught
The global boards are cache-fronted, so opting out left a player visible for up to 60 seconds. The per-event board has always been immediate — v1.4 went out of its way to make opt-out live rather than a join-time snapshot ("hard requirement 1") — and this control must not quietly mean something weaker on the newer boards.
PUT /api/me/leaderboard-opt-outnow invalidates the cache, with a unit regression test pinning it. This is exactly the class of thing the whole-branch review has historically caught, so it's worth a second pair of eyes.Two pre-existing tests needed updating
Adding
unlockedAchievementsto successful action results broke onetoEqualassertion, and the sweep'sgoalCtxcall broke two tests that hand-built a runtime-fields-only config. Both fixed at the assertion/fixture level rather than by suppressing the sweep.The one judgment call, flagged again
social.contractFlopsMinis a floor on the FLOPS contract target (no upper clamp, so it stays a pure rate scale above it). Without it a zero-output player — fresh save, or the instant after a Migrate — gets a target of 0, which is already met, and the contract auto-completes free. Set it to0in the Balancing tab to restore the unguarded behaviour. Documented in spec §5.1 and the README.Verification
npm test— 415 passed, 28 files (was 318 onmain)cd client && npm run build— cleantests/e2e/smoke-v15.mjs— 7/7 PASS, all seven checklist itemstests/e2e/smoke-v14.mjs— 9/9 PASS, no regressions from the shared-code changesNot tagged or pushed as a release — per the usual ritual that's merge, then tag
main, then push the tag.🤖 Generated with Claude Code
https://claude.ai/code/session_013HLPH7zGymsz31RarDnNKS