Skip to content

Commit 477eb06

Browse files
Finish the visible DebateLab to DebateOwl rename (#241)
* Finish the visible DebateLab to DebateOwl rename The header, footer, titles, manifest, emails, and link preview now use the product name from site.json. The one-time notice still says DebateLab is becoming DebateOwl. Routes, storage keys, and the domain stay the same. Co-authored-by: Gáborjáni-Szabó Ádám <Programcode@users.noreply.github.com> * Hyphenate Hungarian suffixes and version the preview image DebateOwl takes Hungarian case endings with a hyphen. The owl mark title matches the new name, and og:image and twitter:image use hero-visual.jpg?v=2. The production canary still requires a DebateOwl title and reloads for the promotion window. Co-authored-by: Gáborjáni-Szabó Ádám <Programcode@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Gáborjáni-Szabó Ádám <Programcode@users.noreply.github.com>
1 parent 81f4125 commit 477eb06

104 files changed

Lines changed: 835 additions & 821 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.claude/skills/verify-debatelab/SKILL.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
---
22
name: verify-debatelab
3-
description: Launch and drive the real DebateLab web app (React client + local Supabase Auth/Postgres/Edge Functions, with either a fake model provider or real OpenRouter pinned to Claude Haiku 5.5 on the Anthropic BYOK key plus real Exa research) to prove a user-facing feature works, with screenshots, ARIA snapshots, provider calls, and database rows as evidence. Use when asked to verify, demo, reproduce, or screenshot DebateLab behavior in a browser, or before calling a DebateLab UI/Edge Function change done.
3+
description: Launch and drive the real DebateOwl web app (React client + local Supabase Auth/Postgres/Edge Functions, with either a fake model provider or real OpenRouter pinned to Claude Haiku 5.5 on the Anthropic BYOK key plus real Exa research) to prove a user-facing feature works, with screenshots, ARIA snapshots, provider calls, and database rows as evidence. Use when asked to verify, demo, reproduce, or screenshot DebateOwl behavior in a browser, or before calling a DebateOwl UI/Edge Function change done.
44
---
55

6-
# Verify DebateLab
6+
# Verify DebateOwl
77

8-
DebateLab is a web app. The surface a user touches is the browser client at `/login` and `/app/*`, backed by Supabase Auth, Postgres/RLS, and Deno Edge Functions. This skill runs all of that locally and drives it with Playwright. It has two modes:
8+
DebateOwl is a web app. The surface a user touches is the browser client at `/login` and `/app/*`, backed by Supabase Auth, Postgres/RLS, and Deno Edge Functions. This skill runs all of that locally and drives it with Playwright. It has two modes:
99

1010
- **Fake (default, free).** `e2e/full-stack/fake-openrouter.mjs` answers every model call with canned text. Proves wiring, rows, and UI, not model behavior.
1111
- **Live (`up --live`, costs money).** The same container becomes a recording proxy to real OpenRouter. It rewrites every chat call to `anthropic/claude-haiku-5.5` pinned to the Anthropic provider with fallbacks off, so it bills the Anthropic BYOK key and not OpenRouter credits (override with `VERIFY_LIVE_MODEL`, which must be an `anthropic/` model), records OpenRouter's reply model as proof, and stops forwarding after `--max-calls` (default 400). Edge Functions also get a real Exa key, so web research and verified citations are real.

‎.claude/skills/verify-debatelab/features/auth-demo-login.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Preconditions:
3838

3939
## Gotchas
4040

41-
- A first sign-in on a new account starts the onboarding tour on `/app`. Its first step (`Welcome to DebateLab`, `Start your first debate here.`) offers `Start debate`. The fixtures pre-seed `debate-trainer-onboarding` to skip it. The tour is tracked per account (store version 1, `completedUserIds`). A version 0 seed with `hasCompletedOnboarding: true` covers only the next account that signs in, so a second account in the same browser sees the tour. Interactive runs click `Skip tour` (`[data-test-id="button-skip"]`). The tour itself is covered in [current-debate](./current-debate.md).
41+
- A first sign-in on a new account starts the onboarding tour on `/app`. Its first step (`Welcome to DebateOwl`, `Start your first debate here.`) offers `Start debate`. The fixtures pre-seed `debate-trainer-onboarding` to skip it. The tour is tracked per account (store version 1, `completedUserIds`). A version 0 seed with `hasCompletedOnboarding: true` covers only the next account that signs in, so a second account in the same browser sees the tour. Interactive runs click `Skip tour` (`[data-test-id="button-skip"]`). The tour itself is covered in [current-debate](./current-debate.md).
4242
- Sessions are stored under the `debate-auth-local` localStorage key in local-preview mode. Don't reuse stub-session helpers (`e2e/helpers/auth.ts`). They fake auth and prove rendering only.
4343
- Google sign-in is not wired to the local stack. Demo codes, email codes and the email link work here.
4444
- The revoked-session check forces one token refresh before it signs out. An Auth outage (network error, 5xx, 429) keeps the session, and that path is covered by `src/test/auth/session-expiry.test.ts`, not by a recipe.

‎.claude/skills/verify-debatelab/features/localization.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# Localization
22

3-
The interface runs in English, Spanish and Hungarian. Every page names itself in the tab title in the interface language ("Generálás · DebateLab" in the app, "Felhasználási feltételek | DebateLab by Pi-Stack" on public pages), form validation and server refusals read in that language, the language switcher sits in every header, and `?lang=es|hu|en` links and the Hungarian and Spanish pages (`/hu`, `/es`, `/hu/tools/…`, `/es/tools/…`) open the app in that language.
3+
The interface runs in English, Spanish and Hungarian. Every page names itself in the tab title in the interface language ("Generálás · DebateOwl" in the app, "Felhasználási feltételek | DebateOwl by Pi-Stack" on public pages), form validation and server refusals read in that language, the language switcher sits in every header, and `?lang=es|hu|en` links and the Hungarian and Spanish pages (`/hu`, `/es`, `/hu/tools/…`, `/es/tools/…`) open the app in that language.
44

55
## Sub-features
66

7-
- loc-titles: `document.title` on app and public routes, per language, and a switch retitling the page without a reload. App routes read `<page> · DebateLab` (`usePrivateRouteHead`); public pages use the `pageHead` catalog section (`usePageHead`), whose English text is also what the prerender writes.
7+
- loc-titles: `document.title` on app and public routes, per language, and a switch retitling the page without a reload. App routes read `<page> · DebateOwl` (`usePrivateRouteHead`); public pages use the `pageHead` catalog section (`usePageHead`), whose English text is also what the prerender writes.
88
- loc-validation: an empty Attack submit shows `validation.caseTextRequired` in the interface language, and nothing shows before the first submit. Generate, Brainstorm and Factoids use the same keys.
99
- loc-switcher: the switcher on `/login`, the 404 page, and the other public pages (`PublicPageShell`), besides the landing page and the app header.
1010
- loc-links: `/?lang=hu` switches and saves the language, sets `<html lang>`, and drops the parameter; `/es` and `/hu` are prerendered pages of their own that keep their address, and Start from `/hu` leads into the app in Hungarian.

‎.claude/skills/verify-debatelab/recipes/auth.spec.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ test("auth-deep-link-email-code: a signed-out deep link signs in by email code a
176176
await page.goto("/app/generate");
177177
await expect(page).toHaveURL(/\/login$/);
178178
await expect(page.getByRole("main")).toHaveCount(1);
179-
await expect(page.getByRole("heading", { level: 1, name: "Sign in to DebateLab" })).toBeVisible();
179+
await expect(page.getByRole("heading", { level: 1, name: "Sign in to DebateOwl" })).toBeVisible();
180180
await evidence.aria("01-login-from-deep-link");
181181

182182
let sentAfter = Date.now();
@@ -230,7 +230,7 @@ test("auth-switch-account: the next account on this browser starts on /app, gets
230230
await evidence.step("Signed in as a second account; landed on /app, not /app/settings");
231231

232232
// AUTH-07: the second account gets its own tour.
233-
const tour = page.getByText("Welcome to DebateLab");
233+
const tour = page.getByText("Welcome to DebateOwl");
234234
await expect(tour).toBeVisible({ timeout: 10_000 });
235235
await evidence.shot("01-second-account-tour");
236236
if (await page.getByRole("button", { name: "Open menu" }).isVisible()) {

‎.claude/skills/verify-debatelab/recipes/current-debate.spec.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ test("debate-tour: a brand-new account starts its first debate from the onboardi
198198

199199
const tooltip = page.locator(".react-joyride__tooltip");
200200
const next = page.locator('[data-test-id="button-primary"]');
201-
await expect(tooltip).toContainText("Welcome to DebateLab", { timeout: 15_000 });
201+
await expect(tooltip).toContainText("Welcome to DebateOwl", { timeout: 15_000 });
202202
await expect(tooltip).toContainText("Start your first debate here.");
203203
await evidence.shot("01-tour-first-step");
204204

‎.claude/skills/verify-debatelab/recipes/localization.spec.ts‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ async function chooseLanguage(page: Page, language: keyof typeof LANGUAGE_NAMES)
3030
await expect(page.locator("html")).toHaveAttribute("lang", language);
3131
}
3232

33-
/** The tab title once the page has set its own (the shell's is just "DebateLab"). */
33+
/** The tab title once the page has set its own (the shell's is just "DebateOwl"). */
3434
async function pageTitle(page: Page, route: string) {
3535
await page.goto(route);
36-
await expect.poll(() => page.title()).not.toBe("DebateLab");
36+
await expect.poll(() => page.title()).not.toBe("DebateOwl");
3737
return page.title();
3838
}
3939

@@ -49,13 +49,13 @@ test("loc-titles: every route's tab title is its own and follows the interface l
4949
await evidence.json("01-document-titles", titles);
5050

5151
for (const route of APP_ROUTES) {
52-
for (const language of ["en", "hu", "es"]) expect(titles[language][route]).toMatch(/ · DebateLab$/);
52+
for (const language of ["en", "hu", "es"]) expect(titles[language][route]).toMatch(/ · DebateOwl$/);
5353
}
5454
for (const route of PUBLIC_ROUTES) {
5555
for (const language of ["en", "hu", "es"]) expect(titles[language][route]).toMatch(new RegExp(`\\| ${BRAND}$`));
5656
}
57-
expect(titles.en["/app/generate"]).toBe(`${en.nav.generate} · DebateLab`);
58-
expect(titles.hu["/app/generate"]).toBe(`${hu.nav.generate} · DebateLab`);
57+
expect(titles.en["/app/generate"]).toBe(`${en.nav.generate} · DebateOwl`);
58+
expect(titles.hu["/app/generate"]).toBe(`${hu.nav.generate} · DebateOwl`);
5959
expect(titles.hu["/no-such-page"]).toBe(hu.pageHead.notFound.title.replace("{{brand}}", BRAND));
6060
// Each language names every page in its own words (the brand aside).
6161
for (const route of [...APP_ROUTES, ...PUBLIC_ROUTES]) {
@@ -65,9 +65,9 @@ test("loc-titles: every route's tab title is its own and follows the interface l
6565
// A switch retitles the page on screen, with no reload.
6666
await page.goto("/app/attack");
6767
await chooseLanguage(page, "en");
68-
await expect(page).toHaveTitle(`${en.nav.attack} · DebateLab`);
68+
await expect(page).toHaveTitle(`${en.nav.attack} · DebateOwl`);
6969
await chooseLanguage(page, "hu");
70-
await expect(page).toHaveTitle(`${hu.nav.attack} · DebateLab`);
70+
await expect(page).toHaveTitle(`${hu.nav.attack} · DebateOwl`);
7171
await evidence.shot("02-attack-title-hu");
7272
});
7373

@@ -96,7 +96,7 @@ test("loc-switcher: sign-in and not-found pages carry the language switcher", as
9696
await evidence.shot("01-login-en");
9797
await chooseLanguage(page, "hu");
9898
await expect(page.getByRole("heading", { level: 1, name: hu.login.title })).toBeVisible();
99-
// "Bejelentkezés a DebateLabba" already names the app, so it gets no suffix.
99+
// "Bejelentkezés a DebateOwl-ba" already names the app, so it gets no suffix.
100100
await expect(page).toHaveTitle(hu.login.title);
101101
await evidence.shot("02-login-hu");
102102

‎agentic/pages.e2e.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const PUBLIC_PAGES = ["/", "/login", "/terms", "/privacy", "/expocit/sources"];
3030
const NAMES: Record<Language, string> = { en: "English", es: "Spanish", hu: "Hungarian" };
3131

3232
const EXEMPT =
33-
"Product names such as DebateLab and ExpoCit, AI model names (Claude Sonnet 5), plan names (Pro), debate format codes and the competition format names kept in English in every language (Public Forum, Lincoln-Douglas, Policy, British Parliamentary, World Schools, Asian Parliamentary), language names offered as choices (English, Español, Magyar), and user content do not count. Technical loanwords the app uses on purpose, such as email, chat, prompt and token, count as translated.";
33+
"Product names such as DebateOwl, DebateLab and ExpoCit, AI model names (Claude Sonnet 5), plan names (Pro), debate format codes and the competition format names kept in English in every language (Public Forum, Lincoln-Douglas, Policy, British Parliamentary, World Schools, Asian Parliamentary), language names offered as choices (English, Español, Magyar), and user content do not count. Technical loanwords the app uses on purpose, such as email, chat, prompt and token, count as translated.";
3434

3535
async function checkPage(browser: Browser, agent: Agent, language: Language) {
3636
await expect(browser.locator("html")).toHaveAttribute("lang", language);

‎agentic/replay/a7ab22475ff220f06530d1b208935a31518cb6002dad033bbe5549c162f9df6e.json‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
"goneAnchors": [
9999
{
100100
"role": "alertdialog",
101-
"name": "Welcome to DebateLab! 🎉Everything in DebateLab belongs to one debate: the motion you are preparing, its sources, and your results. Start your first debate here.Start debate"
101+
"name": "Welcome to DebateOwl! 🎉Everything in DebateOwl belongs to one debate: the motion you are preparing, its sources, and your results. Start your first debate here.Start debate"
102102
},
103103
{
104104
"role": "button",
@@ -113,10 +113,10 @@
113113
},
114114
{
115115
"role": "heading",
116-
"name": "Welcome to DebateLab! 🎉"
116+
"name": "Welcome to DebateOwl! 🎉"
117117
},
118118
{
119-
"text": "Everything in DebateLab belongs to one debate: the motion you are preparing, its sources, and your results. Start your first debate here."
119+
"text": "Everything in DebateOwl belongs to one debate: the motion you are preparing, its sources, and your results. Start your first debate here."
120120
},
121121
{
122122
"role": "button",

‎agentic/replay/cc6903d8aafb702ef5a496a05b9c45338886c52fc41ea6a7c0f6fd1435dfbfec.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"endAnchors": [
3939
{
4040
"role": "image",
41-
"name": "Logotipo de DebateLab"
41+
"name": "Logotipo de DebateOwl"
4242
},
4343
{
4444
"text": "Herramientas"
@@ -69,7 +69,7 @@
6969
"goneAnchors": [
7070
{
7171
"role": "image",
72-
"name": "DebateLab logo"
72+
"name": "DebateOwl logo"
7373
},
7474
{
7575
"text": "Tools"

‎agentic/replay/cec2ee4bacb9750f2fa98e3124caf500077ddc18df231c58d9c29724467af6ac.json‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
"goneAnchors": [
9999
{
100100
"role": "alertdialog",
101-
"name": "Welcome to DebateLab! 🎉Everything in DebateLab belongs to one debate: the motion you are preparing, its sources, and your results. Start your first debate here.Start debate"
101+
"name": "Welcome to DebateOwl! 🎉Everything in DebateOwl belongs to one debate: the motion you are preparing, its sources, and your results. Start your first debate here.Start debate"
102102
},
103103
{
104104
"role": "button",
@@ -113,10 +113,10 @@
113113
},
114114
{
115115
"role": "heading",
116-
"name": "Welcome to DebateLab! 🎉"
116+
"name": "Welcome to DebateOwl! 🎉"
117117
},
118118
{
119-
"text": "Everything in DebateLab belongs to one debate: the motion you are preparing, its sources, and your results. Start your first debate here."
119+
"text": "Everything in DebateOwl belongs to one debate: the motion you are preparing, its sources, and your results. Start your first debate here."
120120
},
121121
{
122122
"role": "button",

0 commit comments

Comments
 (0)