Skip to content

upstream merge 2026-04-27 PR-D1: safe batch (sidebar / fade / panes / relay / model, 7 commits)#448

Merged
MocA-Love merged 7 commits intomainfrom
upstream/batch-2026-04-27-pr-d1
Apr 28, 2026
Merged

upstream merge 2026-04-27 PR-D1: safe batch (sidebar / fade / panes / relay / model, 7 commits)#448
MocA-Love merged 7 commits intomainfrom
upstream/batch-2026-04-27-pr-d1

Conversation

@MocA-Love
Copy link
Copy Markdown
Owner

@MocA-Love MocA-Love commented Apr 28, 2026

Summary

upstream (superset-sh/superset) から fork (MocA-Love/superset) への 2026-04-27 後半バッチ取り込み 第1弾。新規 13 commits を 5 PR に分割した中の PR-D1: safe batch (sidebar / fade / panes / relay / model) (7 commits)。

base は main (#445/#446/#447 マージ後の最新)。conflict は依存順守れば全て clean apply。

取り込み内容 (chronological)

SHA PR# 概要
0eedb03a4 upstream superset-sh#3793 workspace hover card からブランチ rename ダイアログ追加
10a1f1579 upstream superset-sh#3800 sidebar main workspace icons 更新
c1a3e3... upstream superset-sh#3770 shared overflow fade utilities (packages/ui に hook + components 追加、旧 fade-edge.css 削除)
c3a9f088a upstream superset-sh#3791 relay の fly deploy 修正
bec589c79 upstream superset-sh#3808 v2 chat pane model picker に GPT-5.5 追加
cb... upstream superset-sh#3809 pane drops を新タブに許可
556a0368a upstream superset-sh#3813 persistent v2 sidebar hover card

依存順序

Codex 事前調査で確認した依存:

  • 5cceee0cc (pane drops) は 01af7dc8c (overflow fade) の TabBar 移行に依存 → 同 PR 内で順序保持
  • f19cb6ac4 (persistent hover card) は 2183bcf09 (rename branch from hover card) と 180425a5e (icon update) に依存 → 同 PR 内で順序保持

chronological 順で cherry-pick した結果、全 7 件 conflict なし (clean apply)。

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

baseline (/tmp/pr-late-baseline.txt) と比較し全項目健在を確認:

  • 19 個の独自 tRPC procedures 全件健在
  • fork 専用依存: ansi_up, @vscode/ripgrep, @xyflow/react
  • fork マーカー全項目健在
  • electron-builder.tsdmg.size = "4g" 維持
  • desktop version: 1.6.2
  • packages/db/drizzle/ 最大 idx 0039 / packages/local-db/drizzle/ 最大 idx 0072 維持

Test plan

  • bun install 整合性 OK
  • bun run typecheck 全 28 task green
  • bun run lint biome green
  • (ローカル) bun run --filter @superset/desktop build 成功確認
  • (手動) workspace hover card 表示 / branch rename ダイアログ
  • (手動) sidebar main workspace icon 表示
  • (手動) v2 chat の GPT-5.5 選択
  • (手動) pane drop で新タブ作成
  • (手動) v2 sidebar persistent hover card

後続 PR (このバッチ残り)

  • PR-D2: terminal connection diagnostics (2473996a6) — conflict 1ファイル
  • PR-D3: v2 cloud opt-in 反転 (790cbbc6a) — fork 流に書き換え
  • PR-D4: chat / header / v1→v2 keypad loading (298d773ee, 95cff6b36, 50eb12532)
  • PR-D5: PR action header (864a81c03) — 39 files / +2522 行の大物単独 PR

Summary by CodeRabbit

リリースノート

  • 新機能

    • ワークスペースのブランチ名変更機能を追加しました
    • ホバーカード内でブランチを直接編集できるようになりました
    • ペインをタブストリップにドラッグして新しいタブを作成できます
    • GPT-5.5チャットモデルを追加しました
  • 改善

    • テキストとコンテナのオーバーフロー表示を改善し、より見やすくなりました
    • ワークスペースホバーカードのパフォーマンスが向上しました
    • リレーサービスのリソース割り当てを最適化しました

AviPeltz and others added 7 commits April 28, 2026 08:56
)

Click the branch name in a workspace hover card to open a modal that
renames the local git branch via the host service. The GitHub external-
link icon is split out as a separate affordance so the branch name
itself is always the rename trigger.

In the v2 dashboard sidebar, the rename also writes the new branch
through the v2Workspaces optimistic action so the hover card reflects
the new name immediately without waiting for a manual refresh.
* Update sidebar main workspace icons

* Preserve remote sidebar workspace icons

* Separate sidebar remove and close actions

* Stop sidebar action key events bubbling
* Add shared overflow fade utilities

* Simplify overflow-fade components and drop tab scrollbar

Remove duplicate barrel shims, inline forwardRef via React 19 ref-as-prop,
drop redundant layout effect and SSR guards in use-overflow-fade, and
collapse the on-hover tab scrollbar back to hide-scrollbar.

* Stabilize OverflowFadeContainer onOverflowChange firing

Stash the callback in a ref so the effect only fires when measured
overflow flags change, not on every consumer render with an unmemoized
callback.
- Pin `bunx turbo@2.8.7` in the prune stage. Previously unpinned, so
  Docker fetched whatever was latest on npm (2.9.6) — that version
  produces a pruned bun.lock inconsistent with its own pruned
  package.jsons, causing `bun install --frozen-lockfile` to fail.
  Pinning to the project's turbo version eliminates the drift.
- Drop dead `COPY patches patches` left over from superset-sh#3509 (durable-streams
  patch removal). The directory hasn't existed since March, so any
  redeploy from a clean cache failed at this line.
- Bump VM memory from 2gb to 4gb. Fly's `cpu_kind = "performance"` now
  requires ≥4096 MiB; the existing machine was grandfathered but new
  deploys are rejected.
* feat(desktop): persistent v2 sidebar hover card

Replace the per-row Radix HoverCard wrappers with a single sidebar-level
Popover anchored via virtualRef to whichever workspace row is hovered.
Moving between rows now slides the panel rather than unmounting and
remounting, and the content updates in place. The slide is gated by a
data-positioned flag so the initial open doesn't animate from Radix's
off-screen measuring transform.

- Introduces DashboardSidebarHoverProvider (open/close timers, anchor +
  payload state, context-menu suppression, live workspace sync via
  syncIfHovered).
- Introduces DashboardSidebarHoverCardOverlay with the single Popover +
  PopoverAnchor and lifts useDiffStats(hoveredId) up so the row's per-
  item hook can stay focused on its own rendering.
- Strips the HoverCard layer out of DashboardSidebarWorkspaceContextMenu
  and lets the context menu report its open state through the provider.
- Cloud workspaces get hover cards too; only the PR-refresh callback
  remains gated to local-device hosts.

* refactor(desktop): co-locate hover card transition CSS

Move the popover-wrapper transition rule out of globals.css into a
sibling CSS file imported by DashboardSidebarHoverCardOverlay so the
style stays scoped to the component that needs it.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 28, 2026

📝 Walkthrough

ウォークスルー

ホバーカードオーバーレイプロバイダーの導入、ブランチ名変更機能の実装、オーバーフローフェードコンポーネントの新規作成、パネルドラッグアンドドロップ機能の追加により、ダッシュボードサイドバーとワークスペースUIの相互作用を大幅に強化しました。CSS utility削除とDocker/Fly設定の軽微な更新も含まれます。

変更内容

コホート/ファイル 概要
CSS utility削除
apps/desktop/src/renderer/globals.css
.fade-edge-rユーティリティクラスの削除による右端フェード効果の廃止
開発用チャットモデル更新
apps/desktop/src/renderer/lib/dev-chat.ts, packages/trpc/src/router/chat/chat.ts
GPT-5.5モデルの利用可能なチャットモデルリストへの追加
ダッシュボードサイドバーホバー管理
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/providers/DashboardSidebarHoverProvider/*
ホバー状態の一元管理、遅延オープン/クローズ、タイマー処理、ペイロード同期機能を備えた新規プロバイダーコンポーネント及びカスタムフック
ホバーカードオーバーレイコンポーネント
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHoverCardOverlay/*
Radix Popover を用いたホバーカードレンダリング、アニメーション遅延、ワークスペース情報表示
ダッシュボードサイドバー構造変更
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/DashboardSidebar.tsx
新規ホバープロバイダーと Overlay コンポーネントによる全コンテンツの再編成
ワークスペースアイテムホバー統合
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx
ホバープロバイダーの統合、ブランチ名変更ダイアログの条件付きレンダリング、workspace branch 更新処理
ワークスペース削除/削除アクション分離
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx
onDeleteClickをメインワークスペース向けのonRemoveFromSidebarClickと非メイン向けのonCloseWorkspaceClickに分割、アイコンとラベルの条件付きレンダリング
コンテキストメニューホバーカード削除
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceContextMenu/DashboardSidebarWorkspaceContextMenu.tsx
ホバーカード関連の props および HoverCard コンポーネント削除、プロバイダー経由での open/close 制御へ移行
ホバーカードコンテンツブランチ編集
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceHoverCardContent/DashboardSidebarWorkspaceHoverCardContent.tsx, apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/WorkspaceHoverCard/WorkspaceHoverCard.tsx
onEditBranchClickコールバック追加、ブランチ名を編集可能ボタンとして表示
ワークスペースアイコン更新
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx
workspaceType prop 追加、ローカルデバイス向けに main タイプではノートパソコンアイコン表示
ポートグループオーバーフロー処理
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarPortsList/components/DashboardSidebarPortGroup/DashboardSidebarPortGroup.tsx
OverflowFadeContainer への置き換え、子要素監視による動的フェード制御
ブランチ名変更ダイアログ実装
apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/RenameBranchDialog/*, apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/CollapsedWorkspaceItem.tsx, apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceContextMenu.tsx
新規 RenameBranchDialog コンポーネント、ブランチ名変更 API 呼び出し、トースト通知、各ワークスペースリストで状態管理
パネルタブ移動機能拡張
packages/panes/src/core/store/store.ts, packages/panes/src/core/store/store.test.ts
movePaneToNewTabtoIndex オプション追加、カスタム インデックスでのタブ挿入、単体テスト追加
TabBar ドラッグアンドドロップ統合
packages/panes/src/react/components/Workspace/components/TabBar/TabBar.tsx, packages/panes/src/react/components/Workspace/Workspace.tsx
onMovePaneToNewTab コールバック、ドロップされたパネルの型判別、OverflowFadeContainer による overflow 検出リファクタリング
TabItem テキストオーバーフロー処理
packages/panes/src/react/components/Workspace/components/TabBar/components/TabItem/TabItem.tsx
プレーンな <span> から OverflowFadeText コンポーネントへの置き換え
オーバーフローフェード UI コンポーネント
packages/ui/src/components/overflow-fade/OverflowFadeContainer/*, packages/ui/src/components/overflow-fade/OverflowFadeText/*
新規 OverflowFadeContainer および OverflowFadeText コンポーネント、ref 管理、onOverflowChange コールバック、条件付き fade-edge クラス
オーバーフローフェード Hook
packages/ui/src/hooks/use-overflow-fade.ts
新規 useOverflowFade Hook、ResizeObserver/MutationObserver/scroll/resize イベントによる overflow/scroll 状態追跡
UI パッケージエクスポート拡張
packages/ui/package.json, packages/ui/src/components/overflow-fade/fade-edge.css
新規エクスポートパス (./overflow-fade-container, ./overflow-fade-text, ./overflow-fade.css)、CSS ドキュメントコメント削除
インフラ設定更新
apps/relay/Dockerfile, apps/relay/fly.toml
Turbo 明示的バージョン指定 (bunx turbo@2.8.7)、patches ディレクトリコピー削除、Fly VM メモリ 2GB → 4GB

シーケンス図

sequenceDiagram
  participant User as ユーザー
  participant Dashboard as ダッシュボード<br/>サイドバー
  participant Provider as ホバー<br/>プロバイダー
  participant Overlay as ホバーカード<br/>オーバーレイ
  participant Dialog as ブランチ<br/>編集ダイアログ
  participant API as API

  User->>Dashboard: ワークスペース項目にマウスオーバー
  Dashboard->>Provider: requestOpen(id, element, payload)
  Provider->>Provider: 遅延タイマースケジュール (200ms)
  Provider->>Overlay: ホバー状態を更新
  Overlay->>Overlay: アニメーション遅延 (2フレーム)
  Overlay->>User: ホバーカード表示

  User->>Overlay: ブランチ編集ボタンクリック
  Overlay->>Dialog: onEditBranchClick(branchName)
  Dialog->>User: ダイアログ表示

  User->>Dialog: 新しいブランチ名入力 + 送信
  Dialog->>API: git.renameBranch.mutate()
  API->>API: ブランチ名変更実行
  API-->>Dialog: 成功

  Dialog->>Dialog: キャッシュ無効化<br/>(worktree/workspace)
  Dialog->>User: ダイアログクローズ
  Dashboard->>User: UI 更新表示
Loading
sequenceDiagram
  participant User as ユーザー
  participant TabBar as TabBar
  participant DnD as ドラッグ<br/>アンドドロップ
  participant Store as Zustand<br/>ストア
  participant UI as UI更新

  User->>DnD: パネルをタブストリップにドラッグ
  DnD->>DnD: drop イベント検出
  DnD->>DnD: ドロップ item 型判別
  alt パネル型
    DnD->>TabBar: onMovePaneToNewTab(paneId, toIndex)
    TabBar->>Store: movePaneToNewTab({paneId, toIndex})
  else タブ型
    DnD->>Store: 既存タブ順序変更ロジック
  end
  Store->>Store: 新タブ作成、パネル移動
  Store->>UI: state 更新
  UI->>User: TabBar と Pane レイアウト再レンダリング
Loading

推定コードレビュー労力

🎯 4 (複雑) | ⏱️ ~60 分

ポエム

🐰✨ ホバーカードがふわり舞い、
ブランチ編集もしゅっと完了。
オーバーフロー、フェードも美しく、
パネルドラッグで自由自在。
デスクトップ UI、進化の時 🚀

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes a batch merge of 7 upstream commits covering multiple feature areas (sidebar, fade utilities, panes, relay, model).
Description check ✅ Passed The description is comprehensive and well-structured, covering summary, contents, dependencies, fork health check, and test plan. However, it is written entirely in Japanese, which may limit accessibility for some team members.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch upstream/batch-2026-04-27-pr-d1

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 28, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

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

Thank you for your contribution! 🎉

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (10)
apps/desktop/src/renderer/lib/dev-chat.ts (1)

26-30: モデル定義の二重管理は将来的にドリフトしやすいです

今回の追加自体は正しいですが、apps/desktop/src/renderer/lib/dev-chat.tspackages/trpc/src/router/chat/chat.ts で同じモデル一覧を別管理しているため、将来の更新漏れリスクがあります。共有定数(またはサーバー定義を参照する仕組み)への集約を検討してください。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/lib/dev-chat.ts` around lines 26 - 30, The model
list defined inline in apps/desktop/src/renderer/lib/dev-chat.ts (e.g., the
entry with id "openai/gpt-5.5") is duplicated in
packages/trpc/src/router/chat/chat.ts; extract the canonical model list into a
shared constant/module (for example a new exported array like SUPPORTED_MODELS
in a shared package or utils module) and replace the inline arrays in both
dev-chat.ts and chat.ts with imports from that single source, or alternatively
expose the server-side list via the chat router and have dev-chat consume it;
update imports and types so both files reference the same identifier (e.g.,
SUPPORTED_MODELS) to prevent future drift.
apps/relay/fly.toml (1)

31-31: 変更内容を承認します。

メモリ割り当てを4GBに増やす変更は、リレーのデプロイ問題に対処するための適切な調整です。

デプロイ後は、メモリ使用状況を監視して、この増加が問題を解決していることを確認することをお勧めします。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/relay/fly.toml` at line 31, Change is approved: the deployment memory
setting was increased to memory = "4gb"; merge the change (keep the memory key
set to "4gb") and deploy, then monitor runtime memory metrics and logs
post-deploy to confirm the increase resolves the relay OOM/deployment issues and
be prepared to adjust or roll back the memory value if abnormal behavior or cost
concerns arise.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceHoverCardContent/DashboardSidebarWorkspaceHoverCardContent.tsx (1)

71-79: cn()を使用したクラス名の一貫性向上を検討

テンプレートリテラルでの条件付きクラス名構築は機能しますが、他の箇所と同様にcn()ユーティリティを使用することで、より一貫性のあるスタイルになります。

♻️ 提案する変更
 <button
   type="button"
   onClick={() => onEditBranchClick(branch)}
-  className={`group/branch flex min-w-0 flex-1 items-center gap-1 font-mono break-all text-left hover:text-foreground hover:underline ${hasCustomAlias ? "text-xs" : "text-sm"}`}
+  className={cn(
+    "group/branch flex min-w-0 flex-1 items-center gap-1 font-mono break-all text-left hover:text-foreground hover:underline",
+    hasCustomAlias ? "text-xs" : "text-sm"
+  )}
   title="Rename branch"
 >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceHoverCardContent/DashboardSidebarWorkspaceHoverCardContent.tsx`
around lines 71 - 79, Replace the template-literal className on the button in
DashboardSidebarWorkspaceHoverCardContent with the project's cn() utility to
match other components; update the button element that calls
onEditBranchClick(branch) to build classes via cn("group/branch flex min-w-0
flex-1 items-center gap-1 font-mono break-all text-left hover:text-foreground
hover:underline", hasCustomAlias ? "text-xs" : "text-sm",
"group-hover/branch:opacity-100 transition-opacity") so conditional classes are
handled consistently with the rest of the codebase.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx (1)

291-299: 「Spacebar」キー値について

event.key === "Spacebar"は古いIE/Edgeでの名前で、モダンブラウザでは" "が使用されます。現在のターゲットブラウザを考慮すると、"Spacebar"のチェックは不要かもしれませんが、後方互換性のために残すことも合理的です。

♻️ モダンブラウザのみをターゲットにする場合の簡略化
 onKeyDown={(event) => {
   if (
     event.key === "Enter" ||
-    event.key === " " ||
-    event.key === "Spacebar"
+    event.key === " "
   ) {
     event.stopPropagation();
   }
 }}

Also applies to: 319-327

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx`
around lines 291 - 299, In DashboardSidebarExpandedWorkspaceRow update the
onKeyDown handler(s) to use the modern space key value: replace the legacy check
event.key === "Spacebar" with the single-space string (" ") — or, if you want to
keep backward compatibility, keep both checks but prefer the " " check first;
locate the onKeyDown prop in the DashboardSidebarExpandedWorkspaceRow component
(also adjust the other similar onKeyDown occurrence in the same component) and
ensure the handler still calls event.stopPropagation() for Enter and Space.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx (3)

100-103: useMemo の依存配列に setRenameBranchTarget が含まれていない点について

setRenameBranchTargetuseState のセッター関数であり、React によって安定した参照が保証されているため、依存配列に含めなくても動作上は問題ありません。ただし、明示的に含めることでコードの意図がより明確になります。

♻️ より明示的な依存配列
 const hoverPayload = useMemo(
 	() => ({ workspace, onEditBranchClick: setRenameBranchTarget }),
-	[workspace],
+	[workspace, setRenameBranchTarget],
 );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx`
around lines 100 - 103, The useMemo that computes hoverPayload currently lists
only workspace in its dependency array; update the dependency array for the
useMemo call that creates hoverPayload to also include the state setter
setRenameBranchTarget so the intent is explicit (hoverPayload -> useMemo(() =>
({ workspace, onEditBranchClick: setRenameBranchTarget }), [workspace,
setRenameBranchTarget])) while keeping the same returned object shape
referencing workspace and setRenameBranchTarget.

275-285: 冗長な open プロップ条件(expanded view)

expanded view でも同様のパターンがあります。collapsed view と同じ修正を適用できます。

♻️ 提案する修正
 {renameBranchTarget && (
 	<RenameBranchDialog
 		workspaceId={id}
 		currentBranchName={renameBranchTarget}
-		open={renameBranchTarget !== null}
+		open
 		onOpenChange={(open) => {
 			if (!open) setRenameBranchTarget(null);
 		}}
 		onAfterRename={handleAfterBranchRename}
 	/>
 )}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx`
around lines 275 - 285, 現在のコード renders <RenameBranchDialog> only when
renameBranchTarget is truthy but also passes open={renameBranchTarget !== null},
which is redundant; change the usage to either always render the dialog and
control visibility via the open prop (e.g., open={renameBranchTarget !== null})
or, simpler, keep conditional rendering and set open to true (or omit the open
prop) so the dialog doesn't receive a duplicate condition; apply the same fix to
the expanded view variant—update occurrences around RenameBranchDialog,
renameBranchTarget, setRenameBranchTarget, and handleAfterBranchRename to remove
the redundant open={renameBranchTarget !== null} check.

195-205: 冗長な open プロップ条件(collapsed view)

他のファイルと同様に、renameBranchTarget && ブロック内での open={renameBranchTarget !== null} は常に true となります。

♻️ 提案する修正
 {renameBranchTarget && (
 	<RenameBranchDialog
 		workspaceId={id}
 		currentBranchName={renameBranchTarget}
-		open={renameBranchTarget !== null}
+		open
 		onOpenChange={(open) => {
 			if (!open) setRenameBranchTarget(null);
 		}}
 		onAfterRename={handleAfterBranchRename}
 	/>
 )}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx`
around lines 195 - 205, The conditional render uses both "renameBranchTarget &&"
and "open={renameBranchTarget !== null}", which is redundant because the
component is only rendered when renameBranchTarget is truthy; simplify by
removing the redundant runtime check in the prop: keep the conditional render
"renameBranchTarget && <RenameBranchDialog ... />" and change the open prop to a
constant true (e.g., open={true} or simply open) while keeping workspaceId={id},
currentBranchName={renameBranchTarget}, onOpenChange that calls
setRenameBranchTarget(null), and onAfterRename={handleAfterBranchRename}.
apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceContextMenu.tsx (1)

258-267: 冗長な open プロップ条件

renameBranchTarget && の条件ブロック内では、renameBranchTarget は常に truthy なので、open={renameBranchTarget !== null} は常に true となります。シンプルに open={true} または open プロップを renameBranchTarget の条件で制御する方が明確です。

♻️ 提案する修正
 			{renameBranchTarget && (
 				<RenameBranchDialog
 					workspaceId={id}
 					currentBranchName={renameBranchTarget}
-					open={renameBranchTarget !== null}
+					open
 					onOpenChange={(open) => {
 						if (!open) setRenameBranchTarget(null);
 					}}
 				/>
 			)}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceContextMenu.tsx`
around lines 258 - 267, 現在のコードでは外側の条件レンダリングと open={renameBranchTarget !== null}
が重複しているので、冗長さを解消してください:Remove the surrounding conditional render (the
"renameBranchTarget && (...)" check) and instead render RenameBranchDialog
unconditionally but control visibility via the open prop set to
renameBranchTarget !== null; keep workspaceId={id},
currentBranchName={renameBranchTarget} and the onOpenChange handler as-is so
closing clears renameBranchTarget. Use the RenameBranchDialog component and the
renameBranchTarget/open/onOpenChange symbols to locate and update the code.
apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/CollapsedWorkspaceItem.tsx (1)

184-193: 冗長な open プロップ条件(WorkspaceContextMenu.tsx と同様)

renameBranchTarget && ブロック内での open={renameBranchTarget !== null} は常に true になります。

♻️ 提案する修正
 			{renameBranchTarget && (
 				<RenameBranchDialog
 					workspaceId={id}
 					currentBranchName={renameBranchTarget}
-					open={renameBranchTarget !== null}
+					open
 					onOpenChange={(open) => {
 						if (!open) setRenameBranchTarget(null);
 					}}
 				/>
 			)}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/CollapsedWorkspaceItem.tsx`
around lines 184 - 193, 表示ブロックが既に renameBranchTarget && でガードされているため
RenameBranchDialog の open に渡している open={renameBranchTarget !== null}
は冗長です;RenameBranchDialog を表示するブロック内で open を常に true にする(例: open={true} または 単に
open を渡す)か open プロップ自体を削除してコンポーネント側の表示制御に委ね、現在の onOpenChange={(open) => { if
(!open) setRenameBranchTarget(null); }} は維持して renameBranchTarget と
setRenameBranchTarget によるクローズ時のリセット挙動を保ってください。
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceContextMenu/DashboardSidebarWorkspaceContextMenu.tsx (1)

27-27: 深い相対 import ではなく alias import に寄せてください。

このファイルはすでに renderer/... を使っているので、ここも同じ形にしておくと移動・分割時に壊れにくくなります。As per coding guidelines, apps/desktop/**/*.{ts,tsx}: Use aliases as defined in tsconfig.json when possible.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceContextMenu/DashboardSidebarWorkspaceContextMenu.tsx`
at line 27, The import in DashboardSidebarWorkspaceContextMenu.tsx uses a deep
relative path; replace the relative import of useDashboardSidebarHover with the
project alias path (use the existing renderer/... style used elsewhere in this
file) so it reads the aliased module import instead of
"../../../../providers/DashboardSidebarHoverProvider"; update the import
statement that brings in useDashboardSidebarHover to use the tsconfig-defined
alias to keep moves/splits safe and consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/RenameBranchDialog/RenameBranchDialog.tsx`:
- Around line 46-80: The submit flow in handleSubmit creates the renameBranch
mutation before setting the isSubmitting guard, allowing race conditions; fix by
placing a synchronous guard and setting setIsSubmitting(true) immediately after
verifying !isSubmitting and before calling client.git.renameBranch.mutate so
further clicks are blocked, then proceed to create renamePromise, call
toast.promise, await it, call onAfterRename and invalidate caches, and finally
clear setIsSubmitting(false) in the existing finally block; reference
handleSubmit, isSubmitting, setIsSubmitting, client.git.renameBranch.mutate and
toast.promise when making the change.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/WorkspaceHoverCard/WorkspaceHoverCard.tsx`:
- Around line 107-120: ブランチ名を URL エンコードしていないため "#" や "/" などを含む有効な ref が GitHub
リンクを壊す問題があります。WorkspaceHoverCard の該当箇所で href を組み立てている部分(参照シンボル: repoUrl,
branchName, branchExistsOnRemote)を修正し、パス部分に branchName を埋め込む際は必ず
encodeURIComponent(branchName) を使ってエンコードしてから `${repoUrl}/tree/...`
を生成するようにしてください(onClick の stopPropagation など既存の挙動は維持)。

---

Nitpick comments:
In `@apps/desktop/src/renderer/lib/dev-chat.ts`:
- Around line 26-30: The model list defined inline in
apps/desktop/src/renderer/lib/dev-chat.ts (e.g., the entry with id
"openai/gpt-5.5") is duplicated in packages/trpc/src/router/chat/chat.ts;
extract the canonical model list into a shared constant/module (for example a
new exported array like SUPPORTED_MODELS in a shared package or utils module)
and replace the inline arrays in both dev-chat.ts and chat.ts with imports from
that single source, or alternatively expose the server-side list via the chat
router and have dev-chat consume it; update imports and types so both files
reference the same identifier (e.g., SUPPORTED_MODELS) to prevent future drift.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx`:
- Around line 291-299: In DashboardSidebarExpandedWorkspaceRow update the
onKeyDown handler(s) to use the modern space key value: replace the legacy check
event.key === "Spacebar" with the single-space string (" ") — or, if you want to
keep backward compatibility, keep both checks but prefer the " " check first;
locate the onKeyDown prop in the DashboardSidebarExpandedWorkspaceRow component
(also adjust the other similar onKeyDown occurrence in the same component) and
ensure the handler still calls event.stopPropagation() for Enter and Space.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceContextMenu/DashboardSidebarWorkspaceContextMenu.tsx`:
- Line 27: The import in DashboardSidebarWorkspaceContextMenu.tsx uses a deep
relative path; replace the relative import of useDashboardSidebarHover with the
project alias path (use the existing renderer/... style used elsewhere in this
file) so it reads the aliased module import instead of
"../../../../providers/DashboardSidebarHoverProvider"; update the import
statement that brings in useDashboardSidebarHover to use the tsconfig-defined
alias to keep moves/splits safe and consistent.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceHoverCardContent/DashboardSidebarWorkspaceHoverCardContent.tsx`:
- Around line 71-79: Replace the template-literal className on the button in
DashboardSidebarWorkspaceHoverCardContent with the project's cn() utility to
match other components; update the button element that calls
onEditBranchClick(branch) to build classes via cn("group/branch flex min-w-0
flex-1 items-center gap-1 font-mono break-all text-left hover:text-foreground
hover:underline", hasCustomAlias ? "text-xs" : "text-sm",
"group-hover/branch:opacity-100 transition-opacity") so conditional classes are
handled consistently with the rest of the codebase.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx`:
- Around line 100-103: The useMemo that computes hoverPayload currently lists
only workspace in its dependency array; update the dependency array for the
useMemo call that creates hoverPayload to also include the state setter
setRenameBranchTarget so the intent is explicit (hoverPayload -> useMemo(() =>
({ workspace, onEditBranchClick: setRenameBranchTarget }), [workspace,
setRenameBranchTarget])) while keeping the same returned object shape
referencing workspace and setRenameBranchTarget.
- Around line 275-285: 現在のコード renders <RenameBranchDialog> only when
renameBranchTarget is truthy but also passes open={renameBranchTarget !== null},
which is redundant; change the usage to either always render the dialog and
control visibility via the open prop (e.g., open={renameBranchTarget !== null})
or, simpler, keep conditional rendering and set open to true (or omit the open
prop) so the dialog doesn't receive a duplicate condition; apply the same fix to
the expanded view variant—update occurrences around RenameBranchDialog,
renameBranchTarget, setRenameBranchTarget, and handleAfterBranchRename to remove
the redundant open={renameBranchTarget !== null} check.
- Around line 195-205: The conditional render uses both "renameBranchTarget &&"
and "open={renameBranchTarget !== null}", which is redundant because the
component is only rendered when renameBranchTarget is truthy; simplify by
removing the redundant runtime check in the prop: keep the conditional render
"renameBranchTarget && <RenameBranchDialog ... />" and change the open prop to a
constant true (e.g., open={true} or simply open) while keeping workspaceId={id},
currentBranchName={renameBranchTarget}, onOpenChange that calls
setRenameBranchTarget(null), and onAfterRename={handleAfterBranchRename}.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/CollapsedWorkspaceItem.tsx`:
- Around line 184-193: 表示ブロックが既に renameBranchTarget && でガードされているため
RenameBranchDialog の open に渡している open={renameBranchTarget !== null}
は冗長です;RenameBranchDialog を表示するブロック内で open を常に true にする(例: open={true} または 単に
open を渡す)か open プロップ自体を削除してコンポーネント側の表示制御に委ね、現在の onOpenChange={(open) => { if
(!open) setRenameBranchTarget(null); }} は維持して renameBranchTarget と
setRenameBranchTarget によるクローズ時のリセット挙動を保ってください。

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceContextMenu.tsx`:
- Around line 258-267: 現在のコードでは外側の条件レンダリングと open={renameBranchTarget !== null}
が重複しているので、冗長さを解消してください:Remove the surrounding conditional render (the
"renameBranchTarget && (...)" check) and instead render RenameBranchDialog
unconditionally but control visibility via the open prop set to
renameBranchTarget !== null; keep workspaceId={id},
currentBranchName={renameBranchTarget} and the onOpenChange handler as-is so
closing clears renameBranchTarget. Use the RenameBranchDialog component and the
renameBranchTarget/open/onOpenChange symbols to locate and update the code.

In `@apps/relay/fly.toml`:
- Line 31: Change is approved: the deployment memory setting was increased to
memory = "4gb"; merge the change (keep the memory key set to "4gb") and deploy,
then monitor runtime memory metrics and logs post-deploy to confirm the increase
resolves the relay OOM/deployment issues and be prepared to adjust or roll back
the memory value if abnormal behavior or cost concerns arise.
🪄 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: CHILL

Plan: Pro

Run ID: 86491507-d326-4147-905d-f3ad8009c56c

📥 Commits

Reviewing files that changed from the base of the PR and between f805acd and 556a036.

📒 Files selected for processing (36)
  • apps/desktop/src/renderer/globals.css
  • apps/desktop/src/renderer/lib/dev-chat.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/DashboardSidebar.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHoverCardOverlay/DashboardSidebarHoverCardOverlay.css
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHoverCardOverlay/DashboardSidebarHoverCardOverlay.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHoverCardOverlay/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarPortsList/components/DashboardSidebarPortGroup/DashboardSidebarPortGroup.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarCollapsedWorkspaceButton/DashboardSidebarCollapsedWorkspaceButton.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceContextMenu/DashboardSidebarWorkspaceContextMenu.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceHoverCardContent/DashboardSidebarWorkspaceHoverCardContent.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/providers/DashboardSidebarHoverProvider/DashboardSidebarHoverProvider.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/providers/DashboardSidebarHoverProvider/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/CollapsedWorkspaceItem.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/RenameBranchDialog/RenameBranchDialog.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/RenameBranchDialog/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/WorkspaceHoverCard/WorkspaceHoverCard.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/index.ts
  • apps/relay/Dockerfile
  • apps/relay/fly.toml
  • packages/panes/src/core/store/store.test.ts
  • packages/panes/src/core/store/store.ts
  • packages/panes/src/react/components/Workspace/Workspace.tsx
  • packages/panes/src/react/components/Workspace/components/TabBar/TabBar.tsx
  • packages/panes/src/react/components/Workspace/components/TabBar/components/TabItem/TabItem.tsx
  • packages/trpc/src/router/chat/chat.ts
  • packages/ui/package.json
  • packages/ui/src/components/overflow-fade/OverflowFadeContainer/OverflowFadeContainer.tsx
  • packages/ui/src/components/overflow-fade/OverflowFadeContainer/index.ts
  • packages/ui/src/components/overflow-fade/OverflowFadeText/OverflowFadeText.tsx
  • packages/ui/src/components/overflow-fade/OverflowFadeText/index.ts
  • packages/ui/src/components/overflow-fade/fade-edge.css
  • packages/ui/src/hooks/use-overflow-fade.ts
💤 Files with no reviewable changes (2)
  • packages/ui/src/components/overflow-fade/fade-edge.css
  • apps/desktop/src/renderer/globals.css

Comment on lines +46 to +80
const handleSubmit = async () => {
if (isInvalid || isSubmitting) return;
if (!activeHostUrl) {
toast.error("Host service is not available");
return;
}

const client = getHostServiceClientByUrl(activeHostUrl);
const renamePromise = client.git.renameBranch.mutate({
workspaceId,
oldName: currentBranchName,
newName: trimmed,
});

toast.promise(renamePromise, {
loading: `Renaming branch to ${trimmed}...`,
success: `Branch renamed to ${trimmed}`,
error: (err) =>
err instanceof Error ? err.message : "Failed to rename branch",
});

setIsSubmitting(true);
try {
await renamePromise;
onAfterRename?.(trimmed);
void electronUtils.workspaces.getWorktreeInfo.invalidate({
workspaceId,
});
void electronUtils.workspaces.get.invalidate({ id: workspaceId });
void electronUtils.workspaces.getAllGrouped.invalidate();
onOpenChange(false);
} catch {
// toast.promise surfaced the error to the user
} finally {
setIsSubmitting(false);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

重複送信を防ぐ同期ガードが不足しています。

Line [67] で isSubmitting を立てる前に mutation を生成しているため、素早い連打で renameBranch が二重送信される余地があります。非冪等操作なので送信前に同期的なガードを置いてください。

修正案(同期ガード追加)
-import { useEffect, useState } from "react";
+import { useEffect, useRef, useState } from "react";
@@
 	const [value, setValue] = useState(currentBranchName);
 	const [isSubmitting, setIsSubmitting] = useState(false);
+	const isSubmittingRef = useRef(false);
@@
 	const handleSubmit = async () => {
-		if (isInvalid || isSubmitting) return;
+		if (isInvalid || isSubmittingRef.current) return;
 		if (!activeHostUrl) {
 			toast.error("Host service is not available");
 			return;
 		}
 
+		isSubmittingRef.current = true;
+		setIsSubmitting(true);
 		const client = getHostServiceClientByUrl(activeHostUrl);
 		const renamePromise = client.git.renameBranch.mutate({
 			workspaceId,
 			oldName: currentBranchName,
 			newName: trimmed,
 		});
@@
-		setIsSubmitting(true);
 		try {
 			await renamePromise;
@@
 		} finally {
+			isSubmittingRef.current = false;
 			setIsSubmitting(false);
 		}
 	};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/RenameBranchDialog/RenameBranchDialog.tsx`
around lines 46 - 80, The submit flow in handleSubmit creates the renameBranch
mutation before setting the isSubmitting guard, allowing race conditions; fix by
placing a synchronous guard and setting setIsSubmitting(true) immediately after
verifying !isSubmitting and before calling client.git.renameBranch.mutate so
further clicks are blocked, then proceed to create renamePromise, call
toast.promise, await it, call onAfterRename and invalidate caches, and finally
clear setIsSubmitting(false) in the existing finally block; reference
handleSubmit, isSubmitting, setIsSubmitting, client.git.renameBranch.mutate and
toast.promise when making the change.

Comment on lines +107 to +120
{repoUrl && branchExistsOnRemote && (
<a
href={`${repoUrl}/tree/${branchName}`}
target="_blank"
rel="noopener noreferrer"
className="shrink-0 text-muted-foreground hover:text-foreground"
title="Open branch on GitHub"
onClick={(e) => e.stopPropagation()}
>
<LuExternalLink
className="size-3"
strokeWidth={STROKE_WIDTH}
/>
</a>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

ブランチ名は URL エンコードしてから href を組み立ててください。

いまの文字列結合だと、# などの予約文字を含む有効な ref 名で GitHub リンクが途中で壊れます。

修正例
-									href={`${repoUrl}/tree/${branchName}`}
+									href={`${repoUrl}/tree/${encodeURIComponent(branchName)}`}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{repoUrl && branchExistsOnRemote && (
<a
href={`${repoUrl}/tree/${branchName}`}
target="_blank"
rel="noopener noreferrer"
className="shrink-0 text-muted-foreground hover:text-foreground"
title="Open branch on GitHub"
onClick={(e) => e.stopPropagation()}
>
<LuExternalLink
className="size-3"
strokeWidth={STROKE_WIDTH}
/>
</a>
{repoUrl && branchExistsOnRemote && (
<a
href={`${repoUrl}/tree/${encodeURIComponent(branchName)}`}
target="_blank"
rel="noopener noreferrer"
className="shrink-0 text-muted-foreground hover:text-foreground"
title="Open branch on GitHub"
onClick={(e) => e.stopPropagation()}
>
<LuExternalLink
className="size-3"
strokeWidth={STROKE_WIDTH}
/>
</a>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/WorkspaceHoverCard/WorkspaceHoverCard.tsx`
around lines 107 - 120, ブランチ名を URL エンコードしていないため "#" や "/" などを含む有効な ref が GitHub
リンクを壊す問題があります。WorkspaceHoverCard の該当箇所で href を組み立てている部分(参照シンボル: repoUrl,
branchName, branchExistsOnRemote)を修正し、パス部分に branchName を埋め込む際は必ず
encodeURIComponent(branchName) を使ってエンコードしてから `${repoUrl}/tree/...`
を生成するようにしてください(onClick の stopPropagation など既存の挙動は維持)。

@MocA-Love MocA-Love merged commit 1a6cbf9 into main Apr 28, 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