Repository navigation
Conversation
Add a native loopback transport that forwards a local Claude Code harness's model traffic to the build's agent gateway, composing the page's frozen context headers in natively. The harness keeps its own credentials, bodies, streaming, retries and cancellation. Admission follows the page's route revisions, page reloads and shutdown stop every generation, only compiled routes are forwarded, and redirects are never followed. Typed frontend bindings cover the four host commands. The gateway's origin, context header names, reserved prefixes and per-capability upstream bases come only from the version 2 BUZZ_AGENT_GATEWAY build descriptor. One validator in plugin-manager serves build.rs, which refuses an invalid descriptor without echoing it and compiles its canonical form, and the app, which parses that form again at startup and keeps only what native forwarding uses. Unset means off. The validator runs the frontend's canonical descriptor vectors. Co-authored-by: coder2 <4acc49cb93576448ba82e631688c51a40bf03d6a889d78fddf57917d198de10f@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Philip Azar <pazar@squareup.com>
Extend the native transport to goose. A goose generation opens for discovery without a session and is associated with the session goose reports, once, before its first prompt; inference must then name that session in `agent-session-id`. Only goose's serving-endpoints discovery and invocation routes are forwarded, with plain endpoint names. Its upstream base comes from the descriptor's `goose` capability, and a build that configures none leaves goose unforwarded while Claude Code may still forward. Typed bindings add `associateForward`. Co-authored-by: coder2 <4acc49cb93576448ba82e631688c51a40bf03d6a889d78fddf57917d198de10f@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Philip Azar <pazar@squareup.com>
No conflicts. Co-authored-by: Coder1 <db50ef1f1688dc7f3e536c17351e8e994a7466bcbe009794f61d64355c0ffc2e@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Philip Azar <pazar@squareup.com>
2 tasks
baxen
added a commit
that referenced
this pull request
Nov 7, 2026
## Summary These are fixes for three browser-journey flakes that are failing open PRs which don't touch the code under test. The change is test-only. No browser cases are added or removed, and no assertion is relaxed. The red `Browser journeys (chromium, 3/9)` / `(webkit, 4/14)` shards on most open PRs come from a different problem: `sidebar-geometry.spec.mjs:224` is broken on main. #2945 and #2946 already fix it, so this PR leaves it alone. ### 1. `channel-completion.spec.mjs`: cold dev-server load timed out **Evidence:** `Flake check` on #2935 failed `channel-completion.spec.mjs:7` on both engines with `page.goto: Timeout 15000ms exceeded` on `/tests/fixtures/mentions.html?channels&stream&test-controls` ([chromium](https://github.com/block/buzz-app/actions/runs/42317084302/job/128232679087), [webkit](https://github.com/block/buzz-app/actions/runs/42317084302/job/128232678918)). #2935 doesn't touch that page. **Cause:** this is the same cold load #2776 fixed for `mentions.spec.mjs`. Each test here started its own Vite dev server for the same ~1,600-module fixture. **Fix:** - `beforeAll` builds `mentions.html` once and serves it with `build`/`preview`, using the same config as `mentions.spec.mjs`. - The build keeps the dev server's CSS. Tailwind's optimizer and Vite's CSS minifier each round the 20/14 line-height token to `1.42857`, so line boxes become `19.99998px`. In WebKit that put the popup `4.03125px` above the composer, and the test asserts exactly `4`. I confirmed this locally: it fails 5/5 with either setting left on and passes with both off. Turning both off keeps the geometry the test checked before. ### 2. `profiles.spec.mjs:940`: reopening Members right after closing the profile **Evidence:** `Flake check (webkit, 8/9)` on #2909 failed in repeat 8 of 10 ([job](https://github.com/block/buzz-app/actions/runs/42313241314/job/128219877861)). The trace shows this sequence: 1. `Escape` closes the profile panel. 2. Focus returns to "Manage members of One" within 40ms. 3. `Enter` is pressed 10ms later. 4. The DOM after that `Enter` shows the Profile panel again and no Members dialog, so the next `row.click` times out. **Fix:** after each `Escape`, wait for the address to leave the profile (no `"detail"` in the `#buzz=` hash) before reopening Members. This is a lifecycle barrier, not a delay. One step in this test already waited for the panel to unmount before reopening; the other steps didn't wait at all. **Product follow-up (not fixed here):** the order of a dismissal's history return and a quick reopen matters. - If I delay `history.go` by 300ms, the unpatched test takes a different path: the dismissal's `go(-1)` never runs, and the URL stays on the profile visit under the reopened dialog. - A `browser-history` unit sketch (deferred traversal: `push(channel)`, `push(panel)`, `dismiss([panel])`, then `push(settings)` before the traversal commits) lands on `channel`. The new `settings` visit is undone. Someone who owns navigation should decide whether a push during a pending dismissal return should be deferred or replayed. That is a navigation-history change, not a test fix. ### 3. `timeline.mjs` `edge()`: one wheel gesture stopped short **Evidence:** `Browser journeys (webkit, 6/14)` on #2937 failed `history-prefix.spec.mjs:37` with `wheel reaches timeline edge`, `Received: 199` ([job](https://github.com/block/buzz-app/actions/runs/42320781857/job/128244819852)). The trace shows the one `-3251px` wheel ended with `scrollend` and the geometry then held still, so the poll could never pass. **Fix:** `edge()` repeats the gesture, at most four times, until the edge is reached. Every extra gesture must reduce the distance, so an immobile timeline still fails. `upper()` already follows this rule. The case of already being at the edge is unchanged: it still sends one small wheel so production can start paging. ## Not in this PR, from the same survey of the 40 most recently updated open PRs - `sidebar-geometry.spec.mjs:224` (Drafts & sent row) is broken on main since #2733 + #2728 crossed. #2945 is green and #2946 is in CI; either one fixes it. - `solo-chats.spec.mjs:322` (Share, webkit, on #2927) is being handled in draft #2933. - `layout.spec.mjs:803` on #2916 is already fixed on main by #2750. #2916's merge ref predates it. - #2911 (thread virtualization) and #2918 (per-channel notifications) fail consistently in tests their own changes reach, so those look like regressions for their authors, not flakes. ## Validation All runs were local on macOS with `tests/browser/playwright.ci.config.mjs` and `--no-deps`. These are not hosted CI measurements. - `channel-completion.spec.mjs`, `--repeat-each=5`, both engines: 20/20 passed with the change. Before the CSS settings were added, the built fixture failed WebKit 5/5 (`4.03125`). - `profiles.spec.mjs:940`, `--repeat-each=24 --workers=6`, WebKit: passed. It also passed with `history.go/back/forward` delayed by 300ms, in both engines. - `history-prefix`, `history-loading`, `scroll`, `timeline-setup` and `new-message-boundary` (all callers of `edge()`/`end()`), both engines: 70/70 passed. - Full `history-prefix`, `channel-completion` and `profiles` files, both engines: 43/44 passed. The one failure was `profiles.spec.mjs:6` in WebKit, a test this PR doesn't touch. It then passed 4/4 both with and without this change. **Deferred and remaining gaps:** - I couldn't reproduce the cold-load timeout or the WebKit stopping short locally, so I have no local fail-before for those two. The evidence is the CI traces linked above. - The other `edge()` callers (24 spec files) are left to CI. - A green run doesn't prove these flakes are gone. Signed-off-by: Bradley Axen <baxen@squareup.com> Co-authored-by: mbot <3754f8729004d95654c46dbab3129e4ab9ef05cc2534e2a3fbfc155983bd637b@buzz.block.builderlab.xyz>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Buzz can send a local agent's turn through an agent gateway that a build configures (#2632). Claude Code and goose make their own model calls, so the app needs a native way to send those calls to the gateway with the turn's context headers. It must not take over the harness's credentials, request bodies or streaming.
What
associateForwardfor goose.How
BUZZ_AGENT_GATEWAYbuild descriptor. One validator inplugin-managerservesbuild.rsand the app. It refuses an invalid descriptor without echoing it. Unset means off.agent-session-id. Only goose's serving-endpoints discovery and invocation routes are forwarded.Risk
Medium in code size (about 3,600 added lines, mostly Rust), low in effect today. No caller turns on forwarding in this PR, and an unset descriptor means off. The Claude and goose callers come in the PRs stacked on this one.
Testing
Not run yet at this head:
Bigger picture
Review order: #2632 (shared gateway client) → #2479 (Pi) → this PR (native forwarding) → Claude caller → goose caller. Each PR's diff shows only its own layer. The stack conflicts with current
mainand needs a main integration before merge. Ready for review does not mean ready to merge.🤖 Generated with Claude Code