Repository navigation
ci: prepare native browser fixture outside journey timeout - #12
Merged
Merged
Conversation
Signed-off-by: Brain <1a02c72794dcd0f07058a353bc3a81f4028b8c77c92c87fce6d5c8b85970a20b@buzz.block.builderlab.xyz>
wesbillman
marked this pull request as ready for review
September 11, 2026 14:02
morgmart
added a commit
that referenced
this pull request
Sep 11, 2026
…gn-system-handoff * origin/design-system-handoff: ci: prepare native browser fixture outside journey timeout (#12)
matt2e
added a commit
that referenced
this pull request
Nov 5, 2026
**Category:** feature **User Impact:** A pasted GitHub pull request or issue link now reads `repo#N · Title` with a state icon, for example `buzz-app#42 · Fix the thing`, instead of the raw URL. A renamed pull request or issue is renamed in the message on the next status poll. https://github.com/user-attachments/assets/ab14e127-cbb1-4bda-b082-94c3d2d3d3b5 Main (left) and this branch (right), against a stubbed GitHub with made-up repositories. A pasted pull request and an issue link get their titles. Then the stub renames both, and after a 5-minute wait (fast-forwarded on screen) the next status poll renames both links. The titles add no requests: main makes 2, this branch 4, the extra 2 being the issue's first read and its poll. ## What changes **Pull request links.** A pasted pull request URL shows `repo#N` until it is read, then `repo#N · Title`. The state icon is main's. **Issue links.** `/issues/N` links get a state icon and the same label. On main they show the URL with the GitHub logo. | Issue | Icon | Described as | |---|---|---| | Open | GitHub issue mark, green like an open pull request | "Issue, open" | | Closed as completed, or with no reason (as older issues are, matching GitHub) | CheckCircle, purple like a merged pull request | "Issue, closed as completed" | | Closed as not planned or as a duplicate | XCircle, quiet like a closed pull request | "Issue, closed as not planned" | **The label** is built in one place, `PullLink`. It covers message links and composer decorations, pull requests and issues, with and without a title. - The owner is left out: `owner/repo#N · Title` was too long for a link in a message. The repository keeps the URL's casing, so `https://github.com/Block/Buzz-App/issues/7` shows `Buzz-App#7`. - A link that is loading or can't be read shows `repo#N`. - Authored Markdown labels (`[text](url)`) stay as written, with the state icon and no title. - The accessible name is the visible label. The description is the state, such as "Pull request, open". - The owner is still in the hover tooltip, which is the full URL, so same-named repositories in different orgs can be told apart. The tooltip comes from the host link, unchanged, and a unit test now checks it. ## How it works Titles come from the pull request store (`pull-states.ts`) that main's state icons already read. No second fetcher, cache or link registration is added. The existing `pull` renderer at order -1 now also matches `/issues/N`, so the plugin integration test's renderer count is main's: one `buzz.github` and one `buzz.links`. - **Titles add no requests.** - With `gh`, the title is one more field, `title`, in the batched GraphQL state query. Each issue is one more alias in that same query, `issue(number:){state stateReason title}`, so a poll is still one request however many pull requests and issues are shown. - Without `gh`, a pull request's title comes from the `/repos/{owner}/{repo}/pulls/{n}` response the public state read already fetches. An issue is read from `/repos/{owner}/{repo}/issues/{n}` through the same `loadGitHubDetails` call, which now also returns GitHub's `state_reason` and whether the answer is a pull request. - **Renames update in place.** When the store decides whether a read changed anything, it now compares the title and an issue's close reason as well as the state. A rename or a new close reason updates the link on the next poll, with no extra request. - **Issues share the store's machinery:** its cache, canonical keys (a query string, trailing slash or different casing share one entry and one read), batching, hourly public-read budget, polling and hidden-window pause. - **Polling is main's `LINK_POLLING`.** With `gh`, an open link is read every minute while the window is visible. A closed or failing link, or one read from the public API, is read every 5 minutes. Polling pauses while the window is hidden and stops once a pull request is merged, since that can't be undone. A closed issue keeps being read every 5 minutes, like a closed pull request, because both can reopen. Stopping at closed would be a one-line change to `LINK_POLLING`. - **An `/issues/N` URL whose number is a pull request's.** GitHub's issues endpoint also answers for a pull request, adding a `pull_request` key, and the store refuses that answer. With `gh`, `issue(number:)` finds nothing at a pull request's number. Either way the link shows `repo#N`, described as "Issue, unavailable". The `/pull/N` URL is a separate store entry and is titled as usual. - **Agent and tool payloads are unchanged.** - Issues are read at the `state` level only. A `feedback` or `details` watch or read of an issue URL is refused, so agent watches and the panel never read issues. - Agent watches ignore the title, so a rename doesn't wake an agent. - `github_pr_state` returns the same fields as on main, with no title or label. It now checks that its URL is a pull request's, where it used to rely on the store refusing issue URLs, so an issue URL fails with "url must be a GitHub pull request URL". - The Watching tab already showed watched pull requests as `repo#N`. The first commit, `a554c0573`, added its own gh/REST fetcher, cache and a second link registration at order -10. `24484f7ef` replaces that with the store, and `efe0d60a0` and `6c461825d` add issues and the shorter label. The production diff against main is 7 files, +167/−38. ## Which links get titles | Link | This branch | Main | |---|---|---| | Pull request or issue, pasted as its URL (also with a query string, trailing slash or different casing) | `repo#N · Title` with its state icon, kept current while shown | URL. Pull requests get the state icon, issues the GitHub logo | | …in a public repository, without `gh` | Titled from the public API within the hourly public-read budget. Once rate-limited, the last title read stays | URL | | …in a private repository, without `gh` signed in | `repo#N`, "…, unavailable". Titled once `gh` is signed in | URL | | Authored Markdown link | The authored text with the state icon, no title | The same for pull requests. Issues get the GitHub logo | | In the composer while typing | `repo#N`, plus a title only if the store already holds one. Reads nothing | URL | | `/issues/N` where N is a pull request | `repo#N`, "Issue, unavailable" | URL | | Sub-pages (`/files`, `/commits`, `/checks`), comment and review anchors, discussions, repositories, commits, other github.com pages, non-GitHub URLs | Unchanged, rendered by Links | The same | ## How it was verified At `6c461825d`: - **Typecheck and lint:** `bin/pnpm typecheck` and `bin/pnpm lint` pass. - **Unit:** `bin/pnpm exec vitest run src/bundled/github` passes 18 files, 308 tests. The new cases cover: - the title in the GraphQL query and in the public REST read; - the issue alias and the issue REST read; - a poll renaming pull requests and issues; - canonical issue keys; - keeping `/issues/N` and `/pull/N` apart; - the `PullLink` labels in messages and in the composer. With the old label code, 6 of the 13 `PullLink` tests fail. - **Browser:** `layout`, `right-pane-dismissal`, `github-actions`, `github-body`, `github-checklist`, `github-metadata`, `composer-links` and `external-links` pass all 88 cases in Chromium and WebKit, with no retries. - No browser cases were added or removed. - `layout` and `right-pane-dismissal` now find a pasted pull request link by its new name, `repo#N · <fixture title>`. They stay role locators, which wait while a popover hides the page from roles. - Two substring checks are now anchored, so they fail if the owner comes back. - **Integration:** `src/app/pages.integration.test.mjs`, which counts link renderers, passes and is unchanged from main. The full Node suite (`tests/integration/*.test.mjs`) did not finish locally. Under heavy machine load its desktop and web launcher, hooks and CI-sharding tests timed out, and `worktree-icon.test.mjs`, a macOS launcher check, failed to find a module in its temporary checkout. This branch changes none of the code those tests cover. How the videos were made: - **The app:** the browser-test fixture's production frontend, with a synthetic relay and the production broker, in headless Chromium. Main is `a060691e9`; no later commit on main touches `src/bundled/github` or `src/bundled/links`. - **GitHub is a local `page.route` stub.** `example-org/sample-app`, `example-org/private-app` and every title are made up, and the renames are done by the stub. Nothing on real GitHub was contacted. - **Only the public REST path is shown:** the browser build has no `gh`. Not yet verified: - The `gh` path in the desktop app: the GraphQL `title` and `issue(number:)` fields, the 1-minute cadence, and private repositories with `gh` signed in. Only `pull-states.test.ts` covers it. - The running app in both themes, at narrow and wide widths, with enlarged text, and the tooltip on hover. - Human testing. <details> <summary>Before/after videos by case</summary> Main is on the left and this branch on the right. Each pane has a log of its GitHub requests. **1. Pull request links.** Open, draft, merged and closed pull requests are titled. URL variants share one read, and a Markdown label keeps its text. A private-repository 404 shows `private-app#9`. Requests: main 5, this branch 5. https://github.com/user-attachments/assets/37ed8fca-3495-4586-a7ab-fb1a6ff4b2a9 **2. Issue links.** Open, completed, not planned, no reason, and duplicate issues are titled, each with its icon. An `/issues/N` URL whose number is a pull request's is refused, and a comment anchor stays with Links. Requests: main 1 (the `/pull/42` comparison link), this branch 9 (one per distinct issue). https://github.com/user-attachments/assets/48f42b0a-4ff0-42af-abe7-567086335030 **3. Links neither side titles.** Sub-pages, comment and review anchors, a discussion, a commit, a repository and a non-GitHub URL stay with Links and cause no requests. Only the plain `/pull/42` link shown for contrast is read. Requests: main 1, this branch 1. https://github.com/user-attachments/assets/3d8b68f0-c78d-4df5-ad82-2e1e58c5e300 **4. Refresh.** The stub renames pull request #42 and issue #12. After a fast-forwarded 5-minute wait, the next poll renames both on this branch. Main makes the same two pull request reads and changes nothing. Requests: main 2, this branch 4 (the issue's first read and its poll). https://github.com/user-attachments/assets/2b51ce2e-22ec-4903-8de8-8f0b2b0d7301 </details> 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Bill Gao <bgao@squareup.com> Signed-off-by: Matt Toohey <contact@matttoohey.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Matt Toohey <contact@matttoohey.com>
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.
Prepared by Brain on behalf of @wesbillman.
Problem
Main's post-merge run and PR #9 fail during
cargo build --locked -p buzzodz-plugins --example fixture-bridge, before the conversation journey navigates to the app. Main's trace shows approximately 180.17 seconds between the preceding assertion and teardown, matching the fixture helper's 180-second subprocess timeout. Its previous error wrapper omitted spawn errors, exit status and signals, so the exact provisioning failure cannot be recovered from that run.The independent browser shards introduced in #3 no longer inherit the Rust warmup from the ordinary
pnpm testsequence. Their shared Hermit cache could also be populated first by a JS-only job and remain incomplete for Rust consumers.Evidence:
Changes
No production app changes, disabled checks, new retries, increased journey timeouts, or weakened browser assertions. Measurement isolation and the required aggregate are unchanged. No cache hit is required for correctness.
Validation
Studio
BLKD2G9MWNRWY.local, worktree~/.buzz/worktrees/buzz-app-main-ci-setup-20260911, basee355085plus this patch:pnpm check: passed.2bb608f; Git hooks passed.Draft: cold-key Ubuntu validation and human review remain required. In particular inspect both browser fixture setup and total job duration; tool provisioning can occur inside rust-cache before the named build step. No full local scan or native app acceptance claimed. This repairs the observed setup boundary, not a promise that unrelated tests can never fail.
Originating Buzz channel:
improve-ci-running-lefthook(6f1257ed-2132-4a65-b21a-f03159b5dc73), thread88fef838c65c090fe748117265c7433f4a69f99a079ace3302ecb6afa62eab59.