Improve Raycast discovery and workspace setup UX - #137
Conversation
📝 WalkthroughWalkthroughChangesRepository discovery adds targeted query/path searches with cancellation and bounded traversal. Discovered repositories now produce fully seeded workspaces, while branch selection, command suggestions, and related documentation reflect the updated flows. Discovery and workspace flow
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 8✅ Passed checks (8 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
✨ Simplify code
Comment |
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- The new debounced targeted search in DiscoverGitReposView never resets
targetedLoadingQueryon search text change, so the loading state can briefly reflect stale queries; consider clearingtargetedLoadingQueryat the start of the effect whenquerychanges to avoid flickering or incorrect loading indicators. - The git-repo-discovery tests now import
buildSearchRoots,listDefaultRootCandidates, andsearchRootsFromWorkspacesfromgit-repo-discovery, but those helpers are defined ingit-repo-search-roots; either re-export them fromgit-repo-discoveryor point the tests back atgit-repo-search-rootsto keep the test suite aligned with the actual module boundaries.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The new debounced targeted search in DiscoverGitReposView never resets `targetedLoadingQuery` on search text change, so the loading state can briefly reflect stale queries; consider clearing `targetedLoadingQuery` at the start of the effect when `query` changes to avoid flickering or incorrect loading indicators.
- The git-repo-discovery tests now import `buildSearchRoots`, `listDefaultRootCandidates`, and `searchRootsFromWorkspaces` from `git-repo-discovery`, but those helpers are defined in `git-repo-search-roots`; either re-export them from `git-repo-discovery` or point the tests back at `git-repo-search-roots` to keep the test suite aligned with the actual module boundaries.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2dae5252d0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Code Review by Qodo
Context used✅ Compliance rules (platform):
44 rules🔴 Action Required 1.
|
Qodo Fixer🍒 Ready to be cherry-picked — ✅ Merged (0) · ☑ Fixed (5) 🔗 Fix PR: #138 This fix PR was closed automatically. Its branch is preserved so you can cherry pick the changes into the original PR. Prompt for coding agent Process — 5 fixed
|
|
Code review by qodo was updated up to the latest commit d6a42fb |
|
Code review by qodo was updated up to the latest commit 37e55f3 |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
QuickShell.Raycast/src/components/discover-git-repos-view.tsx (1)
173-186: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winQuick Add is no longer instant — give the user feedback.
buildWorkspaceFromReponow runs the full seed, andresolveWorkspaceSetupSuggestionsreaches out to the Suggest CLI before falling back to local heuristics. That's a multi-second blocking gap between pressing Add Workspace and the success toast, with nothing on screen. The Review path at Line 47 gets a "Preparing workspace…" state; quick add gets silence.⏳ Proposed fix
async function handleQuickAdd(directory: string, name: string, remoteUrl?: string | null) { + const preparing = await showToast({ + style: Toast.Style.Animated, + title: "Preparing workspace…", + message: name, + }); try { const workspace = await buildWorkspaceFromRepo(directory, name, remoteUrl); await storage.upsertWorkspace(workspace); await showToast({ style: Toast.Style.Success, title: "Workspace added", message: workspace.name, }); await finishAdd(workspace); } catch (addError) { await showStorageFailure("Add workspace", addError); + } finally { + preparing.hide(); } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@QuickShell.Raycast/src/components/discover-git-repos-view.tsx` around lines 173 - 186, The handleQuickAdd flow provides no feedback while buildWorkspaceFromRepo performs its potentially long-running setup. Add the same “Preparing workspace…” progress state used by the Review path before awaiting buildWorkspaceFromRepo, and ensure it is dismissed or replaced appropriately when the operation completes or fails before showing the existing success or failure feedback.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@QuickShell.Raycast/src/components/discover-git-repos-view.tsx`:
- Around line 95-136: Extract the shared workspace-derived setup currently
duplicated in the targeted-search effect and the usePromise loader: computing
existing workspace directory keys and search roots. Reuse this helper in both
paths, including the existing-directory filtering, so the definition of
already-added repositories remains consistent.
In `@QuickShell.Raycast/src/components/set-target-branch-form.tsx`:
- Around line 126-137: Update the branch-selection conditional in the set-target
form so the dropdown fallback is rendered only after branchChoices has resolved
and contains branches; while branchChoices is still undefined, preserve the
loading/manual-entry flow instead of mounting an item-less Form.Dropdown. Keep
the existing error and empty-branches handling unchanged.
In `@QuickShell.Raycast/src/lib/git-repo-discovery.ts`:
- Around line 322-328: Update the error handling around statSync in
discoverGitReposForQueryAsync to treat EACCES and EPERM like ENOENT and ENOTDIR,
returning null so discovery continues normally. Preserve rethrowing for all
other unexpected errors.
---
Outside diff comments:
In `@QuickShell.Raycast/src/components/discover-git-repos-view.tsx`:
- Around line 173-186: The handleQuickAdd flow provides no feedback while
buildWorkspaceFromRepo performs its potentially long-running setup. Add the same
“Preparing workspace…” progress state used by the Review path before awaiting
buildWorkspaceFromRepo, and ensure it is dismissed or replaced appropriately
when the operation completes or fails before showing the existing success or
failure feedback.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: e876b9f6-7b10-4afe-895e-0d46529f7664
📒 Files selected for processing (10)
QuickShell.Raycast/src/__tests__/discovered-workspace-seed.test.tsQuickShell.Raycast/src/__tests__/git-repo-discovery.test.tsQuickShell.Raycast/src/components/discover-git-repos-view.tsxQuickShell.Raycast/src/components/set-target-branch-form.tsxQuickShell.Raycast/src/components/workspace-form.tsxQuickShell.Raycast/src/lib/discovered-workspace-seed.tsQuickShell.Raycast/src/lib/git-repo-discovery.tsQuickShell.Raycast/src/open-workspace.tsxdocs/architecture/forms.mddocs/architecture/git-and-discover.md
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Trackdubllc/Trackdub(manual)tonythethompson/QuickShell(manual)tonythethompson/numan(manual)tonythethompson/dependency-chain-substrate(manual)
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
QuickShell.Raycast/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Maintain Raycast behavior in parity with Core launch behavior and use the project's Vitest test conventions.
Files:
QuickShell.Raycast/src/open-workspace.tsxQuickShell.Raycast/src/__tests__/discovered-workspace-seed.test.tsQuickShell.Raycast/src/lib/discovered-workspace-seed.tsQuickShell.Raycast/src/__tests__/git-repo-discovery.test.tsQuickShell.Raycast/src/components/set-target-branch-form.tsxQuickShell.Raycast/src/components/discover-git-repos-view.tsxQuickShell.Raycast/src/components/workspace-form.tsxQuickShell.Raycast/src/lib/git-repo-discovery.ts
🪛 LanguageTool
docs/architecture/git-and-discover.md
[grammar] ~102-~102: Ensure spelling is correct
Context: ...paces point at same path. 2. Baseline discover is best-effort and capped — not a full-...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🔍 Remote MCP
Additional review context for PR #137
- PR
#137is open and titled “Improve Raycast discovery and workspace setup UX”; its stated scope is full-seed discover/add parity, searchable command suggestions, uncapped typed repo search with exact-path probing, and a searchable Switch Branch flow. citeturn0search_pull_requeststurn0search_pull_requests createWorkspaceFromDiscoveredGitReponow centralizes discovered-workspace creation: it trims directory/name, falls back toderiveNameFromDirectory, converts suggestion tasks into launch rows, falls back totryGetGitRemoteUrl(directory)whenremoteUrlis missing, copiesdevServerUrlif present, and maps a companion seed withopenOnLaunch: true. It returnsnormalizeWorkspace, which the new test relies on to supply a usable blank launch when no tasks exist. citeturn0pull_request_readdiscoverGitReposForQueryAsyncadds targeted discovery behavior: it normalizes query text by trimming, stripping quotes, and lowercasing; returns immediately for an already-aborted signal; bypasses tree scanning for an exact absolute-path repo match by walking ancestors; and otherwise runs a larger targeted scan withmaxRepos = Infinitybut boundedmaxScanned/maxVisitedbudgets.discoverGitReposAsyncalso now acceptsDiscoveryOptionsincludingrootDirectories,query, andsignal. citeturn0pull_request_read- The Discover Git Repos UI now runs a debounced targeted search with
AbortController, merges cached and targeted results with directory de-duplication, and uses the full workspace seed for Quick Add instead of the former light builder. citeturn0pull_request_read - The branch picker now auto-loads local branches and the saved target, defaults to the saved target if it still exists (otherwise the first branch), shows a searchable dropdown when branches are available, and falls back to manual entry plus retry/error UI when loading fails. The parent action label was renamed from “Set Target Branch…” to “Switch Branch…”. citeturn0pull_request_read
- Docs were updated to describe the new Raycast behavior: full-seed forms use a searchable, nonpersistent Command suggestions dropdown, Raycast discover/search now distinguishes capped baseline discovery from typed searches, and the branch picker is documented as a searchable local-branch dropdown. citeturn0pull_request_read
- Related context: PR
#112introduced the Raycast-localbranchTargets/blockDirtyBranchSwitchgate, and PR#120added Raycast macOS discovery support; both overlap with the areas changed here. citeturn0search_pull_requeststurn0search_pull_requests
🔇 Additional comments (23)
QuickShell.Raycast/src/lib/git-repo-discovery.ts (5)
43-57: LGTM!
72-104: LGTM!Also applies to: 115-149
161-213: LGTM!
253-255: LGTM!
278-303: LGTM!QuickShell.Raycast/src/__tests__/git-repo-discovery.test.ts (3)
1-14: LGTM!
126-149: LGTM!
111-124: 📐 Maintainability & Code QualityNo change needed The Raycast test job runs on
windows-latestandmacos-latest, so these cases already stay within the supported platform gate.> Likely an incorrect or invalid review comment.QuickShell.Raycast/src/components/discover-git-repos-view.tsx (2)
3-14: LGTM!Also applies to: 29-40
138-163: LGTM!Also applies to: 194-209
docs/architecture/git-and-discover.md (1)
71-71: LGTM!Also applies to: 80-81, 102-102
QuickShell.Raycast/src/lib/discovered-workspace-seed.ts (2)
37-65: LGTM!
25-35: 🗄️ Data Integrity & IntegrationNo issue here
same-as-previousis a supported persisted launch value and is resolved later in launch selection/execution, so this path should keep it intact.> Likely an incorrect or invalid review comment.QuickShell.Raycast/src/__tests__/discovered-workspace-seed.test.ts (2)
8-30: LGTM!Also applies to: 44-59
32-42: 🎯 Functional CorrectnessNo issue —
deriveNameFromDirectoryalready splits on both\and/, so this path resolves toempty-reporegardless of host platform.> Likely an incorrect or invalid review comment.docs/architecture/forms.md (1)
32-33: LGTM!QuickShell.Raycast/src/components/set-target-branch-form.tsx (3)
2-3: LGTM!Also applies to: 24-34, 36-36
96-105: LGTM!
107-125: LGTM!QuickShell.Raycast/src/components/workspace-form.tsx (3)
46-46: LGTM!Also applies to: 698-714
725-735: LGTM!
715-722: 🎯 Functional CorrectnessNo cross-half
encodePillKeycollision here. The seed/leftover split already removes seed-command matches from the leftover list, so this render path can’t produce the sametaskType + commandpill from both halves. Any duplicate pills would have to come from upstream input, not this merge.> Likely an incorrect or invalid review comment.QuickShell.Raycast/src/open-workspace.tsx (1)
1149-1153: LGTM!
|
Code review by qodo was updated up to the latest commit 35e8833 |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
QuickShell.Raycast/src/components/set-target-branch-form.tsx (1)
108-114: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winMatch the required “Switch Branch…” flow label.
The submit action currently says
Switch Branch; the PR objective specifiesSwitch Branch….- <Action.SubmitForm title="Switch Branch" onSubmit={handleSubmit} disabled={isLoading} /> + <Action.SubmitForm title="Switch Branch…" onSubmit={handleSubmit} disabled={isLoading} />🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@QuickShell.Raycast/src/components/set-target-branch-form.tsx` around lines 108 - 114, Update the Action.SubmitForm title in the Form actions to use the required “Switch Branch…” label, preserving its existing onSubmit and disabled behavior.QuickShell.Raycast/src/lib/git-repo-discovery.ts (1)
179-201: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winApply the platform gate before direct path probing.
An absolute-path query returns a repository on unsupported platforms because it reaches
repoCandidateFromPathQuerybeforediscoverGitReposAsyncapplies its Windows/macOS gate. Return[]at the start of this function on unsupported platforms.Proposed fix
export async function discoverGitReposForQueryAsync( searchText: string, extraRoots: string[] = [], options?: { @@ }, ): Promise<GitRepoCandidate[]> { + if (!isWindowsPlatform() && !isMacPlatform()) { + return []; + } if (options?.signal?.aborted) { return []; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@QuickShell.Raycast/src/lib/git-repo-discovery.ts` around lines 179 - 201, Update discoverGitReposForQueryAsync to return an empty result immediately on unsupported platforms, before normalizeDiscoveryQuery or repoCandidateFromPathQuery runs. Reuse the same Windows/macOS platform-gating condition used by discoverGitReposAsync.Source: MCP tools
QuickShell.Raycast/src/components/discover-git-repos-view.tsx (1)
155-166: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winRemove newly added directories from targeted results.
finishAddrefreshes only cached discovery. For the active query,targetedSearch.reposis still merged here, so hub mode can continue showing a repository immediately after it was added.Track added directory keys locally and exclude them from
targetedMatches(or invalidate/cancel the active targeted result set when adding).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@QuickShell.Raycast/src/components/discover-git-repos-view.tsx` around lines 155 - 166, Update the result-merging logic in the discover view to track directory keys added by finishAdd and exclude those keys from targetedMatches before merging. Preserve the existing cachedMatches deduplication, and ensure newly added repositories no longer appear for the active query.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@QuickShell.Raycast/src/components/discover-git-repos-view.tsx`:
- Around line 155-166: Update the result-merging logic in the discover view to
track directory keys added by finishAdd and exclude those keys from
targetedMatches before merging. Preserve the existing cachedMatches
deduplication, and ensure newly added repositories no longer appear for the
active query.
In `@QuickShell.Raycast/src/components/set-target-branch-form.tsx`:
- Around line 108-114: Update the Action.SubmitForm title in the Form actions to
use the required “Switch Branch…” label, preserving its existing onSubmit and
disabled behavior.
In `@QuickShell.Raycast/src/lib/git-repo-discovery.ts`:
- Around line 179-201: Update discoverGitReposForQueryAsync to return an empty
result immediately on unsupported platforms, before normalizeDiscoveryQuery or
repoCandidateFromPathQuery runs. Reuse the same Windows/macOS platform-gating
condition used by discoverGitReposAsync.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 74282abf-1c03-4cb5-aa55-e99c03603635
📒 Files selected for processing (3)
QuickShell.Raycast/src/components/discover-git-repos-view.tsxQuickShell.Raycast/src/components/set-target-branch-form.tsxQuickShell.Raycast/src/lib/git-repo-discovery.ts
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Trackdubllc/Trackdub(manual)tonythethompson/QuickShell(manual)tonythethompson/numan(manual)tonythethompson/dependency-chain-substrate(manual)
📜 Review details
⏰ Context from checks skipped due to timeout. (4)
- GitHub Check: Analyze C# with CodeQL
- GitHub Check: Analyze Raycast TypeScript with CodeQL
- GitHub Check: .NET build and test
- GitHub Check: Performance harness (artifacts)
🧰 Additional context used
📓 Path-based instructions (1)
QuickShell.Raycast/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Maintain Raycast behavior in parity with Core launch behavior and use the project's Vitest test conventions.
Files:
QuickShell.Raycast/src/components/set-target-branch-form.tsxQuickShell.Raycast/src/lib/git-repo-discovery.tsQuickShell.Raycast/src/components/discover-git-repos-view.tsx
🔍 Remote MCP DeepWiki, GitHub Copilot
Additional review context
-
Launch-row semantics changed across hosts: related PR
#114establishes thatnullcommands represent explicit “Open in terminal” rows, while blank command drafts are discarded. Suggestion pills must therefore target onlyCommandrows and never overwrite terminal-only rows. -
Workspace seed behavior is covered by new tests: discovered seeds preserve task commands/types, companion metadata, dev-server URL, and repository URL; empty task lists rely on normalization to create one
command: nulllaunch; missing remotes are read from.git/config. -
Discovery now has two distinct modes: the cached baseline remains capped, while targeted search uses
maxRepos = Infinity, finite scan/visit budgets, cancellation, and direct ancestor probing for absolute paths. The tests explicitly verify 55 results beyond the normal cap, aborted searches returning no results, andmaxVisited: 11yielding 10 repositories. -
Related PR
#120introduced the platform gate used by this discovery stack: discovery is enabled only on Windows/macOS, with platform-specific search roots. -
DeepWiki could not provide repository context:
tonythethompson/QuickShellwas not indexed/found.
🔇 Additional comments (3)
QuickShell.Raycast/src/lib/git-repo-discovery.ts (1)
48-95: LGTM!Also applies to: 312-341
QuickShell.Raycast/src/components/discover-git-repos-view.tsx (1)
42-96: LGTM!Also applies to: 101-141
QuickShell.Raycast/src/components/set-target-branch-form.tsx (1)
24-105: LGTM!Also applies to: 126-137
|
Code review by qodo was updated up to the latest commit 278b325 |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
QuickShell.Raycast/src/lib/git-repo-discovery.ts (1)
127-130: 🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick winReserve scan capacity before asynchronous classification.
At Line 99, workers are admitted while
scanned < maxScanned, butscannedis incremented only afterawait fs.stat(...)at Line 111. With concurrency greater than one, multiple workers can pass the guard and later increment the counter, exceeding the configured scan budget. Reserve an in-flight scan slot before the await, release it for repositories/files, and consume it only for non-repository directories.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@QuickShell.Raycast/src/lib/git-repo-discovery.ts` around lines 127 - 130, Update the worker admission and classification flow in git-repo-discovery so scan capacity is reserved before the asynchronous fs.stat call. Use the scanned counter or a dedicated in-flight reservation to prevent concurrent workers from exceeding maxScanned; release the reservation for repositories/files and retain it only for non-repository directories, while preserving the maxRepos limit.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@QuickShell.Raycast/src/components/discover-git-repos-view.tsx`:
- Around line 162-167: Apply the addedDirectoryKeys exclusion to cachedMatches
as well as targetedMatches so directories recorded by finishAdd cannot remain
selectable. Reuse the existing directory-key filtering logic or perform one
shared filtering pass for both result sources, while preserving the seen-based
deduplication behavior.
---
Outside diff comments:
In `@QuickShell.Raycast/src/lib/git-repo-discovery.ts`:
- Around line 127-130: Update the worker admission and classification flow in
git-repo-discovery so scan capacity is reserved before the asynchronous fs.stat
call. Use the scanned counter or a dedicated in-flight reservation to prevent
concurrent workers from exceeding maxScanned; release the reservation for
repositories/files and retain it only for non-repository directories, while
preserving the maxRepos limit.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 80522f74-eb7f-4d40-bc99-355ee0432f9d
📒 Files selected for processing (4)
QuickShell.Raycast/src/__tests__/git-repo-discovery.test.tsQuickShell.Raycast/src/components/discover-git-repos-view.tsxQuickShell.Raycast/src/components/set-target-branch-form.tsxQuickShell.Raycast/src/lib/git-repo-discovery.ts
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Trackdubllc/Trackdub(manual)tonythethompson/QuickShell(manual)tonythethompson/numan(manual)tonythethompson/dependency-chain-substrate(manual)
📜 Review details
⏰ Context from checks skipped due to timeout. (5)
- GitHub Check: Analyze C# with CodeQL
- GitHub Check: Analyze Raycast TypeScript with CodeQL
- GitHub Check: Raycast lint, test, and build
- GitHub Check: .NET build and test
- GitHub Check: Performance harness (artifacts)
🧰 Additional context used
📓 Path-based instructions (1)
QuickShell.Raycast/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Maintain Raycast behavior in parity with Core launch behavior and use the project's Vitest test conventions.
Files:
QuickShell.Raycast/src/__tests__/git-repo-discovery.test.tsQuickShell.Raycast/src/components/discover-git-repos-view.tsxQuickShell.Raycast/src/components/set-target-branch-form.tsxQuickShell.Raycast/src/lib/git-repo-discovery.ts
🔍 Remote MCP DeepWiki, GitHub Copilot
Relevant review context
- PR
#114established the launch-row contract:command: nullmeans an explicit terminal-only launch; blank command drafts are discarded, and suggestion pills must never overwrite terminal-only rows. - PR
#112introduced the related branch-gate behavior: Raycast stores branch targets locally, validates branch names, usesgit switch --, and defaultsblockDirtyBranchSwitchto enabled. - Earlier review findings on this PR identified and resolved:
- missing
.git/configremote fallback; - cancellation of superseded targeted scans;
- targeted search operating independently of baseline-cache loading/failure;
- depth-limit nodes consuming visit budget;
- branch-load error/retry/manual-entry handling;
- blanket exception handling in path probing and targeted search.
- missing
- A remaining informational concern was recorded: targeted discovery sets
maxRepos: Infinity, whilemaxScannedcounts only non-repository directories; repository-dense trees can therefore perform more repository checks than the scan-budget name may imply. - Automated review metadata reports the changes are Raycast TypeScript/docs only; C#/Python contracts,
SessionWorkflowStage, and managed-host lifecycle invariants are not implicated. - DeepWiki could not provide structural context because
tonythethompson/QuickShellis not indexed.
🔇 Additional comments (4)
QuickShell.Raycast/src/lib/git-repo-discovery.ts (1)
98-126: LGTM!Also applies to: 132-159, 179-215
QuickShell.Raycast/src/__tests__/git-repo-discovery.test.ts (1)
111-125: LGTM!QuickShell.Raycast/src/components/discover-git-repos-view.tsx (1)
30-39: LGTM!Also applies to: 102-142, 171-193, 201-216
QuickShell.Raycast/src/components/set-target-branch-form.tsx (1)
24-34: LGTM!Also applies to: 36-105, 107-137
|
Code review by qodo was updated up to the latest commit e181ae4 |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
QuickShell.Raycast/src/components/discover-git-repos-view.tsx (1)
181-190: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winDisable Quick Add while it’s in flight.
handleQuickAdddoes the full build/save path with no per-item pending guard, so the same repo can be added twice before the first run finishes. Track a pending key in component state, disable that action untilfinally, and clear it there.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@QuickShell.Raycast/src/components/discover-git-repos-view.tsx` around lines 181 - 190, Update handleQuickAdd to track the current repository’s pending key in component state, using a stable per-item identifier. Set the key before buildWorkspaceFromRepo and disable the corresponding Quick Add action while it matches; clear it in a finally block so it is released on success or failure.Source: MCP tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@QuickShell.Raycast/src/components/discover-git-repos-view.tsx`:
- Around line 181-190: Update handleQuickAdd to track the current repository’s
pending key in component state, using a stable per-item identifier. Set the key
before buildWorkspaceFromRepo and disable the corresponding Quick Add action
while it matches; clear it in a finally block so it is released on success or
failure.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: f106635e-cec9-49fd-9d22-dc7854a136c0
📒 Files selected for processing (1)
QuickShell.Raycast/src/components/discover-git-repos-view.tsx
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Trackdubllc/Trackdub(manual)tonythethompson/QuickShell(manual)tonythethompson/numan(manual)tonythethompson/dependency-chain-substrate(manual)
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
- GitHub Check: Analyze C# with CodeQL
- GitHub Check: .NET build and test
🧰 Additional context used
📓 Path-based instructions (1)
QuickShell.Raycast/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Maintain Raycast behavior in parity with Core launch behavior and use the project's Vitest test conventions.
Files:
QuickShell.Raycast/src/components/discover-git-repos-view.tsx
🔍 Remote MCP GitHub Copilot
Relevant review context
- PR
#137is open and titled “Improve Raycast discovery and workspace setup UX.” It changes only Raycast TypeScript/TSX and documentation; automated checks found no C#/Python contracts, workflow-stage, or managed-host lifecycle impact. - Related PR
#114establishes the launch-row contract:command: nullrepresents an explicit terminal-only launch; blank command drafts are discarded, and suggestions must not overwrite terminal-only rows. - Related PR
#112introduced Raycast-local branch targets, safegit switch --usage, and the default-enabled dirty-branch gate. - Earlier findings were fixed for remote fallback, targeted-search cancellation, cache-independent searching, depth limits, branch-load recovery, and narrowed exception handling. Remaining informational concern: targeted search uses
maxRepos: Infinity, whilemaxScannedcounts only non-repository directories. - Current review feedback identifies two concrete points to verify:
- Quick Add performs full seeding asynchronously without a “Preparing workspace…” progress indication.
- Discovery’s concurrent workers may exceed
maxScannedbecause capacity is checked before asynchronousstatclassification but incremented afterward.
- CI currently reports successful Raycast Windows and macOS lint/test/build jobs and successful TypeScript CodeQL; .NET build/test and C# CodeQL were still in progress at retrieval time.
🔇 Additional comments (1)
QuickShell.Raycast/src/components/discover-git-repos-view.tsx (1)
3-19: LGTM!Also applies to: 29-39, 78-142, 144-170, 202-217
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
QuickShell.Raycast/src/components/discover-git-repos-view.tsx (1)
190-193: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winShow progress while Quick Add prepares the workspace.
Quick Add now performs the full workspace-seeding flow, but the view exposes no busy state during this await. Users can interpret the action as failed or stalled, unlike the Review flow’s “Preparing workspace…” state. Track the active add and surface it through the list or action UI; clear it in
finally.Suggested direction
+ const [addingDirectory, setAddingDirectory] = useState<string | null>(null); async function handleQuickAdd(directory: string, name: string, remoteUrl?: string | null) { + setAddingDirectory(directory.toLowerCase()); try { const workspace = await buildWorkspaceFromRepo(directory, name, remoteUrl); await storage.upsertWorkspace(workspace); ... } catch (addError) { await showStorageFailure("Add workspace", addError); + } finally { + setAddingDirectory(null); } }Also include
addingDirectory !== nullin the rendered loading state or disable the active row’s action.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@QuickShell.Raycast/src/components/discover-git-repos-view.tsx` around lines 190 - 193, Update handleQuickAdd to track the directory currently being added, set addingDirectory before buildWorkspaceFromRepo, and clear it in finally so failures and successes reset the state. Use addingDirectory !== null in the rendered loading state or disable the active row’s Quick Add action, matching the Review flow’s “Preparing workspace…” behavior.Source: MCP tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@QuickShell.Raycast/src/components/discover-git-repos-view.tsx`:
- Around line 190-193: Update handleQuickAdd to track the directory currently
being added, set addingDirectory before buildWorkspaceFromRepo, and clear it in
finally so failures and successes reset the state. Use addingDirectory !== null
in the rendered loading state or disable the active row’s Quick Add action,
matching the Review flow’s “Preparing workspace…” behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 3860e63c-028c-4735-a0c0-261d9ca2ac38
📒 Files selected for processing (1)
QuickShell.Raycast/src/components/discover-git-repos-view.tsx
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Trackdubllc/Trackdub(manual)tonythethompson/QuickShell(manual)tonythethompson/numan(manual)tonythethompson/dependency-chain-substrate(manual)
📜 Review details
⏰ Context from checks skipped due to timeout. (5)
- GitHub Check: Analyze C# with CodeQL
- GitHub Check: Analyze Raycast TypeScript with CodeQL
- GitHub Check: .NET build and test
- GitHub Check: Performance harness (artifacts)
- GitHub Check: Raycast lint, test, and build
🧰 Additional context used
📓 Path-based instructions (1)
QuickShell.Raycast/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Maintain Raycast behavior in parity with Core launch behavior and use the project's Vitest test conventions.
Files:
QuickShell.Raycast/src/components/discover-git-repos-view.tsx
🔍 Remote MCP GitHub Copilot
Additional review context
-
Quick Add has no progress indicator while full workspace seeding runs.
handleQuickAddawaitsbuildWorkspaceFromRepodirectly; only the Review flow renders “Preparing workspace…”. This may leave Quick Add appearing unresponsive during suggestion/companion detection. -
maxScannedis not a strict concurrent bound. Workers checkscanned < maxScannedbefore asynchronousstat/classification, but incrementscannedlater. Multiple workers can therefore pass the check and collectively exceed the configured scan budget. -
The discovered-workspace seed preserves the related launch-row contract: empty discovery results become a normalized blank launch, while non-empty suggestions are converted into ordered launch rows; repository URL falls back to the local Git remote.
-
Related PR
#114confirms the intended semantics: an explicit terminal-only launch is represented by anullcommand, while ordinary blank command drafts are discarded. -
No DeepWiki or Context7 lookup was necessary: this PR is limited to Raycast TypeScript/TSX and documentation, with no C#/Python boundary, Avalonia binding, or dependency/API upgrade involved.
🔇 Additional comments (1)
QuickShell.Raycast/src/components/discover-git-repos-view.tsx (1)
173-183: LGTM!
|
Code review by qodo was updated up to the latest commit 7c4950e |
|
Code review by qodo was updated up to the latest commit ecbe5e6 |
|
Code review by qodo was updated up to the latest commit 5fcbb01 |
|
Code review by qodo was updated up to the latest commit 21aad23 |
|
Code review by qodo was updated up to the latest commit 2ea919c |
|
Code review by qodo was updated up to the latest commit 696293c |
|
Code review by qodo was updated up to the latest commit 811d50e |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
QuickShell.Raycast/src/__tests__/git-repo-discovery.test.ts (1)
112-187: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winSolid filesystem-backed regression coverage for the new targeted-search behaviors.
Verified the numbers by hand for the trickiest case: "bounds total visited repositories without restoring the result cap" (Line 169-186) — with a single worker,
maxVisited: 11against 1 root + 20 repo children yields exactly 10 matched repos before the visited budget trips, which lines up with the implementation'svisitedcheck at the top of the worker loop.One gap worth adding: all abort coverage here is "already aborted before the call" (Line 160-167). A mid-scan cancellation test (abort the controller after the first tick, assert the scan stops short of the full tree) would validate the
signal?.abortedchecks sprinkled through the worker loop, not just the trivial pre-aborted case.🧪 Suggested addition
it("stops mid-scan once aborted", async () => { const root = mkdtempSync(path.join(os.tmpdir(), "quickshell-git-midabort-")); try { for (let index = 0; index < 20; index += 1) { mkdirSync(path.join(root, `repo-${index.toString().padStart(2, "0")}`, ".git"), { recursive: true }); } const controller = new AbortController(); setTimeout(() => controller.abort(), 0); const repos = await discoverGitReposForQueryAsync("repo-", [], { rootDirectories: [root], concurrency: 1, signal: controller.signal, }); expect(repos.length).toBeLessThan(20); } finally { rmSync(root, { recursive: true, force: true }); } });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@QuickShell.Raycast/src/__tests__/git-repo-discovery.test.ts` around lines 112 - 187, Add a mid-scan cancellation test alongside the existing discoverGitReposForQueryAsync abort coverage. Build a temporary tree with multiple repositories, schedule the AbortController to abort asynchronously after scanning begins, invoke discoverGitReposForQueryAsync with concurrency 1 and the signal, and assert fewer than all repositories are returned while retaining cleanup.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@QuickShell.Raycast/src/__tests__/git-repo-discovery.test.ts`:
- Around line 112-187: Add a mid-scan cancellation test alongside the existing
discoverGitReposForQueryAsync abort coverage. Build a temporary tree with
multiple repositories, schedule the AbortController to abort asynchronously
after scanning begins, invoke discoverGitReposForQueryAsync with concurrency 1
and the signal, and assert fewer than all repositories are returned while
retaining cleanup.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: d1c6a08d-7ca6-40f8-8d7a-ad2f8bae326c
📒 Files selected for processing (3)
QuickShell.Raycast/src/__tests__/git-repo-discovery.test.tsQuickShell.Raycast/src/components/discover-git-repos-view.tsxQuickShell.Raycast/src/lib/git-repo-discovery.ts
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Trackdubllc/Trackdub(manual)tonythethompson/QuickShell(manual)tonythethompson/numan(manual)tonythethompson/dependency-chain-substrate(manual)
📜 Review details
⏰ Context from checks skipped due to timeout. (4)
- GitHub Check: Analyze Raycast TypeScript with CodeQL
- GitHub Check: Analyze C# with CodeQL
- GitHub Check: .NET build and test
- GitHub Check: Performance harness (artifacts)
🧰 Additional context used
📓 Path-based instructions (1)
QuickShell.Raycast/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Maintain Raycast behavior in parity with Core launch behavior and use the project's Vitest test conventions.
Files:
QuickShell.Raycast/src/__tests__/git-repo-discovery.test.tsQuickShell.Raycast/src/components/discover-git-repos-view.tsxQuickShell.Raycast/src/lib/git-repo-discovery.ts
🔍 Remote MCP GitHub Copilot
Additional review context
- Related PR
#120is merged and establishes that Raycast supports both Windows and macOS; repository discovery must therefore retain macOS behavior. Its CI added a macOS test job, and discovery returns results on bothwin32anddarwin. - The current
masterdiscovery implementation still has the legacy constraints:MAX_REPOS = 50,MAX_SCANNED = 2000, depth cutoffwork.depth > MAX_DEPTH, and concurrent workers sharing mutablescanned/resultsstate. This provides direct baseline context for reviewing the PR’s cap, depth, and concurrency changes. - The extension manifest currently declares both
"Windows"and"macOS"platforms, with Node>=20, Vitest^3.0.8, and Raycast Utils^1.19.1; the PR’s discovery changes should remain compatible with this dual-platform runtime.
🔇 Additional comments (11)
QuickShell.Raycast/src/lib/git-repo-discovery.ts (4)
47-47: EACCES/EPERM/ENAMETOOLONG handling confirmed fixed via sharedisExpectedFsLookupError.Matches the previously requested fix; both the direct-path probe (
repoCandidateFromPathQuery) and the async worker now route through the same expected-error set instead of hardcodingENOENT/ENOTDIR.Also applies to: 326-360
99-168: Reserve-before-yield scan budget accounting checks out.Traced this by hand against both new tests: incrementing
scannedbefore theawait fs.stat(so sibling workers see the reservation and bail before issuing their own stat) and releasing it only for non-directories, aborted callers, and confirmed.gitmatches (leaving it permanently consumed for regular scanned directories) matches "Match Core: only non-repo directories consume the scan budget." Simulating themaxVisited: 11test by hand also lands exactly on the expected 10 results. Good fix for the prior TOCTOU-style admission gap.
43-57: 🎯 Functional CorrectnessNo change needed for the targeted-search caps.
189-198: 🎯 Functional CorrectnessNo change needed The fallback scan already passes
signal,maxScanned,maxVisited, andconcurrencyintodiscoverGitReposAsync, and that path enforces the abort and cap checks throughout.QuickShell.Raycast/src/__tests__/git-repo-discovery.test.ts (2)
1-16: LGTM!
189-237: Good coverage for expected-vs-unexpectedfs.statfailures and the concurrency-reservation invariant.The "reserves scan capacity before concurrent stat calls" test (Line 209-236) is a strong regression guard — it directly exercises the exact race the reserve-before-yield pattern was built to prevent, with
maxScanned: 1/concurrency: 4and an instrumentedfs.statmock assertingmaxActiveStats === 1.QuickShell.Raycast/src/components/discover-git-repos-view.tsx (5)
30-40: Quick Add now builds the full workspace seed — matches PR objective.
buildWorkspaceFromReponow resolves setup suggestions, dev server, and companion seed and delegates tocreateWorkspaceFromDiscoveredGitRepo, so Quick Add and "Review Before Adding" produce equivalent workspaces instead of Quick Add taking a thin shortcut.
78-114:addedDirectoryKeysreconciliation logic is correct.Worked through the two relevant paths: on a successful
revalidate(), freshly-fetcheddataalready excludes the just-added directory (it's now a workspace), so the filter in this effect naturally drops that key sincenextis a strict subset check viacachedKeys.has(key). On a failedrevalidate()(per the try/catch added infinishAdd),datadoesn't change reference, so the effect doesn't re-run and the suppression key correctly survives — which is exactly what "reconciles temporary suppression after refresh" needs.
186-201:finishAddnow completes the add flow even when refresh fails — good resilience fix.Wrapping
revalidate()in its own try/catch ensuresonWorkspaceAddedandpop()still run after a storage add succeeds, even if the subsequent list refresh errors out. This directly matches the PR objective "Ensures repository adds complete when refresh fails."
203-229: Duplicate quick-add prevention is race-safe.The synchronous ref check-and-set (
pendingQuickAddKeysRef) at the top ofhandleQuickAddcloses the window between a second click and thedisabledprop's re-render, which a state-only guard wouldn't. Thefinallycleanup correctly clears both the ref and the mirrored state regardless of success/failure path.
268-268: LGTM!
Ensure discoverGitReposForQueryAsync stops early when cancelled after work starts, not only when already aborted. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Code review by qodo was updated up to the latest commit 6ec2eda |
Prevent concurrent workers from oversubscribing maxScanned, and keep the name-search cap-bypass test under Vitest's default timeout on Windows CI. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Code review by qodo was updated up to the latest commit d8bec5b |
Summary
Validation
npm test(247 tests passed)npm run lintnpm run buildgit diff --cached --checkbefore commitSummary by cubic
Improves Raycast repo discovery and workspace setup for faster, more reliable project adds. Quick Add now builds a full seed (commands, companion, remote, dev server), and typed search goes past the result cap, probes absolute paths, and stops mid-scan when cancelled.
New Features
.gitwhen discovery didn’t provide one.Bug Fixes
Written for commit d8bec5b. Summary will update on new commits.