diff --git a/CHANGELOG.md b/CHANGELOG.md
index c45e52f..1543ed9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,7 +8,8 @@
### Changed
- 聊天面板(PR Agent)内部重构:2578 行的单文件 `ChatPane.tsx` 按「容器 / 领域组件 / hooks / 工具方法」分层拆分到 `components/chat/`,状态与生命周期、业务动作、时间线归并各自成 hook,展示组件与工具方法独立成文件。对外接口与界面行为保持不变,仅改善可维护性;token 用量 ↑/↓ 的绿红色值一并从内联样式收进设计令牌与样式类。
-- 首启向导内部重构:`OnboardingWizard.tsx` 的四个步骤组件(欢迎 / 平台 / LLM / 完成)拆分到 `onboarding/steps/` 各自成文件,容器只留向导骨架(步骤指示 + 切换 + 导航)。对外接口与界面行为不变。
+- 首启向导内部重构:`OnboardingWizard.tsx` 的四个步骤组件(欢迎 / 平台 / LLM / 完成)拆分到 `steps/` 各自成文件,容器只留向导骨架(步骤指示 + 切换 + 导航)。对外接口与界面行为不变。
+- `components/` 目录按职责重组:扁平堆叠的组件归入三类——`common/`(基础公共 UI)、`layout/`(应用骨架)、`features/`(业务领域:pr / diff / comments / drafts / settings / chat / onboarding),顶层只剩这三个桶。纯文件位置调整 + import 路径改写,无逻辑 / 界面变更。
### Fixed
diff --git a/apps/desktop/src/renderer/src/App.tsx b/apps/desktop/src/renderer/src/App.tsx
index 03d7e92..4259f41 100644
--- a/apps/desktop/src/renderer/src/App.tsx
+++ b/apps/desktop/src/renderer/src/App.tsx
@@ -13,16 +13,16 @@ import type {
UpdateCheckResult,
} from '@meebox/shared';
import { invoke, subscribe } from './api';
-import { ChatPane, CHAT_MAX_WIDTH, CHAT_MIN_WIDTH } from './components/chat';
+import { ChatPane, CHAT_MAX_WIDTH, CHAT_MIN_WIDTH } from './components/features/chat';
import { wireChatRunStore } from './stores/chat-run-store';
import { wireDraftsStore } from './stores/drafts-store';
import { wireRepoSyncStore } from './stores/repo-sync-store';
-import { MainPane } from './components/MainPane';
-import { OnboardingWizard, type OnboardingResult } from './components/onboarding/OnboardingWizard';
-import { SettingsModal } from './components/SettingsModal';
-import { Sidebar, SIDEBAR_MAX_WIDTH, SIDEBAR_MIN_WIDTH } from './components/Sidebar';
-import { StatusBar } from './components/StatusBar';
-import { TitleBar } from './components/TitleBar';
+import { MainPane } from './components/layout/MainPane';
+import { OnboardingWizard, type OnboardingResult } from './components/features/onboarding/OnboardingWizard';
+import { SettingsModal } from './components/features/settings/SettingsModal';
+import { Sidebar, SIDEBAR_MAX_WIDTH, SIDEBAR_MIN_WIDTH } from './components/layout/Sidebar';
+import { StatusBar } from './components/layout/StatusBar';
+import { TitleBar } from './components/layout/TitleBar';
interface BootstrapState {
info: AppInfo;
diff --git a/apps/desktop/src/renderer/src/components/Avatar.tsx b/apps/desktop/src/renderer/src/components/common/Avatar.tsx
similarity index 99%
rename from apps/desktop/src/renderer/src/components/Avatar.tsx
rename to apps/desktop/src/renderer/src/components/common/Avatar.tsx
index 59e5471..f8fbc1d 100644
--- a/apps/desktop/src/renderer/src/components/Avatar.tsx
+++ b/apps/desktop/src/renderer/src/components/common/Avatar.tsx
@@ -1,5 +1,5 @@
import { useEffect, useState } from 'react';
-import { invoke } from '../api';
+import { invoke } from '../../api';
interface AvatarProps {
connectionId: string;
diff --git a/apps/desktop/src/renderer/src/components/BitbucketImage.tsx b/apps/desktop/src/renderer/src/components/common/BitbucketImage.tsx
similarity index 99%
rename from apps/desktop/src/renderer/src/components/BitbucketImage.tsx
rename to apps/desktop/src/renderer/src/components/common/BitbucketImage.tsx
index dc5ef78..9ff3dec 100644
--- a/apps/desktop/src/renderer/src/components/BitbucketImage.tsx
+++ b/apps/desktop/src/renderer/src/components/common/BitbucketImage.tsx
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
import { useTranslation } from 'react-i18next';
-import { invoke } from '../api';
+import { invoke } from '../../api';
/**
* react-markdown 默认 url sanitize 只允许 http/https/mailto/tel 协议,
diff --git a/apps/desktop/src/renderer/src/components/ConfirmModal.tsx b/apps/desktop/src/renderer/src/components/common/ConfirmModal.tsx
similarity index 100%
rename from apps/desktop/src/renderer/src/components/ConfirmModal.tsx
rename to apps/desktop/src/renderer/src/components/common/ConfirmModal.tsx
diff --git a/apps/desktop/src/renderer/src/components/ErrorBoundary.tsx b/apps/desktop/src/renderer/src/components/common/ErrorBoundary.tsx
similarity index 100%
rename from apps/desktop/src/renderer/src/components/ErrorBoundary.tsx
rename to apps/desktop/src/renderer/src/components/common/ErrorBoundary.tsx
diff --git a/apps/desktop/src/renderer/src/components/LlmProviderIcon.tsx b/apps/desktop/src/renderer/src/components/common/LlmProviderIcon.tsx
similarity index 100%
rename from apps/desktop/src/renderer/src/components/LlmProviderIcon.tsx
rename to apps/desktop/src/renderer/src/components/common/LlmProviderIcon.tsx
diff --git a/apps/desktop/src/renderer/src/components/Loading.tsx b/apps/desktop/src/renderer/src/components/common/Loading.tsx
similarity index 100%
rename from apps/desktop/src/renderer/src/components/Loading.tsx
rename to apps/desktop/src/renderer/src/components/common/Loading.tsx
diff --git a/apps/desktop/src/renderer/src/components/MermaidDiagram.tsx b/apps/desktop/src/renderer/src/components/common/MermaidDiagram.tsx
similarity index 100%
rename from apps/desktop/src/renderer/src/components/MermaidDiagram.tsx
rename to apps/desktop/src/renderer/src/components/common/MermaidDiagram.tsx
diff --git a/apps/desktop/src/renderer/src/components/PlatformIcon.tsx b/apps/desktop/src/renderer/src/components/common/PlatformIcon.tsx
similarity index 100%
rename from apps/desktop/src/renderer/src/components/PlatformIcon.tsx
rename to apps/desktop/src/renderer/src/components/common/PlatformIcon.tsx
diff --git a/apps/desktop/src/renderer/src/components/icons.tsx b/apps/desktop/src/renderer/src/components/common/icons.tsx
similarity index 100%
rename from apps/desktop/src/renderer/src/components/icons.tsx
rename to apps/desktop/src/renderer/src/components/common/icons.tsx
diff --git a/apps/desktop/src/renderer/src/components/markdownMermaid.tsx b/apps/desktop/src/renderer/src/components/common/markdownMermaid.tsx
similarity index 100%
rename from apps/desktop/src/renderer/src/components/markdownMermaid.tsx
rename to apps/desktop/src/renderer/src/components/common/markdownMermaid.tsx
diff --git a/apps/desktop/src/renderer/src/components/chat/ChatPane.tsx b/apps/desktop/src/renderer/src/components/features/chat/ChatPane.tsx
similarity index 98%
rename from apps/desktop/src/renderer/src/components/chat/ChatPane.tsx
rename to apps/desktop/src/renderer/src/components/features/chat/ChatPane.tsx
index d6ac6c6..8fc8c40 100644
--- a/apps/desktop/src/renderer/src/components/chat/ChatPane.tsx
+++ b/apps/desktop/src/renderer/src/components/features/chat/ChatPane.tsx
@@ -1,11 +1,11 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { LocalPrStatus, PrAgentStatus, StoredPullRequest } from '@meebox/shared';
-import { ChatIcon, TrashIcon } from '../icons';
-import { ConfirmModal } from '../ConfirmModal';
-import { PaneLoading } from '../Loading';
-import { useChatRunStore } from '../../stores/chat-run-store';
-import { useDraftsForPr } from '../../stores/drafts-store';
+import { ChatIcon, TrashIcon } from '../../common/icons';
+import { ConfirmModal } from '../../common/ConfirmModal';
+import { PaneLoading } from '../../common/Loading';
+import { useChatRunStore } from '../../../stores/chat-run-store';
+import { useDraftsForPr } from '../../../stores/drafts-store';
import { CHAT_MAX_WIDTH, CHAT_MIN_WIDTH } from './constants';
import { useChatSession } from './hooks/useChatSession';
import { useChatActions } from './hooks/useChatActions';
diff --git a/apps/desktop/src/renderer/src/components/chat/commands.ts b/apps/desktop/src/renderer/src/components/features/chat/commands.ts
similarity index 100%
rename from apps/desktop/src/renderer/src/components/chat/commands.ts
rename to apps/desktop/src/renderer/src/components/features/chat/commands.ts
diff --git a/apps/desktop/src/renderer/src/components/chat/components/AgentStep.tsx b/apps/desktop/src/renderer/src/components/features/chat/components/AgentStep.tsx
similarity index 98%
rename from apps/desktop/src/renderer/src/components/chat/components/AgentStep.tsx
rename to apps/desktop/src/renderer/src/components/features/chat/components/AgentStep.tsx
index 1aa1c7e..1c3c8d6 100644
--- a/apps/desktop/src/renderer/src/components/chat/components/AgentStep.tsx
+++ b/apps/desktop/src/renderer/src/components/features/chat/components/AgentStep.tsx
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { AgentStep } from '@meebox/shared';
-import { RobotIcon } from '../../icons';
+import { RobotIcon } from '../../../common/icons';
import { formatElapsed, formatTokens } from '../utils/format';
import { Spinner } from './shared';
diff --git a/apps/desktop/src/renderer/src/components/chat/components/ChatEmpty.tsx b/apps/desktop/src/renderer/src/components/features/chat/components/ChatEmpty.tsx
similarity index 98%
rename from apps/desktop/src/renderer/src/components/chat/components/ChatEmpty.tsx
rename to apps/desktop/src/renderer/src/components/features/chat/components/ChatEmpty.tsx
index 7be5fd1..f3d351d 100644
--- a/apps/desktop/src/renderer/src/components/chat/components/ChatEmpty.tsx
+++ b/apps/desktop/src/renderer/src/components/features/chat/components/ChatEmpty.tsx
@@ -1,6 +1,6 @@
import { useTranslation } from 'react-i18next';
import type { PrAgentStatus, StoredPullRequest } from '@meebox/shared';
-import { ChatIcon } from '../../icons';
+import { ChatIcon } from '../../../common/icons';
import { Bullet } from './shared';
export function ChatEmpty({
diff --git a/apps/desktop/src/renderer/src/components/chat/components/ChatInputBar.tsx b/apps/desktop/src/renderer/src/components/features/chat/components/ChatInputBar.tsx
similarity index 99%
rename from apps/desktop/src/renderer/src/components/chat/components/ChatInputBar.tsx
rename to apps/desktop/src/renderer/src/components/features/chat/components/ChatInputBar.tsx
index adffc79..2616b37 100644
--- a/apps/desktop/src/renderer/src/components/chat/components/ChatInputBar.tsx
+++ b/apps/desktop/src/renderer/src/components/features/chat/components/ChatInputBar.tsx
@@ -1,7 +1,7 @@
import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { LocalPrStatus, PrAgentStatus, ReviewRunTool, StoredPullRequest } from '@meebox/shared';
-import { AutoReviewIcon, SendIcon, StopIcon } from '../../icons';
+import { AutoReviewIcon, SendIcon, StopIcon } from '../../../common/icons';
import { COMMANDS, type CommandSpec } from '../commands';
import { loadChatHistory, pushChatHistory } from '../utils/chat-history';
diff --git a/apps/desktop/src/renderer/src/components/chat/components/ConversationMessage.tsx b/apps/desktop/src/renderer/src/components/features/chat/components/ConversationMessage.tsx
similarity index 97%
rename from apps/desktop/src/renderer/src/components/chat/components/ConversationMessage.tsx
rename to apps/desktop/src/renderer/src/components/features/chat/components/ConversationMessage.tsx
index 35747db..54a06e6 100644
--- a/apps/desktop/src/renderer/src/components/chat/components/ConversationMessage.tsx
+++ b/apps/desktop/src/renderer/src/components/features/chat/components/ConversationMessage.tsx
@@ -1,6 +1,6 @@
import { useTranslation } from 'react-i18next';
import type { AgentMessage } from '@meebox/shared';
-import { ChatIcon } from '../../icons';
+import { ChatIcon } from '../../../common/icons';
import { VERDICT_LABEL_KEY } from '../constants';
import { Md } from './shared';
diff --git a/apps/desktop/src/renderer/src/components/chat/components/FindingCard.tsx b/apps/desktop/src/renderer/src/components/features/chat/components/FindingCard.tsx
similarity index 98%
rename from apps/desktop/src/renderer/src/components/chat/components/FindingCard.tsx
rename to apps/desktop/src/renderer/src/components/features/chat/components/FindingCard.tsx
index 8f9161f..e8d325b 100644
--- a/apps/desktop/src/renderer/src/components/chat/components/FindingCard.tsx
+++ b/apps/desktop/src/renderer/src/components/features/chat/components/FindingCard.tsx
@@ -4,10 +4,10 @@ import ReactMarkdown from 'react-markdown';
import remarkBreaks from 'remark-breaks';
import remarkGfm from 'remark-gfm';
import type { Finding, PrDocSectionKey, ReviewDraft } from '@meebox/shared';
-import { ChevronIcon } from '../../icons';
-import { mermaidComponents, walkthroughMdComponents } from '../../markdownMermaid';
-import { REMOTE_REHYPE_PLUGINS } from '../../../markdown';
-import { translatePrAgentLabels } from '../../../utils/translate-pr-agent';
+import { ChevronIcon } from '../../../common/icons';
+import { mermaidComponents, walkthroughMdComponents } from '../../../common/markdownMermaid';
+import { REMOTE_REHYPE_PLUGINS } from '../../../../markdown';
+import { translatePrAgentLabels } from '../../../../utils/translate-pr-agent';
import {
pillStyle,
sectionLabel,
diff --git a/apps/desktop/src/renderer/src/components/chat/components/QueuedView.tsx b/apps/desktop/src/renderer/src/components/features/chat/components/QueuedView.tsx
similarity index 96%
rename from apps/desktop/src/renderer/src/components/chat/components/QueuedView.tsx
rename to apps/desktop/src/renderer/src/components/features/chat/components/QueuedView.tsx
index 17fd2b4..2319e28 100644
--- a/apps/desktop/src/renderer/src/components/chat/components/QueuedView.tsx
+++ b/apps/desktop/src/renderer/src/components/features/chat/components/QueuedView.tsx
@@ -1,7 +1,7 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { ReviewRunTool } from '@meebox/shared';
-import { CloseIcon } from '../../icons';
+import { CloseIcon } from '../../../common/icons';
import { AskQuestion } from './shared';
/**
diff --git a/apps/desktop/src/renderer/src/components/chat/components/RulePreviewModal.tsx b/apps/desktop/src/renderer/src/components/features/chat/components/RulePreviewModal.tsx
similarity index 92%
rename from apps/desktop/src/renderer/src/components/chat/components/RulePreviewModal.tsx
rename to apps/desktop/src/renderer/src/components/features/chat/components/RulePreviewModal.tsx
index 2ea7fe0..ce57d3b 100644
--- a/apps/desktop/src/renderer/src/components/chat/components/RulePreviewModal.tsx
+++ b/apps/desktop/src/renderer/src/components/features/chat/components/RulePreviewModal.tsx
@@ -2,8 +2,8 @@ import { useTranslation } from 'react-i18next';
import ReactMarkdown from 'react-markdown';
import remarkBreaks from 'remark-breaks';
import remarkGfm from 'remark-gfm';
-import { mermaidComponents } from '../../markdownMermaid';
-import { REMOTE_REHYPE_PLUGINS } from '../../../markdown';
+import { mermaidComponents } from '../../../common/markdownMermaid';
+import { REMOTE_REHYPE_PLUGINS } from '../../../../markdown';
import type { MatchedRule } from '../types';
export function RulePreviewModal({
diff --git a/apps/desktop/src/renderer/src/components/chat/components/RunResultView.tsx b/apps/desktop/src/renderer/src/components/features/chat/components/RunResultView.tsx
similarity index 99%
rename from apps/desktop/src/renderer/src/components/chat/components/RunResultView.tsx
rename to apps/desktop/src/renderer/src/components/features/chat/components/RunResultView.tsx
index 81717f5..83e7f25 100644
--- a/apps/desktop/src/renderer/src/components/chat/components/RunResultView.tsx
+++ b/apps/desktop/src/renderer/src/components/features/chat/components/RunResultView.tsx
@@ -1,7 +1,7 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { Finding, ReviewDraft, ReviewRun } from '@meebox/shared';
-import { RetryIcon } from '../../icons';
+import { RetryIcon } from '../../../common/icons';
import { orderFindings } from '../utils/findings';
import { formatStartTime, formatTokens, runStatusLabel } from '../utils/format';
import { extractTokenUsage, type TokenUsage } from '../utils/tokens';
diff --git a/apps/desktop/src/renderer/src/components/chat/components/RunningView.tsx b/apps/desktop/src/renderer/src/components/features/chat/components/RunningView.tsx
similarity index 100%
rename from apps/desktop/src/renderer/src/components/chat/components/RunningView.tsx
rename to apps/desktop/src/renderer/src/components/features/chat/components/RunningView.tsx
diff --git a/apps/desktop/src/renderer/src/components/chat/components/shared.tsx b/apps/desktop/src/renderer/src/components/features/chat/components/shared.tsx
similarity index 92%
rename from apps/desktop/src/renderer/src/components/chat/components/shared.tsx
rename to apps/desktop/src/renderer/src/components/features/chat/components/shared.tsx
index e6a2b2a..1a4b173 100644
--- a/apps/desktop/src/renderer/src/components/chat/components/shared.tsx
+++ b/apps/desktop/src/renderer/src/components/features/chat/components/shared.tsx
@@ -3,10 +3,10 @@ import { useTranslation } from 'react-i18next';
import ReactMarkdown from 'react-markdown';
import remarkBreaks from 'remark-breaks';
import remarkGfm from 'remark-gfm';
-import { QuestionIcon } from '../../icons';
-import { mermaidComponents } from '../../markdownMermaid';
-import { REMOTE_REHYPE_PLUGINS } from '../../../markdown';
-import { parseAnsi, segmentStyle } from '../../../utils/ansi';
+import { QuestionIcon } from '../../../common/icons';
+import { mermaidComponents } from '../../../common/markdownMermaid';
+import { REMOTE_REHYPE_PLUGINS } from '../../../../markdown';
+import { parseAnsi, segmentStyle } from '../../../../utils/ansi';
export function Spinner() {
return ;
diff --git a/apps/desktop/src/renderer/src/components/chat/constants.ts b/apps/desktop/src/renderer/src/components/features/chat/constants.ts
similarity index 100%
rename from apps/desktop/src/renderer/src/components/chat/constants.ts
rename to apps/desktop/src/renderer/src/components/features/chat/constants.ts
diff --git a/apps/desktop/src/renderer/src/components/chat/hooks/useChatActions.ts b/apps/desktop/src/renderer/src/components/features/chat/hooks/useChatActions.ts
similarity index 99%
rename from apps/desktop/src/renderer/src/components/chat/hooks/useChatActions.ts
rename to apps/desktop/src/renderer/src/components/features/chat/hooks/useChatActions.ts
index 0178073..849a05b 100644
--- a/apps/desktop/src/renderer/src/components/chat/hooks/useChatActions.ts
+++ b/apps/desktop/src/renderer/src/components/features/chat/hooks/useChatActions.ts
@@ -11,7 +11,7 @@ import type {
ReviewRunTool,
StoredPullRequest,
} from '@meebox/shared';
-import { invoke } from '../../../api';
+import { invoke } from '../../../../api';
import { htmlInlineToMarkdown, stripFindingMarker } from '../utils/findings';
interface UseChatActionsParams {
diff --git a/apps/desktop/src/renderer/src/components/chat/hooks/useChatSession.ts b/apps/desktop/src/renderer/src/components/features/chat/hooks/useChatSession.ts
similarity index 99%
rename from apps/desktop/src/renderer/src/components/chat/hooks/useChatSession.ts
rename to apps/desktop/src/renderer/src/components/features/chat/hooks/useChatSession.ts
index 9e8829e..cdf292c 100644
--- a/apps/desktop/src/renderer/src/components/chat/hooks/useChatSession.ts
+++ b/apps/desktop/src/renderer/src/components/features/chat/hooks/useChatSession.ts
@@ -1,6 +1,6 @@
import { useEffect, useRef, useState, type MutableRefObject } from 'react';
import type { AgentMessage, AgentStep, ReviewRun } from '@meebox/shared';
-import { invoke, subscribe } from '../../../api';
+import { invoke, subscribe } from '../../../../api';
import { RUNS_PAGE_SIZE } from '../constants';
import type { MatchedRule } from '../types';
diff --git a/apps/desktop/src/renderer/src/components/chat/hooks/useChatTimeline.ts b/apps/desktop/src/renderer/src/components/features/chat/hooks/useChatTimeline.ts
similarity index 100%
rename from apps/desktop/src/renderer/src/components/chat/hooks/useChatTimeline.ts
rename to apps/desktop/src/renderer/src/components/features/chat/hooks/useChatTimeline.ts
diff --git a/apps/desktop/src/renderer/src/components/chat/index.ts b/apps/desktop/src/renderer/src/components/features/chat/index.ts
similarity index 100%
rename from apps/desktop/src/renderer/src/components/chat/index.ts
rename to apps/desktop/src/renderer/src/components/features/chat/index.ts
diff --git a/apps/desktop/src/renderer/src/components/chat/types.ts b/apps/desktop/src/renderer/src/components/features/chat/types.ts
similarity index 100%
rename from apps/desktop/src/renderer/src/components/chat/types.ts
rename to apps/desktop/src/renderer/src/components/features/chat/types.ts
diff --git a/apps/desktop/src/renderer/src/components/chat/utils/chat-history.ts b/apps/desktop/src/renderer/src/components/features/chat/utils/chat-history.ts
similarity index 100%
rename from apps/desktop/src/renderer/src/components/chat/utils/chat-history.ts
rename to apps/desktop/src/renderer/src/components/features/chat/utils/chat-history.ts
diff --git a/apps/desktop/src/renderer/src/components/chat/utils/findings.ts b/apps/desktop/src/renderer/src/components/features/chat/utils/findings.ts
similarity index 100%
rename from apps/desktop/src/renderer/src/components/chat/utils/findings.ts
rename to apps/desktop/src/renderer/src/components/features/chat/utils/findings.ts
diff --git a/apps/desktop/src/renderer/src/components/chat/utils/format.ts b/apps/desktop/src/renderer/src/components/features/chat/utils/format.ts
similarity index 100%
rename from apps/desktop/src/renderer/src/components/chat/utils/format.ts
rename to apps/desktop/src/renderer/src/components/features/chat/utils/format.ts
diff --git a/apps/desktop/src/renderer/src/components/chat/utils/tokens.ts b/apps/desktop/src/renderer/src/components/features/chat/utils/tokens.ts
similarity index 100%
rename from apps/desktop/src/renderer/src/components/chat/utils/tokens.ts
rename to apps/desktop/src/renderer/src/components/features/chat/utils/tokens.ts
diff --git a/apps/desktop/src/renderer/src/components/CommentEditEditor.tsx b/apps/desktop/src/renderer/src/components/features/comments/CommentEditEditor.tsx
similarity index 99%
rename from apps/desktop/src/renderer/src/components/CommentEditEditor.tsx
rename to apps/desktop/src/renderer/src/components/features/comments/CommentEditEditor.tsx
index e5ab58a..2b575ef 100644
--- a/apps/desktop/src/renderer/src/components/CommentEditEditor.tsx
+++ b/apps/desktop/src/renderer/src/components/features/comments/CommentEditEditor.tsx
@@ -1,6 +1,6 @@
import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
-import { invoke } from '../api';
+import { invoke } from '../../../api';
interface CommentEditEditorProps {
prLocalId: string;
diff --git a/apps/desktop/src/renderer/src/components/CommentReplyEditor.tsx b/apps/desktop/src/renderer/src/components/features/comments/CommentReplyEditor.tsx
similarity index 98%
rename from apps/desktop/src/renderer/src/components/CommentReplyEditor.tsx
rename to apps/desktop/src/renderer/src/components/features/comments/CommentReplyEditor.tsx
index 0deb1af..a2588fd 100644
--- a/apps/desktop/src/renderer/src/components/CommentReplyEditor.tsx
+++ b/apps/desktop/src/renderer/src/components/features/comments/CommentReplyEditor.tsx
@@ -1,6 +1,6 @@
import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
-import { invoke } from '../api';
+import { invoke } from '../../../api';
interface CommentReplyEditorProps {
prLocalId: string;
diff --git a/apps/desktop/src/renderer/src/components/CommentsPanel.tsx b/apps/desktop/src/renderer/src/components/features/comments/CommentsPanel.tsx
similarity index 97%
rename from apps/desktop/src/renderer/src/components/CommentsPanel.tsx
rename to apps/desktop/src/renderer/src/components/features/comments/CommentsPanel.tsx
index 8c18fa7..5202525 100644
--- a/apps/desktop/src/renderer/src/components/CommentsPanel.tsx
+++ b/apps/desktop/src/renderer/src/components/features/comments/CommentsPanel.tsx
@@ -4,16 +4,16 @@ import ReactMarkdown from 'react-markdown';
import remarkBreaks from 'remark-breaks';
import remarkGfm from 'remark-gfm';
import type { PlatformCapabilities, PrComment, StoredPullRequest } from '@meebox/shared';
-import { invoke, subscribe } from '../api';
-import i18n from '../i18n';
-import { formatBackendError, type FormattedError } from '../errors';
-import { REMOTE_REHYPE_PLUGINS } from '../markdown';
-import { Avatar } from './Avatar';
-import { makeBitbucketImageFor, transformBitbucketUrl } from './BitbucketImage';
+import { invoke, subscribe } from '../../../api';
+import i18n from '../../../i18n';
+import { formatBackendError, type FormattedError } from '../../../errors';
+import { REMOTE_REHYPE_PLUGINS } from '../../../markdown';
+import { Avatar } from '../../common/Avatar';
+import { makeBitbucketImageFor, transformBitbucketUrl } from '../../common/BitbucketImage';
import { CommentEditEditor } from './CommentEditEditor';
import { CommentReplyEditor } from './CommentReplyEditor';
-import { ConfirmModal } from './ConfirmModal';
-import { mermaidComponents } from './markdownMermaid';
+import { ConfirmModal } from '../../common/ConfirmModal';
+import { mermaidComponents } from '../../common/markdownMermaid';
// 行内代码上下文用 Monaco,懒加载随 DiffView 同一套 Monaco chunk 按需拉取,不进入口包。
const InlineCodeContext = lazy(() =>
import('./InlineCodeContext').then((m) => ({ default: m.InlineCodeContext })),
diff --git a/apps/desktop/src/renderer/src/components/InlineCodeContext.tsx b/apps/desktop/src/renderer/src/components/features/comments/InlineCodeContext.tsx
similarity index 97%
rename from apps/desktop/src/renderer/src/components/InlineCodeContext.tsx
rename to apps/desktop/src/renderer/src/components/features/comments/InlineCodeContext.tsx
index b4c0c32..b68d854 100644
--- a/apps/desktop/src/renderer/src/components/InlineCodeContext.tsx
+++ b/apps/desktop/src/renderer/src/components/features/comments/InlineCodeContext.tsx
@@ -1,14 +1,14 @@
// 必须在用到 @monaco-editor/react 之前执行(见 DiffView 同款说明)。本文件经
// React.lazy 动态加载 → Monaco 随本 chunk 按需拉取,不进入口包。
-import '../monaco-setup';
+import '../../../monaco-setup';
import { Editor, type Monaco } from '@monaco-editor/react';
import type { editor } from 'monaco-editor';
import { memo, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { PrCommentAnchor, StoredPullRequest } from '@meebox/shared';
-import { invoke } from '../api';
-import { editorFontSize } from '../editor-font';
-import { languageFor } from '../utils/language';
+import { invoke } from '../../../api';
+import { editorFontSize } from '../../../editor-font';
+import { languageFor } from '../../../utils/language';
interface InlineCodeContextProps {
pr: StoredPullRequest;
diff --git a/apps/desktop/src/renderer/src/components/DiffSearchPanel.tsx b/apps/desktop/src/renderer/src/components/features/diff/DiffSearchPanel.tsx
similarity index 99%
rename from apps/desktop/src/renderer/src/components/DiffSearchPanel.tsx
rename to apps/desktop/src/renderer/src/components/features/diff/DiffSearchPanel.tsx
index 3b7b7fe..eca54e8 100644
--- a/apps/desktop/src/renderer/src/components/DiffSearchPanel.tsx
+++ b/apps/desktop/src/renderer/src/components/features/diff/DiffSearchPanel.tsx
@@ -3,8 +3,8 @@ import { useTranslation } from 'react-i18next';
import type { TFunction } from 'i18next';
import { editor as MonacoEditorNs } from 'monaco-editor';
import type { DiffChangedFile } from '@meebox/shared';
-import { invoke } from '../api';
-import { languageFor } from '../utils/language';
+import { invoke } from '../../../api';
+import { languageFor } from '../../../utils/language';
/**
* 搜索 PR diff 全部变更文件内容。仿 Bitbucket "Search code" 入口的行为:
diff --git a/apps/desktop/src/renderer/src/components/DiffView.tsx b/apps/desktop/src/renderer/src/components/features/diff/DiffView.tsx
similarity index 98%
rename from apps/desktop/src/renderer/src/components/DiffView.tsx
rename to apps/desktop/src/renderer/src/components/features/diff/DiffView.tsx
index acad950..57b8314 100644
--- a/apps/desktop/src/renderer/src/components/DiffView.tsx
+++ b/apps/desktop/src/renderer/src/components/features/diff/DiffView.tsx
@@ -1,6 +1,6 @@
// 必须在用到 @monaco-editor/react 之前执行(loader.config 指向本地 monaco)。
// 本文件经 React.lazy 动态加载,故 Monaco 随本 chunk 按需拉取,不进入口包。
-import '../monaco-setup';
+import '../../../monaco-setup';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { createRoot, type Root } from 'react-dom/client';
@@ -21,23 +21,23 @@ import type {
SyncProgressEvent,
} from '@meebox/shared';
import { policyForPlatform } from '@meebox/shared';
-import { invoke, subscribe } from '../api';
-import { editorFontSize } from '../editor-font';
-import { formatBackendError, type FormattedError } from '../errors';
-import { REMOTE_REHYPE_PLUGINS } from '../markdown';
-import { useDraftsForPr } from '../stores/drafts-store';
-import { Avatar } from './Avatar';
-import { DraftZone } from './DraftZone';
-import { ErrorBoundary } from './ErrorBoundary';
-import { makeBitbucketImageFor, transformBitbucketUrl } from './BitbucketImage';
-import { CommentEditEditor } from './CommentEditEditor';
-import { CommentReplyEditor } from './CommentReplyEditor';
-import { ConfirmModal } from './ConfirmModal';
+import { invoke, subscribe } from '../../../api';
+import { editorFontSize } from '../../../editor-font';
+import { formatBackendError, type FormattedError } from '../../../errors';
+import { REMOTE_REHYPE_PLUGINS } from '../../../markdown';
+import { useDraftsForPr } from '../../../stores/drafts-store';
+import { Avatar } from '../../common/Avatar';
+import { DraftZone } from '../drafts/DraftZone';
+import { ErrorBoundary } from '../../common/ErrorBoundary';
+import { makeBitbucketImageFor, transformBitbucketUrl } from '../../common/BitbucketImage';
+import { CommentEditEditor } from '../comments/CommentEditEditor';
+import { CommentReplyEditor } from '../comments/CommentReplyEditor';
+import { ConfirmModal } from '../../common/ConfirmModal';
import { DiffSearchPanel } from './DiffSearchPanel';
import { FileTree } from './FileTree';
-import { PaneLoading } from './Loading';
-import { FileTreeIcon, SearchIcon } from './icons';
-import { languageFor } from '../utils/language';
+import { PaneLoading } from '../../common/Loading';
+import { FileTreeIcon, SearchIcon } from '../../common/icons';
+import { languageFor } from '../../../utils/language';
interface DiffViewProps {
pr: StoredPullRequest;
diff --git a/apps/desktop/src/renderer/src/components/FileTree.tsx b/apps/desktop/src/renderer/src/components/features/diff/FileTree.tsx
similarity index 99%
rename from apps/desktop/src/renderer/src/components/FileTree.tsx
rename to apps/desktop/src/renderer/src/components/features/diff/FileTree.tsx
index a4eaa3d..acd2bc3 100644
--- a/apps/desktop/src/renderer/src/components/FileTree.tsx
+++ b/apps/desktop/src/renderer/src/components/features/diff/FileTree.tsx
@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import type { TFunction } from 'i18next';
import { Icon } from '@iconify/react';
import type { DiffChangedFile } from '@meebox/shared';
-import { ChevronIcon } from './icons';
+import { ChevronIcon } from '../../common/icons';
interface FileTreeProps {
files: DiffChangedFile[];
diff --git a/apps/desktop/src/renderer/src/components/DraftZone.tsx b/apps/desktop/src/renderer/src/components/features/drafts/DraftZone.tsx
similarity index 99%
rename from apps/desktop/src/renderer/src/components/DraftZone.tsx
rename to apps/desktop/src/renderer/src/components/features/drafts/DraftZone.tsx
index e93d06d..a4bfade 100644
--- a/apps/desktop/src/renderer/src/components/DraftZone.tsx
+++ b/apps/desktop/src/renderer/src/components/features/drafts/DraftZone.tsx
@@ -4,8 +4,8 @@ import ReactMarkdown from 'react-markdown';
import remarkBreaks from 'remark-breaks';
import remarkGfm from 'remark-gfm';
import type { ReviewDraft } from '@meebox/shared';
-import { ConfirmModal } from './ConfirmModal';
-import { TrashIcon } from './icons';
+import { ConfirmModal } from '../../common/ConfirmModal';
+import { TrashIcon } from '../../common/icons';
interface DraftZoneProps {
draft: ReviewDraft;
diff --git a/apps/desktop/src/renderer/src/components/DraftsPanel.tsx b/apps/desktop/src/renderer/src/components/features/drafts/DraftsPanel.tsx
similarity index 98%
rename from apps/desktop/src/renderer/src/components/DraftsPanel.tsx
rename to apps/desktop/src/renderer/src/components/features/drafts/DraftsPanel.tsx
index 0d28354..f485fcb 100644
--- a/apps/desktop/src/renderer/src/components/DraftsPanel.tsx
+++ b/apps/desktop/src/renderer/src/components/features/drafts/DraftsPanel.tsx
@@ -4,9 +4,9 @@ import ReactMarkdown from 'react-markdown';
import remarkBreaks from 'remark-breaks';
import remarkGfm from 'remark-gfm';
import type { PlatformCapabilities, ReviewDraft, StoredPullRequest } from '@meebox/shared';
-import { invoke } from '../api';
-import { useDraftsForPr } from '../stores/drafts-store';
-import { ConfirmModal } from './ConfirmModal';
+import { invoke } from '../../../api';
+import { useDraftsForPr } from '../../../stores/drafts-store';
+import { ConfirmModal } from '../../common/ConfirmModal';
// posted 已不存在 (发布成功即删本地),筛选项只保留 publishable / all / rejected
type Filter = 'all' | 'publishable' | 'rejected';
diff --git a/apps/desktop/src/renderer/src/components/PublishReviewModal.tsx b/apps/desktop/src/renderer/src/components/features/drafts/PublishReviewModal.tsx
similarity index 99%
rename from apps/desktop/src/renderer/src/components/PublishReviewModal.tsx
rename to apps/desktop/src/renderer/src/components/features/drafts/PublishReviewModal.tsx
index 37ba806..f9a6440 100644
--- a/apps/desktop/src/renderer/src/components/PublishReviewModal.tsx
+++ b/apps/desktop/src/renderer/src/components/features/drafts/PublishReviewModal.tsx
@@ -1,7 +1,7 @@
import { useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { ReviewDraft } from '@meebox/shared';
-import { invoke } from '../api';
+import { invoke } from '../../../api';
/**
* 批量发布草稿到 Bitbucket 的确认 modal。M4 发布闭环最后一公里。
diff --git a/apps/desktop/src/renderer/src/components/onboarding/OnboardingWizard.tsx b/apps/desktop/src/renderer/src/components/features/onboarding/OnboardingWizard.tsx
similarity index 98%
rename from apps/desktop/src/renderer/src/components/onboarding/OnboardingWizard.tsx
rename to apps/desktop/src/renderer/src/components/features/onboarding/OnboardingWizard.tsx
index 5ebdef8..e9a5218 100644
--- a/apps/desktop/src/renderer/src/components/onboarding/OnboardingWizard.tsx
+++ b/apps/desktop/src/renderer/src/components/features/onboarding/OnboardingWizard.tsx
@@ -1,15 +1,15 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { LANGUAGE_OPTIONS, type LlmProfile, type SupportedLanguage } from '@meebox/shared';
-import { invoke } from '../../api';
-import i18n, { persistLanguage, resolveUiLanguage } from '../../i18n';
+import { invoke } from '../../../api';
+import i18n, { persistLanguage, resolveUiLanguage } from '../../../i18n';
import {
connDraftCanSave,
fromConnDraft,
type ConnDraft,
type ConnEntry,
-} from '../ConnectionForm';
-import { newProfileId } from '../LlmProfileForm';
+} from '../settings/ConnectionForm';
+import { newProfileId } from '../settings/LlmProfileForm';
import { WelcomeStep } from './steps/WelcomeStep';
import { PlatformStep } from './steps/PlatformStep';
import { LlmStep } from './steps/LlmStep';
diff --git a/apps/desktop/src/renderer/src/components/onboarding/steps/DoneStep.tsx b/apps/desktop/src/renderer/src/components/features/onboarding/steps/DoneStep.tsx
similarity index 92%
rename from apps/desktop/src/renderer/src/components/onboarding/steps/DoneStep.tsx
rename to apps/desktop/src/renderer/src/components/features/onboarding/steps/DoneStep.tsx
index b9c3cf0..9d2033c 100644
--- a/apps/desktop/src/renderer/src/components/onboarding/steps/DoneStep.tsx
+++ b/apps/desktop/src/renderer/src/components/features/onboarding/steps/DoneStep.tsx
@@ -1,5 +1,5 @@
import { useTranslation } from 'react-i18next';
-import { SuccessBadgeIcon } from '../../icons';
+import { SuccessBadgeIcon } from '../../../common/icons';
export function DoneStep({ submitting, error }: { submitting: boolean; error: string | null }) {
const { t } = useTranslation();
diff --git a/apps/desktop/src/renderer/src/components/onboarding/steps/LlmStep.tsx b/apps/desktop/src/renderer/src/components/features/onboarding/steps/LlmStep.tsx
similarity index 95%
rename from apps/desktop/src/renderer/src/components/onboarding/steps/LlmStep.tsx
rename to apps/desktop/src/renderer/src/components/features/onboarding/steps/LlmStep.tsx
index 7eb409e..725386d 100644
--- a/apps/desktop/src/renderer/src/components/onboarding/steps/LlmStep.tsx
+++ b/apps/desktop/src/renderer/src/components/features/onboarding/steps/LlmStep.tsx
@@ -1,8 +1,8 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { LlmProfile } from '@meebox/shared';
-import { LLM_PROVIDERS, LlmProfileForm } from '../../LlmProfileForm';
-import { LlmProviderIcon } from '../../LlmProviderIcon';
+import { LLM_PROVIDERS, LlmProfileForm } from '../../settings/LlmProfileForm';
+import { LlmProviderIcon } from '../../../common/LlmProviderIcon';
export function LlmStep({
draft,
diff --git a/apps/desktop/src/renderer/src/components/onboarding/steps/PlatformStep.tsx b/apps/desktop/src/renderer/src/components/features/onboarding/steps/PlatformStep.tsx
similarity index 94%
rename from apps/desktop/src/renderer/src/components/onboarding/steps/PlatformStep.tsx
rename to apps/desktop/src/renderer/src/components/features/onboarding/steps/PlatformStep.tsx
index 7bcacff..7d6ed80 100644
--- a/apps/desktop/src/renderer/src/components/onboarding/steps/PlatformStep.tsx
+++ b/apps/desktop/src/renderer/src/components/features/onboarding/steps/PlatformStep.tsx
@@ -1,8 +1,8 @@
import { useTranslation } from 'react-i18next';
-import { invoke } from '../../../api';
-import { ConnectionForm, type ConnDraft } from '../../ConnectionForm';
-import { PLATFORM_META } from '../../PlatformIcon';
-import { FolderIcon } from '../../icons';
+import { invoke } from '../../../../api';
+import { ConnectionForm, type ConnDraft } from '../../settings/ConnectionForm';
+import { PLATFORM_META } from '../../../common/PlatformIcon';
+import { FolderIcon } from '../../../common/icons';
export function PlatformStep({
connDraft,
diff --git a/apps/desktop/src/renderer/src/components/onboarding/steps/WelcomeStep.tsx b/apps/desktop/src/renderer/src/components/features/onboarding/steps/WelcomeStep.tsx
similarity index 93%
rename from apps/desktop/src/renderer/src/components/onboarding/steps/WelcomeStep.tsx
rename to apps/desktop/src/renderer/src/components/features/onboarding/steps/WelcomeStep.tsx
index e6195c0..eca3036 100644
--- a/apps/desktop/src/renderer/src/components/onboarding/steps/WelcomeStep.tsx
+++ b/apps/desktop/src/renderer/src/components/features/onboarding/steps/WelcomeStep.tsx
@@ -1,7 +1,7 @@
import { useRef } from 'react';
import { useTranslation } from 'react-i18next';
-import { invoke } from '../../../api';
-import { PullRequestIcon } from '../../icons';
+import { invoke } from '../../../../api';
+import { PullRequestIcon } from '../../../common/icons';
export function WelcomeStep({ onStart }: { onStart: () => void }) {
const { t } = useTranslation();
diff --git a/apps/desktop/src/renderer/src/components/CommitsPanel.tsx b/apps/desktop/src/renderer/src/components/features/pr/CommitsPanel.tsx
similarity index 96%
rename from apps/desktop/src/renderer/src/components/CommitsPanel.tsx
rename to apps/desktop/src/renderer/src/components/features/pr/CommitsPanel.tsx
index 96c79d6..4fc66a4 100644
--- a/apps/desktop/src/renderer/src/components/CommitsPanel.tsx
+++ b/apps/desktop/src/renderer/src/components/features/pr/CommitsPanel.tsx
@@ -2,9 +2,9 @@ import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { TFunction } from 'i18next';
import type { PrCommit, StoredPullRequest } from '@meebox/shared';
-import { invoke } from '../api';
-import { formatBackendError, type FormattedError } from '../errors';
-import { Avatar } from './Avatar';
+import { invoke } from '../../../api';
+import { formatBackendError, type FormattedError } from '../../../errors';
+import { Avatar } from '../../common/Avatar';
interface CommitsPanelProps {
pr: StoredPullRequest;
diff --git a/apps/desktop/src/renderer/src/components/PrInfoView.tsx b/apps/desktop/src/renderer/src/components/features/pr/PrInfoView.tsx
similarity index 92%
rename from apps/desktop/src/renderer/src/components/PrInfoView.tsx
rename to apps/desktop/src/renderer/src/components/features/pr/PrInfoView.tsx
index cdf64ab..13628a5 100644
--- a/apps/desktop/src/renderer/src/components/PrInfoView.tsx
+++ b/apps/desktop/src/renderer/src/components/features/pr/PrInfoView.tsx
@@ -2,9 +2,9 @@ import { useMemo } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import type { ReviewerStatus, StoredPullRequest } from '@meebox/shared';
-import { REMOTE_REHYPE_PLUGINS } from '../markdown';
-import { makeBitbucketImageFor, transformBitbucketUrl } from './BitbucketImage';
-import { mermaidComponents } from './markdownMermaid';
+import { REMOTE_REHYPE_PLUGINS } from '../../../markdown';
+import { makeBitbucketImageFor, transformBitbucketUrl } from '../../common/BitbucketImage';
+import { mermaidComponents } from '../../common/markdownMermaid';
interface PrInfoViewProps {
pr: StoredPullRequest;
diff --git a/apps/desktop/src/renderer/src/components/PrItem.tsx b/apps/desktop/src/renderer/src/components/features/pr/PrItem.tsx
similarity index 97%
rename from apps/desktop/src/renderer/src/components/PrItem.tsx
rename to apps/desktop/src/renderer/src/components/features/pr/PrItem.tsx
index a6f3421..104bc10 100644
--- a/apps/desktop/src/renderer/src/components/PrItem.tsx
+++ b/apps/desktop/src/renderer/src/components/features/pr/PrItem.tsx
@@ -1,7 +1,7 @@
import { useTranslation } from 'react-i18next';
import type { AgentRecommendationVerdict, StoredPullRequest } from '@meebox/shared';
-import { Avatar } from './Avatar';
-import { PersonIcon, PullRequestIcon, StarIcon } from './icons';
+import { Avatar } from '../../common/Avatar';
+import { PersonIcon, PullRequestIcon, StarIcon } from '../../common/icons';
/** 评审建议 verdict → 复用 chatPane.agent.* 文案(不另加 i18n)。 */
const VERDICT_TITLE: Record = {
diff --git a/apps/desktop/src/renderer/src/components/ConnectionForm.tsx b/apps/desktop/src/renderer/src/components/features/settings/ConnectionForm.tsx
similarity index 98%
rename from apps/desktop/src/renderer/src/components/ConnectionForm.tsx
rename to apps/desktop/src/renderer/src/components/features/settings/ConnectionForm.tsx
index b666abb..5f601b2 100644
--- a/apps/desktop/src/renderer/src/components/ConnectionForm.tsx
+++ b/apps/desktop/src/renderer/src/components/features/settings/ConnectionForm.tsx
@@ -2,8 +2,8 @@ import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { TFunction } from 'i18next';
import { GITHUB_DOTCOM_API_BASE, GITLAB_DOTCOM_API_BASE, type Config } from '@meebox/shared';
-import { invoke } from '../api';
-import { EyeIcon, EyeOffIcon } from './icons';
+import { invoke } from '../../../api';
+import { EyeIcon, EyeOffIcon } from '../../common/icons';
// 连接编辑用的扁平草稿(Connection 是嵌套的 auth/clone,拍平后表单好写),存盘前还原。
// 设置页 ConnectionEditorModal 与首启向导 PlatformStep 共用同一份草稿形状 + 表单。
diff --git a/apps/desktop/src/renderer/src/components/LlmProfileForm.tsx b/apps/desktop/src/renderer/src/components/features/settings/LlmProfileForm.tsx
similarity index 99%
rename from apps/desktop/src/renderer/src/components/LlmProfileForm.tsx
rename to apps/desktop/src/renderer/src/components/features/settings/LlmProfileForm.tsx
index 36cf3fa..f4f52b2 100644
--- a/apps/desktop/src/renderer/src/components/LlmProfileForm.tsx
+++ b/apps/desktop/src/renderer/src/components/features/settings/LlmProfileForm.tsx
@@ -1,8 +1,8 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { LlmProfile, LlmProvider } from '@meebox/shared';
-import i18n from '../i18n';
-import { EyeIcon, EyeOffIcon } from './icons';
+import i18n from '../../../i18n';
+import { EyeIcon, EyeOffIcon } from '../../common/icons';
export interface ProviderMeta {
value: LlmProvider;
diff --git a/apps/desktop/src/renderer/src/components/SettingsModal.tsx b/apps/desktop/src/renderer/src/components/features/settings/SettingsModal.tsx
similarity index 99%
rename from apps/desktop/src/renderer/src/components/SettingsModal.tsx
rename to apps/desktop/src/renderer/src/components/features/settings/SettingsModal.tsx
index 016f189..f9c50fc 100644
--- a/apps/desktop/src/renderer/src/components/SettingsModal.tsx
+++ b/apps/desktop/src/renderer/src/components/features/settings/SettingsModal.tsx
@@ -9,9 +9,9 @@ import {
type SupportedLanguage,
type UpdateCheckResult,
} from '@meebox/shared';
-import { invoke } from '../api';
-import i18n, { persistLanguage, resolveUiLanguage } from '../i18n';
-import { ConfirmModal } from './ConfirmModal';
+import { invoke } from '../../../api';
+import i18n, { persistLanguage, resolveUiLanguage } from '../../../i18n';
+import { ConfirmModal } from '../../common/ConfirmModal';
import {
ConnectionForm,
connDraftCanSave,
@@ -30,9 +30,9 @@ import {
PencilIcon,
TagIcon,
TrashIcon,
-} from './icons';
-import { LlmProviderIcon } from './LlmProviderIcon';
-import { PLATFORM_META } from './PlatformIcon';
+} from '../../common/icons';
+import { LlmProviderIcon } from '../../common/LlmProviderIcon';
+import { PLATFORM_META } from '../../common/PlatformIcon';
interface SettingsModalProps {
info: AppInfo;
diff --git a/apps/desktop/src/renderer/src/components/MainPane.tsx b/apps/desktop/src/renderer/src/components/layout/MainPane.tsx
similarity index 97%
rename from apps/desktop/src/renderer/src/components/MainPane.tsx
rename to apps/desktop/src/renderer/src/components/layout/MainPane.tsx
index d7da308..57b62c7 100644
--- a/apps/desktop/src/renderer/src/components/MainPane.tsx
+++ b/apps/desktop/src/renderer/src/components/layout/MainPane.tsx
@@ -6,17 +6,17 @@ import type {
ReviewerStatus,
StoredPullRequest,
} from '@meebox/shared';
-import { invoke } from '../api';
-import { useDraftsForPr } from '../stores/drafts-store';
-import { CommentsPanel } from './CommentsPanel';
-import { CommitsPanel } from './CommitsPanel';
+import { invoke } from '../../api';
+import { useDraftsForPr } from '../../stores/drafts-store';
+import { CommentsPanel } from '../features/comments/CommentsPanel';
+import { CommitsPanel } from '../features/pr/CommitsPanel';
// Monaco 编辑器(~10MB)懒加载:只有真正切到 Diff tab 才拉取 DiffView chunk,
// 不阻塞窗口首帧 / PR 列表 / 首启向导。
-const DiffView = lazy(() => import('./DiffView').then((m) => ({ default: m.DiffView })));
-import { DraftsPanel } from './DraftsPanel';
-import { PaneLoading } from './Loading';
-import { PrInfoView } from './PrInfoView';
-import { PublishReviewModal } from './PublishReviewModal';
+const DiffView = lazy(() => import('../features/diff/DiffView').then((m) => ({ default: m.DiffView })));
+import { DraftsPanel } from '../features/drafts/DraftsPanel';
+import { PaneLoading } from '../common/Loading';
+import { PrInfoView } from '../features/pr/PrInfoView';
+import { PublishReviewModal } from '../features/drafts/PublishReviewModal';
import {
ApproveIcon,
GlobeIcon,
@@ -24,7 +24,7 @@ import {
PersonIcon,
PullRequestIcon,
WhitespaceIcon,
-} from './icons';
+} from '../common/icons';
interface MainPaneProps {
pr: StoredPullRequest | null;
diff --git a/apps/desktop/src/renderer/src/components/Sidebar.tsx b/apps/desktop/src/renderer/src/components/layout/Sidebar.tsx
similarity index 98%
rename from apps/desktop/src/renderer/src/components/Sidebar.tsx
rename to apps/desktop/src/renderer/src/components/layout/Sidebar.tsx
index 349dc48..f7057d7 100644
--- a/apps/desktop/src/renderer/src/components/Sidebar.tsx
+++ b/apps/desktop/src/renderer/src/components/layout/Sidebar.tsx
@@ -6,9 +6,9 @@ import type {
PrDiscoveryFilter,
StoredPullRequest,
} from '@meebox/shared';
-import { invoke, subscribe } from '../api';
-import { useChatRunStore } from '../stores/chat-run-store';
-import { PrItem } from './PrItem';
+import { invoke, subscribe } from '../../api';
+import { useChatRunStore } from '../../stores/chat-run-store';
+import { PrItem } from '../features/pr/PrItem';
// 'conflict' / 'mergeable' 是按远端 merge 状态跨 localStatus 横切的筛选;'all' 不限定
type FilterKey = 'all' | LocalPrStatus | 'conflict' | 'mergeable';
diff --git a/apps/desktop/src/renderer/src/components/StatusBar.tsx b/apps/desktop/src/renderer/src/components/layout/StatusBar.tsx
similarity index 99%
rename from apps/desktop/src/renderer/src/components/StatusBar.tsx
rename to apps/desktop/src/renderer/src/components/layout/StatusBar.tsx
index 5aeca64..6f5d9d4 100644
--- a/apps/desktop/src/renderer/src/components/StatusBar.tsx
+++ b/apps/desktop/src/renderer/src/components/layout/StatusBar.tsx
@@ -2,9 +2,9 @@ import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { TFunction } from 'i18next';
import type { Config, ConnectionSummary, PrAgentStatus, UpdateCheckResult } from '@meebox/shared';
-import { invoke } from '../api';
-import { useChatRunStore } from '../stores/chat-run-store';
-import { useRepoSyncStore } from '../stores/repo-sync-store';
+import { invoke } from '../../api';
+import { useChatRunStore } from '../../stores/chat-run-store';
+import { useRepoSyncStore } from '../../stores/repo-sync-store';
import {
PanelToggleIcon,
PersonIcon,
@@ -13,7 +13,7 @@ import {
RobotOffIcon,
SettingsIcon,
SyncIcon,
-} from './icons';
+} from '../common/icons';
interface StatusBarProps {
prsCount: number;
diff --git a/apps/desktop/src/renderer/src/components/TitleBar.tsx b/apps/desktop/src/renderer/src/components/layout/TitleBar.tsx
similarity index 100%
rename from apps/desktop/src/renderer/src/components/TitleBar.tsx
rename to apps/desktop/src/renderer/src/components/layout/TitleBar.tsx