Skip to content

upstream 取り込み PR #2b: v2 project create + big features / 8 commits + drizzle 0071#406

Merged
MocA-Love merged 13 commits intomainfrom
upstream/batch-2b-big-features
Apr 24, 2026
Merged

upstream 取り込み PR #2b: v2 project create + big features / 8 commits + drizzle 0071#406
MocA-Love merged 13 commits intomainfrom
upstream/batch-2b-big-features

Conversation

@MocA-Love
Copy link
Copy Markdown
Owner

Summary

upstream 取り込み PR #2b: 大物 feature / DB migration バッチ 8 commits + 修復。Codex 事前調査を経て scheduled agent runs (superset-sh#3576) と link-click (superset-sh#3600) は別 PR #2c に分離。

v2 project create (superset-sh#3566) は 59 files / +7314 lines の最大規模 cherry-pick で、fork 固有機能 (19 procedure, TERMINAL_OPTIONS, SUPERSET_WORKSPACE_NAME など) を全て維持しつつ取り込み。

取り込み内容(8 commits)

  1. 2b7c6119c feat(v2): minimal project create/import for workspaces (feat(v2): minimal project create/import for workspaces superset-sh/superset#3566)
  2. cb6036dfd fix(desktop): stop spurious folder picker (fix(desktop): stop spurious folder picker on settings → dashboard nav superset-sh/superset#3602) ← PR fix(desktop): prevent browser webview reload on tab/workspace switch #2 から送り
  3. 5d895f12c feat(desktop): infer project name from folder on import (feat(desktop): infer project name from folder on import superset-sh/superset#3605) ← PR fix(desktop): prevent browser webview reload on tab/workspace switch #2 から送り
  4. 1141a7164 feat(desktop): v2 project settings with setup/relocate path (feat(desktop): v2 project settings with setup/relocate path superset-sh/superset#3606)
  5. 4b8887284 feat(desktop): v1 review comments open in a pane like v2 (feat(desktop): v1 review comments open in a pane like v2 superset-sh/superset#3596)
  6. 5aead3361 feat(desktop): port v1 projects + workspaces into v2 (feat(desktop): port v1 projects + workspaces into v2 superset-sh/superset#3670)
  7. 37a47ed26 fix(desktop): v2 file-open honors CMD+O editor choice (fix(desktop): v2 file-open honors CMD+O editor choice superset-sh/superset#3674) ← PR feat(desktop): AIコミットメッセージ自動生成 #4 から送り
  8. a510c187b feat(desktop): v2 Changes file list shift/cmd-click policy (feat(desktop): v2 Changes file list shift/cmd-click policy superset-sh/superset#3683)

追加 fix commits(3 件)

  • 683ab6f41 chore(local-db): remove upstream 0041_v1_migration_state migration (number collision)
    • fork 最大 idx 70 と衝突する upstream 0041 を削除、schema だけ保持
  • (本 commit) fix(desktop): resolve PR #2b typecheck errors post cherry-pick
    • upstream 99a1ca66f (Chat UX Enhancements superset-sh/superset#3039 Chat UX) からの必要ファイル補完 (TiptapPromptEditor, QuestionInputOverlay 等 9 ファイル)
    • route path 移行修正 (/settings/project//settings/projects/)
    • 型整合性調整、prop 受け取り、neonProjectId projection 追加
    • drizzle-kit generate0071_v1_migration_state を再生成

PR #2c へ分離(別 PR で処理)

Codex 事前調査で分離判定:

Fork 側のコンフリクト解決

v2 project create (superset-sh#3566) の 9 files conflict 解消:

  • ChatInputFooter.tsx (v1/v2): TiptapPromptEditor/QuestionInputOverlay 採用
  • layout.tsx: AddRepositoryModalsKeepAliveWorkspaces 両方維持
  • V2WorkspacesList.tsx / v2-workspaces/page.tsx: upstream 版 (pinned/others 分離) 採用
  • error-types.ts: ProjectNotSetupCause コメント追加
  • project.ts / v2-project.ts: upstream 方式採用
  • packages/shared/package.json: simple-git-unsafe エクスポート + dedupe 維持

v1 review pane (superset-sh#3596): fork 固有 19 GitHub 拡張 mutations を全て維持 + openCommentPane/handleOpenComment を追加

v1→v2 migration (superset-sh#3670):

  • apps/desktop/src/lib/trpc/routers/index.ts: migration: createMigrationRouter() を既存 router に追加
  • packages/local-db/src/schema/schema.ts: v1MigrationState テーブル定義を 1 箇所に集約
  • upstream の 0041_v1_migration_state.sql と snapshot/journal entry を削除
  • bunx drizzle-kit generate --name="v1_migration_state"0071_v1_migration_state として再生成

v2 file-open (superset-sh#3674):

  • external/index.ts: withResolveGuard パターン + nodePath.isAbsolute チェック
  • usePathActions/FileSearchResultItem/FileTreeItem: cwdworktreePath 変更 (fork の branch / copySupersetLink パラメータ維持)

v2 Changes file list (superset-sh#3683):

  • fork 独自 electronTrpc import を維持しつつ新規 hooks imports を統合

Fork 固有機能ヘルスチェック

baseline 比較で 全項目健在:

Test plan

  • bun install 正常完了
  • bun run typecheck グリーン (27/27)
  • bun run lint グリーン
  • bun run --filter @superset/desktop build exit 0 成功 (dmg/zip/blockmap 生成)
  • fork 固有機能 baseline 比較で regression ゼロ
  • 19 procedure が workspaces.githubExtended 配下で健在
  • drizzle/0071_v1_migration_state.sql 生成
  • desktop dev 起動確認
  • v2 project の create/import/relocate flow 動作確認
  • v1→v2 migration flow 動作確認 (projects + workspaces port)
  • v1 review comment pane が CommentPane として開く
  • v2 file-open で CMD+O editor choice が反映される
  • v2 Changes file list で shift/cmd-click policy が動く

次の PR

  • PR #2c (最後): e2b9f42 scheduled agent runs + d006f60 link-click → これで upstream 0 commits 達成 (完遂目標)

Kitenite and others added 10 commits April 24, 2026 09:47
)

* docs: v2 project create/import design + plan

Simplified redesign after PR review. Collapses the earlier three-signal
backing model (cloud + per-host cloud signal + local) into two signals
(cloud + local-only), removes the v2_host_projects cloud table and
Electric sync, drops per-row state decoration on the sidebar, and moves
backing checks to action time (workspace-create modal, error paths).

* feat(trpc): v2Projects.findByGitHubRemote + jwt-scoped create

Adds the cloud-side matcher used by host-service's folder-first import
flow: given a clone URL, returns candidate projects the user has access
to whose GitHub repo matches (case-insensitively). Named findByGitHubRemote
(not findByRemote) because the match is GitHub-specific.

v2Projects.create switches to jwtProcedure with an explicit
organizationId + repoCloneUrl, matching the shape host-service needs to
call from project.create. No existing callers.

parseGitHubRemote moves from packages/host-service to packages/shared so
both cloud tRPC and host-service consume the same implementation.

* feat(host-service): project.create / setup / list / findByPath / remove

Full create/import lifecycle in host-service:

- project.list — DB read of host-service.projects. Pure, no filesystem
  probing. Stale paths surface via operation errors, not proactive checks.
- project.findByPath — validate git root, read remote, forward to cloud
  v2Projects.findByGitHubRemote. Backs the folder-first import picker.
- project.create — discriminated-union mode (empty/clone/importLocal/
  template); Phase 1 ships clone + importLocal only, empty and template
  throw NOT_IMPLEMENTED.
- project.setup — discriminated-union mode (clone/import) with
  acknowledgeWorkspaceInvalidation gate on the re-point case.
- project.remove — local worktree + repo dir teardown.

Cloud backing (v2_host_projects) is intentionally absent: there is no
per-host cloud signal in this design. Backing is a local-only concept,
checked at action time.

Adds ProjectNotSetupCause to the error formatter so the renderer can
catch throws from workspace.create (next commit) and open the Pin & Set
Up modal inline.

* feat(desktop): add-repository modals at dashboard layout level

Three flows for getting projects onto this device:

- New project — clone a GitHub URL into a chosen parent directory.
  Drives project.create(mode=clone).
- Import existing folder — native picker → project.findByPath branches on
  candidate count. 0 → name + create (importLocal). 1, not set up here →
  auto-advance to project.setup. 1, already set up → destructive re-point
  confirmation. >1 → picker modal.
- Pin & set up — clone an existing cloud project onto this device.
  Drives project.setup(mode=clone), with forceRepoint entry for repair.

All three modals are mounted once at the dashboard layout level via
AddRepositoryModals, and opened through a small zustand store. Sidebar
header "Add repository" dropdown triggers New project / Import folder.

* feat(desktop): workspaces-tab Available section + folder-first import trigger

Lists cloud projects in the user's active org that aren't pinned
locally. Pin & set up per row runs project.setup. Header dropdown
("Add repository") mirrors the sidebar — "+ New project" +
"Import existing folder." Entry points route through the dashboard-level
AddRepositoryModals via the shared zustand store.

useAvailableV2Projects powers the section: antijoin
v2Projects ∖ v2SidebarProjects scoped to the active organization,
with the existing v2-workspaces search filter applied.

* feat(desktop): workspace-create inline setup + remote-device stub

- Host-service workspaceCreation.{create,checkout,adopt} throw
  PROJECT_NOT_SETUP (PRECONDITION_FAILED + cause { kind, projectId })
  when this host has no local project row. No more silent auto-clone
  into ~/.superset/repos/ — the user explicitly picks where to clone.

- Pending workspace-create page intercepts data.projectNotSetup on the
  error, opens the Pin & set up modal pre-filled with the project, and
  registers a one-shot onSuccess callback to retry the original intent
  once setup resolves. The pending row stays in "creating" through the
  modal so the UI doesn't flicker to failed.

- Clicking a remote-device workspace row lands on the new
  WorkspaceNotOnThisHostState stub: explains the workspace lives on
  another host, offers "Set up here" (opens Pin & set up for the
  project) or "Browse workspaces." V2 workspace page checks
  host.machineId via live query and renders the stub before mounting
  the pane tree, which would otherwise crash on a foreign worktree.

* Fix infinite import

* fix: pre-existing notification test, a11y labels, design doc shape

- notification-manager.test: update expected strings to match source
  (strings changed in superset-sh#3039; test wasn't updated, CI was red on main too)
- DashboardSidebarHeader: aria-label="Add repository" on icon-only
  dropdown triggers so screen readers announce them (tooltips don't
  count as accessible names)
- docs/design/v2-project-create-import: correct v2Projects.create input
  shape (jwt-scoped { organizationId, name, slug, repoCloneUrl })

* feat(desktop): unify new-workspace pickers + link popovers, strip chat link UI

- Unify DevicePicker / ProjectPickerPill / CompareBaseBranchPicker to a
  shared FORM_PICKER_TRIGGER_CLASS: no background, h-[22px], text-[11px]
  text-muted-foreground, size-3 icons, align="start" dropdowns. Bump the
  project trigger thumbnail to size-4; drop the leftover `!` override
  (twMerge handles it).

- DevicePicker: icon-only trigger (aria-label + title surface the name).

- Rewrite IssueLinkCommand / PRLinkCommand / GitHubIssueLinkCommand to
  one codepath each: accept a button as `children`, wrap it in
  PopoverTrigger, own their open state internally. No more shared
  plusMenuRef, no more external open/onOpenChange/anchorRef coordination,
  no manual onPointerDownOutside anchor-guard — Radix handles toggle and
  dismiss natively so clicking a trigger while its popover is open
  closes it like every other picker.

- v2 NewWorkspace PromptGroup: drop the three popover-open useStates +
  plusMenuRef + manual toggle handlers. AttachmentButtons becomes a
  layout shell that renders the three trigger elements as props; each
  wraps a shared LinkTrigger (tooltip + pill button).

- Chat (v1 + v2) + v1 NewWorkspace PromptGroup: remove the link-issue
  popover wiring (IssueLinkCommand usage, ChatShortcuts' onLinkIssue
  callback). PlusMenu in chat collapses from a dropdown with
  attach/link options to a plain attachment button.

- Temporarily disable v2 ChatPane render: it predates this PR and is
  missing ChatServiceProvider (introduced in PR superset-sh#3088), so
  chatServiceTrpc has no context in TiptapPromptEditor. Replaced with a
  "Chat pane is temporarily disabled" placeholder; original render body
  commented out for quick restoration.

* feat(desktop): host-scoped project picker with Available / Needs setup sections

The v2 new-workspace picker was listing every cloud project the user
had access to, regardless of whether it was set up on the selected
device. That produced the PROJECT_NOT_SETUP error path on submit —
reviewers flagged the pending-row-stuck-in-creating fallout as a P1.

Root-cause fix: split the project list by selected-host availability.

- `useHostProjectIds(hostTarget)` queries host-service `project.list`
  on the chosen device (local via activeHostUrl, remote via relay) and
  returns the set of set-up project IDs.
- PromptGroup splits `recentProjects` into `availableProjects` +
  `needSetupProjects` using that set; changing the device refetches.
- ProjectPickerPill renders two CommandGroup sections: Available (click
  selects) and Needs setup (click opens Pin & set up for that project).
- Pin & set up already invalidates `["project", "list", activeHostUrl]`
  on success, so after setup the project flips to Available — user
  picks it and continues normally.

While `project.list` is loading or errors, everything falls back to
Available — picker stays usable; any real failure surfaces via the
existing workspace-create error path.

* lint

* fix(desktop): IssueLinkCommand uncontrolled close + PlusMenu aria-label

- IssueLinkCommand: the refactored popover-trigger API made `open` and
  `onOpenChange` optional so callers (v2 PromptGroup) could let Radix
  manage state. But `handleSelect` only fired the optional controlled
  callback, so in uncontrolled mode the popover never closed after
  picking an issue. Track state ourselves via a controllable-state
  pattern: internal `useState` when the prop is absent, caller's value
  when passed. `setOpen` always writes through, so close-on-select
  works in both modes.

- PlusMenu: add aria-label="Add attachment" to the icon-only trigger.
  Radix Tooltip sets aria-describedby on the trigger, not
  aria-labelledby, so screen readers previously announced it as an
  unlabeled button.

* refactor(desktop): drop controlled-open props from IssueLinkCommand; extend aria-label fix

- IssueLinkCommand: only caller passes `onSelect + children`, so the
  optional open/onOpenChange pass-through was dead code. Simplify to
  always-internal state. Radix Popover has no imperative close from
  inside its content — owning state is the canonical shadcn/cmdk
  pattern, not scaffolding.

- AttachmentButtons (v2): add aria-label to the shared LinkTrigger (so
  Link issue / Link GitHub issue / Link pull request all announce a
  name) and to the paperclip. Same fix as PlusMenu — Radix Tooltip
  sets aria-describedby on the trigger, not aria-labelledby, so
  tooltip-only buttons read as unlabeled to screen readers.

* fix(trpc): scope v2Project.findByGitHubRemote + modal picker to active org

host-service is pinned to a single organization at boot (env.ORGANIZATION_ID);
its local projects table has no orgId column. Project discovery was leaking
across orgs:

- v2Project.findByGitHubRemote used ctx.organizationIds (plural, all
  accessible orgs). The folder-first picker would surface candidates from
  orgs the current host can't set up, producing a confusing NOT_FOUND when
  host-service then called v2Project.get with its own org.
- DashboardNewWorkspaceModalContent queried collections.v2Projects with no
  org filter. Same over-fetch, same downstream failure.

Align both with the rest of the codebase (v2Project.get / create,
useAvailableV2Projects, useWorkspaceHostOptions) which take/filter by an
explicit active orgId:

- findByGitHubRemote: add organizationId input, authorize it against
  ctx.organizationIds (same shape as get/create), filter candidates by it.
- host-service project.findByPath: pass ctx.organizationId through.
- DashboardNewWorkspaceModalContent: .where(eq(projects.organizationId,
  activeOrganizationId)) on the live query, matching useAvailableV2Projects.

* Lint

* fix(host-service): clone-then-cloud in project.createFromClone, rollback on cloud failure

Matches the local-first-then-cloud pattern already used by
workspace.create (workspace-creation.ts:860-918, which git-worktree-adds
first then registers cloud with a rollback on failure).

Previously createFromClone called v2Project.create before cloneRepoInto,
so any clone failure (network, bad URL, auth, dir collision) left a cloud
v2_projects row with nothing local backing it on any host. Retrying the
flow with corrected input accumulated more orphans.

Reorder: clone first, register cloud in try/catch, rmSync the freshly-
created clone if cloud-create or persistLocalProject throws.

* fix(host-service): move project.create visibility into GitHub-provisioning modes

Only empty + template modes provision a new GitHub repo and need to tell
the GitHub App whether it should be private or public. clone +
importLocal reuse an existing remote where visibility is already set —
the top-level field was required but ignored for those two paths.

Move `visibility: z.enum(["private", "public"])` into the empty and
template variants of the discriminated union. Drop it from clone/
importLocal callers. Update design doc to match.

* refactor(desktop): use Radix composition for link-command tooltips, drop dead chat-link wiring

Responds to saddlepaddle + Kitenite reviews on PR superset-sh#3566.

- IssueLinkCommand / PRLinkCommand / GitHubIssueLinkCommand now own the
  Popover + Tooltip composition internally via
  `PopoverTrigger asChild > TooltipTrigger asChild`. Callers pass a plain
  PromptInputButton + a tooltipLabel prop. Removes the LinkTrigger
  forwardRef + `{...rest}` spread trick that was sneaking Popover props
  through an intermediate Tooltip wrapper.
- Delete the misleading JSDoc at IssueLinkCommand claiming Radix can't be
  closed imperatively — PopoverClose exists; the controlled-open pattern
  we use is just shadcn's canonical combobox.
- Drop orphaned `_issueLinkOpen` / `_addLinkedIssue` + the
  `setIssueLinkOpen` prop threaded through ChatShortcuts in both v1 and
  v2 chat, plus the same dead state in v1 NewWorkspaceModal PromptGroup.
- Retire the CHAT_LINK_ISSUE hotkey entry — its only consumer was the
  dead setIssueLinkOpen toggle.

* chore: trim past-state narration + what-describing comments

- Drop "previously this did X" / "introduced in PR superset-sh#3088" / commented-out
  renderPane block in v2 usePaneRegistry chat pane.
- Collapse JSDocs that only restated the function's name (ParentDirectoryPicker,
  AddRepositoryModals layout blurb, per-method docs on UseFolderFirstImportResult,
  persistLocalProject).
- Tighten the explanatory comments that still earn their keep (pending
  PROJECT_NOT_SETUP interceptor, PinAndSetupModal conflict state, store
  onSuccess / forceRepoint prop docs).

* refactor(desktop): strip v2 discovery/recovery surface to MVP

Two rules for v1:
- Sidebar = pinned projects.
- Workspaces tab = every workspace in the user's active org.

Code deletes:
- V2AvailableProjectsSection, useAvailableV2Projects, useHostProjectIds.
- v2UsersHosts innerJoin in useAccessibleV2Workspaces — tab no longer
  drops rows when host access changes.
- Available-section wiring in V2WorkspacesList + v2-workspaces/page.tsx.
- Available / Needs-setup split in ProjectPickerPill and the
  openPinAndSetup bridge in PromptGroup. Also removes the wrong-host
  bug (cubic AF_o, saddlepaddle CXVQ) as dead code.
- PROJECT_NOT_SETUP recovery loop in the pending page — failure is a
  plain toast now.

Docs realigned:
- design/v2-project-create-import.md opens with the two rules and
  moves Available / inline setup / backing signals to an explicit
  "Out of scope for v1" block.
- plans/20260417-v2-project-create-import-impl.md mirrors the same
  deferrals; Phase-1 checklist is now all checked.

Net −537 lines. Typecheck + lint clean.

* refactor(desktop): open remote-host workspaces without gating

Previously any workspace whose hostMachineId didn't match the local
machine landed on a WorkspaceNotOnThisHostState stub. That hid the
workspace from the user entirely when the whole point is to let them
see it. Delete the gate, delete the stub component, and let the
workspace page render for any host. Operations that assume local
filesystem (terminal spawn, local git) fail at the point they run.

Also slims the page's live query — projectGithubOwner, projectName,
hostMachineId etc. were only fed into the stub.

Design doc + plan updated to reflect the no-gating posture.

Resolves saddlepaddle CTvC.

* refactor(desktop): extract FormPickerTrigger component

Addresses saddlepaddle CWlq — the shared style for the three top-of-modal
pickers (Device / Project / Branch) lived as a string constant in
types.ts, which is an odd place for a className and doesn't compose.

Promote it to a named FormPickerTrigger component that encapsulates the
base button styles and accepts extra className + native button props.
The three call sites lose their raw <button type="button"> +
backtick-composed classNames.

Drops FORM_PICKER_TRIGGER_CLASS from types.ts.

* refactor(desktop): remove dead PinAndSetupModal + async-hygiene sweep

PinAndSetupModal had zero remaining callers after the MVP cut — the
pending-page PROJECT_NOT_SETUP interceptor and the Available-section
"Pin & set up" button were the only two. Delete the whole modal,
its store action, useOpenPinAndSetupModal hook, PinAndSetupTarget
type, and the forceRepoint plumbing that existed only to support it.

Also addresses the async-hygiene nits on the surviving surfaces:
- useFolderFirstImport.start wraps selectDirectory.mutateAsync in
  try/catch → reportError (coderabbit nmS, cubic op5).
- ParentDirectoryPicker.handleBrowse wraps the same (cubic op8).
- AddRepositoryModals effect adds .catch on startRef.current()
  (cubic oqE).
- FolderFirstImportModal keys CandidatePickerContent on repoPath so
  selectedId resets per import (coderabbit nmM).

Docs + plan updated to reflect the removed modal + ENOENT recovery
deferral.

Net −205 lines. Typecheck + lint clean.

* refactor(host-service): reject re-pointing instead of confirming it

v1 has no re-point UX. project.setup now treats an existing row as:
- same resolved path → no-op success (idempotent; fixes the false
  CONFLICT that cubic/coderabbit flagged on same-path setup).
- different path → CONFLICT with the existing path in the message,
  no escape hatch. User must project.remove first if they genuinely
  want to move the project.

Drops `acknowledgeWorkspaceInvalidation` from the input, the ack
branch of the CONFLICT guard, and the setupFromClone/setupFromImport
helpers + SetupContext type in handlers.ts (the setup path is small
enough to inline).

Client drops the confirm-repoint state, confirmRepoint method,
ConfirmRepointContent component, and the conflict branch in
SetupInvokeResult — none of which have anything to retry against.

Also fixes the TOCTOU race in cloneRepoInto: replaces
existsSync + rmSync-on-error with mkdirSync (atomic claim) +
rmSync-on-error, so clone failure can't delete a directory this
process didn't create.

Resolves coderabbit nmb, nmd, and cubic oqN.

* fix(desktop): unify workspaces-tab empty state

The onboarding "No workspaces yet" check was reading already-filtered
pinned/others counts, so a search that matched nothing landed on the
onboarding copy instead of the clear-filters UI.

Collapse to a single !hasAnyMatches branch that picks copy + icon
based on hasActiveFilters. Drops the bogus hasAnyWorkspaces check.

Resolves cubic CrwE.

* revert queries

* Clean up dead code

* refactor(desktop): port v1 new-project UI into NewProjectModal

Replace the bespoke name + clone-URL + parent-picker form with v1's
new-project page layout: a Location row (text input + browse button),
three mode tiles (Clone/Empty/Template), and a per-mode form. Only
Clone is wired up; Empty + Template carry "(coming soon)" since v2
project.create throws NOT_IMPLEMENTED for them.

Location auto-populates to ~/.superset/projects via window.getHomeDir.
Project name is derived from the clone URL's last segment so the form
matches v1 (no explicit name field).

ParentDirectoryPicker deleted — the inline Input + folder button
replaces it and there's no other caller.

* feat(db/trpc): decouple v2 projects from GitHub App installs

v2Projects previously required a non-null githubRepositoryId, which
gated project creation on the org having installed the repo via the
GitHub App. Cloning any other repo (public, not installed, or non-
matching) failed at the cloud step after a successful local clone.

Changes:
- githubRepositoryId becomes nullable with ON DELETE SET NULL,
  matching v1's projects table.
- repoCloneUrl is added as the canonical source of truth for the
  remote URL. Also nullable so empty-mode / local-only projects
  without a remote can coexist.
- UNIQUE(organization_id, lower(repo_clone_url)) prevents two
  projects from claiming the same repo in one org. NULLs don't
  collide, so URL-less projects still work.
- v2Project.create accepts an optional repoCloneUrl, canonicalizes
  via parseGitHubRemote, and links a matching github_repositories
  row case-insensitively when one exists. Unique-violation (23505)
  surfaces as CONFLICT with per-constraint messaging.
- v2Project.findByGitHubRemote matches on v2Projects.repoCloneUrl
  directly instead of joining through the installation table, so
  unlinked projects are discoverable.
- v2Project.get drops the derived repoCloneUrl — consumers read the
  stored column or the joined githubRepository directly.

Migration 0034 bundles all five schema changes. Nullable-safe: no
backfill required for existing rows.

* No candidate thing

* feat(desktop): flag projects not set up on selected host in new-workspace modal

After picking a host in DevicePicker, each project in ProjectPickerPill
shows an amber warning triangle when that host doesn't have the project
set up locally. A matching "Project needs to be set up" note appears
next to the ⌘↵ hint when the currently-selected project needs setup,
so the user sees the blocker before submitting.

Setup state comes from a per-host project.list query (re-added to the
host-service router). The RPC is resolved through the standard
getHostServiceClientByUrl path — local uses activeHostUrl, remote/cloud
goes through the relay. If the host is unreachable we treat setup as
unknown and hide the indicator rather than falsely flagging everything.

Submit path is unchanged: picking a not-set-up project still fires
workspace.create, which throws PROJECT_NOT_SETUP and surfaces as the
existing toast. Inline setup UX is still deferred.

* chore: biome format fix + sync design doc to workspaces-tab filter

- git.ts: biome wants the ghMsg ternary wrapped; main's 27e243b added
  the catch block and the CI biome check caught it post-merge.
- design doc: the workspaces tab code filters to hosts the user is
  linked to via v2_users_hosts, not every workspace in the org. Update
  wording to match what shipped; note teammate workspaces on unshared
  hosts are not surfaced in v1.

* docs: move v2 project create/import plan to plans/done

Plan is shipped — move per AGENTS.md rule 7 and drop the rewrite/history
notes in both plan and design doc since the PR body is the canonical
record of what was cut.

* docs: drop rewrite/history notes from plan and design doc

Captured in PR body instead.

* chore: trim restating/navigational comments in project handlers
…superset-sh#3602)

* fix(desktop): stop spurious folder picker on settings → dashboard nav

The folder-first import flow was plumbed through a zustand counter plus a
useEffect in AddRepositoryModals. The counter outlives component mounts,
but the effect runs on every mount — so once a user ever clicked "Import
existing folder," every subsequent remount of the dashboard layout
(including the one that happens when navigating back from Settings)
re-ran the effect and re-opened the native directory picker.

Remove the indirection. DashboardSidebarHeader now owns useFolderFirstImport
and renders FolderFirstImportModal itself; the dropdown item calls
folderImport.start() directly on click. No store pulse, no effect.

* fix(desktop): drop dead promise-rejection catch on folderImport.start
…3605)

* feat(desktop): infer project name from folder, skip naming modal on import

When a folder import has no matching cloud project, infer the project
name from the folder basename and create the project directly instead
of opening a modal asking the user to type a name. Mirrors v1's
upsertProject behavior. Users can still rename after import.

Removes FolderFirstImportModal and its no-match state machine.

* refactor(desktop): extract getBaseName helper with tests

Promote the inline inferProjectName in useFolderFirstImport and the
duplicate getBaseName in FilesView/utils into a shared helper at
renderer/lib/pathBasename. Fixes the trailing-separator edge case in
the old FilesView impl (/foo/ now returns "foo" instead of "").

Add 27 unit tests covering posix, Windows, UNC, trailing/consecutive
separators, dotfiles, unicode, emoji, and degenerate inputs.

* fix(desktop): drop FolderFirstImportModal usage in sidebar header

Main added a FolderFirstImportModal reference in DashboardSidebarHeader
after this branch removed the modal. Remove the stale import and the
two renders — the hook now triggers import directly via start().
…-sh#3606)

* feat(desktop): v2 project settings with setup/relocate path

Adds a settings surface for cloud-synced (v2) projects so users can
point an existing v2 project at a local clone, or move it to a new
folder when the original location was wrong. The shared projects list
now shows both v1 and v2 entries; v2 rows route to the new dedicated
settings tree.

- host-service: `project.setup` accepts `allowRelocate` on import mode;
  when the cloud project has no `repoCloneUrl`, reads the local origin
  and backfills via a new cloud `v2Project.linkRepoCloneUrl` procedure.
- Adds `project.get` + `project.findBackfillConflict` (precheck that
  surfaces when another org project already owns the same repo).
- UI: new `/settings/v2-project/$projectId/general` page with a
  "Project Location" section that handles both initial setup and
  relocation (with a confirm dialog warning about orphaned worktrees).
  On conflict, offers to redirect to the existing project.

* fix(v2): decouple slug from project rename

Renaming a v2 project previously auto-derived slug from the new name
and sent both to v2Project.update, hitting v2_projects_org_slug_unique
when another project in the org already owned the derived slug. Only
update name; slug stays stable from create time (edit as a separate
action if/when needed).

Also drops the ad-hoc 23505 handling in v2Project.{create,update,
linkRepoCloneUrl} — the real conflict paths all pre-check, so the only
writes that can still violate a unique index are rare races where the
generic error surface is acceptable.

* refactor(desktop): split-pane settings/projects with unified detail route

Collapses the separate /settings/project and /settings/v2-project
trees into a single /settings/projects layout. Left pane lists v1 + v2
projects (deduped as before); right pane renders the selected
project's detail at /settings/projects/\$projectId. The detail route
branches on v2 cloud-collection membership and renders the existing
ProjectSettings or V2ProjectSettings component.

Also removes the in-page "Back to Projects" button from the project
settings header — the sidebar already provides navigation. Repoints
every caller (workspace sidebar, dashboard sidebar, workspace run
button, v2 conflict redirect, settings-sidebar matchRoute) to the new
URL. Old route files deleted; cloud/secrets tree left in place as
orphan (no external callers).

* refactor(desktop): split sidebar into Cloud + Local sections

* refactor(desktop): label projects sidebar sections v1/v2, drop icons

* refactor(desktop): hide v1/v2 section headers when only one group exists

* refactor(desktop): clean up v1 project settings page

- Drop icons from every SettingsSection; title alone carries meaning
- Collapse redundant labels/descriptions (Branch Prefix, Base Branch)
- Remove the Terminal Presets section (it only redirects to /settings/terminal)
- Consolidate the three Scripts editors into tabs (Setup/Teardown/Run)
- Tighten the header: project name + muted path subtitle

* fix(desktop): drop stale title reference in ScriptsEditor drop zone

* refactor(desktop): drop dividers, tighten Appearance row

- Remove per-section border-t; rely on wider vertical spacing (space-y-8)
- Inline Appearance color + icon upload + Hide image into one flex row
- Drop redundant TabsContent top margin in ScriptsEditor

* refactor(desktop): clean up v2 project settings, add delete action

- Strip the self-styled wrapper from ProjectLocationSection; reuse the
  shared SettingsSection from v1 so layout and spacing match.
- Add Danger Zone section with a DeleteProjectSection that calls
  v2Project.delete (with AlertDialog confirm). On success navigates
  back to /settings/projects.
- Show repoCloneUrl as a muted subtitle in the v2 project header.

* fix(desktop): correct relative import path in V2ProjectSettings

* refactor(desktop): only show ClickablePath underline + external icon on hover

* feat(v2): editable repoCloneUrl in project settings

- Extend v2Project.update to accept repoCloneUrl (canonicalize, auto-link
  github_repositories row, clear via null).
- Add a Repository section with an Input + Save button; replaces the
  read-only subtitle in the header.

* Lint

* refactor(desktop): show repo URL as text, reveal input only on Edit

* refactor(desktop): rename to Host Service Location, show host name

Row is structured as [host label | path | action] so we can iterate to
show every connected host once multi-host support lands.

* style(desktop): biome import reorder

* feat(desktop): offer Clone + Import when host needs setup

Not-set-up rows now show two actions: Clone here (picks a parent dir
and runs setup mode=clone) and Import existing (picks a repo path).
Clone is disabled when the project has no linked repoCloneUrl.

* fix: PR review feedback for v2 settings

- Sidebar dedup was built from v1 groups, hiding any linked v1 row
  even when its v2 twin wasn't loaded; build set from v2Projects.
- project.setup: move rejectIfRepoint above linkRepoCloneUrl so a
  rejected repoint doesn't permanently link the cloud project to the
  candidate folder's origin.
- v2Project.linkRepoCloneUrl: make the update atomic via
  'isNull(repoCloneUrl) AND org match' in WHERE; treat zero rows as
  CONFLICT to close the two-concurrent-imports race.
- ProjectLocationSection: mirror the backfill-conflict precheck on
  the relocate path, and keep isSubmitting true while the conflict
  dialog is open.
…#3596)

* feat(desktop): v1 review comments open in a pane like v2

Clicking a review comment in v1's ReviewPanel now opens it as a full
pane rendering the comment body (markdown, code blocks, tables), instead
of opening the GitHub URL. The "Open on GitHub" action remains as a
separate icon in the comment row.

Adds a "comment" pane type to the v1 tabs store (shared types,
createCommentPane/createCommentTabWithPane helpers, openCommentPane
action that reuses an existing comment pane per workspace) and a new
CommentPane view wired into TabView alongside file/chat/browser panes.

* feat(desktop): comment pane toolbar shows avatar + GitHub link

* fix(desktop): sync tab name when reusing comment pane + correct section comment
* feat(desktop): port v1 projects + workspaces + sidebar state into v2

First-time v2 launch now migrates the user's v1 local data into v2 cloud +
local stores and surfaces a branded summary modal. Covers projects (dedup
via GitHub remote, link-or-create), worktrees (adopt into v2_workspaces with
legacy-path support), sections (including empty ones), and sidebar ordering
with v1→v2 normalization. Idempotent across runs via a new v1_migration_state
table.

Followups tracked: SUPER-469, SUPER-470, SUPER-471.

* fix(desktop): address CodeRabbit feedback on v1→v2 migration

- Scope v1_migration_state PK to (organization_id, v1_id, kind) so
  migrating the same v1 row under different orgs keeps independent state.
  Regenerated 0041 in place (pre-ship, no chained migration needed).
- Reuse v1 section id as v2 section id — deterministic mapping makes the
  rerun guard in writeV2SidebarState actually dedup; prior crypto.randomUUID
  would silently duplicate sections on every rerun.
- Add sr-only DialogTitle + DialogDescription to V1MigrationSummaryModal
  for assistive tech; keep the visual welcome header as-is.
- Stable React keys in summary entry lists (include array index).
- Log warning when v2Project.findByGitHubRemote returns multiple candidates
  so the constraint-slip case is diagnosable post-hoc.
…eep only schema

The upstream cherry-pick added 0041_v1_migration_state.sql and journal entry,
but fork already has idx 0041–0070. Remove the SQL file and journal entry;
schema change (v1MigrationState table) is kept for drizzle-kit generate later.
* fix(desktop): v2 file-open honors CMD+O editor choice

v2 click-to-open-externally (FilesTab tree, DiffPane entries, terminal
links, file pane header) was always hitting Cursor regardless of the
editor the user picked in the v2 Open In dropdown. Root cause: the
server-side `resolveDefaultEditor` only consults v1 localDb tables, so
it never saw the v2 choice (which lives client-side in tanstack-db
`v2SidebarProjects.defaultOpenInApp`). The hook now forwards that
choice to `openFileInEditor` as an explicit `app` override.

Also fixes a silent path-resolution bug that produced doubled paths
like `<worktree>/apps/desktop/apps/desktop/...` when relative diff
paths were opened without a cwd: `resolvePath` now throws
`RelativePathWithoutCwdError` instead of falling back to Electron's
`process.cwd()`, and the tRPC input field is renamed `cwd` →
`worktreePath` so the intent is explicit.

Extracted `useV2ProjectDefaultApp(projectId)` as the single source of
truth for reading/writing the v2 preference — used by both
`V2OpenInMenuButton` (write on open) and `useOpenInExternalEditor`
(read on open).

* docs(desktop): mention worktreePath not cwd in withResolveGuard comment

* lint
…sh#3683)

* feat(desktop): v2 Changes file list shift/cmd-click policy

Mirror the v2 Files tab click policy on the Changes sidebar: plain click
reuses an existing diff pane (or smart-places into the active tab),
shift+click opens the diff in a new tab, and cmd/ctrl+click opens the
file in the external editor.

* refactor(desktop): centralize v2 sidebar modifier-click intent

Extract the meta/ctrl -> editor, shift -> new tab, else -> select
dispatch into a shared getSidebarClickIntent() helper so the Files tab
tree item and the Changes file row resolve modifiers the same way.

* refactor(desktop): use path aliases for deep-relative imports

* feat(desktop): right-click menu + hover tooltip for v2 sidebar items

Surface the click/shift-click/cmd-click actions on v2 file and diff rows
so they stay discoverable: add a hover tooltip that lists the modifier
shortcuts, and a right-click menu with Open / Open in New Tab / Open in
Editor (with shortcut hints) plus the existing path actions. Changes
rows get the menu for the first time; Files rows gain explicit Open /
Open in New Tab / Open in Editor entries in place of the unwired "Open
to the Side" placeholder.

* fix(desktop): nest Tooltip inside ContextMenuTrigger so right-click works

* fix(desktop): gate cmd-click to files only in v2 Files sidebar
PR #2b 8 cherry-pick 後の typecheck エラーを修正:

- TiptapPromptEditor / QuestionInputOverlay モジュールを upstream から補完
  (cherry-pick で取りこぼされた新規ファイル群)
- settings/project/$projectId/cloud/{page,secrets/page}.tsx の route
  string を fork の実 route に合わせて修正
- ChatInputFooter 型 props の不整合解消
- V2WorkspacesList の prop 型調整
- ReviewPanel の upstream comment pane 追加 API を fork の 19 procedure と
  併存させる形で統合
- packages/local-db: drizzle-kit generate で 0071_v1_migration_state
  migration SQL と snapshot を生成 (upstream 0041 は fork 最大 idx 70 と
  衝突するため、schema.ts の重複 export を削除して drizzle-kit で再生成)
- packages/ui/src/components/ai-elements/prompt-input.tsx の型拡張

bun run typecheck: 全 27/27 pass
bun run lint: pass
fork 固有機能 (19 procedure, TERMINAL_OPTIONS, SUPERSET_WORKSPACE_NAME,
dmg.size 4g, 依存) 全健在
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 24, 2026

Important

Review skipped

Too many files!

This PR contains 152 files, which is 2 over the limit of 150.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 122ff7ca-7b02-4670-9853-89f0934f5287

📥 Commits

Reviewing files that changed from the base of the PR and between c81ef94 and 324074c.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (152)
  • apps/desktop/package.json
  • apps/desktop/plans/20260422-2100-v1-to-v2-port.md
  • apps/desktop/src/lib/trpc/routers/external/helpers.test.ts
  • apps/desktop/src/lib/trpc/routers/external/helpers.ts
  • apps/desktop/src/lib/trpc/routers/external/index.ts
  • apps/desktop/src/lib/trpc/routers/index.ts
  • apps/desktop/src/lib/trpc/routers/migration/index.ts
  • apps/desktop/src/lib/trpc/routers/workspaces/procedures/query.ts
  • apps/desktop/src/main/lib/notifications/notification-manager.test.ts
  • apps/desktop/src/main/lib/notifications/notification-manager.ts
  • apps/desktop/src/renderer/components/Chat/ChatInterface/components/ChatInputFooter/ChatInputFooter.tsx
  • apps/desktop/src/renderer/components/Chat/ChatInterface/components/ChatInputFooter/components/ChatComposerControls/ChatComposerControls.tsx
  • apps/desktop/src/renderer/components/Chat/ChatInterface/components/ChatInputFooter/components/ChatShortcuts/ChatShortcuts.tsx
  • apps/desktop/src/renderer/components/Chat/ChatInterface/components/ChatInputFooter/components/QuestionInputOverlay/QuestionInputOverlay.tsx
  • apps/desktop/src/renderer/components/Chat/ChatInterface/components/ChatInputFooter/components/QuestionInputOverlay/index.ts
  • apps/desktop/src/renderer/components/Chat/ChatInterface/components/IssueLinkCommand/IssueLinkCommand.tsx
  • apps/desktop/src/renderer/components/Chat/ChatInterface/components/PlusMenu/PlusMenu.tsx
  • apps/desktop/src/renderer/components/Chat/ChatInterface/components/TiptapPromptEditor/FileMentionNode.tsx
  • apps/desktop/src/renderer/components/Chat/ChatInterface/components/TiptapPromptEditor/SlashCommandNode.tsx
  • apps/desktop/src/renderer/components/Chat/ChatInterface/components/TiptapPromptEditor/SlashCommandPreviewPopover.tsx
  • apps/desktop/src/renderer/components/Chat/ChatInterface/components/TiptapPromptEditor/TiptapPromptEditor.tsx
  • apps/desktop/src/renderer/components/Chat/ChatInterface/components/TiptapPromptEditor/index.ts
  • apps/desktop/src/renderer/components/Chat/ChatInterface/components/TiptapPromptEditor/parseTextToEditorContent.ts
  • apps/desktop/src/renderer/components/Chat/ChatInterface/components/TiptapPromptEditor/serializeEditorToText.ts
  • apps/desktop/src/renderer/components/Chat/ChatInterface/hooks/useSlashCommands/index.ts
  • apps/desktop/src/renderer/components/Chat/ChatInterface/hooks/useSlashCommands/useSlashCommands.ts
  • apps/desktop/src/renderer/components/NewWorkspaceModal/components/PromptGroup/PromptGroup.tsx
  • apps/desktop/src/renderer/hotkeys/registry.ts
  • apps/desktop/src/renderer/lib/pathBasename/index.ts
  • apps/desktop/src/renderer/lib/pathBasename/pathBasename.test.ts
  • apps/desktop/src/renderer/lib/pathBasename/pathBasename.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/AddRepositoryModals/AddRepositoryModals.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/AddRepositoryModals/components/NewProjectModal/NewProjectModal.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/AddRepositoryModals/components/NewProjectModal/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/AddRepositoryModals/hooks/useFolderFirstImport/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/AddRepositoryModals/hooks/useFolderFirstImport/useFolderFirstImport.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/AddRepositoryModals/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHeader/DashboardSidebarHeader.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarProjectSection/hooks/useDashboardSidebarProjectSectionActions/useDashboardSidebarProjectSectionActions.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/TopBar/components/V2OpenInMenuButton/V2OpenInMenuButton.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/TopBar/components/WorkspaceRunButton/WorkspaceRunButton.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/pending/$pendingId/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/WorkspaceSidebar.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/components/FilesTab/FilesTab.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/components/FilesTab/components/WorkspaceFilesTreeItem/WorkspaceFilesTreeItem.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/components/FilesTab/components/WorkspaceFilesTreeItem/components/FileContextMenu/FileContextMenu.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/hooks/useChangesTab/components/ChangesFileList/ChangesFileList.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/hooks/useChangesTab/components/ChangesFileList/components/FileRow/FileRow.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/hooks/useChangesTab/components/ChangesTabContent/ChangesTabContent.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/hooks/useChangesTab/useChangesTab.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useOpenInExternalEditor/useOpenInExternalEditor.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/WorkspaceChatInterface/components/ChatInputFooter/ChatInputFooter.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/WorkspaceChatInterface/components/ChatInputFooter/components/ChatComposerControls/ChatComposerControls.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/WorkspaceChatInterface/components/ChatInputFooter/components/ChatShortcuts/ChatShortcuts.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/DiffPane/DiffPane.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/usePaneRegistry.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/utils/clickModifierLabels/clickModifierLabels.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/utils/clickModifierLabels/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/utils/getSidebarClickIntent/getSidebarClickIntent.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/utils/getSidebarClickIntent/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/V2WorkspacesList.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/PromptGroup.tsx
  • apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/components/AttachmentButtons/AttachmentButtons.tsx
  • apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/components/CompareBaseBranchPicker/CompareBaseBranchPicker.tsx
  • apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/components/FormPickerTrigger/FormPickerTrigger.tsx
  • apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/components/FormPickerTrigger/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/components/GitHubIssueLinkCommand/GitHubIssueLinkCommand.tsx
  • apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/components/PRLinkCommand/PRLinkCommand.tsx
  • apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/components/ProjectPickerPill/ProjectPickerPill.tsx
  • apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/types.ts
  • apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/components/DevicePicker/DevicePicker.tsx
  • apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceModalContent/DashboardNewWorkspaceModalContent.tsx
  • apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceModalContent/hooks/useSelectedHostProjectIds/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceModalContent/hooks/useSelectedHostProjectIds/useSelectedHostProjectIds.ts
  • apps/desktop/src/renderer/routes/_authenticated/components/V1MigrationSummaryModal/V1MigrationSummaryModal.tsx
  • apps/desktop/src/renderer/routes/_authenticated/components/V1MigrationSummaryModal/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/hooks/useMigrateV1DataToV2/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/hooks/useMigrateV1DataToV2/migrate.test.ts
  • apps/desktop/src/renderer/routes/_authenticated/hooks/useMigrateV1DataToV2/migrate.ts
  • apps/desktop/src/renderer/routes/_authenticated/hooks/useMigrateV1DataToV2/normalize.test.ts
  • apps/desktop/src/renderer/routes/_authenticated/hooks/useMigrateV1DataToV2/normalize.ts
  • apps/desktop/src/renderer/routes/_authenticated/hooks/useMigrateV1DataToV2/useMigrateV1DataToV2.ts
  • apps/desktop/src/renderer/routes/_authenticated/hooks/useMigrateV1DataToV2/writeSidebarState.test.ts
  • apps/desktop/src/renderer/routes/_authenticated/hooks/useMigrateV1DataToV2/writeSidebarState.ts
  • apps/desktop/src/renderer/routes/_authenticated/hooks/useV2ProjectDefaultApp/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/hooks/useV2ProjectDefaultApp/useV2ProjectDefaultApp.ts
  • apps/desktop/src/renderer/routes/_authenticated/settings/components/ClickablePath/ClickablePath.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/components/SettingsSidebar/ProjectsSettings.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/project/$projectId/cloud/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/project/$projectId/cloud/secrets/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/project/$projectId/components/ProjectSettings/ProjectSettings.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/project/$projectId/components/ProjectSettings/components/ScriptsEditor/ScriptsEditor.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/project/$projectId/components/ProjectSettingsHeader/ProjectSettingsHeader.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/project/$projectId/general/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/project/$projectId/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/projects/$projectId/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/projects/components/ProjectsSettingsSidebar/ProjectsSettingsSidebar.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/projects/components/ProjectsSettingsSidebar/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/settings/projects/layout.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/projects/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/v2-project/$projectId/components/V2ProjectSettings/V2ProjectSettings.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/v2-project/$projectId/components/V2ProjectSettings/components/DeleteProjectSection/DeleteProjectSection.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/v2-project/$projectId/components/V2ProjectSettings/components/DeleteProjectSection/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/settings/v2-project/$projectId/components/V2ProjectSettings/components/ProjectLocationSection/ProjectLocationSection.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/v2-project/$projectId/components/V2ProjectSettings/components/ProjectLocationSection/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/settings/v2-project/$projectId/components/V2ProjectSettings/components/RepositorySection/RepositorySection.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/v2-project/$projectId/components/V2ProjectSettings/components/RepositorySection/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/settings/v2-project/$projectId/components/V2ProjectSettings/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectHeader.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/SetupScriptCard/SetupScriptCard.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ChangesContent/components/FileDiffSection/FileDiffSection.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/CommentPane/CommentPane.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/CommentPane/comment-pane.css
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/CommentPane/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/FileItem/FileItem.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ReviewPanel/ReviewPanel.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/hooks/usePathActions.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/FilesView/FilesView.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/FilesView/components/FileSearchResultItem/FileSearchResultItem.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/FilesView/components/FileTreeItem/FileTreeItem.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/FilesView/utils/new-item-paths.ts
  • apps/desktop/src/renderer/stores/add-repository-modal.ts
  • apps/desktop/src/renderer/stores/tabs/store.ts
  • apps/desktop/src/renderer/stores/tabs/types.ts
  • apps/desktop/src/renderer/stores/tabs/utils.ts
  • apps/desktop/src/shared/tabs-types.ts
  • docs/design/v2-project-create-import.md
  • packages/db/drizzle/0034_v2_projects_decouple_github_install_add_clone_url.sql
  • packages/db/drizzle/meta/0034_snapshot.json
  • packages/db/drizzle/meta/_journal.json
  • packages/db/src/schema/schema.ts
  • packages/host-service/src/runtime/pull-requests/utils/parse-github-remote/index.ts
  • packages/host-service/src/runtime/pull-requests/utils/parse-github-remote/parse-github-remote.ts
  • packages/host-service/src/trpc/error-types.ts
  • packages/host-service/src/trpc/index.ts
  • packages/host-service/src/trpc/router/project/handlers.ts
  • packages/host-service/src/trpc/router/project/project.ts
  • packages/host-service/src/trpc/router/project/utils/git-remote.ts
  • packages/host-service/src/trpc/router/project/utils/persist-project.ts
  • packages/host-service/src/trpc/router/project/utils/resolve-repo.ts
  • packages/host-service/src/trpc/router/workspace-creation/workspace-creation.ts
  • packages/local-db/drizzle/0071_v1_migration_state.sql
  • packages/local-db/drizzle/meta/0071_snapshot.json
  • packages/local-db/drizzle/meta/_journal.json
  • packages/local-db/src/schema/schema.ts
  • packages/trpc/src/router/v2-project/v2-project.ts
  • packages/ui/src/components/ai-elements/prompt-input.tsx
  • plans/done/20260417-v2-project-create-import-impl.md

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch upstream/batch-2b-big-features

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 24, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ⚠️ Neon database branch
  • ⚠️ Electric Fly.io app

Thank you for your contribution! 🎉

…uperset-sh#3039

test が期待する upstream 新仕様 ("Awaiting Response" / "is waiting for your reply") に実装を合わせる。cherry-pick 取り込み時に test のみ upstream 側に置き換わり、実装が fork 旧仕様 ("Input Needed" / "needs your attention") のままだった不整合を修正。
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 80639ed104

ℹ️ 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".

Comment thread packages/trpc/src/router/v2-project/v2-project.ts
Comment thread apps/desktop/src/lib/trpc/routers/external/index.ts Outdated
Codex final review で HIGH 指摘された branch-type workspace の migration
skip 問題を修正。

upstream の migrate.ts は `workspace.worktreeId` がある場合のみ
`v1WorktreePath` を算出していたため、fork 独自の v1 `type="branch"`
workspace (worktreeId: null) では adopt() に worktreePath が渡らず、
host-service 側の listWorktreeBranches() が primary working tree を
skip する仕様と重なり、"worktree_not_registered" で失われていた。

branch-type では project.mainRepoPath を明示的に worktreePath として
渡すことで、adopt() が primary 側の checked-out branch を正しく解決
できるようにする。
P1: v2Projects.get に repoCloneUrl fallback を復元
- migration 0034 は repo_clone_url を nullable で追加したが既存 row を
  backfill しないため、pre-migration projects は repoCloneUrl = null
  のまま。下流の clone/setup パスが BAD_REQUEST で失敗する問題。
- githubRepository.fullName から `https://github.com/<fullName>.git`
  を導出する fallback を追加。

P2: external.openFileInEditor の no-editor fallback でエラー surface
- shell.openPath は失敗時に throw せず非空文字列を返す仕様。
- その戻り値をチェックして TRPCError を throw、上流にエラー通知。
@MocA-Love MocA-Love merged commit 0e30a85 into main Apr 24, 2026
12 of 13 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.

4 participants