From ddcd38e1686344df453cf6ec8ee15dac4446d80d Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Thu, 15 Oct 2026 19:29:50 -0700 Subject: [PATCH] fix(first-session): Run it here above the fold at 1440x900, and the invitation code stops claiming it unlocks hosting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QA 2026-10-16 (fresh account, production f8b43625): - With "Run it here" chosen at 1440x900, the act's top edge sat at y=882, under the "Add a computer" box, so a stranger saw a selected card and no button until they scrolled. - The register form's invitation field said the code "Unlocks hosted agents", but Run it here works without one (hosted is capped per user, not gated). A stranger without a code read hosting as locked. - V2AgentBYO: the error line and the act now come straight after the fields they act on, above "Add a computer". Measured in Chromium at 1440x900, this branch's frontend against production, unverified test account (the verify banner showing), IBM Plex loaded: act top 882 → 647, fully in view, and the centre hit-tests to the button. Still fully in view at 1440x780. - Register (en + zh-CN): the code "Unlocks hiring from the catalog" (the cloudAgents entitlement); the hint says you can still run an agent here or bring your own. Settings' redeem success no longer says "Hosted agents unlocked". zh copy per the zh-cn-ui-localization glossary (应用市场, 智能体, 你; 「在这里运行」 matches the card title). - Tests: the act precedes "Add a computer" in the document (mutation: main's order fails it), and neither language's invitation or redeem copy says the code unlocks hosting. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_0157AG2wo8mJYqKezXNs48Ya --- frontend/src/i18n/locales/en.json | 6 +-- frontend/src/i18n/locales/zh-CN.json | 6 +-- .../v2/__tests__/V2AgentBYOHosted.test.tsx | 17 +++++++++ frontend/src/v2/__tests__/V2Register.test.tsx | 20 ++++++++++ frontend/src/v2/components/V2AgentBYO.tsx | 37 ++++++++++--------- frontend/src/v2/components/V2Register.tsx | 8 ++-- 6 files changed, 68 insertions(+), 26 deletions(-) diff --git a/frontend/src/i18n/locales/en.json b/frontend/src/i18n/locales/en.json index 5396e2619f..f21cce772f 100644 --- a/frontend/src/i18n/locales/en.json +++ b/frontend/src/i18n/locales/en.json @@ -239,8 +239,8 @@ "title": "Create your account", "subtitle": "Join the shared space where agents and humans collaborate.", "invitationCode": "Invitation code (optional)", - "invitationPlaceholder": "Unlocks hosted agents", - "invitationHint": "No code? Leave blank — you can bring your own agents and redeem a code later in Settings.", + "invitationPlaceholder": "Unlocks hiring from the catalog", + "invitationHint": "No code? Leave blank — you can still run an agent here or bring your own, and redeem a code later in Settings.", "submit": "Create account", "creating": "Creating account...", "alreadyHaveAccount": "Already have an account?", @@ -1791,7 +1791,7 @@ "unlocking": "Unlocking…", "gated": "Hiring an agent from the catalog needs an invitation code during beta.", "haveCode": "Have an invitation code?", - "success": "Hosted agents unlocked — hire your first one from the catalog." + "success": "Catalog unlocked — hire your first agent." }, "empty": { "title": "Build your AI team", diff --git a/frontend/src/i18n/locales/zh-CN.json b/frontend/src/i18n/locales/zh-CN.json index 5b93e8c45d..b3be6abdee 100644 --- a/frontend/src/i18n/locales/zh-CN.json +++ b/frontend/src/i18n/locales/zh-CN.json @@ -239,8 +239,8 @@ "title": "注册", "subtitle": "加入这个让智能体与人共同协作的空间。", "invitationCode": "邀请码(选填)", - "invitationPlaceholder": "解锁托管智能体", - "invitationHint": "没有邀请码?可以留空——你仍可接入自己的智能体,之后再到设置中兑换邀请码。", + "invitationPlaceholder": "解锁应用市场中的智能体", + "invitationHint": "没有邀请码?可以留空——你仍可选择「在这里运行」或接入自己的智能体,之后再到设置中兑换邀请码。", "submit": "注册", "creating": "正在注册…", "alreadyHaveAccount": "已有账号?", @@ -1783,7 +1783,7 @@ "unlocking": "解锁中…", "gated": "内测期间,从应用市场雇用智能体需要邀请码。", "haveCode": "有邀请码?", - "success": "已解锁托管智能体 —— 从应用市场雇佣第一个智能体。" + "success": "已解锁应用市场——去雇用你的第一个智能体吧。" }, "empty": { "title": "组建你的 AI 团队", diff --git a/frontend/src/v2/__tests__/V2AgentBYOHosted.test.tsx b/frontend/src/v2/__tests__/V2AgentBYOHosted.test.tsx index 10f135addb..92157b273b 100644 --- a/frontend/src/v2/__tests__/V2AgentBYOHosted.test.tsx +++ b/frontend/src/v2/__tests__/V2AgentBYOHosted.test.tsx @@ -139,6 +139,23 @@ describe('V2AgentBYO — Run it here', () => { expect(screen.getByText(/sam-agent is live in Workspace/i)).toBeInTheDocument(); }); + // QA 2026-10-16: with "Run it here" chosen at 1440x900, the act's top edge + // sat at y=882, under the "Add a computer" box, so a stranger saw a selected + // card and no button. The act now comes straight after the fields it acts on. + // jsdom has no layout, so this pins the order; the fold itself was checked + // in a real browser at 1440x900 (see the PR). + test('the act comes before the "Add a computer" box', async () => { + mockGet({ configured: true, status: { runtime: { lastPollAt: 1 } } }); + renderPage(); + + await waitFor(() => expect(screen.getByTestId('byo-mode-hosted')).toBeInTheDocument()); + fireEvent.click(screen.getByTestId('byo-mode-hosted')); + const act = screen.getByRole('button', { name: /^run it here$/i }); + const addComputer = await screen.findByTestId('byo-add-computer'); + // eslint-disable-next-line no-bitwise + expect(act.compareDocumentPosition(addComputer) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy(); + }); + test('a connect-card deep link (?name=) keeps "Bring your own runtime" selected even when hosting is available', async () => { mockGet({ configured: true, status: { runtime: { lastPollAt: 1 } } }); // Scout's connect_local_agent card lands here with the seat it proposed: the diff --git a/frontend/src/v2/__tests__/V2Register.test.tsx b/frontend/src/v2/__tests__/V2Register.test.tsx index f13d5ef73c..471ad7b962 100644 --- a/frontend/src/v2/__tests__/V2Register.test.tsx +++ b/frontend/src/v2/__tests__/V2Register.test.tsx @@ -144,4 +144,24 @@ describe('V2Register', () => { expect(screen.queryByText(/join the Community pod/)).not.toBeInTheDocument(); expect(screen.queryByRole('link', { name: 'sign in now' })).not.toBeInTheDocument(); }); + + // QA 2026-10-16: the field said the code "Unlocks hosted agents", but + // "Run it here" works without one (hosted is capped per user, not gated), so + // a stranger with no code read hosting as locked. The code unlocks hiring from + // the catalog (the cloudAgents entitlement), and the copy says that, in both + // languages. + it('never tells a stranger the invitation code unlocks hosting', async () => { + renderRegister(); + + const field = await screen.findByLabelText(/invitation code/i); + expect(field).toHaveAttribute('placeholder', 'Unlocks hiring from the catalog'); + expect(field.getAttribute('placeholder')).not.toMatch(/host/i); + expect(screen.getByText(/you can still run an agent here or bring your own/i)).toBeInTheDocument(); + + // eslint-disable-next-line global-require + const zh = require('../../i18n/locales/zh-CN.json'); + const { invitationPlaceholder, invitationHint } = zh.auth.register; + expect(`${invitationPlaceholder} ${invitationHint}`).not.toMatch(/托管/); + expect(zh.yourTeam.redeem.success).not.toMatch(/托管/); + }); }); diff --git a/frontend/src/v2/components/V2AgentBYO.tsx b/frontend/src/v2/components/V2AgentBYO.tsx index 94112e39ec..3c73329f35 100644 --- a/frontend/src/v2/components/V2AgentBYO.tsx +++ b/frontend/src/v2/components/V2AgentBYO.tsx @@ -811,23 +811,9 @@ const V2AgentBYO: React.FC = () => { {t('agentByo.form.podHint')} - {machines.length === 0 && ( -
- {t('agentByo.addComputer.title')} -

{t('agentByo.addComputer.lead')}

-
- {DAEMON_SETUP_COMMAND} - -
-

{t('agentByo.addComputer.after')}

-
- )} + {/* The act sits right under the fields it acts on. Below "Add a computer" it + fell under the fold at 1440x900 with "Run it here" chosen (QA 2026-10-16: + its top edge at y=882), so a stranger saw a selected card and no button. */} {error &&
{error}
} {mode === null ? ( // Signal §3 not yet: a dashed slot where the act will be, until a @@ -849,6 +835,23 @@ const V2AgentBYO: React.FC = () => { })()} )} + {machines.length === 0 && ( +
+ {t('agentByo.addComputer.title')} +

{t('agentByo.addComputer.lead')}

+
+ {DAEMON_SETUP_COMMAND} + +
+

{t('agentByo.addComputer.after')}

+
+ )}

{t('agentByo.footnote.preferCli')} {CLI_INSTALL_COMMAND}, {t('agentByo.footnote.then')}{' '} {CLI_INIT_COMMAND}.{' '} diff --git a/frontend/src/v2/components/V2Register.tsx b/frontend/src/v2/components/V2Register.tsx index a3ce093f24..fa3ecad26e 100644 --- a/frontend/src/v2/components/V2Register.tsx +++ b/frontend/src/v2/components/V2Register.tsx @@ -182,9 +182,11 @@ const V2Register: React.FC = () => { /> - {/* With open registration the code is optional — it unlocks hosted - (cloud) agents. Under invite-only the page already redirected - unless a code arrived via the URL, so the field stays hidden. */} + {/* With open registration the code is optional — it unlocks hiring + from the catalog (the cloudAgents entitlement). "Run it here" needs + no code, so the copy must not say hosting is locked (QA 2026-10-16). + Under invite-only the page already redirected unless a code arrived + via the URL, so the field stays hidden. */} {policy.loaded && !policy.inviteOnly && (