Skip to content

feat: let web search widen past the focused session's workspace - #312

Merged
saucam merged 1 commit into
mainfrom
feat/web-search-scope-toggle
Sep 1, 2026
Merged

feat: let web search widen past the focused session's workspace#312
saucam merged 1 commit into
mainfrom
feat/web-search-scope-toggle

Conversation

@saucam

@saucam saucam commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Third and last surface. #309 gave the TUI a Tab toggle, #311 gave Telegram a button, and the web UI still had no way to ask for a cross-workspace search while a session was focused.

The gap

The web UI's anchoring was already correct — it passed the focused session's workdir, which is what Telegram had to be fixed to do. But the scope was derived and never overridable:

...(focusedSession()?.workdir
  ? { workdir: focusedSession()!.workdir, scope: "workspace" }
  : { scope: "all" })

Global search was reachable only by accident, when nothing happened to be focused. With a session open you searched one directory, and the 73% precision@1 path the feature exists for was unreachable.

The change

A segmented control in the modal header switches This workspace / All workspaces.

  • It's an override on top of the derived default, not a replacement — so focusing a session later doesn't silently undo a choice the user made
  • Hidden entirely when nothing is focused; a toggle with one meaningful position is noise
  • The debounce effect now depends on scope as well as query, so flipping re-runs the current query instead of leaving stale hits from the other regime on screen
  • Zero hits under workspace scope offers a widen button inline — same reasoning as the Telegram keyboard, since an empty scoped result is exactly when widening helps

Ctrl+K is taken for open/close, so this is a click target rather than a key. Results already render hit.workdir, so global hits were legible without further work.

A workspace is a directory, not a session family

Worth recording because it's easy to misread. workspaceIdFromPath hashes workdir + account_id + project_id, so:

  • Every session that ever ran in that directory under the same tenant shares the workspace, related or not
  • A fork isolated into a git worktree gets a different path, so it lands outside its parent's scope

That second point is precisely the history cross-workspace search recovers, and it's invisible unless you can ask for it.

Verification

  • bun run typecheck clean (root + web)
  • bun run lint clean (360 files)
  • daemon suite: 2401 pass, 19 skip, 0 fail
  • web suite: 430 pass (41 files), 5 new
  • The two behavioural tests were confirmed to fail without the scope dependency in the effect, so they're real rather than passing either way

Co-authored-by: Claude Opus 5 (1M context) noreply@anthropic.com

🤖 Generated with Claude Code

Third and last surface. #309 gave the TUI a Tab toggle and #311 gave
Telegram a button; the web UI still had no way to ask for a cross-workspace
search while a session was focused.

Its anchoring was already right -- it passed the focused session's workdir,
which is what Telegram had to be fixed to do -- but the scope was derived
and never overridable:

    ...(focusedSession()?.workdir
      ? { workdir: focusedSession()!.workdir, scope: "workspace" }
      : { scope: "all" })

So global search was reachable only by accident, when nothing happened to be
focused. With a session open you searched one directory, and the 73%
precision@1 path the feature exists for was unreachable.

A segmented control in the modal header now switches This workspace / All
workspaces. It is an override on top of the derived default rather than a
replacement for it, so focusing a session later does not silently undo a
choice the user made. The control is hidden entirely when nothing is
focused, because there is no workspace to scope to and a toggle with one
meaningful position is noise.

The debounce effect now depends on scope as well as query, so flipping
re-runs the current query instead of leaving stale hits from the other
regime on screen. Zero hits under workspace scope also offers a widen
button inline -- the same reasoning as the Telegram keyboard, since an
empty scoped result is exactly when widening helps.

Ctrl+K is taken for open/close, so this is a click target rather than a
key. Results already render hit.workdir, so global hits were legible
without further work.

Worth recording, since it is easy to misread: a workspace is a DIRECTORY,
not a session family. workspaceIdFromPath hashes workdir + account_id +
project_id, so every session that ever ran in that directory under the same
tenant shares the workspace, related or not -- and a fork isolated into a
git worktree gets a different path, so it lands OUTSIDE its parent's scope.
That is precisely the history cross-workspace search recovers.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@saucam
saucam merged commit 500ff52 into main Sep 1, 2026
4 checks passed
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.

3 participants