Show hidden threads that are waiting on the user - #4408
Closed
MacHatter1 wants to merge 1 commit into
Closed
MacHatter1 wants to merge 1 commit into
MacHatter1 wants to merge 1 commit into
Conversation
A hidden thread stays out of the sidebar and out of unread/pending attention, and only a thread with a parent notifies anyone when it blocks. So a hidden root thread waiting on an approval or question (a Workflows worker, for instance) stalls with nothing in the app pointing at it, sometimes for the whole run timeout. The app now shows an app-wide tray for pending interactions on hidden threads: a "N background threads need you" pill at the bottom right that opens the existing pending-interaction banners, expanded, each answerable in place and linking to its thread with the owner's title. It skips the open thread, lights the favicon dot, and uses the shared responsive popover, so compact viewports get the drawer. The tray's list is a lazy chunk, preloaded once something is waiting, so the boot payload grows by about 4 KB. The chunk shares the banner with the thread route, which splits the banner out of the route's largest chunk, so the SplitWorkspaceRoute budget rises 2.5 KiB raw and 4.5 KiB brotli. The data comes from a new GET /threads/pending-interactions route that lists active interactions across threads (visibility any, hidden or visible; newest first; limit 1-200) with their thread and owner (the parent, else the lifecycle owner). The existing interactions-changed broadcast already reaches every client, so the tray refreshes on it, on archive and on delete. It is also available as bb.sdk.threads.experimental_listPendingInteractions and `bb thread interactions pending`, with the guide, JSON guide, command index and api_to_audit entries updated.
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.
Human comments
What was wrong
Hidden threads are left out of the sidebar and out of pending attention, and when a thread blocks on a person, the only notification goes to its parent (
requestChildThreadNeedsAttentionNotificationreturns early unlessparentThreadIdis set). A hidden root thread, which is what every Workflows worker is and what--visibility hiddencreates, has no parent. So when one stopped for an approval or a question, nothing in the app pointed at it, and it waited until someone opened it by ID or the run timed out. The repro, real-world cases and code links are in #4407.What changed
The fix surfaces waiting interactions on hidden threads without changing hidden-thread visibility, the sidebar or notifications.
BackgroundAttentionTray, mounted app-wide inAppLayout. While any hidden thread is waiting, a "N background threads need you" pill sits at the bottom right of every page. It opens a "Waiting on you" popover that lists the existingThreadPendingInteractionBanners, so every interaction kind (approvals, questions, plan reviews, plugin requests) is answerable in place. Each item links to its thread, titled "thread · owner". The thread that's already open is skipped, since its own banner shows. The popover uses the shared responsivePopover, so compact viewports get the drawer.ThreadPendingInteractionBannergains aninitiallyExpandedprop, defaulting tofalse, so thread views are unchanged. The favicon dot also lights while something is waiting (shouldShowFaviconAttentionDotgainsbackgroundThreadNeedsAttention).GET /api/v1/threads/pending-interactions. It lists active (pending/resolving) interactions across threads, newest first, and leaves out archived and deleted threads.visibility:any(the default),hiddenorvisible.limit: 1–200, default 50.listActivePendingInteractionAttentionin@bb/db,listPendingInteractionAttentionon the pending-interaction lifecycle, and the route and schemas in@bb/server-contract.interactions-changedthread-list broadcast, and on thread archive and delete, through the cache registry and invalidation groups.bb.sdk.threads.experimental_listPendingInteractions({ visibility, limit }), with an entry indocs/api_to_audit.md.bb thread interactions pending [--visibility any|hidden|visible] [--limit <n>] [--json]is documented inbb-guide-threads.md,bb-guide-json.mdand the bb-cli command index.ThreadPendingInteractionBannerwith the thread route, the bundler moves the banner and three helpers out of the route's largest chunk into shared chunks. The SplitWorkspaceRoute closure grows by 2.0 KB raw and 5.1 KB brotli, from chunk overhead rather than new route code.bundle-budget.jsonraises those limits by 2.5 KiB raw and 4.5 KiB brotli, with a dated note. The raw rise also covers the 0.3 KB thatmainis already over at a19b3ed, which currently fails CI onmain.No
HOST_DAEMON_PROTOCOL_VERSIONchange and no provider changes. Hidden threads stay hidden.More screenshots
The pill, on a page where the sidebar shows no threads:
On a phone (390×844), the tray opens as a bottom drawer:
After Allow once, the hidden thread carries on and the pill goes away:
How you verified
New tests (the route and the tray are new, so they fail on
main):apps/server/test/public/public-thread-pending-interaction-attention.test.ts(5 tests). The response is parsed with the contract schema. The tests cover:hidden,visible,anyand default visibility filters;limit, with0and201rejected with a 400.apps/app/src/components/notifications/BackgroundAttentionTray.test.tsx(7 tests):faviconAttentionDot.test.ts: 2 new cases, for the dot on and off with a hidden thread waiting.cache-owner-registry.test.tsdeclares the new query key for both cache owners, threeAppLayouttest files mock the tray, and the SDK public-types test lists the new method.Commands, on this branch:
pnpm exec turbo run build typecheck lint(CI's check step): 188/188 tasks passed. Lint reports 0 errors, and none of the existing@bb/appwarnings are in changed files.node apps/app/scripts/check-bundle-budget.mjspasses:mainat a19b3ednode scripts/check-provider-literal-ratchet.mjsandnode scripts/check-source-nul.mjsboth pass.pnpm exec turbo run test:@bb/app: 5148 passed and 5 skipped, across 561 files.@bb/db584,@bb/server-contract78,@bb/sdk113 and@bb/cli862 passed.@bb/templates: all passed. The external scaffold test needsNPM_CONFIG_USERCONFIGpointed at an empty file on this machine, because my~/.npmrcsetsallow-scripts, which npm 11 rejects for project-scoped installs.@bb/server: 3270 passed and 2 failed. Both failures are 5 s timeouts intest/app/install-machine-script.test.tsunder full-suite load. That file passes 48/48 on its own, and it fails the same way onmainhere.Manual, in an isolated
pnpm devinstance with its own data directory and ports:mainat a19b3ed: a hidden Claude Code thread inaccept-edits, asked to runcurl -sI https://example.com, blocked on "Allow network connection to example.com?". Nothing in the app pointed at it (screenshot above).bb thread interactions pending --visibility hiddenlisted it, marked(hidden). Afterwards it printed "No interactions are waiting".bb thread list --project <proj>showed no threads while the approval waited.Fixes #4407