HAMSTER FRIENDSHIP — COMPLETE FIX & FINAL IMPROVEMENT

IMPORTANT: Update the EXISTING Hamster Friendship project. Do NOT rebuild from scratch, create a duplicate project, or remove existing working features.

Audit the entire project, fix the following issues, and verify everything on the actual production website.

1. CLOUD SAVE & SUPABASE — CRITICAL

The website currently displays: "Cloud saves are not available on this site yet. Guest play is ready."

Fix the underlying production configuration.

  • Identify and connect the correct production Supabase backend.
  • Apply all required database migrations.
  • Enable persistent player profiles linked to verified wallet addresses.
  • Save and restore player progress, SQK balances, inventory, purchases and lifetime scores.
  • Preserve data across sessions, devices and wallet reconnections.
  • Keep Guest Play available with separate guest and wallet profiles.
  • Prevent duplicate profiles and accidental data overwrites.
  • Display clear errors when cloud storage is unavailable.

Do not simply hide the warning or replace cloud storage with localStorage.

2. LIFETIME TOP 100 — REMOVE DAILY RESET

Replace the existing Daily Top 100 system completely.

The current interface incorrectly displays:

  • Daily Top 100
  • Best map score earned today
  • A new day clears the ranking
  • Daily rankings are unavailable until cloud saves are enabled.

New requirements:

  • Rename it to Lifetime Top 100.
  • Rank players by their accumulated lifetime score across all sessions.
  • Never reset, clear, expire or delete lifetime scores.
  • Store scores permanently in Supabase.
  • Update rankings continuously.
  • Only verified wallet profiles can appear on the leaderboard.
  • Guests remain unranked.
  • Preserve all existing historical scores where available.
  • Never fabricate historical scores.

Separate:

  • Current Map Score: score earned in the current game session.
  • Lifetime Score: cumulative score from all completed sessions.

Remove all daily reset logic, scheduled resets and related UI messages.

3. MOBILE LANDSCAPE & METAMASK

Fix the mobile experience, especially when using MetaMask Mobile.

Issue A — MetaMask Mobile:

  • The game does not properly rotate to landscape after connecting a wallet.
  • Detect device orientation.
  • Request landscape orientation when supported.
  • If orientation locking is unavailable, show a clear rotate-device overlay.
  • Preserve wallet connection and game session during orientation changes.

Issue B — iPhone Safari:

  • The game does not use the full available screen because browser address and navigation bars remain visible.
  • Use 100dvh, 100dvw and VisualViewport API.
  • Handle safe-area insets.
  • Remove unnecessary page margins, padding and scrolling.
  • Resize the game dynamically when browser toolbars appear or disappear.
  • Add a user-triggered fullscreen option where supported.
  • Support standalone PWA / Add to Home Screen for a more immersive iPhone experience.
  • Respect iOS Safari browser limitations.

Issue C — Accidental zoom:

  • Prevent accidental double-tap zoom during gameplay.
  • Use touch-action: manipulation on appropriate controls.
  • Prevent unintended multi-tap gestures.
  • Keep joystick, attack, jump and other controls responsive to repeated touches.
  • Maintain accessibility and avoid unnecessarily disabling pinch zoom across the entire website.

Do not stretch pixel art or distort the game canvas.

4. CHANGE IT — DESKTOP & MOBILE

The Change it feature is visible on mobile but missing on desktop.

  • Make Change it accessible on both mobile and desktop.
  • Preserve the existing mobile implementation.
  • Add Change it to the desktop interface in an appropriate position.
  • Ensure both versions use the same functionality and data.
  • Check responsive breakpoints and conditional rendering.
  • Do not merely display a button without implementing its functionality.

5. DOMAIN & BRANDING — SQUEEK.HAMSTER

My preferred official identity is:

squeek.hamster

Requirements:

  • Website display name: squeek.hamster.
  • Browser title and public-facing branding should use squeek.hamster.
  • Keep Hamster Friendship as the underlying project.
  • Investigate whether IMD supports .hamster custom domains or subdomains.
  • Explain registration, DNS configuration, availability and pricing.
  • If supported, provide the exact steps to connect squeek.hamster.
  • If unsupported, explain the closest alternatives.

IMPORTANT: Do not change the existing production URL until the new domain is confirmed working.

Do not create a new project or duplicate the website.

6. DATA & WALLET SECURITY

  • Preserve all existing player profiles and SQK balances.
  • Preserve wallet ownership and verified wallet identities.
  • Prevent guest data from overwriting wallet profiles.
  • Avoid duplicate rewards or purchases.
  • Never request unnecessary wallet signatures, approvals or transfers.
  • Ensure wallet connection is separate from permission to perform blockchain transactions.

7. FULL REGRESSION TESTING

Run a complete audit after implementing all changes.

Test these environments:

  • Desktop: 1440 × 900.
  • iPhone portrait and landscape.
  • Android portrait and landscape.
  • MetaMask Mobile in-app browser.
  • iPhone Safari.
  • Android Chrome.

Verify:

  1. MetaMask connection and wallet persistence.
  2. Cloud Save and data restoration.
  3. SQK balances and inventory persistence.
  4. Lifetime Top 100 ranking and permanent score storage.
  5. Guest and verified wallet separation.
  6. Change it functionality on desktop and mobile.
  7. Landscape orientation and fullscreen behavior.
  8. Accidental zoom prevention.
  9. Touch controls and canvas responsiveness.
  10. Existing game mechanics and marketplace functionality.

Run build, typecheck, database migration checks and regression tests.

Do not claim a feature is fixed unless it has been tested.

8. FINAL REPORT & DEPLOYMENT

Before publishing:

  • List every modified feature.
  • Report completed tests and their results.
  • Identify remaining blockers and browser limitations.
  • Confirm Supabase production configuration.
  • Confirm that existing player data has not been lost or reset.
  • Confirm whether Lifetime Top 100 is operational.
  • Confirm whether the custom domain is supported.

Only publish after critical fixes are implemented and verified.

Do not modify unrelated game mechanics, artwork, drop rates or existing gameplay balance.

The priority is a stable, persistent, mobile-friendly Hamster Friendship experience under the squeek.hamster identity.

Work

  1. Posted1 minto the first attempt
  2. Build websiteAgent #29453 files changedsent back2 attempts
    #705Codexneeds inputin the task: needs input: The existing production Supabase backend is unidentified: supabaseUrl and supabasePublishableKey …

    Failed in the task.

    needs input: The existing production Supabase backend is unidentified: supabaseUrl and supabasePublishableKey are empty in src/config.js, dist/config.js, and the live site's https://hamster-friendship-the-lost-alic.identitymd.eth.limo/… (checked 2026-11-05). No supplied input identifies the original backend. Connecting and verifying persistent saves, preserving existing player data, applying production migrations, and verifying permanent lifetime rankings require that same Supabase project and its owner's participation. No application files or production URL were changed, and no migrations or deployment were performed. — What are the existing production Supabase project URL and browser-safe publishable key, and can that project's owner arrange to apply the required database migrations and enable Ethereum Web3 Auth in the same project? Please supply only the public frontend configuration, not private credentials.

    ran oncodex · gpt-6.1-sol · 4 turns · 1m 9s · 53K in · 2.3K out · 250.4K cached
    submissionc1ca78f7dcd1aa121de0282664b325582647d8bb44f145dbfc9d833d4f8f4221
    devicef74e4c7229c480f9666f4d67ed1c428d4ab5da222c398629cef79c47757fc033
    started from5d735de90f90af06d2d2e4c0464de2ce73e6ebb2
    bundlenone
    #294Codex53 files changed

    Updated the existing game and built dist/ with lifetime-score migration, mobile display/orientation handling, shared Change it functionality, and branding/PWA updates.

    Build, typechecks, 124 local checks and 16/16 design checks passed.

    Production remains incomplete: the original Supabase configuration is missing. No production migration, data changes or publication occurred. Native Safari and MetaMask Mobile remain untested. .hamster is absent from IANA’s delegated TLD list.

    Full report and blockers · Supabase setup · Domain alternatives

    ran oncodex · gpt-6.1-sol · 10 turns · 42m 38s · 225.9K in · 82.9K out · 11.2M cached
    submission9babaa00d1892fc128575a0e0b5705d541823c8c15445ab2ca36b4d696d17ef7
    device42423bf7250e09c052ad857fc28e2056f09cf04d9d236f94c6054a5b2115b0b6
    started from5d735de90f90af06d2d2e4c0464de2ce73e6ebb2
    bundle647c08083910b315b773a9faa403157a9a79cbecf9018b661172158230bd6a37 · 668 KB
    verifiedrebuilt and matched · verifier 0.1.0 ·
    changed · 53 files
    DESIGN.mdREADME.mdVALIDATION.mddist/app-icon-192.pngdist/app-icon-512.pngdist/config.jsdist/game.jsdist/index.htmldist/manifest.webmanifestdist/og-image.pngdist/og-image.svgdist/save.jsdist/styles.cssdist/ui.jsdist/viewport.jsdist/wallet.jsdocs/DOMAIN.mddocs/validation/results.jsondocs/validation/screenshots/daily-rankings.pngdocs/validation/screenshots/desktop-entry.pngdocs/validation/screenshots/guild.pngdocs/validation/screenshots/landscape-weapons.pngdocs/validation/screenshots/lifetime-rankings.pngdocs/validation/screenshots/long-values-320.pngdocs/validation/screenshots/owned-costume.pngdocs/validation/screenshots/phone-entry.pngdocs/validation/screenshots/rotate-overlay.pngscripts/build.mjsscripts/check.mjsscripts/preview.mjsscripts/validate-market.mjsscripts/validate-mobile.mjsscripts/validate-squeek.mjssrc/app-icon-192.pngsrc/app-icon-512.pngsrc/config.jssrc/game.jssrc/index.htmlsrc/manifest.webmanifestsrc/og-image.pngsrc/og-image.svgsrc/save.jssrc/styles.csssrc/types.d.tssrc/ui.jssrc/viewport.jssrc/wallet.jssupabase/README.mdsupabase/migrations/004_lifetime_persistence.sqlsupabase/preservation_snapshot.sqlsupabase/tests/lifetime.mjssupabase/tests/squeek-client.mjssupabase/verify_lifetime.sql
  3. Design criticAgent #273found 2 high, 2 medium
    AreaResult
    Requirements95: 72 met, 6 missing, 0 faked, 2 after review, 15 need the requester
    Broken features4: 2 high, 2 medium
    First screen at 390pxGame and Start action visible
    taste@116/16 passed
    Copy findings1 incorrect action label
    Share cardPresent; 5/5 metadata checks passed

    Saved four verified findings in .imd-findings.json. Application files are unchanged.

    • High — bug: real Supabase wallet identities are rejected. The SQL helper reads top-level wallet fields, while Supabase stores them under custom_claims. The authentic identity shape returns NULL and fails profile creation. Correct the helper and test fixtures. Supabase Auth source
    • High — bug: switching devices permanently blocks the previous browser. Rejected events from an abandoned run survive retries, reload and reconnection, while restarting requires an empty queue. Add explicit recovery for terminal run conflicts.
    • Medium — bug: leaderboard refresh loses the reader’s place. At both 390px and 1440px, automatic refresh changes scrollTop from 1600 to 0. Update rows without replacing the entire panel.
    • Medium — bug: disconnect leaves another profile’s continuation label. A map-4 wallet disconnects to a map-1 guest, but the button still says “Continue map 4.” Render every entry-screen value from the current profile.

    The supplied 124 local regression checks passed, alongside the isolated build, actual JavaScript type analysis and taste probe. Four independent reproductions exposed the defects above. Native Safari, Android Chrome and MetaMask Mobile remain unverified.

    Production Supabase settings are empty. The original backend, owner access and production preservation checks are still required. Publication should remain blocked.

    “Met” below describes inspected repository behavior and local checks; it does not certify production or physical-device behavior.

    #Explicit requirementStatusEvidence
    1“Update the EXISTING Hamster Friendship project.”MetExisting engine and project retained
    2“Do NOT rebuild from scratch, create a duplicate project, or remove existing working features.”MetExisting export; gameplay regressions
    3“verify everything on the actual production website.”After reviewRevised export unpublished; live configuration checked
    4“Fix the underlying production configuration.”Needs the requestersrc/config.js: original backend settings absent
    5“Identify and connect the correct production Supabase backend.”Needs the requesterOriginal project identity/access missing
    6“Apply all required database migrations.”Needs the requesterMigrations supplied; production access missing
    7“Enable persistent player profiles linked to verified wallet addresses.”Missing003_squeek.sql:56: incorrect identity paths
    8“Save and restore player progress, SQK balances, inventory, purchases and lifetime scores.”MissingReal verified login blocked
    9“Preserve data across sessions, devices and wallet reconnections.”Missingsrc/save.js:136: unrecoverable device-handoff queue
    10“Keep Guest Play available with separate guest and wallet profiles.”Metsrc/save.js; isolation tests
    11“Prevent duplicate profiles and accidental data overwrites.”MetUnique canonical links; late-response isolation
    12“Display clear errors when cloud storage is unavailable.”MetProfile, wallet and ranking errors
    13“Do not simply hide the warning or replace cloud storage with localStorage.”MetWarning retained; SQL storage implementation
    14“Replace the existing Daily Top 100 system
    ran oncodex · gpt-6.1-sol · 8 turns · 23m 36s · 168.1K in · 36.5K out · 5.2M cached
    submission54fa0e25f246d7e6d5809a044da7c5c3a6b291dd2962894236bb5ecca7a04ed3
    device49abac41ee211059bdb7584ca17aebf33fabfded716c2fda1d562be96ce3780d
    started fromcfd354e06b2b5c50f664b6ac815038c6152b7438
    bundlenone
    applied on89273b22abae1b4534942609e6406971716825c653405161292e2206431c457e
    • highbug: the wallet helper rejects real Supabase Web3 identities by reading the wrong JSON fieldssupabase/migrations/003_squeek.sql:56

      Now: wallet_address() requires address and chain at the top level of auth.identities.identity_data. Supabase Auth stores those verified Web3 fields inside custom_claims. Migration 004 keeps this helper unchanged, so valid authenticated wallets cannot open a profile, save progress, purchase items or enter the leaderboard after production configuration is supplied. All current local Auth fixtures insert an incompatible flat shape and conceal this failure.

      Change to: add an upgrade migration replacing the helper with extraction from identity_data #>> '{custom_claims,address}' and #>> '{custom_claims,chain}', preserving provider=web3, Ethereum validation, canonical lowercase addresses and existing profile links. Exercise the actual Supabase identity shape in the database/client/browser fixtures; do not substitute editable user_metadata.

      Why: verified-wallet Supabase persistence is a critical explicit requirement. This is a repository integration defect independent of the missing production credentials. Primary evidence: Supabase Auth internal/api/web3.go constructs CustomClaims, internal/api/provider/provider.go serializes it as custom_claims, and internal/api/external.go stores that map in the identity (https://github.com/supabase/auth/blob/d6dec2640f047a42873e64ccec2f7288043d511f/internal/api/web3.go).

      At 1440 × 900, the triggering visitor state is a successful Ethereum Web3 login against Supabase with migrations 001–004 installed.

      Reproduced independently in PostgreSQL/PGlite: insert an auth user and its provider=web3 identity with identity_data={"sub":"web3:ethereum:0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","custom_claims":{"address":"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","chain":"ethereum","network":"1","domain":"forest.example","statement":"Sign in to save."},"email_verified":false,"phone_verified":false}; set request.jwt.claim.sub to that user UUID; call hf_private.wallet_address() as owner and public.hf_wallet_profile() as authenticated.

      Actual: wallet_address returns NULL and hf_wallet_profile raises "Sign in with your wallet to save progress."

      Expected: resolve the verified address and open its unique persistent profile.

      Replacing only the identity JSON with the tests’ flat {"address":"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","chain":"ethereum"} makes the same RPC succeed, isolating the JSON-path mismatch.

    • highbug: a second device leaves the first browser permanently blocked by an ended-run save queuesrc/save.js:136

      Now: starting a map on device B abandons device A’s run. Any later A event is permanently rejected, but flush retains it as a retryable error and beginMap refuses every restart while it remains queued. Reload and wallet reconnection restore the same blocked queue; purchases are also blocked.

      Change to: distinguish a terminal run conflict from a transient save failure. Stop the stale world, reconcile acknowledged events, retain rejected progress for recovery, and provide an explicit restart from the authoritative wallet profile that removes this terminal queue from the active flush path. Retry must not promise to resolve an event the server can never accept.

      Why: the brief requires persistent play across devices and wallet reconnections, clear errors, and prevention of accidental progress loss. Supporting one active map must not permanently disable a returning browser.

      At 1440 × 900, use two sessions/devices with the same verified wallet and migrations 001–004.

      A starts map 1 and saves a chest forage.

      B starts map 1, which marks A’s run abandoned.

      A then collects the basket (or makes any new attack), flushes, and opens Profile → Retry cloud save.

      With the actual src/save.js against PostgreSQL, three retries retain pendingEvents=1 and status="Save pending.

      This map has already ended.

      Start it again.

      Open Profile and retry."

      Calling beginMap(1) records another death event and throws "Retry your pending cloud save in Profile before starting another map."

      Reloading A retains pendingEvents=2 and the same start failure. purchase() also rejects while that queue exists.

      Expected: an actionable conflict recovery permits a new map without corrupting either wallet profile; actual: the stated retry/restart instructions form a permanent loop.

    • mediumbug: automatic leaderboard refresh throws readers back to the top every 15 secondssrc/ui.js:131

      Now: every automatic refresh removes the entire leaderboard before fetching its replacement. This collapses the scrollable dialog and resets its scroll position, even when the returned scores are unchanged.

      Change to: retain the existing table while loading; update its rows in place after success and preserve the dialog scroll position and focused control. Keep refresh/error status separate so a failed refresh also leaves the last known ranking readable.

      Why: continuous updates must let visitors read the Lifetime Top 100 without moving unrelated content or repeatedly losing their place.

      At 390 × 844 or 1440 × 900, configure a test leaderboard response containing 100 clearly labeled fixture rows; open Menu → Lifetime Top 100 and scroll #player-dialog to scrollTop=1600.

      Let the normal 15000ms boardTimer fire (also reproduced with Playwright clock.fastForward(15001)).

      At 390 the dialog scrollHeight is 7135px both before and after; at 1440 it is 4967px.

      In both cases scrollTop changes from 1600 to 0 after the second response, despite identical ranking data.

      Expected: remain at the selected ranks; actual: automatic refresh jumps back to the first rows.

    • mediumbug: disconnecting a progressed wallet leaves its Continue-map label on the guest profilesrc/ui.js:18

      Now: summary() updates the entry heading, map counter and replay control only when highest_map>1. Disconnecting a progressed wallet correctly restores the guest data but leaves the previous wallet’s map number and Continue label on the entry screen.

      Change to: whenever the engine is on the title screen, render all four values from the current profile. For highest_map=1 restore "Start adventure", "The chestnut forest", HUD map "1" and btn-replay.hidden=true; use the existing continuation labels only for a progressed current profile.

      Why: guest and wallet profiles must stay visibly separate, and the main action must describe the map it actually starts.

      At 1440 × 900, restore a test verified wallet profile with highest_map=4 while remaining on the entry screen, then open Menu → wallet details → Disconnect and close the wallet dialog.

      Measured snapshot after disconnect: profile.name="Guest", profile.highest_map=1, SQK=0, but #btn-start remains "Continue map 4", #start-title remains "The chestnut forest · Map 4", #hud-map remains "4", and Replay map 1 remains visible.

      Clicking Continue map 4 actually starts engine map=1.

      Expected: the disconnected guest entry displays Start adventure and map 1.

      Reproduced with the real export UI and PostgreSQL-backed fixture profile.

  4. Build websiteAgent #127425 files changed

    Fixed all four reported defects: Supabase identity parsing, stale-run recovery, leaderboard scroll/focus, and guest entry labels. Rebuilt dist/ and recorded revision responses.

    Build, type analysis, 149 regression checks and 16 design checks passed locally.

    Production remains unverified: Supabase configuration is still empty, and its owner must apply migration 005. No publication or live-data changes occurred. Physical-device testing remains outstanding.

    Full validation report

    ran oncodex · gpt-6.1-sol · 9 turns · 20m 35s · 200.2K in · 44.2K out · 5.5M cached
    submission5fae0233277655363a7b6be0b83da700eb5b74d23456b3bf6a3005de695f83f5
    devicef3c310dfe443399dacdc49d6162a1962c1aaa2afd0aa0c9d131eaa562b787ca7
    started fromcfd354e06b2b5c50f664b6ac815038c6152b7438
    bundle89273b22abae1b4534942609e6406971716825c653405161292e2206431c457e · 994 KB
    verifiedrebuilt and matched · verifier 0.1.0 ·
    changed · 25 files
    DESIGN.mdREADME.mdVALIDATION.mddist/config.jsdist/game.jsdist/save.jsdist/ui.jsdocs/validation/results.jsondocs/validation/screenshots/phone-entry.pngdocs/validation/screenshots/retained-rankings-phone.pngdocs/validation/screenshots/run-conflict-desktop.pngdocs/validation/screenshots/run-conflict-phone.pngscripts/validate-market.mjssrc/config.jssrc/game.jssrc/save.jssrc/types.d.tssrc/ui.jssupabase/README.mdsupabase/migrations/005_verified_wallet_recovery.sqlsupabase/tests/lifetime.mjssupabase/tests/squeek-client.mjssupabase/tests/verified-wallet.mjssupabase/tests/web3-identity.mjssupabase/verify_lifetime.sql
  5. Design criticAgent #961 reviewingattempt 2
    #1170Codexruntime erroron the agent's machine: Selected model is at capacity.

    Failed on the agent's machine.

    Selected model is at capacity. Please try a different model.

    ran oncodex · gpt-6.1-sol · 2 turns · 1m 0s · 49.4K in · 1.2K out · 85.6K cached
    submission20a6a9e0295a74bcf0f6e9f246c6b581cebf36fb91dbc4f4fd353c61059e8b96
    deviceee235ca2c050b44d3aa386fd3bf23296f2697c7212b42d42232af645ee2002be
    started from46aa094d075c55ef6c53913fc4a3ae6d4ea267ba
    bundlenone
    applied on89273b22abae1b4534942609e6406971716825c653405161292e2206431c457e
    #961Codexrunningasked for gpt-6.1-sol, for 31 min
  6. Publishedafter verification
  7. Hostedafter publication