Repository navigation
Fix the 11 bugs from today's QA pass (H1, M1–M5, L1–L5) - #184
Conversation
H1: when Supabase refuses a signed-in request (401 from REST or Functions, 401/403 from Auth's user lookup), force a token refresh outside the request. If Auth refuses that too, sign this browser out locally and show "Your session expired. Sign in again." on /login. Outages, 5xx and rate limits keep the session. M4: the code field keeps digits only, Verify waits for six digits, and a refused code says it may be wrong or expired. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tings (M1, M2, L2) M1: when Crossfire's first AI turn is refused for the daily limit, the round goes back to setup (no clock) and the daily-limit dialog Ask uses opens. A round with exchanges keeps its state and can still be ended. Ending a round with no exchange by hand no longer shows an error. M2: Sparring setup warns when today's remaining requests are fewer than the round needs, and an opponent or judge turn refused for the limit opens the same dialog. L2: one shared dialog component for every 402 in these tools, a localized inline message instead of the server's English text, and Settings shows requests used today and when they refresh. The client count now leaves out refused calls and jev_* helper rows, reads the account's own rate_limits override, and is null (never blocking) when it cannot be read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Auto-saved sources are matched per debate by a normalized URL (host lower-cased without www, no scheme, fragment, tracking parameters or trailing slash). A page already in the debate's Library gets its research metadata refreshed instead of a second row; the student's title, folder and on/off choice stay. Batches from tools that finish together run one after another so each sees the rows the last one saved. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Below the sm breakpoint a source title takes two lines instead of one truncated line, and the type badge (already shown by the row icon) is hidden to give it room. On touch screens the delete button is 44px and the whole 44px square around the on/off switch toggles it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Settings no longer hard-codes "Signed in with Google". Under the email it shows how the account signs in, from what Auth recorded: Google, email code, both, or demo code. The description keeps only the API key sentence. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Edges are announced as "From Thesis to Argument 1" (computed for the canvas only, never saved) instead of "Edge from thesis to c1". React Flow 11 has no prop for its keyboard help text, so a small component puts the EN/ES/HU help into the two description elements it renders. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/login, /app/* and /share/* (including a share link that no longer works) get a page title from the existing route labels, such as "Generate · DebateLab", and robots "noindex, nofollow" while on screen, matching the X-Robots-Tag vercel.json already sends. /expocit/sources is left as it is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the Ask label in replays architecture.md describes the revoked-session check (H1), one Library row per page per debate (M3), and what the remaining-requests estimate can and cannot know (M1, M2, L2). The Ask message box's accessible name is now its label (L4), so the two recorded agentic replays target that name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… requests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
M5: on touch screens the Library on/off switch gets its 44px tap area from a pseudo-element, the same way the Checkbox does. Wrapping it in a label did not forward taps reliably. L4: page titles end in "DebateLab" (the shell's title) rather than the longer brand name from site.json, as the QA report asked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
getUserFacingAIError now turns a daily-limit or trial refusal into the limit dialog's own text, so Crossfire and Sparring stop printing the server's English message. Sparring's change matches open PR #178 line for line, so that file merges cleanly; #178's fuller helper in error-display.ts should replace this one when it lands. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Deployment failed for project debate-navigator with the following error: Learn More: https://vercel.com/adam-gaborjanis-projects?upgradeToPro=build-rate-limit |
|
Warning Review limit reachedEnable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. Next included review available in 11 minutes. View limit details
Note 🎁 Summarized by CodeRabbit Free
Comment |
|
Deployment failed for project debatelab-staging with the following error: Learn More: https://vercel.com/adam-gaborjanis-projects?upgradeToPro=build-rate-limit |
Fixes the 11 bugs from this morning's QA pass (H1, M1–M5, L1–L5). One PR, one commit per bug or pair, plus docs, verify recipes and two small follow-ups the browser checks caught. Frontend only: no migrations, no Edge Function changes, nothing to deploy beyond the normal Vercel build.
Use the staging preview to check these (staging sign-in with an email code works; the trial is 5 AI requests a day).
Bugs
H1: a revoked session looked signed in, and saves showed "saved".
/user), it forces one token refresh after that request finishes. If Auth refuses the refresh too, the session is dead: the browser signs out locally and /login says "Your session expired. Sign in again." A network error, 5xx or 429 keeps the session (that is Stop treating an Auth outage as a successful local save #171's outage case).debate-auth-staging→access_tokento any invalid JWT,refresh_tokentox,expires_atto now + 3000. Reload /app. You land on /login with the message, once. A second reload doesn't show it again.M1: Crossfire started its clock when the first AI turn was refused, and couldn't be ended.
M2: Sparring let an out-of-quota user start a 38-minute round.
rate_limitsrows (server-only by RLS), so its count is an estimate. The server's 402 still decides.M3: research saved the same page to the Library again and again.
www., no scheme,#fragment, tracking parameters or trailing slash). A page already in the debate's Library gets its research metadata refreshed instead of a new row; your title, folder and on/off choice stay. Batches from tools that finish at the same time now run one after another, so each sees what the last saved.M4: a wrong email code was called "expired", and letters were sent.
otp_expiredfor both.) The field keeps digits only, a pasted "123 456" becomes "123456", and Verify stays disabled until there are exactly 6 digits.12ab(it shows12, Verify disabled) → type000000→ Verify → the new message.M5: mobile Library cut titles to a few characters, and row controls were tiny.
smbreakpoint a title wraps to two lines, and the type badge (the row icon already shows the type) hides to make room. On touch screens the delete button is 44×44, and the on/off switch gets a 44 px-tall tap area, the same way the Checkbox does.L1: Settings told everyone "Signed in with Google".
L2: the limit messages disagreed, and remaining requests were never shown.
jev_*helper rows, reads your ownrate_limitsoverride, and is hidden whenever any read fails.L3: flowchart screen-reader text stayed English, and edges were internal ids.
ariaLabelConfig(that arrived in v12), so a small component puts the translated keyboard help into the two description elements React Flow renders.aria-label.L4: unlabeled controls and one title for every page.
L5: private routes were indexable with a generic title.
robots: noindex, nofollowand a page title while on screen. That matches theX-Robots-Tagheader vercel.json already sends for crawlers that don't run JS. /expocit/sources is untouched, as asked.document.querySelector('meta[name=robots]').contentisnoindex, nofollow, and the landing page is back toindex, followafter you leave.What I ran (local, at the final head)
npm run verify: docs:check, lint, typecheck, unit tests (51 files), collaboration (30), test:edge (361), build, test:sw, and the desktop @smoke browser set (30/30). All passed. This is a local result, not CI.src/test/auth/session-expiry.test.ts: which responses count, revoked vs outage vs rate limit vs 5xx, one check at a time, the check runs after the request), M4 (src/test/auth/login-otp.test.tsx), M3 (src/lib/ai/sources.test.ts: URL variants, two tools at once → one insert and one update, other debates unaffected), M1 (src/test/crossfire/crossfire-daily-limit.test.tsx).verify-debatelab, fake provider, local Supabase), desktop-chromium and mobile-chromium:auth-session-expired(QA's H1 steps),cross-daily-limit+spar-daily-limit(the realaifunction's 402),cross-end-early. All pass.auth,practice,library,case-generation,ai-toolspass.account: 8 of 10 pass.timer-runfails on both viewports, but that comes from main: Keep timer shortcuts away from buttons and open menus #172 made timer shortcuts ignore a focused button, and the recipe pressesrwhile the Pause button has focus. This PR doesn't touch the timer.e2e/helpers/auth.ts) now answers the token refresh with the same stub session. Without that, H1 correctly signs out the bogus stub session, and the render-only smoke tests would also have sent refresh requests to production Auth.Not verified: staging or production (I ran nothing there), real model output (fake provider), Google sign-in.
Overlap with other PRs
The branch is rebased on current main, which already includes #171, #173, #158, #170, #172, #174, #175, #169, #159, #160 and #163. Nothing here redoes them; H1 builds on #171, and the dialog is #173's version.
Against the PRs still open, checked with
git merge-tree:src/lib/ai/error-display.ts. Both add a subscription-error branch togetUserFacingAIError; take Weight the daily AI quota by model and cap AI spend at $2 a week (BYOK Claude excluded) #178'ssubscriptionLimitMessageversion.SparringPage.tsxmerges cleanly because I made those lines match Weight the daily AI quota by model and cap AI spend at $2 a week (BYOK Claude excluded) #178's. After Weight the daily AI quota by model and cap AI spend at $2 a week (BYOK Claude excluded) #178 lands, the remaining-requests estimate (Settings line, Sparring warning) counts requests, not weighted units, so it will read low for Opus or Sonnet users until it uses Weight the daily AI quota by model and cap AI spend at $2 a week (BYOK Claude excluded) #178's weights. It only warns and informs, so nothing gets blocked.Follow-ups (not in this PR)
(debate_id, normalized url)to stop cross-tab duplicates (M3).timer-runrecipe for Keep timer shortcuts away from buttons and open menus #172's behavior (pressrafter moving focus off the button).🤖 Generated with Claude Code