Skip to content

feat(web): start work from the palette's typed text - #806

Open
danyaberezun wants to merge 2 commits into
global-search-hostfrom
global-search-start
Open

danyaberezun wants to merge 2 commits into
global-search-hostfrom
global-search-start

Conversation

@danyaberezun

@danyaberezun danyaberezun commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

With #804 and #805 the palette finds things and runs commands, but a typed task description still dead-ends in "No matches": starting work means leaving the box for ⌘N and retyping the prompt. Every 2026 agent app keeps creation out of its finder (Warp walked its "search and run" box back, Claude bound creation to an explicit mode) — but all of them let the typed text travel to the creation surface.

Third PR of the global-search stack; stacked on #805.

Redesign (Oct 26). The first cut started work immediately with Tab-cycled targets (new workspace / project folder / current chat), ⌘↵ and ⇧⌘↵. Reviews found target/dialog mismatches, a steer-vs-follow-up hazard and a git.listBranches regression — all symptoms of a second start path. The redesign keeps one: the dialog.

Rebased on main (Oct 28, twice) with the rest of the stack (search is protocol v96 now; this PR adds no protocol).

Review (Oct 28). A design review and three rounds of code review (GPT-6 Astra, Claude Fable 5.1) changed:

  • Held keys. A held ↵ / ⌘↵ acts once in the palette, and the Create dialog ignores the key's repeats, so the press that opens it never submits it (before, a long press created the workspace and sent the prompt unseen).
  • An open dialog is kept. An attention notification can open the palette over the Create dialog; a start then keeps that dialog as it is — its draft and any creation in flight untouched.
  • A selected Start row stays put. Host rows that land while it is selected go below it and never become the top hit (the row-level split is feat: host search for the palette — files, specs, plans, chat transcripts and previews #805's). A lone Start row is deliberately not held: right after each keystroke it is alone until the host answers, so holding it would put every host-only match below Start and turn ↵ on a file search into a start; ⌘↵ is the start that never depends on rows.
  • Smaller: the prompt drops a scope prefix the search dropped (an older host's /…), quotes alone offer no start, the row is offered offline like New workspace, the ⌘N dialog badge is gone (the row shows its ⌘↵ keycaps), the live region no longer counts the row as a result, and the live spec checks only the handoff.

Approach

  • The typed text is always a valid result. Whenever the query has text in the All or Work scope, the last section is Start work: one row «Start work with “”…» showing its ⌘↵ keycaps. ↵ on it, or ⌘↵ from any row, closes the palette and opens the shell's Create-workspace dialog with the text as the prompt — target, base branch and model are chosen where they always are. Nothing starts without the dialog.
  • One rule, one prompt. startEligible(parsed) (a term in the All or Work scope) gates the row, the shortcut and its footer hint alike; startPrompt(raw, parsed) hands over the text as typed (only the scope prefix stripped — whitespace, quotes and tokens untouched), never the matcher's normalized terms.
  • search never imports panels. PaletteStart is { openDialog(text) }; shell binds it to the same keyboard-owned NewWorkspaceDialog instance ⌘N opens, through its existing initialPrompt. NewWorkspaceDialog itself is untouched (the earlier panels/startWork.ts extraction is gone — it had one consumer left).
  • The row is offered whenever New workspace is (opening a dialog is not a host mutation) and is never written to the learning store (its id is the same for every text).

Deferred: the "chat without a project" target (PR4), images and templates from the palette (the dialog keeps them).

Changes

  • apps/web/src/search: PaletteStart prop, the start row kind and section (START_ROW_ID, startEligible, startPrompt), Mod+↵, footer hint; SPEC section "Start from the typed text".
  • apps/web/src/shell: useSearchPalette builds PaletteStart from the context project; Shell's keyboard-opened dialog accepts an initialPrompt; shell/SPEC.md and commands/SPEC.md coverage row updated.
  • packages/locales/en.json: search.group.start, search.start.title / .subtitle, search.hint.start.
  • apps/web/src/panels/NewWorkspaceDialog.tsx: the prompt's Enter submits only on a fresh press (!e.repeat).
  • e2e: search-palette.spec.ts gains "the Start work row and Mod+Enter open the Create-workspace dialog prefilled" (and that > hides the row), "a held Enter or Mod+Enter opens the Create-workspace dialog once and never submits it", and "a Start row the user selected keeps its place and its Enter when host rows land after it" (the host reply held on the socket); search-start.live.spec.ts (@agent) goes palette → dialog → Create and checks the exact prompt the new workspace's chat is sent; e2e/fixtures/app.ts exports loadPersistedWorkspaces.
  • README: the capability bullet now says ⌘↵ opens Create workspace with the typed text.

Screenshots

Same scenario (the Default workspace of sample-project, a task typed into the palette, ↑ to the last row), 1280×800.

Before — PR2 (#805): a task description matches nothing, the palette is a dead end After — the typed text is the Start work row, badged ⌘N dialog, with ⌘↵ start in the footer
PR2 palette: "No matches" for a typed task description PR3 palette: a Start work section with the row "Start work with “Refactor the auth module”…", badged ⌘N dialog
After — ↵ on the row: the Create-workspace dialog with the text as the prompt
The Create workspace dialog open with "Refactor the auth module" prefilled in the prompt field

Testing

All on the final head (bd5d56e96) unless noted:

  • bunx turbo run typecheck --filter='!@thinkrail/desktop' → 24/24 green; bun run lint, check:i18n, check:compiler, check:spec-surface, check:boundaries, check:deps, check:seams → green
  • apps/web bun test → 2049 pass (new: the start row's placement against late rows, the quote-only rule, the stripped prompt)
  • bun run e2e e2e/search-palette.spec.ts --repeat-each=3 → 54 passed (and ×4 → 72 passed on the previous head); e2e/changes-review.spec.ts --repeat-each=4 → 68 passed (a one-off failure of its large-diff test in a loaded full run did not reproduce)
  • bun run e2e (full no-agent suite, 8 shards) → all passed
  • bun run e2e:full e2e/search-start.live.spec.ts → 1 passed: the dialog opens prefilled, Create sends exactly the typed text as the new chat's first prompt, and the agent answers

Related issues

Part of the global-search stack (#804 → #805 → this).

Checklist

  • Fast gates pass: bun run lint, bun run typecheck, bun run test
  • E2E suite passes for app-affecting changes (bun run e2e, or bun run e2e:full when touching agent behavior)
  • Before/after screenshots are included for frontend changes, or marked not applicable
  • Relevant SPEC.md / top-level specs updated to reflect any boundary, contract, or behavior change
  • I have read the Contributing guide and agree to the Code of Conduct

@jetbrains-air jetbrains-air Bot 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.

Requesting changes — please address the blocking inline finding.

Comment thread apps/web/src/panels/startWork.ts Outdated
Comment thread apps/web/src/search/SearchPalette.tsx Outdated
Comment thread apps/web/src/search/SearchPalette.tsx Outdated

@jetbrains-air jetbrains-air Bot 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.

Requesting changes — please address the blocking inline finding.

@danyaberezun
danyaberezun added this pull request to stack #807 October 22, 2026 05:56

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A few more issues on top of the existing ones. The first four are blocking, the last three are non-blocking nits.

Comment thread apps/web/src/search/SearchPalette.tsx Outdated
Comment thread apps/web/src/shell/useSearchPalette.ts Outdated
Comment thread apps/web/src/panels/startWork.ts Outdated
Comment thread apps/web/src/panels/startWork.ts Outdated
Comment thread apps/web/src/search/SearchPalette.tsx Outdated
Comment thread apps/web/src/search/SearchPalette.tsx Outdated
Comment thread e2e/search-start.live.spec.ts Outdated

@jetbrains-air jetbrains-air Bot 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.

Requesting changes — please address the blocking inline findings.

@jetbrains-air jetbrains-air Bot 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 — ready to merge.

@jetbrains-air jetbrains-air Bot 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 — ready to merge.

@jetbrains-air jetbrains-air Bot 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 — ready to merge.

@jetbrains-air jetbrains-air Bot 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 — ready to merge.

A typed query in the All or Work scope ends in one row «Start work with
“…”…»; Enter on it, or Mod+Enter from any row, closes the palette and
opens the shell's Create-workspace dialog with the text as the prompt, so
the target, base branch and model are chosen where they always are and
nothing starts without the dialog. The row is disabled offline like every
host mutation and is never remembered by the learning store.
… and late replies

A held Enter or Mod+Enter acts once in the palette, and the Create-workspace dialog ignores the key's
repeats, so the press that opens it never submits it. A start never replaces a Create dialog that is
already open (an attention notification can open the palette over it), so its draft and any creation
in flight survive. Rows a host reply brings while a selection is held land after the Start row too and
never as the top hit, so a selected Start row does not move; a lone Start row is not held, so host-only
matches still rank above it. The prompt drops a scope prefix the search dropped, quotes alone are no
start, the row is offered offline like New workspace, its badge no longer advertises a chord the palette
does not bind, the live region does not count it as a result, and the live test checks only the handoff.
@danyaberezun

Copy link
Copy Markdown
Collaborator Author

@jetbrains-air please review — rebased with the stack onto main 7b07d5c5f, plus one review-round fix commit (bd5d56e96): a held Enter / ⌘Enter acts once and the Create dialog ignores key repeats; a start keeps an already-open Create dialog; a selected Start row keeps its place when host rows land (the row-level cohort split is #805's); the prompt drops a stripped scope prefix; quotes alone offer no start; no offline gate (like New workspace); no ⌘N badge; the live region no longer counts the Start row; the live spec checks only the handoff.

@jetbrains-air jetbrains-air Bot 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 — ready to merge.

This branch has not been deployed

No deployments
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