镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

fix(builderlab): clarify remote-agent account availability - #2764

Merged
tellaho merged 4 commits into
mainfrom
tho/builderlab-no-access
Nov 6, 2026
Merged

tellaho merged 4 commits into
mainfrom
tho/builderlab-no-access

Conversation

@tellaho

@tellaho tellaho commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Overview

Category: fix

User Impact: People whose Builderlab account lacks remote-agent access see a clear availability status without a misleading button.

Problem: Harness defaults shows a “Coming soon” button for signed-in accounts without remote-agent access, implying a scheduled rollout. Clicking it only opens account information.

Solution: Show quiet “Unavailable for this account” text without an action. Keep account management in Settings → Builderlab and preserve signed-out sign-in and recovery actions. Closing the sign-in dialog returns focus to the quiet status when its button disappears.

Changes

File changes

src/features/agents/service.ts
Allow a provider to supply supporting status text and explicitly omit its Harness defaults action.

src/bundled/agents/AgentDefaults.tsx
Render that status through the shared PreferenceRow while preserving existing setup controls for actionable states. The status can receive programmatic return focus without adding a Tab stop or action.

src/bundled/agents/AgentDefaults.test.tsx
Cover the status-only row, restoration of the default setup action, and focus return after in-dialog sign-in with Escape and Close.

src/bundled/agents/ProviderDialog.tsx
Allow the existing return-focus ref to point to status text as well as a button.

src/bundled/builderlab/index.tsx
Declare the signed-in no-access state as status-only and remove the rollout promise from dialog copy.

src/bundled/builderlab/index.test.tsx
Check the no-access row across missing/false capabilities, the in-dialog denial message and focus return, while retaining sign-in/capability-transition coverage.

src/bundled/builderlab/agents/RemoteAgents.tsx
Use the same quiet availability wording in Builderlab Settings.

src/bundled/builderlab/agents/client.ts
Use accurate account-availability copy when refusing remote-agent calls.

src/bundled/builderlab/agents/client.test.ts
Retain coverage that denial sends no remote requests and retains no replay state.

src/bundled/builderlab/README.md
Document the status and account-management location.

docs/agents.md
Document the provider status/action contract.

docs/buzz-help.md
Explain the account-specific unavailable state.

Reproduction steps

  1. With Builderlab enabled and signed out, open Settings → Agent setup → Harness defaults and activate its sign-in action.
  2. Sign in inside the dialog with an account without remote-agent access. The dialog should explain that remote agents are unavailable for this account.
  3. Dismiss with Escape or Close. Focus should return to the row's “Unavailable for this account” text. The row should have no button, and Tab should move on normally.
  4. Open Settings → Builderlab to manage the account. Its Remote agents section should show the same unavailable status.
  5. Sign out, then return to Harness defaults. The contextual sign-in action should be available again.

Validation

Current head: d41a400aeeee39339238e4580cbd028df40da045.

  • All 21 tests in the affected AgentDefaults and Builderlab plugin files pass. The new Escape and Close regressions fail at 26d944d with focus on the document body, then pass with the fix.
  • The real built-app workflow passes in headless Chromium and WebKit at the current head: keyboard sign-in inside the dialog, no-access messaging, Escape and Close focus return, and Tab continuation. Account/relay responses are mocked.
  • Required pre-commit/pre-push gates pass, including TypeScript/related unit tests, design guards and the native lane.

The full validation run at initial head 26d944d1596f13e6d8ccd0804311fa4c9e50c060 remains useful context:

  • pnpm check, pnpm build, pnpm design:build, Rust formatting and workspace Clippy passed.
  • Full Vitest: 18,694 passed, 22 pre-existing skips; 995 passing files and 8 skipped files. Node integration: 277 passed, 1 pre-existing skip. Plugin-manager Rust tests: 126 passed.
  • Full native tests hit a SIGSEGV, also reproduced by the isolated window_state::tests::onboarding_snapshot_is_kept_until_next_launch_restore test. This branch changes no Rust sources.
  • Design-viewer browser tests failed during collection because Playwright parsed claude.png as source; the same failure reproduced on untouched main f9ce9dfc4.
  • The full 2,298-case app-browser run was stopped for hosted CI: 9 passed, 1 interrupted, 2,288 did not run. It is not reported as passing.

Native no-access account acceptance, human acceptance and independent review remain pending; this PR stays draft.

No permanent browser tests were added or removed. The existing capability and access-gating tests were updated, and a colocated host test covers the status-only contract. Temporary browser checks exercise real layout, in-dialog sign-in and keyboard focus recovery in Chromium and WebKit.

Screenshots

Mock account/relay data; real compiled app UI in headless Chromium. The no-access account responses are mocked; native FI no-access acceptance remains unverified. Before uses main f9ce9dfc4; after uses 26d944d (the row appearance is unchanged by the focus fix). The channel list and sign-in screens are excluded.

Theme / size Before After
Dark Before: Coming soon button After: quiet account availability status
Light Before in light theme After in light theme
760px, 150% text Before with enlarged text After with enlarged text

Replace the rollout promise with quiet account-specific status in Harness defaults. Keep account management in Builderlab Settings and preserve contextual sign-in and recovery.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
@tellaho

tellaho commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor Author

🤖 Review round 1

Posted by Princess Donut, an AI review agent, through Taylor's GitHub account. Reviewed exact head 26d944d1596f13e6d8ccd0804311fa4c9e50c060.

Verdict: changes requested. There is one Medium issue; everything else in scope holds.

Medium: keyboard focus is lost when sign-in from the Harness defaults row ends in no access

Builderlab has no direct attention action, so a signed-out user who activates Log in to Builderlab opens the provider dialog and signs in there. If the account has no remote-agent access, the row switches to status-only while the dialog is still open, and the dialog's return-focus target, the row button, is removed. When the user closes the dialog, focus falls to the document body instead of returning to the row. On main the button stays (relabelled "Coming soon"), so focus comes back to it. This is the main route a no-access user takes to reach this state, so it is a real keyboard and screen-reader regression.

I reproduced it with a throwaway jsdom test (not committed) using the real Harness defaults row and dialog. A row starts with a labelled attention action, the dialog opens from it, the snapshot changes in place, then Escape. With a string label, focus returns to the row button. With attentionLabel: null, focus lands on BODY.

Suggested fix: keep a stable return-focus target when the trigger disappears, such as a programmatically focusable status element (the row's status text) that the dialog falls back to. Add a regression test for this in-dialog transition. The current tests only cover rows that render directly in the status-only state, and this PR removed the only dialog assertion for the no-access state without replacing it. That leaves the dialog's "unavailable for this account" status line untested.

Low: the help text names the Builderlab account location loosely

The help text says "Manage its account in Builderlab Settings." Nearby help entries use bold navigation paths, and the account lives at Settings → Builderlab (the Builderlab card under Plugins). Matching that convention would make it easier for users, and for agents answering from the help file, to find.

Nit: the README now under-describes where the status appears

The README says Harness defaults "shows only 'Unavailable for this account'", but the Builderlab Settings remote-agents section and the provider dialog show the same status too. Consider "Harness defaults and Builderlab Settings show…" so the doc matches the code.

Checked and clean

  • attentionLabel: null scope. Only the Harness defaults row reads attentionLabel; no other surface does. The null check applies per row, and Builderlab is the only provider passing null. Goose, Claude and Codex pass strings, so their buttons and labels are unchanged. With no attentionDescription, the new subtitle and aria-describedby are both undefined, so other rows render as before. The new test also shows that switching from null to an omitted label restores the default "Set up …" action.
  • Signed-out Builderlab. It still reports attention with "Log in to Builderlab", and the dialog still offers sign-in and recovery.
  • Non-FI, self-hosted and plugin-disabled users. The provider is only registered when Builderlab sign-in is available, and a disabled plugin registers nothing. The only changed branch is signed-in without the capability. The remote-agent client still refuses list and create calls before sending any requests, now with the new message, and the client tests prove that.
  • Docs. The agents.md contract text matches the type comment and the row behaviour: null means status only, and an omitted label keeps the default action.

tellaho and others added 3 commits November 5, 2026 23:19
Keep the provider dialog return target on the status text when sign-in replaces its button. Cover Escape and Close, and assert Builderlab account denial inside the sign-in dialog.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
@tellaho

tellaho commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Fixed all three findings in d41a400aeeee39339238e4580cbd028df40da045.

The dialog now returns focus to the non-tabbable status text when sign-in removes its button. Escape and Close regressions fail at the reviewed head and pass with the fix; the Builderlab integration test again asserts the no-access dialog message. The help uses Settings → Builderlab, and the README describes all three status locations.

Validation: 21 affected-file tests, real built-app focus/sign-in checks in Chromium and WebKit with mocked account data, and all required push gates pass. The earlier native/design-viewer validation limits remain documented. The PR stays draft for CI and recheck.

@tellaho

tellaho commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Review round 2

Posted by Princess Donut, an AI review agent, through Taylor's GitHub account. Reviewed exact head d41a400aeeee39339238e4580cbd028df40da045 (three fix commits on top of round-1 head 26d944d15).

Verdict: clean. All three round-1 findings are fixed, and I found no new defects in the fixes.

Medium (focus lost after in-dialog sign-in without access): fixed

  • When the row turns status-only, its status text becomes the dialog's return-focus target. The status text is focusable only from code (tabIndex=-1), so it adds no Tab stop and no action. In every other state the button or the inline default control remains the target, as before.
  • When the button is removed and the status text appears in the same update, React clears the old reference before setting the new one, so the target ends up on the status text.
  • Widening the dialog's return-focus type from button to any element is safe: the only caller of the dialog that changed is this row.
  • I checked that the tests prove the fix. At this head, the two affected test files pass (21 tests). Then I put back the round-1 versions of only the row and dialog components and kept the new tests. Four tests fail: the new Escape and Close regressions, and the Builderlab sign-in test for both no-access capability values. With the fix restored, all pass and the tree is clean. The Builderlab test now signs in through the real Harness defaults dialog. It asserts the no-access line inside the dialog (the restored dialog assertion) and that focus returns to the row's status after Escape. The Builderlab Settings sign-in path is still covered by the second half of that test and by other tests.

Low (help text location): fixed

The help text now uses the bold Settings → Builderlab path, matching the surrounding entries.

Nit (README wording): fixed

The README now says the status appears in both Harness defaults and Builderlab Settings, that the dialog explains the restriction, and that the row has no action. That matches the code.

Commit attribution checked: Taylor is the author, Carl is credited as co-author, and each commit carries Taylor's sign-off. Hosted CI remains the broad gate.

@tellaho
tellaho marked this pull request as ready for review November 6, 2026 07:56
@tellaho
tellaho requested review from a team as code owners November 6, 2026 07:56

@kalvinnchau kalvinnchau left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Approved at d41a400. No actionable findings.

The provider status/action contract and its callers remain consistent: Builderlab accounts without capability receive status-only feedback, other providers retain their actions, and sign-out restores the sign-in action. Focus restoration handles the original button being replaced while the dialog is open. Capability checks still deny remote calls before transport or replay-state creation; account fencing and provider error isolation remain intact.

Validation covered:

  • 118 passing tests across the three affected test files. Removing either the status span focus-ref assignment or tabindex caused both Escape/Close regression tests to fail, supporting the usefulness of those assertions.
  • Actual compiled application with the production broker in Chromium and WebKit: sign-in without access, Escape/Close focus return, Tab continuation, reload retention, Settings status, sign-out, and login failure/retry plus capability transitions. Denied journeys sent no Beekeeper requests. Account and relay upstreams were modeled with isolated identities and storage.
  • CI run 42180304554 verified at this head, including all six Vitest shards, browser journeys, Rust/native fixture and the required gate. Windows native was skipped.

Remaining limits: real Builderlab accounts and relay, successful identity binding, native credentials/storage/IPC, and theme/width/enlarged-text acceptance were not validated. Design-fixture collection independently failed while parsing claude.png as JavaScript; this was not established as a regression introduced here. The author-reported native SIGSEGV was not independently verified.

@tellaho
tellaho merged commit 351db91 into main Nov 6, 2026
111 of 113 checks passed
@tellaho
tellaho deleted the tho/builderlab-no-access branch November 6, 2026 18:29
wpfleger96 added a commit that referenced this pull request Nov 6, 2026
…leanup

* origin/main:
  feat(agents): let app-hosted agents read their owner's channels and members (#2745)
  NEXUS-4271: Expose installed plugin status (#2754)
  fix(menu): stop clipping lifecycle actions behind a hidden scrollbar (#2716)
  feat(agents): give approved external apps the selected agent's full Buzz tools (#2707)
  AIDA-2549: Keep Claude settings drafts in sync (#2841)
  fix(channels): keep a channel's side panels open when returning to it (#2838)
  fix(builderlab): clarify remote-agent account availability (#2764)
  fix(sidebar): rename Remove from Team to Close conversation (#2845)
  perf(channels): cut header and name-matching work in large channels (#2726)
  fix(browser): silence a browser page once its tab goes away (#2721)
  Community Mesh: shared compute plugin (including agent type) (#941)
  perf(relay): cut main-thread work from profile updates (#2730)
  fix(composer): lead the channel placeholder with its sidebar icon (#2829)
  test(activity): scope preview assertions to the request row (#2843)
  perf(search): fold people names once across palette keystrokes (#2570)
  fix(github): keep PR watches running when localStorage is full (#2699)
  Make drafts and sent part of Messages (#2728)
  fix(canvas): render every Canvas within the save limit (#2839)

# Conflicts:
#	.github/workflows/release.yml
cheng-block added a commit to cheng-block/buzz-app that referenced this pull request Nov 6, 2026
…ime-hint

* upstream/main:
  ci: give the native job room for a cold Rust cache (block#2867)
  fix(pairing): refuse unknown communities natively and name the requesting process (block#2835)
  Add per-interest Attention pause and management controls (block#2847)
  feat(drafts): show where unsent drafts wait (block#2853)
  feat(agents): let app-hosted agents read their owner's channels and members (block#2745)
  NEXUS-4271: Expose installed plugin status (block#2754)
  fix(menu): stop clipping lifecycle actions behind a hidden scrollbar (block#2716)
  feat(agents): give approved external apps the selected agent's full Buzz tools (block#2707)
  AIDA-2549: Keep Claude settings drafts in sync (block#2841)
  fix(channels): keep a channel's side panels open when returning to it (block#2838)
  fix(builderlab): clarify remote-agent account availability (block#2764)
  fix(sidebar): rename Remove from Team to Close conversation (block#2845)
  perf(channels): cut header and name-matching work in large channels (block#2726)
  fix(browser): silence a browser page once its tab goes away (block#2721)
  Community Mesh: shared compute plugin (including agent type) (block#941)
  perf(relay): cut main-thread work from profile updates (block#2730)
  fix(composer): lead the channel placeholder with its sidebar icon (block#2829)
  test(activity): scope preview assertions to the request row (block#2843)
  perf(search): fold people names once across palette keystrokes (block#2570)
  fix(github): keep PR watches running when localStorage is full (block#2699)

Signed-off-by: Cheng Peng <cheng@block.xyz>
Co-authored-by: Cursor <cursoragent@cursor.com>
cheng-block added a commit to cheng-block/buzz-app that referenced this pull request Nov 6, 2026
…ions-literal-markdown

* upstream/main: (38 commits)
  fix(composer): let Option+Up/Down switch conversations from an empty composer (block#2832)
  fix(reactions): Scope timed reactions to the selected video (block#2796)
  fix(communities): name what the Join dialog is doing instead of "Working…" (block#2822)
  docs(agents): explain the per-conversation MCP cost of Claude agents (block#2683)
  fix(avatars): keep unsaved avatar drafts and focus, and validate the URL late (block#2714)
  fix(agents): offer stream and forum connection setup only to channel members (block#2749)
  Describe Attention as what the agent does, not its tools (block#2865)
  Let a local Codex agent join its owner's huddle by voice (block#2321)
  ci: give the native job room for a cold Rust cache (block#2867)
  fix(pairing): refuse unknown communities natively and name the requesting process (block#2835)
  Add per-interest Attention pause and management controls (block#2847)
  feat(drafts): show where unsent drafts wait (block#2853)
  feat(agents): let app-hosted agents read their owner's channels and members (block#2745)
  NEXUS-4271: Expose installed plugin status (block#2754)
  fix(menu): stop clipping lifecycle actions behind a hidden scrollbar (block#2716)
  feat(agents): give approved external apps the selected agent's full Buzz tools (block#2707)
  AIDA-2549: Keep Claude settings drafts in sync (block#2841)
  fix(channels): keep a channel's side panels open when returning to it (block#2838)
  fix(builderlab): clarify remote-agent account availability (block#2764)
  fix(sidebar): rename Remove from Team to Close conversation (block#2845)
  ...

Signed-off-by: Cheng Peng <cheng@block.xyz>
Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants