diff --git a/app/shared/package.json b/app/shared/package.json
index bb4d4bccc..d555eb5a9 100644
--- a/app/shared/package.json
+++ b/app/shared/package.json
@@ -28,8 +28,7 @@
"./ui/*": "./src/ui/*.tsx",
"./ui/*.css": "./src/ui/*.module.css",
"./lib/utils": "./src/lib/utils.ts",
- "./shadcn/ui/*": "./src/shadcn/ui/*.tsx",
- "./shadcn/ai-elements/*": "./src/shadcn/ai-elements/*.tsx"
+ "./shadcn/ui/*": "./src/shadcn/ui/*.tsx"
},
"scripts": {
"test": "vitest run",
diff --git a/app/workbench/README.md b/app/workbench/README.md
index a6af53379..8dfea2adf 100644
--- a/app/workbench/README.md
+++ b/app/workbench/README.md
@@ -8,6 +8,23 @@ docs/projects/tasks/settings 页面、mainchain 状态条、terminal host、floa
`workbench` 是端级 shell 层;`shared` 是跨端原语层,
workbench 是端级巨石,两者拆包后依赖方向固定为 **workbench → shared 单向**。
+## 目录
+
+根目录只放 shell 与跨域件:`AgentHubWorkbench*`、`WorkbenchFrame*`、
+`WorkspaceHeader`、`GlobalRail`、`WorkbenchRoutes`、`index.ts` 入口、图标
+registry、preferences/layout、以及 `pages/`、`auxPanel/`、`terminal/`、
+`team/`、`floating/`、`mainchain/`、`sessionImport/`、`__tests__/`。
+
+| 目录 | 内容 |
+|---|---|
+| `composer/` | UnifiedComposer 与其 picker / 附件 / mention / 审批 / dispatch queue 子件、纯 helper |
+| `transcript/` | 会话转录与工程列:ConversationHost/Sidebar、ChatViewBridge、transcript chrome、goal banner、mainchain 状态条 |
+| `routes/` | 每个 route 的 view + hook + helpers/planners/model(agents、tasks、docs、projects、settings、usage) |
+| `inspector/` | 右侧 Inspector 面板、resizer、模式面板、自动展开 hook |
+
+模块与测试同目录;移动文件时改相对导入即可,包外消费者只认
+`package.json` 的 exports,不认内部路径。
+
## 边界
- 依赖方向:`workbench` 可以 import `shared`(深导入走 `@shared/*` 别名,
diff --git a/app/workbench/src/AgentHubWorkbench.tsx b/app/workbench/src/AgentHubWorkbench.tsx
index 200ed1e4d..e5f5e4c3d 100644
--- a/app/workbench/src/AgentHubWorkbench.tsx
+++ b/app/workbench/src/AgentHubWorkbench.tsx
@@ -7,21 +7,21 @@ import type { GlobalRailPage } from './GlobalRail';
import styles from './AgentHubWorkbench.module.css';
import { useWorkbenchPanelLayout } from './useWorkbenchPanelLayout';
import { useWorkbenchProfileChrome } from './useWorkbenchProfileChrome';
-import { useWorkbenchSessionChrome } from './useWorkbenchSessionChrome';
-import { useWorkbenchTranscriptChrome } from './useWorkbenchTranscriptChrome';
+import { useWorkbenchSessionChrome } from './transcript/useWorkbenchSessionChrome';
+import { useWorkbenchTranscriptChrome } from './transcript/useWorkbenchTranscriptChrome';
import { useWorkbenchGlobalShortcuts } from './useWorkbenchGlobalShortcuts';
import { useWorkbenchTaskDeepLinks } from './useWorkbenchTaskDeepLinks';
-import { WorkbenchTaskDeepLinkProvider } from './workbenchTaskDeepLinks';
+import { WorkbenchTaskDeepLinkProvider } from './routes/workbenchTaskDeepLinks';
import { GlobalSearchDialog } from './GlobalSearchDialog';
import { WORKBENCH_INSPECTOR_QUICK_OPEN_EVENT } from './desktopChromeEvents';
-import { isEditableKeyboardTarget } from './workbenchSessionChromeHelpers';
+import { isEditableKeyboardTarget } from './transcript/workbenchSessionChromeHelpers';
import { WorkbenchFrame } from './WorkbenchFrame';
import {
engineeringColumnActivitySignal,
useEngineeringColumnAutoOpen,
-} from './useEngineeringColumnAutoOpen';
+} from './inspector/useEngineeringColumnAutoOpen';
import { WorkbenchProfileOverlays } from './WorkbenchProfileOverlays';
-import { WorkbenchTranscriptOverlays } from './WorkbenchTranscriptOverlays';
+import { WorkbenchTranscriptOverlays } from './transcript/WorkbenchTranscriptOverlays';
import {
buildProfileChromeOptions,
buildProfileOverlaysProps,
diff --git a/app/workbench/src/AgentHubWorkbenchHelpers.test.ts b/app/workbench/src/AgentHubWorkbenchHelpers.test.ts
index 7537e81bd..012558c1f 100644
--- a/app/workbench/src/AgentHubWorkbenchHelpers.test.ts
+++ b/app/workbench/src/AgentHubWorkbenchHelpers.test.ts
@@ -2,8 +2,8 @@ import { describe, expect, it, vi } from 'vitest';
import type { AgentHubPlatform, WorkbenchConversation } from '@shared/platform';
import type { TranscriptBlock } from '@shared/transcript';
import type { GlobalRailPage } from './GlobalRail';
-import type { WorkbenchSessionChrome } from './workbenchSessionChromeHelpers';
-import type { WorkbenchTranscriptChrome } from './useWorkbenchTranscriptChrome';
+import type { WorkbenchSessionChrome } from './transcript/workbenchSessionChromeHelpers';
+import type { WorkbenchTranscriptChrome } from './transcript/useWorkbenchTranscriptChrome';
import type { WorkbenchProfileChrome } from './useWorkbenchProfileChrome';
import type { WorkbenchPanelLayout } from './useWorkbenchPanelLayout';
import type { AgentHubWorkbenchProps } from './AgentHubWorkbenchTypes';
diff --git a/app/workbench/src/AgentHubWorkbenchHelpers.ts b/app/workbench/src/AgentHubWorkbenchHelpers.ts
index 4b2327ece..35cc54855 100644
--- a/app/workbench/src/AgentHubWorkbenchHelpers.ts
+++ b/app/workbench/src/AgentHubWorkbenchHelpers.ts
@@ -2,17 +2,17 @@ import type { Dispatch, SetStateAction } from 'react';
import type { WorkbenchConversation } from '@shared/platform';
import type { GlobalRailPage } from './GlobalRail';
import type { WorkbenchFrameProps } from './workbenchFrameTypes';
-import type { UseWorkbenchSessionChromeOptions, WorkbenchSessionChrome } from './workbenchSessionChromeHelpers';
+import type { UseWorkbenchSessionChromeOptions, WorkbenchSessionChrome } from './transcript/workbenchSessionChromeHelpers';
import type {
UseWorkbenchTranscriptChromeOptions,
WorkbenchTranscriptChrome,
-} from './useWorkbenchTranscriptChrome';
+} from './transcript/useWorkbenchTranscriptChrome';
import type {
UseWorkbenchProfileChromeOptions,
WorkbenchProfileChrome,
} from './useWorkbenchProfileChrome';
import type { WorkbenchPanelLayout } from './useWorkbenchPanelLayout';
-import type { WorkbenchTranscriptOverlaysProps } from './WorkbenchTranscriptOverlays';
+import type { WorkbenchTranscriptOverlaysProps } from './transcript/WorkbenchTranscriptOverlays';
import type { WorkbenchProfileOverlaysProps } from './WorkbenchProfileOverlays';
import type { AgentHubWorkbenchProps } from './AgentHubWorkbenchTypes';
diff --git a/app/workbench/src/AgentHubWorkbenchTypes.ts b/app/workbench/src/AgentHubWorkbenchTypes.ts
index 6a76b688e..6dce3ccee 100644
--- a/app/workbench/src/AgentHubWorkbenchTypes.ts
+++ b/app/workbench/src/AgentHubWorkbenchTypes.ts
@@ -5,14 +5,14 @@ import type {
} from '@shared/platform';
import type { TranscriptBlock, ApprovalDecisionAction } from '@shared/transcript';
import type { ConnectionStatusKind } from './GlobalRail';
-import type { RuntimeEvidenceSnapshot } from './RightInspector';
+import type { RuntimeEvidenceSnapshot } from './inspector/RightInspector';
import type {
WorkbenchAgentProfilesStatus,
WorkbenchContactsData,
WorkbenchContactsActions,
WorkbenchDocumentsActions,
} from './WorkbenchRoutes';
-import type { AgentConfig, ProjectDraft, DocRow } from './pages';
+import type { AgentConfig, ProjectDraft, DocRow } from './pages/index';
import type { SkillMarketItem, MCPMarketItem } from './pages/AgentsPage';
import type { ProjectInfo } from './pages/ProjectsPage';
import type { WorkbenchAttentionInput } from './workbenchAttentionModel';
diff --git a/app/workbench/src/GlobalRail.tsx b/app/workbench/src/GlobalRail.tsx
index 58d8623f4..16dcb4d19 100644
--- a/app/workbench/src/GlobalRail.tsx
+++ b/app/workbench/src/GlobalRail.tsx
@@ -1,6 +1,6 @@
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
-import { ProfilePopover, DemoToast } from './floating';
+import { ProfilePopover, DemoToast } from './floating/index';
import { DesignNavIcon, type DesignNavIconName } from './designIcons';
import { CHATVIEW_I18N_NAMESPACE } from '@shared/chatview/i18n/resources';
import { Tooltip } from '@shared/ui/Tooltip';
diff --git a/app/workbench/src/SplitConversationPane.test.tsx b/app/workbench/src/SplitConversationPane.test.tsx
index da53eac35..d3d889de8 100644
--- a/app/workbench/src/SplitConversationPane.test.tsx
+++ b/app/workbench/src/SplitConversationPane.test.tsx
@@ -14,7 +14,7 @@ beforeAll(async () => {
await useTestI18nLanguage('en');
});
-vi.mock('./ChatViewBridge', () => ({
+vi.mock('./transcript/ChatViewBridge', () => ({
ChatViewBridge: (props: { displayTranscript: TranscriptBlock[] }) => (
),
diff --git a/app/workbench/src/SplitConversationPane.tsx b/app/workbench/src/SplitConversationPane.tsx
index d1aab269d..f7fc5e79b 100644
--- a/app/workbench/src/SplitConversationPane.tsx
+++ b/app/workbench/src/SplitConversationPane.tsx
@@ -14,7 +14,7 @@ import { useTranslation } from 'react-i18next';
import type { WorkbenchConversation } from '@shared/platform';
import type { TranscriptBlock } from '@shared/transcript';
import { CHATVIEW_I18N_NAMESPACE } from '@shared/chatview/i18n/resources';
-import { ChatViewBridge } from './ChatViewBridge';
+import { ChatViewBridge } from './transcript/ChatViewBridge';
import { DesignNavIcon } from './designIcons';
import { ContextMenu, type ContextMenuItem } from './floating/ContextMenu';
import type { ConversationLiveStatus } from './workbenchAttentionModel';
diff --git a/app/workbench/src/UnifiedComposerParts.tsx b/app/workbench/src/UnifiedComposerParts.tsx
deleted file mode 100644
index e441b0bf0..000000000
--- a/app/workbench/src/UnifiedComposerParts.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-/* ═══════════════════════════════════════════════════════════════════════
- UnifiedComposer presentational subpanels — barrel module (#706).
-
- Subcomponents live in ComposerContextParts / ComposerAttachmentParts /
- ComposerControlParts. Pure helpers in ComposerPartsHelpers. Visuals use the
- shadcn/Tailwind token bridge; no composer chrome remains in the CSS module.
- ═══════════════════════════════════════════════════════════════════════ */
-
-export {
- ComposerMentionChips,
- ComposerQuoteBar,
- ComposerReplyBar,
- ComposerEditBar,
- ComposerStatusStrip,
-} from './ComposerContextParts';
-
-export {
- ComposerAttachmentBar,
- ComposerAttachmentChip,
-} from './ComposerAttachmentParts';
-
-export {
- ComposerAgentPicker,
- ComposerApprovalModePicker,
- ComposerAttachButton,
- ComposerSendButton,
- ComposerTargetPicker,
-} from './ComposerControlParts';
diff --git a/app/workbench/src/WorkbenchFrame.attention.test.tsx b/app/workbench/src/WorkbenchFrame.attention.test.tsx
index 673f570f4..ffe7ecba0 100644
--- a/app/workbench/src/WorkbenchFrame.attention.test.tsx
+++ b/app/workbench/src/WorkbenchFrame.attention.test.tsx
@@ -32,12 +32,12 @@ vi.mock('./WorkbenchFrameParts', () => ({
WorkspaceLoadingState: () => ,
}));
-vi.mock('./terminal', () => ({
+vi.mock('./terminal/index', () => ({
TerminalPanel: () => ,
}));
// The real strip would need i18n; the wiring contract is what this file pins.
-vi.mock('./MainchainStatusStrip', () => ({
+vi.mock('./transcript/MainchainStatusStrip', () => ({
MainchainStatusStrip: (props: {
attention?: WorkbenchAttentionCounts;
onOpenRunningQueue?: () => void;
diff --git a/app/workbench/src/WorkbenchFrame.split.test.tsx b/app/workbench/src/WorkbenchFrame.split.test.tsx
index 83c971466..52e968389 100644
--- a/app/workbench/src/WorkbenchFrame.split.test.tsx
+++ b/app/workbench/src/WorkbenchFrame.split.test.tsx
@@ -36,11 +36,11 @@ vi.mock('./GlobalRail', () => ({
GlobalRail: () => ,
}));
-vi.mock('./MainchainStatusStrip', () => ({
+vi.mock('./transcript/MainchainStatusStrip', () => ({
MainchainStatusStrip: () => ,
}));
-vi.mock('./terminal', () => ({
+vi.mock('./terminal/index', () => ({
TerminalPanel: () => ,
}));
diff --git a/app/workbench/src/WorkbenchFrame.terminalDock.test.tsx b/app/workbench/src/WorkbenchFrame.terminalDock.test.tsx
index 3c999e0e1..f2b2e170a 100644
--- a/app/workbench/src/WorkbenchFrame.terminalDock.test.tsx
+++ b/app/workbench/src/WorkbenchFrame.terminalDock.test.tsx
@@ -17,7 +17,7 @@ vi.mock('./WorkbenchFrameParts', () => ({
WorkspaceLoadingState: () => ,
}));
-vi.mock('./terminal', () => ({
+vi.mock('./terminal/index', () => ({
TerminalPanel: (props: { localTerminal?: boolean; terminal?: unknown }) => (
({ last: null as Record
| null }));
-vi.mock('./ConversationSidebar', () => ({
+vi.mock('./transcript/ConversationSidebar', () => ({
ConversationSidebar: (props: Record) => (
({
),
}));
-vi.mock('./ConversationHost', () => ({
+vi.mock('./transcript/ConversationHost', () => ({
ConversationHost: (props: Record
) => {
hostPropsLog.last = props;
return (
@@ -47,7 +47,7 @@ vi.mock('./ConversationHost', () => ({
},
}));
-vi.mock('./RightInspector', () => ({
+vi.mock('./inspector/RightInspector', () => ({
RightInspector: (props: Record) => (
({
),
}));
-vi.mock('./ChatEngineeringColumn', () => ({
+vi.mock('./transcript/ChatEngineeringColumn', () => ({
ChatEngineeringColumn: (props: Record
) => (
{
});
});
-/* ═══════════════════ Draft persistence ═══════════════════ */
-
const draftComposer: ComposerState = {
conversationId: 'hub-session-draft',
text: '',
diff --git a/app/workbench/src/UnifiedComposer.tsx b/app/workbench/src/composer/UnifiedComposer.tsx
similarity index 91%
rename from app/workbench/src/UnifiedComposer.tsx
rename to app/workbench/src/composer/UnifiedComposer.tsx
index d85c208fc..4446a1fce 100644
--- a/app/workbench/src/UnifiedComposer.tsx
+++ b/app/workbench/src/composer/UnifiedComposer.tsx
@@ -27,7 +27,7 @@ import {
filterAvailableMentionOptions,
partitionAttachmentsBySize,
} from './unifiedComposerHelpers';
-import styles from './AgentHubWorkbench.module.css';
+import styles from '../AgentHubWorkbench.module.css';
import {
ComposerAgentPicker,
ComposerApprovalModePicker,
@@ -42,12 +42,7 @@ import {
ComposerTargetPicker as ComposerTargetPickerBase,
} from './UnifiedComposerParts';
-/* #21 性能:composer 状态每次击键都变(textarea 值必要更新),UnifiedComposer
- 自身每击键重渲染不可避免;但子面板的 props 在击键时大多保持稳定(数据来自
- composer 状态的稳定引用 + useCallback 稳定的回调),包一层 React.memo 跳过
- 不必要的子树重渲染。
- ─ ComposerAgentPicker / ComposerStatusStrip 未包:availableMentionOptions /
- statusItems 每次渲染由纯函数重建(新引用),memo 无效。 */
+// Every keystroke re-renders the composer; memo the subpanels whose props stay stable.
const ComposerReplyBar = React.memo(ComposerReplyBarBase);
const ComposerQuoteBar = React.memo(ComposerQuoteBarBase);
const ComposerEditBar = React.memo(ComposerEditBarBase);
@@ -113,8 +108,6 @@ export function UnifiedComposer({
const { chromeModel } = view;
const fileInputRef = useRef
(null);
- /* #21 性能:稳定回调(依赖仅 dispatchComposer —— useReducer dispatch 跨渲染
- 稳定),配合上方子组件 React.memo,跳过击键时子面板的不必要重渲染。 */
const handleCancelReply = useCallback(() => dispatchComposer(cancelReplyAction()), [dispatchComposer]);
const handleCancelQuote = useCallback(() => dispatchComposer(cancelQuoteAction()), [dispatchComposer]);
const handleCancelEdit = useCallback(() => dispatchComposer(cancelEditAction()), [dispatchComposer]);
@@ -154,14 +147,6 @@ export function UnifiedComposer({
onExecutionTargetChange?.('');
}, [runtime.executionTargetId, executionTargets, onExecutionTargetChange]);
- /* ═══════════════ @mention inline popover ═══════════════
- The textarea reports every text/cursor change to evaluateTrigger; an
- active '@' before the caret (preceded by whitespace, no whitespace in
- the query segment) opens the popover. The popover reuses the existing
- mentionableAgents data + planAddMentionAction so dispatchRole ('context'
- vs 'dispatch') semantics flow through unchanged. IME composition is
- guarded via compositionRef so '@' detection never fires mid-composition. */
-
const [mentionTrigger, setMentionTrigger] = useState(null);
const [mentionActiveIndex, setMentionActiveIndex] = useState(0);
const [popoverCoords, setPopoverCoords] = useState(null);
@@ -170,14 +155,6 @@ export function UnifiedComposer({
const textareaRef = useRef(null);
const listboxId = useId();
- /* ═══════════════ Draft persistence ═══════════════
- Save composer draft per conversationId via requestIdleCallback
- batching, load on mount, flush on hidden, clear on submit (empty
- state). #1822: the persisted payload now also carries uploaded
- attachment refs and the reply/quote context; in-flight attachments
- are additionally kept in a memory cache so a same-session
- conversation switch restores them fully. */
-
const draftLoadedRef = useRef(null);
const pendingDraftRef = useRef<{
conversationId: string;
@@ -236,7 +213,6 @@ export function UnifiedComposer({
flushDraft();
}
- // ══ Load draft (first time per conversationId) ══
if (draftLoadedRef.current !== cid) {
draftLoadedRef.current = cid;
// Only load when the composer is empty (fresh mount / conversation switch).
@@ -297,7 +273,6 @@ export function UnifiedComposer({
}
}
- // ══ Save / clear draft ══
if (
composer.text === '' &&
composer.mentions.length === 0 &&
@@ -350,10 +325,6 @@ export function UnifiedComposer({
};
}, []);
- /* ═══════════════ Auto-grow (#1822) ═══════════════
- The composer textarea is rows=1; grow it to fit the content up to
- the CSS max-height instead of scrolling forever at one line. */
-
useEffect(() => {
const textarea = textareaRef.current;
if (!textarea) return;
@@ -535,15 +506,6 @@ export function UnifiedComposer({
if (effect.kind === 'submit') event.currentTarget.form?.requestSubmit();
}
- /* ═══════════════ onPaste / onDrop attachment ═══════════════
- Extract File objects from clipboard paste or file drag-and-drop, convert
- to ComposerAttachment (via browserFilesToComposerAttachments for content
- preview + hash), and dispatch into the composer store. Upload is deferred
- to ConversationHost on submit. Orthogonal to @mention popover — no
- interaction with evaluateTrigger / compositionRef.
- Size gate: files over MAX_ATTACHMENT_BYTES are
- rejected up front with a toast instead of failing mid-upload. */
-
async function handleAttachFiles(files: File[]): Promise {
if (files.length === 0 || view.isSubmitting) return;
const { accepted, rejected } = partitionAttachmentsBySize(files);
diff --git a/app/workbench/src/composer/UnifiedComposerParts.tsx b/app/workbench/src/composer/UnifiedComposerParts.tsx
new file mode 100644
index 000000000..53653c2a6
--- /dev/null
+++ b/app/workbench/src/composer/UnifiedComposerParts.tsx
@@ -0,0 +1,20 @@
+export {
+ ComposerMentionChips,
+ ComposerQuoteBar,
+ ComposerReplyBar,
+ ComposerEditBar,
+ ComposerStatusStrip,
+} from './ComposerContextParts';
+
+export {
+ ComposerAttachmentBar,
+ ComposerAttachmentChip,
+} from './ComposerAttachmentParts';
+
+export {
+ ComposerAgentPicker,
+ ComposerApprovalModePicker,
+ ComposerAttachButton,
+ ComposerSendButton,
+ ComposerTargetPicker,
+} from './ComposerControlParts';
diff --git a/app/workbench/src/composerApprovalMode.test.ts b/app/workbench/src/composer/composerApprovalMode.test.ts
similarity index 100%
rename from app/workbench/src/composerApprovalMode.test.ts
rename to app/workbench/src/composer/composerApprovalMode.test.ts
diff --git a/app/workbench/src/composerApprovalMode.ts b/app/workbench/src/composer/composerApprovalMode.ts
similarity index 64%
rename from app/workbench/src/composerApprovalMode.ts
rename to app/workbench/src/composer/composerApprovalMode.ts
index 1fe82938f..52234fc81 100644
--- a/app/workbench/src/composerApprovalMode.ts
+++ b/app/workbench/src/composer/composerApprovalMode.ts
@@ -2,22 +2,9 @@ import type { ApprovalMode } from '@shared/composer';
import type { PermissionModeOption } from '@shared/ui';
/**
- * #1816 — composer approval-mode picker mapping.
- *
- * Semantics (documented, matching both platform dispatchers):
- * - 'suggest' (default): no override — the agent applies its own permission
- * policy. Web sends approval_mode: "suggest"; desktop's edgePermissionMode
- * returns no permissionMode override.
- * - 'workspace-write': desktop maps to Edge permissionMode 'acceptEdits'.
- * - 'read-only': desktop maps to Edge permissionMode 'plan'.
- *
- * The shared PermissionModePicker uses Edge permission-mode vocabulary for
- * its option values ('acceptEdits' / 'plan') so the option icons stay
- * meaningful; 'suggest' keeps a Settings glyph.
- *
- * `APPROVAL_MODE_ROWS` is the single source for the mode → picker-value →
- * label-key mapping, and every function below is a lookup on it, so a mode
- * can no longer be present in one mapping and missing from another.
+ * Composer approval mode → picker value + label key. `suggest` is a no-op
+ * override; the other two reuse the Edge vocabulary (`acceptEdits` / `plan`)
+ * so the shared picker icons stay meaningful.
*/
interface ApprovalModeRow {
diff --git a/app/workbench/src/composerDocumentFileDrop.test.ts b/app/workbench/src/composer/composerDocumentFileDrop.test.ts
similarity index 100%
rename from app/workbench/src/composerDocumentFileDrop.test.ts
rename to app/workbench/src/composer/composerDocumentFileDrop.test.ts
diff --git a/app/workbench/src/composerDocumentFileDrop.ts b/app/workbench/src/composer/composerDocumentFileDrop.ts
similarity index 75%
rename from app/workbench/src/composerDocumentFileDrop.ts
rename to app/workbench/src/composer/composerDocumentFileDrop.ts
index a182272ac..6d1b5d8cb 100644
--- a/app/workbench/src/composerDocumentFileDrop.ts
+++ b/app/workbench/src/composer/composerDocumentFileDrop.ts
@@ -7,16 +7,6 @@ import {
} from './unifiedComposerHelpers';
import { dispatchComposerAttachmentAdds } from './unifiedComposerHostHelpers';
-/* ═══════════════════════════════════════════════════════════════════════
- composerDocumentFileDrop — document-level file drop routing (#1822).
-
- Files dragged onto the transcript/sidebar/headers used to open in the
- browser. These handlers intercept any Files drag outside the composer
- form and route it to the composer attachment chips instead. Extracted
- from ConversationHost so the routing decisions are unit-testable;
- ConversationHost only owns listener registration and the dragging flag.
- ═══════════════════════════════════════════════════════════════════════ */
-
export interface ComposerDocumentFileDropCallbacks {
dispatchComposer: Dispatch;
onToast: (message: string) => void;
diff --git a/app/workbench/src/composerMentionPopoverHelpers.test.ts b/app/workbench/src/composer/composerMentionPopoverHelpers.test.ts
similarity index 100%
rename from app/workbench/src/composerMentionPopoverHelpers.test.ts
rename to app/workbench/src/composer/composerMentionPopoverHelpers.test.ts
diff --git a/app/workbench/src/composerMentionPopoverHelpers.ts b/app/workbench/src/composer/composerMentionPopoverHelpers.ts
similarity index 82%
rename from app/workbench/src/composerMentionPopoverHelpers.ts
rename to app/workbench/src/composer/composerMentionPopoverHelpers.ts
index ced1ed680..b531b5505 100644
--- a/app/workbench/src/composerMentionPopoverHelpers.ts
+++ b/app/workbench/src/composer/composerMentionPopoverHelpers.ts
@@ -1,18 +1,3 @@
-/* ═══════════════════════════════════════════════════════════════════════
- composerMentionPopoverHelpers — pure + DOM plumbing for the @mention
- popover: keyboard navigation plan, viewport-clamped
- positioning, and best-effort caret coordinate measurement.
-
- - `planMentionPopoverKeyDown` / `clampPopoverPosition` are pure and
- fully unit-testable.
- - `measureCaretCoords` is a defensive DOM measurement (mirror-div
- technique) that returns null in environments without layout (jsdom),
- letting the host fall back to an anchored position.
-
- No React. The host wires these into the textarea keydown handler and
- a layout effect that positions the popover.
- ═══════════════════════════════════════════════════════════════════════ */
-
/** Keyboard effect the host should apply while the mention popover is open. */
export type MentionPopoverKeyEffect =
| { kind: 'none' }
diff --git a/app/workbench/src/composerMentionTrigger.test.ts b/app/workbench/src/composer/composerMentionTrigger.test.ts
similarity index 100%
rename from app/workbench/src/composerMentionTrigger.test.ts
rename to app/workbench/src/composer/composerMentionTrigger.test.ts
diff --git a/app/workbench/src/composerMentionTrigger.ts b/app/workbench/src/composer/composerMentionTrigger.ts
similarity index 74%
rename from app/workbench/src/composerMentionTrigger.ts
rename to app/workbench/src/composer/composerMentionTrigger.ts
index 42b4ff256..bdef9388c 100644
--- a/app/workbench/src/composerMentionTrigger.ts
+++ b/app/workbench/src/composer/composerMentionTrigger.ts
@@ -1,19 +1,5 @@
import type { ComposerMention } from '@shared/composer';
-/* ═══════════════════════════════════════════════════════════════════════
- composerMentionTrigger — pure @mention trigger detection for the
- UnifiedComposer textarea.
-
- Detects an active '@' trigger immediately preceding the caret, extracts
- the query segment, filters mentionable candidates, and computes the text
- slice that must be removed when a candidate is inserted as a chip.
-
- Pure + framework-agnostic: no React, no DOM. The host (UnifiedComposer)
- wires these into textarea onChange/onSelect and the popover selection
- handler. Mention data + dispatchRole semantics flow unchanged through
- the existing `addMention` reducer action — see planAddMentionAction.
- ═══════════════════════════════════════════════════════════════════════ */
-
export interface MentionTrigger {
/** Offset of the '@' trigger char in the composer text. */
atOffset: number;
diff --git a/app/workbench/src/unifiedComposerHelpers.test.ts b/app/workbench/src/composer/unifiedComposerHelpers.test.ts
similarity index 100%
rename from app/workbench/src/unifiedComposerHelpers.test.ts
rename to app/workbench/src/composer/unifiedComposerHelpers.test.ts
diff --git a/app/workbench/src/unifiedComposerHelpers.ts b/app/workbench/src/composer/unifiedComposerHelpers.ts
similarity index 93%
rename from app/workbench/src/unifiedComposerHelpers.ts
rename to app/workbench/src/composer/unifiedComposerHelpers.ts
index 1ea2ba108..7c1c6afe6 100644
--- a/app/workbench/src/unifiedComposerHelpers.ts
+++ b/app/workbench/src/composer/unifiedComposerHelpers.ts
@@ -1,13 +1,6 @@
import type { ComposerAttachment, ComposerMention, ComposerState } from '@shared/composer';
import { canSubmitComposer, formatComposerAttachmentSize } from '@shared/composer';
-import type { ComposerSubmitBehavior } from './workbenchPreferences';
-
-/* ═══════════════════════════════════════════════════════════════════════
- unifiedComposerHelpers — pure helpers for UnifiedComposer (#638).
-
- Status/label builders, mention filtering, and submit-key planners.
- No React hooks.
- ═══════════════════════════════════════════════════════════════════════ */
+import type { ComposerSubmitBehavior } from '../workbenchPreferences';
export interface AttachmentUploadState {
percent: number;
diff --git a/app/workbench/src/unifiedComposerHostActions.test.ts b/app/workbench/src/composer/unifiedComposerHostActions.test.ts
similarity index 100%
rename from app/workbench/src/unifiedComposerHostActions.test.ts
rename to app/workbench/src/composer/unifiedComposerHostActions.test.ts
diff --git a/app/workbench/src/unifiedComposerHostActions.ts b/app/workbench/src/composer/unifiedComposerHostActions.ts
similarity index 81%
rename from app/workbench/src/unifiedComposerHostActions.ts
rename to app/workbench/src/composer/unifiedComposerHostActions.ts
index 883613fe8..7691d20e7 100644
--- a/app/workbench/src/unifiedComposerHostActions.ts
+++ b/app/workbench/src/composer/unifiedComposerHostActions.ts
@@ -6,13 +6,6 @@ import type {
} from '@shared/composer';
import { findMentionById } from './unifiedComposerHelpers';
-/* ═══════════════════════════════════════════════════════════════════════
- unifiedComposerHostActions — pure action builders (#780).
-
- Mention/attachment/text/reply/quote action builders and attachment
- dispatch helpers. No React hooks.
- ═══════════════════════════════════════════════════════════════════════ */
-
/** Plan mention add action from a picker selection. */
export function planAddMentionAction(
mentionableAgents: ComposerMention[],
diff --git a/app/workbench/src/unifiedComposerHostFilePick.test.ts b/app/workbench/src/composer/unifiedComposerHostFilePick.test.ts
similarity index 100%
rename from app/workbench/src/unifiedComposerHostFilePick.test.ts
rename to app/workbench/src/composer/unifiedComposerHostFilePick.test.ts
diff --git a/app/workbench/src/unifiedComposerHostFilePick.ts b/app/workbench/src/composer/unifiedComposerHostFilePick.ts
similarity index 87%
rename from app/workbench/src/unifiedComposerHostFilePick.ts
rename to app/workbench/src/composer/unifiedComposerHostFilePick.ts
index 6e42c4e71..dffac6fdf 100644
--- a/app/workbench/src/unifiedComposerHostFilePick.ts
+++ b/app/workbench/src/composer/unifiedComposerHostFilePick.ts
@@ -1,12 +1,5 @@
import type { ComposerAttachment } from '@shared/composer';
-/* ═══════════════════════════════════════════════════════════════════════
- unifiedComposerHostFilePick — pure file-picker planners (#780).
-
- File-input / native-picker planners and attachment resolution.
- No React hooks.
- ═══════════════════════════════════════════════════════════════════════ */
-
export type ComposerFilePickPlan =
| { kind: 'noop' }
| { kind: 'native' }
diff --git a/app/workbench/src/unifiedComposerHostHelpers.test.ts b/app/workbench/src/composer/unifiedComposerHostHelpers.test.ts
similarity index 100%
rename from app/workbench/src/unifiedComposerHostHelpers.test.ts
rename to app/workbench/src/composer/unifiedComposerHostHelpers.test.ts
diff --git a/app/workbench/src/unifiedComposerHostHelpers.ts b/app/workbench/src/composer/unifiedComposerHostHelpers.ts
similarity index 69%
rename from app/workbench/src/unifiedComposerHostHelpers.ts
rename to app/workbench/src/composer/unifiedComposerHostHelpers.ts
index bbfe9386a..d9457e130 100644
--- a/app/workbench/src/unifiedComposerHostHelpers.ts
+++ b/app/workbench/src/composer/unifiedComposerHostHelpers.ts
@@ -1,17 +1,3 @@
-/* ═══════════════════════════════════════════════════════════════════════
- unifiedComposerHostHelpers — stable public surface for UnifiedComposer
- host pure helpers (#718 / helper module #780).
-
- Implementation lives in:
- - unifiedComposerHostViewModel
- - unifiedComposerHostKeyDown
- - unifiedComposerHostActions
- - unifiedComposerHostFilePick
-
- Re-exports keep import paths stable for UnifiedComposer and tests.
- No React hooks.
- ═══════════════════════════════════════════════════════════════════════ */
-
export type {
AttachmentUploadState,
ComposerExecutionTarget,
diff --git a/app/workbench/src/unifiedComposerHostKeyDown.test.ts b/app/workbench/src/composer/unifiedComposerHostKeyDown.test.ts
similarity index 100%
rename from app/workbench/src/unifiedComposerHostKeyDown.test.ts
rename to app/workbench/src/composer/unifiedComposerHostKeyDown.test.ts
diff --git a/app/workbench/src/unifiedComposerHostKeyDown.ts b/app/workbench/src/composer/unifiedComposerHostKeyDown.ts
similarity index 89%
rename from app/workbench/src/unifiedComposerHostKeyDown.ts
rename to app/workbench/src/composer/unifiedComposerHostKeyDown.ts
index 0ee45a24c..07f7dd7db 100644
--- a/app/workbench/src/unifiedComposerHostKeyDown.ts
+++ b/app/workbench/src/composer/unifiedComposerHostKeyDown.ts
@@ -1,5 +1,5 @@
import type { ComposerAction, ComposerAttachment } from '@shared/composer';
-import type { ComposerSubmitBehavior } from './workbenchPreferences';
+import type { ComposerSubmitBehavior } from '../workbenchPreferences';
import {
buildTextWithNewline,
canSubmitFromKeyDown,
@@ -7,13 +7,6 @@ import {
} from './unifiedComposerHelpers';
import { setComposerTextAction } from './unifiedComposerHostActions';
-/* ═══════════════════════════════════════════════════════════════════════
- unifiedComposerHostKeyDown — pure keydown planners (#780).
-
- Keydown event field readers, submit/newline planners, and host effect
- mappers. No React hooks.
- ═══════════════════════════════════════════════════════════════════════ */
-
export type ComposerHostKeyDownPlan =
| { kind: 'none' }
| { kind: 'insert-newline'; nextText: string; caret: number }
diff --git a/app/workbench/src/unifiedComposerHostViewModel.test.ts b/app/workbench/src/composer/unifiedComposerHostViewModel.test.ts
similarity index 100%
rename from app/workbench/src/unifiedComposerHostViewModel.test.ts
rename to app/workbench/src/composer/unifiedComposerHostViewModel.test.ts
diff --git a/app/workbench/src/unifiedComposerHostViewModel.ts b/app/workbench/src/composer/unifiedComposerHostViewModel.ts
similarity index 91%
rename from app/workbench/src/unifiedComposerHostViewModel.ts
rename to app/workbench/src/composer/unifiedComposerHostViewModel.ts
index 428925af5..ed5635f75 100644
--- a/app/workbench/src/unifiedComposerHostViewModel.ts
+++ b/app/workbench/src/composer/unifiedComposerHostViewModel.ts
@@ -11,7 +11,7 @@ import type {
QuoteContext,
ReplyToContext,
} from '@shared/composer';
-import type { ComposerSubmitBehavior } from './workbenchPreferences';
+import type { ComposerSubmitBehavior } from '../workbenchPreferences';
import {
COMPOSER_FILE_ACCEPT,
deriveUnifiedComposerState,
@@ -22,16 +22,6 @@ import {
type UnifiedComposerDerivedState,
} from './unifiedComposerHelpers';
-/* ═══════════════════════════════════════════════════════════════════════
- unifiedComposerHostViewModel — pure host view/chrome builders (#780).
-
- Props types, runtime defaults, chrome visibility, chrome render model,
- and combined host view-model builders.
- No React hooks.
- exactOptionalPropertyTypes: only assign `?: T` fields when defined,
- unless the public field type explicitly allows `| undefined`.
- ═══════════════════════════════════════════════════════════════════════ */
-
export type {
AttachmentUploadState,
ComposerExecutionTarget,
diff --git a/app/workbench/src/hubDataMapping.test.ts b/app/workbench/src/hubDataMapping.test.ts
index f4b475de1..34ff02687 100644
--- a/app/workbench/src/hubDataMapping.test.ts
+++ b/app/workbench/src/hubDataMapping.test.ts
@@ -1,6 +1,6 @@
import { beforeAll, describe, expect, it } from 'vitest';
import { useTestI18nLanguage } from '@shared/testing/i18n';
-import type { ProjectInfo } from './pages';
+import type { ProjectInfo } from './pages/index';
import {
contactInfoToMember,
hubDocumentToDocRow,
diff --git a/app/workbench/src/hubDataMapping.ts b/app/workbench/src/hubDataMapping.ts
index 98db69bf2..84bdd1517 100644
--- a/app/workbench/src/hubDataMapping.ts
+++ b/app/workbench/src/hubDataMapping.ts
@@ -11,7 +11,7 @@
import { appDateLocaleTag } from '@shared/i18n/locale';
import { SHARED_WORKBENCH_I18N_NAMESPACE } from '@shared/i18n';
import { getI18n } from 'react-i18next';
-import type { ContactMember, ProjectInfo } from './pages';
+import type { ContactMember, ProjectInfo } from './pages/index';
import type { WorkbenchContactsData } from './WorkbenchRoutes';
import type { DocRow } from './pages/DocsPage';
import type { WorkbenchConversation } from '@shared/platform';
diff --git a/app/workbench/src/index.ts b/app/workbench/src/index.ts
index 2ee4d1c93..c8b9e8548 100644
--- a/app/workbench/src/index.ts
+++ b/app/workbench/src/index.ts
@@ -1,10 +1,10 @@
export { AgentHubWorkbench } from './AgentHubWorkbench';
-export { ChatViewBridge } from './ChatViewBridge';
-export { ConversationSidebar } from './ConversationSidebar';
+export { ChatViewBridge } from './transcript/ChatViewBridge';
+export { ConversationSidebar } from './transcript/ConversationSidebar';
export { GlobalRail } from './GlobalRail';
-export { RightInspector } from './RightInspector';
-export { UnifiedComposer } from './UnifiedComposer';
-export { WorkbenchGoalBanner } from './WorkbenchGoalBanner';
+export { RightInspector } from './inspector/RightInspector';
+export { UnifiedComposer } from './composer/UnifiedComposer';
+export { WorkbenchGoalBanner } from './transcript/WorkbenchGoalBanner';
export { WorkbenchRoutes } from './WorkbenchRoutes';
export { WorkspaceHeader } from './WorkspaceHeader';
export {
@@ -22,8 +22,8 @@ export {
export {
buildMainchainSummary,
runtimeEvidenceSourceSummary,
-} from './mainchain';
-export { MainchainStatusStrip } from './MainchainStatusStrip';
+} from './mainchain/index';
+export { MainchainStatusStrip } from './transcript/MainchainStatusStrip';
export {
buildActiveConversationAttention,
deriveConversationLiveStatus,
@@ -31,7 +31,7 @@ export {
isRunActive,
summarizeWorkbenchAttention,
} from './workbenchAttentionModel';
-export { GOAL_TOOL_NAMES, deriveGoalSummary } from './workbenchGoalSummary';
+export { GOAL_TOOL_NAMES, deriveGoalSummary } from './transcript/workbenchGoalSummary';
export type { TranscriptContextMenuEvent, TranscriptPointerEvent } from './transcriptEventTypes';
export {
buildAgentCapabilityContractFromConfig,
@@ -84,18 +84,18 @@ export {
/* ── Types ── */
export type { AgentHubWorkbenchProps } from './AgentHubWorkbench';
-export type { ChatViewBridgeProps } from './ChatViewBridge';
-export type { ConversationSidebarProps } from './ConversationSidebar';
+export type { ChatViewBridgeProps } from './transcript/ChatViewBridge';
+export type { ConversationSidebarProps } from './transcript/ConversationSidebar';
export type { GlobalRailProps, GlobalRailPage, ConnectionStatusKind } from './GlobalRail';
-export type { RightInspectorProps, RuntimeEvidenceSnapshot } from './RightInspector';
-export type { UnifiedComposerProps } from './UnifiedComposer';
+export type { RightInspectorProps, RuntimeEvidenceSnapshot } from './inspector/RightInspector';
+export type { UnifiedComposerProps } from './composer/UnifiedComposer';
export type {
MainchainNode,
MainchainSummary,
MainchainStatusKind,
MainchainWorkbenchStatus,
-} from './mainchain';
-export type { MainchainStatusStripProps } from './MainchainStatusStrip';
+} from './mainchain/index';
+export type { MainchainStatusStripProps } from './transcript/MainchainStatusStrip';
export type {
ActiveConversationAttentionInput,
ConversationLiveStatus,
@@ -103,8 +103,8 @@ export type {
WorkbenchAttentionInput,
WorkbenchAttentionSummary,
} from './workbenchAttentionModel';
-export type { WorkbenchGoalBannerProps } from './WorkbenchGoalBanner';
-export type { WorkbenchGoalStatus, WorkbenchGoalSummary } from './workbenchGoalSummary';
+export type { WorkbenchGoalBannerProps } from './transcript/WorkbenchGoalBanner';
+export type { WorkbenchGoalStatus, WorkbenchGoalSummary } from './transcript/workbenchGoalSummary';
export type {
WorkbenchAgentProfilesStatus,
WorkbenchContactsData,
@@ -126,7 +126,7 @@ export {
TasksPage,
DevicesPage,
TokenUsagePage,
-} from './pages';
+} from './pages/index';
export type {
AgentsPageProps,
AgentConfig,
@@ -170,31 +170,31 @@ export type {
TokenUsagePageProps,
TokenUsagePageTeam,
TokenUsagePageRun,
-} from './pages';
+} from './pages/index';
/* ═══ Inspector panels ═══ */
export {
OverviewPanel,
FilePreview,
BrowserPreview,
-} from './inspector';
+} from './inspector/index';
export type {
OverviewPanelProps,
TaskItem as InspectorTaskItem,
FileItem,
FilePreviewProps,
BrowserPreviewProps,
-} from './inspector';
+} from './inspector/index';
/* ═══ Terminal host shell (#1174) ═══ */
export {
TerminalPanel,
isLocalTerminalEnabled,
-} from './terminal';
+} from './terminal/index';
export type {
TerminalPanelLabels,
TerminalPanelProps,
-} from './terminal';
+} from './terminal/index';
/* ═══ Floating components ═══ */
export {
@@ -203,7 +203,7 @@ export {
PersonPanel,
ProfilePopover,
DemoToast,
-} from './floating';
+} from './floating/index';
export type {
ContextMenuProps,
ContextMenuItem,
@@ -212,11 +212,11 @@ export type {
PersonPanelProps,
ProfilePopoverProps,
DemoToastProps,
-} from './floating';
+} from './floating/index';
-export * from './auxPanel';
+export * from './auxPanel/index';
-export * from './sessionImport';
+export * from './sessionImport/index';
/* ═══ Team subagent stream (#1478 / #1406) ═══ */
export {
@@ -228,7 +228,7 @@ export {
type SubagentStreamListener,
type TeamSubagentStreamEvent,
type SubagentStreamOverlayProps,
-} from './team';
+} from './team/index';
/* ═══ Inline message delegation (#1406) ═══ */
export {
@@ -241,4 +241,4 @@ export {
type DelegationEntry,
type DelegationStatus,
type MessageDelegationListener,
-} from './team';
+} from './team/index';
diff --git a/app/workbench/src/RightInspector.tsx b/app/workbench/src/inspector/RightInspector.tsx
similarity index 98%
rename from app/workbench/src/RightInspector.tsx
rename to app/workbench/src/inspector/RightInspector.tsx
index f549c2b84..cf66ff28d 100644
--- a/app/workbench/src/RightInspector.tsx
+++ b/app/workbench/src/inspector/RightInspector.tsx
@@ -11,9 +11,9 @@ import {
defaultVisibleTabs,
getInspectorTabs,
type InspectorMode,
-} from './inspector';
-import { WORKBENCH_INSPECTOR_QUICK_OPEN_EVENT } from './desktopChromeEvents';
-import styles from './AgentHubWorkbench.module.css';
+} from './index';
+import { WORKBENCH_INSPECTOR_QUICK_OPEN_EVENT } from '../desktopChromeEvents';
+import styles from '../AgentHubWorkbench.module.css';
import { RightInspectorModePanel } from './RightInspectorModePanel';
import { RightInspectorResizer } from './RightInspectorResizer';
import {
diff --git a/app/workbench/src/RightInspectorModePanel.tsx b/app/workbench/src/inspector/RightInspectorModePanel.tsx
similarity index 98%
rename from app/workbench/src/RightInspectorModePanel.tsx
rename to app/workbench/src/inspector/RightInspectorModePanel.tsx
index 7af0d95c8..a8dcc6a95 100644
--- a/app/workbench/src/RightInspectorModePanel.tsx
+++ b/app/workbench/src/inspector/RightInspectorModePanel.tsx
@@ -11,12 +11,12 @@ import {
type PreviewFile,
type RunResultInfo,
type TaskItem,
-} from './inspector';
+} from './index';
import type { DagNode } from '@shared/ui/DagTree';
import type { FileDiff } from '@shared/types/chat';
import { useTranslation } from 'react-i18next';
import { CHATVIEW_I18N_NAMESPACE } from '@shared/chatview/i18n/resources';
-import styles from './AgentHubWorkbench.module.css';
+import styles from '../AgentHubWorkbench.module.css';
/* ═══════════════════════════════════════════════════════════════════════
RightInspectorModePanel — mode tabpanel bodies for RightInspector (#661).
diff --git a/app/workbench/src/RightInspectorResizer.tsx b/app/workbench/src/inspector/RightInspectorResizer.tsx
similarity index 96%
rename from app/workbench/src/RightInspectorResizer.tsx
rename to app/workbench/src/inspector/RightInspectorResizer.tsx
index 538386d8d..daf2f2ed5 100644
--- a/app/workbench/src/RightInspectorResizer.tsx
+++ b/app/workbench/src/inspector/RightInspectorResizer.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { CHATVIEW_I18N_NAMESPACE } from '@shared/chatview/i18n/resources';
-import styles from './AgentHubWorkbench.module.css';
+import styles from '../AgentHubWorkbench.module.css';
/* ═══════════════════════════════════════════════════════════════════════
RightInspectorResizer — keyboard/pointer vertical resizer chrome for
diff --git a/app/workbench/src/rightInspectorHelpers.test.ts b/app/workbench/src/inspector/rightInspectorHelpers.test.ts
similarity index 100%
rename from app/workbench/src/rightInspectorHelpers.test.ts
rename to app/workbench/src/inspector/rightInspectorHelpers.test.ts
diff --git a/app/workbench/src/rightInspectorHelpers.ts b/app/workbench/src/inspector/rightInspectorHelpers.ts
similarity index 94%
rename from app/workbench/src/rightInspectorHelpers.ts
rename to app/workbench/src/inspector/rightInspectorHelpers.ts
index a70c66aa5..d7adf0a8f 100644
--- a/app/workbench/src/rightInspectorHelpers.ts
+++ b/app/workbench/src/inspector/rightInspectorHelpers.ts
@@ -4,20 +4,20 @@ import type { RuntimeEvidenceSnapshot } from '@shared/inspector';
import type { FileDiff } from '@shared/types/chat';
import type { DagNode } from '@shared/ui/DagTree';
import { buildDagNodesFromTranscript } from '@shared/ui/DagTree';
-import { isThemedBlankPreviewUrl } from './inspector/BrowserPreview';
-import type { PreviewFile } from './inspector/FilePreviewRouter';
+import { isThemedBlankPreviewUrl } from './BrowserPreview';
+import type { PreviewFile } from './FilePreviewRouter';
import {
evidenceOverviewFiles,
evidenceOverviewTasks,
-} from './inspector/InspectorModePanels';
-import type { InspectorTranslator } from './inspector/InspectorModePanelHelpers';
-import type { InspectorMode, InspectorTabDef } from './inspector/InspectorTabChrome';
-import type { FileItem, TaskItem } from './inspector/OverviewPanel';
+} from './InspectorModePanels';
+import type { InspectorTranslator } from './InspectorModePanelHelpers';
+import type { InspectorMode, InspectorTabDef } from './InspectorTabChrome';
+import type { FileItem, TaskItem } from './OverviewPanel';
import {
runtimeDiffPreviewFile,
runtimeEvidenceOverviewFiles,
runtimeEvidenceOverviewTasks,
-} from './inspector/RuntimeEvidencePanel';
+} from './RuntimeEvidencePanel';
/* ═══════════════════════════════════════════════════════════════════════
rightInspectorHelpers — pure helpers for RightInspector (#661).
diff --git a/app/workbench/src/rightInspectorTypes.ts b/app/workbench/src/inspector/rightInspectorTypes.ts
similarity index 94%
rename from app/workbench/src/rightInspectorTypes.ts
rename to app/workbench/src/inspector/rightInspectorTypes.ts
index 7c72fb0dd..477abed09 100644
--- a/app/workbench/src/rightInspectorTypes.ts
+++ b/app/workbench/src/inspector/rightInspectorTypes.ts
@@ -8,8 +8,8 @@ import type {
SubagentTranscriptBlock,
SubtaskTranscriptBlock,
} from '@shared/transcript';
-import type { FileItem, RunResultInfo } from './inspector/OverviewPanel';
-import type { BrowserPreviewFocusRequest } from './workbenchSessionChromeHelpers';
+import type { FileItem, RunResultInfo } from './OverviewPanel';
+import type { BrowserPreviewFocusRequest } from '../transcript/workbenchSessionChromeHelpers';
/* ═══════════════════════════════════════════════════════════════════════
rightInspectorTypes — public props / shared types for
diff --git a/app/workbench/src/useEngineeringColumnAutoOpen.test.tsx b/app/workbench/src/inspector/useEngineeringColumnAutoOpen.test.tsx
similarity index 97%
rename from app/workbench/src/useEngineeringColumnAutoOpen.test.tsx
rename to app/workbench/src/inspector/useEngineeringColumnAutoOpen.test.tsx
index 8bf764d88..80fc00e70 100644
--- a/app/workbench/src/useEngineeringColumnAutoOpen.test.tsx
+++ b/app/workbench/src/inspector/useEngineeringColumnAutoOpen.test.tsx
@@ -1,6 +1,6 @@
import { act, renderHook, waitFor } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
-import type { WorkbenchPanelLayout } from './useWorkbenchPanelLayout';
+import type { WorkbenchPanelLayout } from '../useWorkbenchPanelLayout';
import {
canAutoOpenEngineeringColumn,
engineeringColumnActivitySignal,
@@ -9,7 +9,7 @@ import {
import {
readEngineeringColumnPreference,
writeEngineeringColumnPreference,
-} from './workbenchPreferences';
+} from '../workbenchPreferences';
function layoutMock(collapsed: boolean) {
return {
diff --git a/app/workbench/src/useEngineeringColumnAutoOpen.ts b/app/workbench/src/inspector/useEngineeringColumnAutoOpen.ts
similarity index 95%
rename from app/workbench/src/useEngineeringColumnAutoOpen.ts
rename to app/workbench/src/inspector/useEngineeringColumnAutoOpen.ts
index 3d874cd88..cdb40cf35 100644
--- a/app/workbench/src/useEngineeringColumnAutoOpen.ts
+++ b/app/workbench/src/inspector/useEngineeringColumnAutoOpen.ts
@@ -1,12 +1,12 @@
import { useCallback, useEffect, useMemo, useRef } from 'react';
import type { RuntimeEvidenceSnapshot } from '@shared/inspector';
import type { AgentHubPlatform } from '@shared/platform';
-import type { WorkbenchPanelLayout } from './useWorkbenchPanelLayout';
+import type { WorkbenchPanelLayout } from '../useWorkbenchPanelLayout';
import {
readEngineeringColumnPreference,
writeEngineeringColumnPreference,
-} from './workbenchPreferences';
-import { WORKSPACE_MOUNT_COLLAPSE_INSPECTOR_WIDTH } from './workbenchLayoutConstants';
+} from '../workbenchPreferences';
+import { WORKSPACE_MOUNT_COLLAPSE_INSPECTOR_WIDTH } from '../workbenchLayoutConstants';
export interface EngineeringColumnActivityInput {
isAgentRunning?: boolean | undefined;
diff --git a/app/workbench/src/mainchain/buildMainchainSummary.ts b/app/workbench/src/mainchain/buildMainchainSummary.ts
index db73ae120..93e094b3e 100644
--- a/app/workbench/src/mainchain/buildMainchainSummary.ts
+++ b/app/workbench/src/mainchain/buildMainchainSummary.ts
@@ -1,6 +1,6 @@
import type { AgentHubPlatform } from '@shared/platform';
import type { EvidenceRef, TranscriptBlock } from '@shared/transcript';
-import type { RuntimeEvidenceSnapshot } from '../RightInspector';
+import type { RuntimeEvidenceSnapshot } from '../inspector/RightInspector';
import type { MainchainNode, MainchainSummary } from './types';
export type MainchainWorkbenchStatus = {
diff --git a/app/workbench/src/pages/AgentsPage.tsx b/app/workbench/src/pages/AgentsPage.tsx
index b466b75ab..f62d5c105 100644
--- a/app/workbench/src/pages/AgentsPage.tsx
+++ b/app/workbench/src/pages/AgentsPage.tsx
@@ -18,11 +18,11 @@ import {
AgentModelsView,
AgentAuditView,
DataSourceBadge,
-} from './agents';
+} from './agents/index';
import type {
AgentsPaneId,
AgentsPageProps,
-} from './agents';
+} from './agents/index';
/* ═══════════════════════════════════════════════════════════════════════
AgentsPage — AgentHub v4
@@ -61,7 +61,7 @@ export type {
CCSwitchStatusInfo,
CCSwitchProviderInfo,
AgentsPageProps,
-} from './agents';
+} from './agents/index';
/* ═══════════════════════════════════════════════════════════════════════
AgentsPage
diff --git a/app/workbench/src/pages/ContactsPage.tsx b/app/workbench/src/pages/ContactsPage.tsx
index fadda1f94..cac50bd46 100644
--- a/app/workbench/src/pages/ContactsPage.tsx
+++ b/app/workbench/src/pages/ContactsPage.tsx
@@ -6,8 +6,8 @@ import {
AddContactModal,
ContactMain,
ContactNav,
-} from './contacts';
-import type { ContactsPageProps } from './contacts';
+} from './contacts/index';
+import type { ContactsPageProps } from './contacts/index';
/* ═══════════════════════════════════════════════════════════════════════
ContactsPage — pure presentational workbench page
@@ -30,7 +30,7 @@ export type {
ContactModalTab,
ContactProfile,
ContactsPageProps,
-} from './contacts';
+} from './contacts/index';
// ── Main component ──
diff --git a/app/workbench/src/pages/DocsPage.tsx b/app/workbench/src/pages/DocsPage.tsx
index 0afe13d20..649c18fc4 100644
--- a/app/workbench/src/pages/DocsPage.tsx
+++ b/app/workbench/src/pages/DocsPage.tsx
@@ -3,8 +3,8 @@ import styles from './DocsPage.module.css';
import {
DocMain,
DocsNav,
-} from './docs';
-import type { DocsPageProps } from './docs';
+} from './docs/index';
+import type { DocsPageProps } from './docs/index';
/* ═══════════════════════════════════════════════════════════════════════
DocsPage — pure presentational workbench page
@@ -21,7 +21,7 @@ export type {
DocsPane,
DocsPageNavItem,
DocsPageProps,
-} from './docs';
+} from './docs/index';
// ── Main component ──
diff --git a/app/workbench/src/pages/ProjectsPage.test.tsx b/app/workbench/src/pages/ProjectsPage.test.tsx
index 353d56858..8eaf88c85 100644
--- a/app/workbench/src/pages/ProjectsPage.test.tsx
+++ b/app/workbench/src/pages/ProjectsPage.test.tsx
@@ -3,7 +3,7 @@ import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest';
import { fireEvent, render, screen, within } from '../__tests__/setup';
import { ProjectsPage } from './ProjectsPage';
import { WORKBENCH_MOCK_PROJECTS } from '../mockData';
-import type { ProjectInfo, ProjectsPageProps } from './projects';
+import type { ProjectInfo, ProjectsPageProps } from './projects/index';
// Projects copy resolves via the sharedWorkbench namespace; opt into the zh
// bundle of the shared test i18next instance (Issue #1717).
diff --git a/app/workbench/src/pages/ProjectsPage.tsx b/app/workbench/src/pages/ProjectsPage.tsx
index 52b381898..8fff49cf8 100644
--- a/app/workbench/src/pages/ProjectsPage.tsx
+++ b/app/workbench/src/pages/ProjectsPage.tsx
@@ -5,8 +5,8 @@ import {
ProjectMain,
ProjectNav,
useProjectEditor,
-} from './projects';
-import type { ProjectsPageProps } from './projects';
+} from './projects/index';
+import type { ProjectsPageProps } from './projects/index';
/* ═══════════════════════════════════════════════════════════════════════
ProjectsPage — pure presentational workbench page
@@ -26,7 +26,7 @@ export type {
ProjectDraft,
ProjectTab,
ProjectsPageProps,
-} from './projects';
+} from './projects/index';
// ── Main component ──
diff --git a/app/workbench/src/pages/SettingsPage.tsx b/app/workbench/src/pages/SettingsPage.tsx
index 9804ff2a3..630a75529 100644
--- a/app/workbench/src/pages/SettingsPage.tsx
+++ b/app/workbench/src/pages/SettingsPage.tsx
@@ -3,8 +3,8 @@ import styles from './SettingsPage.module.css';
import {
SettingsMain,
SettingsNav,
-} from './settings';
-import type { SettingsPageProps } from './settings';
+} from './settings/index';
+import type { SettingsPageProps } from './settings/index';
/* ═══════════════════════════════════════════════════════════════════════
SettingsPage — AgentHub v4
@@ -20,7 +20,7 @@ export type {
SettingsPageProps,
SettingsPaneId,
StatePanelKind,
-} from './settings';
+} from './settings/index';
/* ═══════════════════════════════════════════════════════════════════════
Main export
diff --git a/app/workbench/src/pages/TasksPage.tsx b/app/workbench/src/pages/TasksPage.tsx
index f5c96f98c..f3be957b4 100644
--- a/app/workbench/src/pages/TasksPage.tsx
+++ b/app/workbench/src/pages/TasksPage.tsx
@@ -3,8 +3,8 @@ import styles from './TasksPage.module.css';
import {
TaskMain,
TaskNav,
-} from './tasks';
-import type { TasksPageProps } from './tasks';
+} from './tasks/index';
+import type { TasksPageProps } from './tasks/index';
/* ═══════════════════════════════════════════════════════════════════════
TasksPage — pure presentational workbench page
@@ -24,7 +24,7 @@ export type {
TaskGroup,
TaskEditDraft,
TasksPageProps,
-} from './tasks';
+} from './tasks/index';
// ── Main component ──
diff --git a/app/workbench/src/pages/contacts/ContactMainParts.tsx b/app/workbench/src/pages/contacts/ContactMainParts.tsx
index 81e87edbf..a330f8c24 100644
--- a/app/workbench/src/pages/contacts/ContactMainParts.tsx
+++ b/app/workbench/src/pages/contacts/ContactMainParts.tsx
@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import { SHARED_WORKBENCH_I18N_NAMESPACE } from '@shared/i18n';
import { StatusNotice } from '@shared/ui';
import { DesignNavIcon } from '../../designIcons';
-import { ProfilePopover } from '../../floating';
+import { ProfilePopover } from '../../floating/index';
import styles from '../ContactsPage.module.css';
import { QuickActionGrid } from './ContactRows';
import {
diff --git a/app/workbench/src/pages/docs/DocTableViews.tsx b/app/workbench/src/pages/docs/DocTableViews.tsx
index 4da3a1534..d41993a8c 100644
--- a/app/workbench/src/pages/docs/DocTableViews.tsx
+++ b/app/workbench/src/pages/docs/DocTableViews.tsx
@@ -7,7 +7,7 @@ import { useTranslation } from 'react-i18next';
import { SHARED_WORKBENCH_I18N_NAMESPACE } from '@shared/i18n';
import { DesignNavIcon } from '../../designIcons';
import type { WorkbenchDocumentPreview } from '../../documentPreview';
-import { FilePreview } from '../../inspector';
+import { FilePreview } from '../../inspector/index';
import {
resolveWorkbenchProfile,
type WorkbenchProfileSource,
diff --git a/app/workbench/src/pages/projects/ProjectPanelParts.tsx b/app/workbench/src/pages/projects/ProjectPanelParts.tsx
index 049ac34d7..457ed0b73 100644
--- a/app/workbench/src/pages/projects/ProjectPanelParts.tsx
+++ b/app/workbench/src/pages/projects/ProjectPanelParts.tsx
@@ -11,7 +11,7 @@ import { useTranslation } from 'react-i18next';
import { SHARED_WORKBENCH_I18N_NAMESPACE } from '@shared/i18n';
import { DesignFileIcon } from '../../designIcons';
import type { WorkbenchDocumentPreview } from '../../documentPreview';
-import { FilePreview } from '../../inspector';
+import { FilePreview } from '../../inspector/index';
import {
resolveWorkbenchProfile,
type WorkbenchProfileSource,
diff --git a/app/workbench/src/pages/settings/SettingsPanes.tsx b/app/workbench/src/pages/settings/SettingsPanes.tsx
index 2713df29a..5a7479fc7 100644
--- a/app/workbench/src/pages/settings/SettingsPanes.tsx
+++ b/app/workbench/src/pages/settings/SettingsPanes.tsx
@@ -20,9 +20,9 @@ import {
LocalCliDiscoveryStatus,
StatePreviewSection,
} from './SettingsPaneParts';
-import { SessionImportList } from '../../sessionImport';
+import { SessionImportList } from '../../sessionImport/index';
import { ThemePresetPicker } from './ThemePresetPicker';
-import { writeClipboardText } from '../../workbenchTranscriptChromeStateHelpers';
+import { writeClipboardText } from '../../transcript/workbenchTranscriptChromeStateHelpers';
import { resolvePermissionValue } from './SettingsPaneHelpers';
import { PERMISSION_ROWS } from './types';
import type { SettingsPageProps, SettingsPaneId } from './types';
diff --git a/app/workbench/src/pages/tasks/TaskMainViews.tsx b/app/workbench/src/pages/tasks/TaskMainViews.tsx
index d5ea297d9..f4873a5bd 100644
--- a/app/workbench/src/pages/tasks/TaskMainViews.tsx
+++ b/app/workbench/src/pages/tasks/TaskMainViews.tsx
@@ -15,7 +15,7 @@ import styles from '../TasksPage.module.css';
import { TaskSelectionStrip, TaskTable } from './TaskTableViews';
import { buildViewModes, paneTitle, StatCard } from './shared';
import type { TasksPageProps } from './types';
-import { needsHubOnlyMergeNotice } from '../../workbenchBoardColumns';
+import { needsHubOnlyMergeNotice } from '../../routes/workbenchBoardColumns';
export type TaskMainProps = Pick<
TasksPageProps,
diff --git a/app/workbench/src/pages/tasks/TaskReviewMerge.test.tsx b/app/workbench/src/pages/tasks/TaskReviewMerge.test.tsx
index 9c22d62d3..ef1270ff8 100644
--- a/app/workbench/src/pages/tasks/TaskReviewMerge.test.tsx
+++ b/app/workbench/src/pages/tasks/TaskReviewMerge.test.tsx
@@ -4,7 +4,7 @@ import { fireEvent, render, screen, within } from '../../__tests__/setup';
import { useTestI18nLanguage } from '@shared/testing/i18n';
import { TaskMain } from './TaskMainViews';
import type { TasksPageProps, TaskGroup, TaskItem } from './types';
-import type { TaskReviewMergePort } from '../../workbenchBoardColumns';
+import type { TaskReviewMergePort } from '../../routes/workbenchBoardColumns';
/* ═══════════════════════════════════════════════════════════════════════
review-before-merge behavior (#1999):
diff --git a/app/workbench/src/pages/tasks/TaskTableParts.tsx b/app/workbench/src/pages/tasks/TaskTableParts.tsx
index ed216cdbe..44e326a07 100644
--- a/app/workbench/src/pages/tasks/TaskTableParts.tsx
+++ b/app/workbench/src/pages/tasks/TaskTableParts.tsx
@@ -28,7 +28,7 @@ import {
resolveReviewMergeDecision,
type BoardColumnTone,
type TaskReviewMergePort,
-} from '../../workbenchBoardColumns';
+} from '../../routes/workbenchBoardColumns';
/* ═══════════════════════════════════════════════════════════════════════
TaskTableParts — presentational parts for TaskTableViews
diff --git a/app/workbench/src/pages/tasks/types.ts b/app/workbench/src/pages/tasks/types.ts
index 05c35e368..5ff38a022 100644
--- a/app/workbench/src/pages/tasks/types.ts
+++ b/app/workbench/src/pages/tasks/types.ts
@@ -3,7 +3,7 @@
═══════════════════════════════════════════════════════════════════════ */
import type { WorkbenchProfileSource } from '../../profileRegistry';
-import type { BoardColumnTone, TaskReviewMergePort } from '../../workbenchBoardColumns';
+import type { BoardColumnTone, TaskReviewMergePort } from '../../routes/workbenchBoardColumns';
import type { AgentHubSurface } from '@shared/platform';
export type TaskStatus =
diff --git a/app/workbench/src/WorkbenchAgentsRouteView.tsx b/app/workbench/src/routes/WorkbenchAgentsRouteView.tsx
similarity index 94%
rename from app/workbench/src/WorkbenchAgentsRouteView.tsx
rename to app/workbench/src/routes/WorkbenchAgentsRouteView.tsx
index a9cf13f2f..311716986 100644
--- a/app/workbench/src/WorkbenchAgentsRouteView.tsx
+++ b/app/workbench/src/routes/WorkbenchAgentsRouteView.tsx
@@ -1,13 +1,13 @@
import React, { useMemo } from 'react';
import type { WorkbenchAgent } from '@shared/platform';
-import type { AgentConfig, SkillMarketItem, MCPMarketItem } from './pages/AgentsPage';
-import { AgentsPage } from './pages/AgentsPage';
+import type { AgentConfig, SkillMarketItem, MCPMarketItem } from '../pages/AgentsPage';
+import { AgentsPage } from '../pages/AgentsPage';
import {
WORKBENCH_MOCK_AGENT_AUDIT_ROWS,
WORKBENCH_MOCK_AGENT_MODEL_HEALTH,
WORKBENCH_MOCK_AGENT_POLICY_RULES,
WORKBENCH_MOCK_AGENT_TOOL_OPTIONS,
-} from './mockData';
+} from '../mockData';
import type {
WorkbenchAgentsRoute,
WorkbenchAgentsRouteStatus,
@@ -26,8 +26,8 @@ export interface WorkbenchAgentsRouteViewProps {
mcpMarketItems?: MCPMarketItem[] | undefined;
mcpMarketLoading?: boolean | undefined;
mcpMarketError?: string | undefined;
- ccSwitchStatus?: import('./pages/AgentsPage').CCSwitchStatusInfo | undefined;
- ccSwitchProviders?: import('./pages/AgentsPage').CCSwitchProviderInfo[] | undefined;
+ ccSwitchStatus?: import('../pages/AgentsPage').CCSwitchStatusInfo | undefined;
+ ccSwitchProviders?: import('../pages/AgentsPage').CCSwitchProviderInfo[] | undefined;
}
/** Thin agents route shell: pure model + AgentsPage prop wiring. */
diff --git a/app/workbench/src/WorkbenchContactsRouteView.tsx b/app/workbench/src/routes/WorkbenchContactsRouteView.tsx
similarity index 91%
rename from app/workbench/src/WorkbenchContactsRouteView.tsx
rename to app/workbench/src/routes/WorkbenchContactsRouteView.tsx
index eb77c7264..1a20ee883 100644
--- a/app/workbench/src/WorkbenchContactsRouteView.tsx
+++ b/app/workbench/src/routes/WorkbenchContactsRouteView.tsx
@@ -1,5 +1,5 @@
import React, { useMemo } from 'react';
-import { ContactsPage } from './pages/ContactsPage';
+import { ContactsPage } from '../pages/ContactsPage';
import type { WorkbenchContactsRoute } from './useWorkbenchContactsRoute';
import { buildContactsPageProps } from './workbenchRoutesHelpers';
diff --git a/app/workbench/src/WorkbenchDevicesRouteView.test.tsx b/app/workbench/src/routes/WorkbenchDevicesRouteView.test.tsx
similarity index 100%
rename from app/workbench/src/WorkbenchDevicesRouteView.test.tsx
rename to app/workbench/src/routes/WorkbenchDevicesRouteView.test.tsx
diff --git a/app/workbench/src/WorkbenchDevicesRouteView.tsx b/app/workbench/src/routes/WorkbenchDevicesRouteView.tsx
similarity index 91%
rename from app/workbench/src/WorkbenchDevicesRouteView.tsx
rename to app/workbench/src/routes/WorkbenchDevicesRouteView.tsx
index 508378f32..bf8a41b12 100644
--- a/app/workbench/src/WorkbenchDevicesRouteView.tsx
+++ b/app/workbench/src/routes/WorkbenchDevicesRouteView.tsx
@@ -1,6 +1,6 @@
import React from 'react';
-import { DevicesPage } from './pages/DevicesPage';
-import type { DevicesPageTarget } from './pages/DevicesPage';
+import { DevicesPage } from '../pages/DevicesPage';
+import type { DevicesPageTarget } from '../pages/DevicesPage';
/* ═══════════════════════════════════════════════════════════════════════
WorkbenchDevicesRouteView — thin route shell for the Devices page (#1819).
diff --git a/app/workbench/src/WorkbenchDocsRouteView.tsx b/app/workbench/src/routes/WorkbenchDocsRouteView.tsx
similarity index 84%
rename from app/workbench/src/WorkbenchDocsRouteView.tsx
rename to app/workbench/src/routes/WorkbenchDocsRouteView.tsx
index 0a3291350..85bbe32a5 100644
--- a/app/workbench/src/WorkbenchDocsRouteView.tsx
+++ b/app/workbench/src/routes/WorkbenchDocsRouteView.tsx
@@ -1,6 +1,6 @@
import React, { useMemo } from 'react';
-import type { WorkbenchProfileSource } from './profileRegistry';
-import { DocsPage } from './pages/DocsPage';
+import type { WorkbenchProfileSource } from '../profileRegistry';
+import { DocsPage } from '../pages/DocsPage';
import type { WorkbenchDocsRoute } from './useWorkbenchDocsRoute';
import { buildDocsPageProps } from './workbenchRoutesHelpers';
diff --git a/app/workbench/src/WorkbenchProjectsRouteView.tsx b/app/workbench/src/routes/WorkbenchProjectsRouteView.tsx
similarity index 85%
rename from app/workbench/src/WorkbenchProjectsRouteView.tsx
rename to app/workbench/src/routes/WorkbenchProjectsRouteView.tsx
index c394f37b2..b1ebec2fc 100644
--- a/app/workbench/src/WorkbenchProjectsRouteView.tsx
+++ b/app/workbench/src/routes/WorkbenchProjectsRouteView.tsx
@@ -1,6 +1,6 @@
import React, { useMemo } from 'react';
-import type { WorkbenchProfileSource } from './profileRegistry';
-import { ProjectsPage } from './pages/ProjectsPage';
+import type { WorkbenchProfileSource } from '../profileRegistry';
+import { ProjectsPage } from '../pages/ProjectsPage';
import type { WorkbenchProjectsRoute } from './useWorkbenchProjectsRoute';
import { buildProjectsPageProps } from './workbenchRoutesHelpers';
diff --git a/app/workbench/src/WorkbenchSettingsRouteView.tsx b/app/workbench/src/routes/WorkbenchSettingsRouteView.tsx
similarity index 96%
rename from app/workbench/src/WorkbenchSettingsRouteView.tsx
rename to app/workbench/src/routes/WorkbenchSettingsRouteView.tsx
index 670cc03b7..09f5fa217 100644
--- a/app/workbench/src/WorkbenchSettingsRouteView.tsx
+++ b/app/workbench/src/routes/WorkbenchSettingsRouteView.tsx
@@ -1,6 +1,6 @@
import React, { useMemo } from 'react';
import type { LocalCliDiscoveryManifest, RuntimeSessionSummary } from '@shared/platform';
-import { SettingsPage } from './pages/SettingsPage';
+import { SettingsPage } from '../pages/SettingsPage';
import type { WorkbenchSettingsRoute } from './useWorkbenchSettingsRoute';
import { buildSettingsPageProps } from './workbenchRoutesHelpers';
diff --git a/app/workbench/src/WorkbenchTasksRouteView.test.tsx b/app/workbench/src/routes/WorkbenchTasksRouteView.test.tsx
similarity index 97%
rename from app/workbench/src/WorkbenchTasksRouteView.test.tsx
rename to app/workbench/src/routes/WorkbenchTasksRouteView.test.tsx
index 6d59e7479..bf1554f8b 100644
--- a/app/workbench/src/WorkbenchTasksRouteView.test.tsx
+++ b/app/workbench/src/routes/WorkbenchTasksRouteView.test.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
-import { fireEvent, render, screen } from './__tests__/setup';
-import type { TaskItem } from './pages';
+import { fireEvent, render, screen } from '../__tests__/setup';
+import type { TaskItem } from '../pages/index';
import type { WorkbenchTasksRoute } from './useWorkbenchTasksRoute';
import { WorkbenchTasksRouteView } from './WorkbenchTasksRouteView';
import {
diff --git a/app/workbench/src/WorkbenchTasksRouteView.tsx b/app/workbench/src/routes/WorkbenchTasksRouteView.tsx
similarity index 96%
rename from app/workbench/src/WorkbenchTasksRouteView.tsx
rename to app/workbench/src/routes/WorkbenchTasksRouteView.tsx
index ed92fa0a6..c9076ab7a 100644
--- a/app/workbench/src/WorkbenchTasksRouteView.tsx
+++ b/app/workbench/src/routes/WorkbenchTasksRouteView.tsx
@@ -2,9 +2,9 @@ import React, { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { CHATVIEW_I18N_NAMESPACE } from '@shared/chatview/i18n/resources';
import { SHARED_WORKBENCH_I18N_NAMESPACE } from '@shared/i18n';
-import type { WorkbenchProfileSource } from './profileRegistry';
-import { DesignNavIcon } from './designIcons';
-import { TasksPage } from './pages/TasksPage';
+import type { WorkbenchProfileSource } from '../profileRegistry';
+import { DesignNavIcon } from '../designIcons';
+import { TasksPage } from '../pages/TasksPage';
import type { WorkbenchTasksRoute } from './useWorkbenchTasksRoute';
import { buildTasksPageDerivedModel } from './workbenchTasksPageModel';
import type { TaskReviewMergePort } from './workbenchBoardColumns';
@@ -13,7 +13,7 @@ import {
useWorkbenchTaskDeepLinkActions,
useWorkbenchTaskDeepLinkSnapshot,
} from './workbenchTaskDeepLinks';
-import styles from './AgentHubWorkbench.module.css';
+import styles from '../AgentHubWorkbench.module.css';
export interface WorkbenchTasksRouteViewProps {
tasksRoute: WorkbenchTasksRoute;
diff --git a/app/workbench/src/WorkbenchUsageRouteView.test.tsx b/app/workbench/src/routes/WorkbenchUsageRouteView.test.tsx
similarity index 100%
rename from app/workbench/src/WorkbenchUsageRouteView.test.tsx
rename to app/workbench/src/routes/WorkbenchUsageRouteView.test.tsx
diff --git a/app/workbench/src/WorkbenchUsageRouteView.tsx b/app/workbench/src/routes/WorkbenchUsageRouteView.tsx
similarity index 89%
rename from app/workbench/src/WorkbenchUsageRouteView.tsx
rename to app/workbench/src/routes/WorkbenchUsageRouteView.tsx
index 929e4e1c4..1fcd6ac7c 100644
--- a/app/workbench/src/WorkbenchUsageRouteView.tsx
+++ b/app/workbench/src/routes/WorkbenchUsageRouteView.tsx
@@ -1,6 +1,6 @@
import React from 'react';
-import { TokenUsagePage } from './pages/TokenUsagePage';
-import type { TokenUsagePageTeam } from './pages/TokenUsagePage';
+import { TokenUsagePage } from '../pages/TokenUsagePage';
+import type { TokenUsagePageTeam } from '../pages/TokenUsagePage';
/* ═══════════════════════════════════════════════════════════════════════
WorkbenchUsageRouteView — thin route shell for the Token usage board (#1819).
diff --git a/app/workbench/src/useWorkbenchAgentsRoute.test.ts b/app/workbench/src/routes/useWorkbenchAgentsRoute.test.ts
similarity index 99%
rename from app/workbench/src/useWorkbenchAgentsRoute.test.ts
rename to app/workbench/src/routes/useWorkbenchAgentsRoute.test.ts
index 1503ef0a7..fe50bacf8 100644
--- a/app/workbench/src/useWorkbenchAgentsRoute.test.ts
+++ b/app/workbench/src/routes/useWorkbenchAgentsRoute.test.ts
@@ -8,7 +8,7 @@ import {
WORKBENCH_MOCK_AGENT_MODELS,
WORKBENCH_MOCK_AGENT_SKILL_OPTIONS,
WORKBENCH_MOCK_AGENT_TOOL_OPTIONS,
-} from './mockData';
+} from '../mockData';
import {
useWorkbenchAgentsRoute,
type UseWorkbenchAgentsRouteOptions,
diff --git a/app/workbench/src/useWorkbenchAgentsRoute.ts b/app/workbench/src/routes/useWorkbenchAgentsRoute.ts
similarity index 98%
rename from app/workbench/src/useWorkbenchAgentsRoute.ts
rename to app/workbench/src/routes/useWorkbenchAgentsRoute.ts
index f9a49703b..145bbcf69 100644
--- a/app/workbench/src/useWorkbenchAgentsRoute.ts
+++ b/app/workbench/src/routes/useWorkbenchAgentsRoute.ts
@@ -1,7 +1,7 @@
import { useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { SHARED_WORKBENCH_I18N_NAMESPACE } from '@shared/i18n';
-import type { AgentsPaneId, AgentConfig } from './pages/AgentsPage';
+import type { AgentsPaneId, AgentConfig } from '../pages/AgentsPage';
import {
buildWorkbenchAgentsRouteHandlers,
isAgentBusyWith,
diff --git a/app/workbench/src/useWorkbenchContactsRoute.test.ts b/app/workbench/src/routes/useWorkbenchContactsRoute.test.ts
similarity index 99%
rename from app/workbench/src/useWorkbenchContactsRoute.test.ts
rename to app/workbench/src/routes/useWorkbenchContactsRoute.test.ts
index 5b0b852c3..57a237595 100644
--- a/app/workbench/src/useWorkbenchContactsRoute.test.ts
+++ b/app/workbench/src/routes/useWorkbenchContactsRoute.test.ts
@@ -3,7 +3,7 @@ import { describe, expect, it } from 'vitest';
import {
WORKBENCH_MOCK_CONTACT_MEMBER_POOL,
WORKBENCH_MOCK_PAGE_SIZE,
-} from './mockData';
+} from '../mockData';
import { useWorkbenchContactsRoute } from './useWorkbenchContactsRoute';
describe('useWorkbenchContactsRoute mock cursor pagination ', () => {
diff --git a/app/workbench/src/useWorkbenchContactsRoute.ts b/app/workbench/src/routes/useWorkbenchContactsRoute.ts
similarity index 99%
rename from app/workbench/src/useWorkbenchContactsRoute.ts
rename to app/workbench/src/routes/useWorkbenchContactsRoute.ts
index fa90ee9a0..51ac92639 100644
--- a/app/workbench/src/useWorkbenchContactsRoute.ts
+++ b/app/workbench/src/routes/useWorkbenchContactsRoute.ts
@@ -4,7 +4,7 @@ import type {
ContactGroup,
ContactMember,
ServiceDesk,
-} from './pages';
+} from '../pages/index';
import {
WORKBENCH_MOCK_CONTACT_GROUPS,
WORKBENCH_MOCK_CONTACT_MEMBER_POOL,
@@ -15,7 +15,7 @@ import {
WORKBENCH_MOCK_PENDING_CONTACTS,
WORKBENCH_MOCK_SERVICE_DESKS,
readMockCursorPage,
-} from './mockData';
+} from '../mockData';
/** Contact mutation callbacks wired to Hub API. */
export interface WorkbenchContactsActions {
diff --git a/app/workbench/src/useWorkbenchDocsRoute.test.ts b/app/workbench/src/routes/useWorkbenchDocsRoute.test.ts
similarity index 98%
rename from app/workbench/src/useWorkbenchDocsRoute.test.ts
rename to app/workbench/src/routes/useWorkbenchDocsRoute.test.ts
index c68b602a9..6fc6c771f 100644
--- a/app/workbench/src/useWorkbenchDocsRoute.test.ts
+++ b/app/workbench/src/routes/useWorkbenchDocsRoute.test.ts
@@ -1,8 +1,8 @@
// real_tested=true
import { act, renderHook } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';
-import type { DocRow } from './pages';
-import { WORKBENCH_MOCK_DOC_ROWS, WORKBENCH_MOCK_DOC_SHORTCUTS } from './mockData';
+import type { DocRow } from '../pages/index';
+import { WORKBENCH_MOCK_DOC_ROWS, WORKBENCH_MOCK_DOC_SHORTCUTS } from '../mockData';
import { useWorkbenchDocsRoute } from './useWorkbenchDocsRoute';
/* ═══════════════════════════════════════════════════════════════════════
diff --git a/app/workbench/src/useWorkbenchDocsRoute.ts b/app/workbench/src/routes/useWorkbenchDocsRoute.ts
similarity index 95%
rename from app/workbench/src/useWorkbenchDocsRoute.ts
rename to app/workbench/src/routes/useWorkbenchDocsRoute.ts
index a8e06312c..8b68b6bd6 100644
--- a/app/workbench/src/useWorkbenchDocsRoute.ts
+++ b/app/workbench/src/routes/useWorkbenchDocsRoute.ts
@@ -1,7 +1,7 @@
import { useState } from 'react';
-import type { DocRow, DocsPane } from './pages';
-import type { WorkbenchDocumentPreview } from './documentPreview';
-import { WORKBENCH_MOCK_DOC_ROWS, WORKBENCH_MOCK_DOC_SHORTCUTS } from './mockData';
+import type { DocRow, DocsPane } from '../pages/index';
+import type { WorkbenchDocumentPreview } from '../documentPreview';
+import { WORKBENCH_MOCK_DOC_ROWS, WORKBENCH_MOCK_DOC_SHORTCUTS } from '../mockData';
import { createDocPreview } from './workbenchDocPreview';
/** Document mutation callbacks wired to Hub Documents API. */
diff --git a/app/workbench/src/useWorkbenchProjectsRoute.test.ts b/app/workbench/src/routes/useWorkbenchProjectsRoute.test.ts
similarity index 98%
rename from app/workbench/src/useWorkbenchProjectsRoute.test.ts
rename to app/workbench/src/routes/useWorkbenchProjectsRoute.test.ts
index ae33bd9ff..2b4cd9040 100644
--- a/app/workbench/src/useWorkbenchProjectsRoute.test.ts
+++ b/app/workbench/src/routes/useWorkbenchProjectsRoute.test.ts
@@ -1,6 +1,6 @@
import { renderHook } from '@testing-library/react';
import { describe, expect, it } from 'vitest';
-import type { ProjectDraft, ProjectInfo } from './pages';
+import type { ProjectDraft, ProjectInfo } from '../pages/index';
import {
useWorkbenchProjectsRoute,
type WorkbenchProjectsStatus,
diff --git a/app/workbench/src/useWorkbenchProjectsRoute.ts b/app/workbench/src/routes/useWorkbenchProjectsRoute.ts
similarity index 96%
rename from app/workbench/src/useWorkbenchProjectsRoute.ts
rename to app/workbench/src/routes/useWorkbenchProjectsRoute.ts
index 423277df0..2bf9ad5fe 100644
--- a/app/workbench/src/useWorkbenchProjectsRoute.ts
+++ b/app/workbench/src/routes/useWorkbenchProjectsRoute.ts
@@ -4,9 +4,9 @@ import type {
ProjectDraft,
ProjectInfo,
ProjectTab,
-} from './pages';
-import { WORKBENCH_MOCK_PROJECTS } from './mockData';
-import type { WorkbenchDocumentPreview } from './documentPreview';
+} from '../pages/index';
+import { WORKBENCH_MOCK_PROJECTS } from '../mockData';
+import type { WorkbenchDocumentPreview } from '../documentPreview';
import { createProjectArtifactPreview } from './workbenchProjectPreview';
export interface WorkbenchProjectsStatus {
diff --git a/app/workbench/src/useWorkbenchSettingsRoute.test.ts b/app/workbench/src/routes/useWorkbenchSettingsRoute.test.ts
similarity index 98%
rename from app/workbench/src/useWorkbenchSettingsRoute.test.ts
rename to app/workbench/src/routes/useWorkbenchSettingsRoute.test.ts
index c37c9919b..7a52050b7 100644
--- a/app/workbench/src/useWorkbenchSettingsRoute.test.ts
+++ b/app/workbench/src/routes/useWorkbenchSettingsRoute.test.ts
@@ -2,9 +2,9 @@
import { act, renderHook } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import type { SettingsPort } from '@shared/platform/types';
-import { WORKBENCH_MOCK_SETTINGS_DEFAULTS } from './mockData';
-import { createSettingsService } from './settingsService';
-import type { SettingsService } from './settingsService';
+import { WORKBENCH_MOCK_SETTINGS_DEFAULTS } from '../mockData';
+import { createSettingsService } from '../settingsService';
+import type { SettingsService } from '../settingsService';
import {
createSettingsDefaults,
useWorkbenchSettingsRoute,
@@ -12,7 +12,7 @@ import {
import {
WORKBENCH_COMPOSER_SUBMIT_BEHAVIOR_KEY,
readComposerSubmitBehavior,
-} from './workbenchPreferences';
+} from '../workbenchPreferences';
/**
* Controllable SettingsService double: same surface as the real service but
diff --git a/app/workbench/src/useWorkbenchSettingsRoute.ts b/app/workbench/src/routes/useWorkbenchSettingsRoute.ts
similarity index 96%
rename from app/workbench/src/useWorkbenchSettingsRoute.ts
rename to app/workbench/src/routes/useWorkbenchSettingsRoute.ts
index 7bf8f5296..7a1328e45 100644
--- a/app/workbench/src/useWorkbenchSettingsRoute.ts
+++ b/app/workbench/src/routes/useWorkbenchSettingsRoute.ts
@@ -5,10 +5,10 @@ import {
composerSubmitBehaviorLabel,
readComposerSubmitBehavior,
writeComposerSubmitBehavior,
-} from './workbenchPreferences';
-import { WORKBENCH_MOCK_SETTINGS_DEFAULTS } from './mockData';
-import type { SettingsService } from './settingsService';
-import type { SettingsPaneId } from './pages';
+} from '../workbenchPreferences';
+import { WORKBENCH_MOCK_SETTINGS_DEFAULTS } from '../mockData';
+import type { SettingsService } from '../settingsService';
+import type { SettingsPaneId } from '../pages/index';
export type WorkbenchSettingsValues = typeof WORKBENCH_MOCK_SETTINGS_DEFAULTS;
export type WorkbenchSettingsErrorKind = 'init' | 'write';
diff --git a/app/workbench/src/useWorkbenchTasksRoute.test.ts b/app/workbench/src/routes/useWorkbenchTasksRoute.test.ts
similarity index 99%
rename from app/workbench/src/useWorkbenchTasksRoute.test.ts
rename to app/workbench/src/routes/useWorkbenchTasksRoute.test.ts
index 0e4cd4f43..cda90bb92 100644
--- a/app/workbench/src/useWorkbenchTasksRoute.test.ts
+++ b/app/workbench/src/routes/useWorkbenchTasksRoute.test.ts
@@ -3,7 +3,7 @@ import { beforeEach, beforeAll, describe, expect, it } from 'vitest';
import {
WORKBENCH_MOCK_PAGE_SIZE,
WORKBENCH_MOCK_TASK_POOL,
-} from './mockData';
+} from '../mockData';
import { flattenTaskGroups } from './workbenchTaskGroups';
import { useWorkbenchTasksRoute } from './useWorkbenchTasksRoute';
import { useTestI18nLanguage } from '@shared/testing/i18n';
diff --git a/app/workbench/src/useWorkbenchTasksRoute.ts b/app/workbench/src/routes/useWorkbenchTasksRoute.ts
similarity index 98%
rename from app/workbench/src/useWorkbenchTasksRoute.ts
rename to app/workbench/src/routes/useWorkbenchTasksRoute.ts
index f235bd86d..ec9a44004 100644
--- a/app/workbench/src/useWorkbenchTasksRoute.ts
+++ b/app/workbench/src/routes/useWorkbenchTasksRoute.ts
@@ -1,13 +1,13 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { SHARED_WORKBENCH_I18N_NAMESPACE } from '@shared/i18n';
-import type { TaskGroup, TaskItem, TasksPane, ViewMode } from './pages';
-import type { TaskEditDraft } from './pages/TasksPage';
+import type { TaskGroup, TaskItem, TasksPane, ViewMode } from '../pages/index';
+import type { TaskEditDraft } from '../pages/TasksPage';
import {
WORKBENCH_MOCK_PAGE_SIZE,
WORKBENCH_MOCK_TASK_POOL,
readMockCursorPage,
-} from './mockData';
+} from '../mockData';
import {
type TaskGroupMode,
type TaskSortMode,
diff --git a/app/workbench/src/workbenchAgentsPageModel.test.ts b/app/workbench/src/routes/workbenchAgentsPageModel.test.ts
similarity index 98%
rename from app/workbench/src/workbenchAgentsPageModel.test.ts
rename to app/workbench/src/routes/workbenchAgentsPageModel.test.ts
index f110f8572..b9ed9c85c 100644
--- a/app/workbench/src/workbenchAgentsPageModel.test.ts
+++ b/app/workbench/src/routes/workbenchAgentsPageModel.test.ts
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest';
-import type { AgentConfig } from './pages/AgentsPage';
+import type { AgentConfig } from '../pages/AgentsPage';
import {
buildAgentRecentShortcuts,
buildAgentsPageDerivedModel,
diff --git a/app/workbench/src/workbenchAgentsPageModel.ts b/app/workbench/src/routes/workbenchAgentsPageModel.ts
similarity index 97%
rename from app/workbench/src/workbenchAgentsPageModel.ts
rename to app/workbench/src/routes/workbenchAgentsPageModel.ts
index 77770745e..4f4932005 100644
--- a/app/workbench/src/workbenchAgentsPageModel.ts
+++ b/app/workbench/src/routes/workbenchAgentsPageModel.ts
@@ -3,11 +3,11 @@ import type {
MarketTemplate,
ModelRoute,
ToolMatrixAgent,
-} from './pages/AgentsPage';
+} from '../pages/AgentsPage';
import {
WORKBENCH_MOCK_AGENT_MARKET_TEMPLATES,
-} from './mockData';
-import { workbenchAgentColor, workbenchProfileInitials } from './profileRegistry';
+} from '../mockData';
+import { workbenchAgentColor, workbenchProfileInitials } from '../profileRegistry';
export interface AgentsPageDerivedModel {
confirmCount: number;
diff --git a/app/workbench/src/workbenchAgentsRouteHelpers.test.ts b/app/workbench/src/routes/workbenchAgentsRouteHelpers.test.ts
similarity index 99%
rename from app/workbench/src/workbenchAgentsRouteHelpers.test.ts
rename to app/workbench/src/routes/workbenchAgentsRouteHelpers.test.ts
index 3ec44d008..3a806f3fb 100644
--- a/app/workbench/src/workbenchAgentsRouteHelpers.test.ts
+++ b/app/workbench/src/routes/workbenchAgentsRouteHelpers.test.ts
@@ -1,7 +1,7 @@
import { describe, expect, it, vi } from 'vitest';
import { SHARED_WORKBENCH_I18N_NAMESPACE } from '@shared/i18n';
import { createTestI18n } from '@shared/testing/i18n';
-import type { AgentConfig } from './pages/AgentsPage';
+import type { AgentConfig } from '../pages/AgentsPage';
import {
buildAgentFieldPatch,
buildWorkbenchAgentsRouteHandlers,
@@ -292,7 +292,7 @@ describe('workbenchAgentsRouteHelpers', () => {
});
it('builds route handlers that apply add/save/delete plans to state setters', async () => {
- let agentsPane: import('./pages/AgentsPage').AgentsPaneId = 'market';
+ let agentsPane: import('../pages/AgentsPage').AgentsPaneId = 'market';
let selectedAgentId: string | undefined = 'a1';
let agentDrafts: Record = {};
let draftAgentIds: string[] = [];
diff --git a/app/workbench/src/workbenchAgentsRouteHelpers.ts b/app/workbench/src/routes/workbenchAgentsRouteHelpers.ts
similarity index 99%
rename from app/workbench/src/workbenchAgentsRouteHelpers.ts
rename to app/workbench/src/routes/workbenchAgentsRouteHelpers.ts
index a3dc9a8f3..331440bb3 100644
--- a/app/workbench/src/workbenchAgentsRouteHelpers.ts
+++ b/app/workbench/src/routes/workbenchAgentsRouteHelpers.ts
@@ -1,17 +1,17 @@
import type { TFunction } from 'i18next';
import type { WorkbenchAgent } from '@shared/platform';
-import type { AgentConfig, AgentsPaneId, ModelInfo, ModelState, ToolPermission } from './pages/AgentsPage';
+import type { AgentConfig, AgentsPaneId, ModelInfo, ModelState, ToolPermission } from '../pages/AgentsPage';
import {
WORKBENCH_MOCK_AGENT_CONFIGS,
WORKBENCH_MOCK_AGENT_MODELS,
WORKBENCH_MOCK_AGENT_SKILL_OPTIONS,
WORKBENCH_MOCK_AGENT_TOOL_OPTIONS,
-} from './mockData';
+} from '../mockData';
import {
createMarketInstalledAgent,
workbenchAgentToAgentConfig,
-} from './workbenchAgentMapping';
-import { uniqueSorted } from './agentProfileCatalogHelpers';
+} from '../workbenchAgentMapping';
+import { uniqueSorted } from '../agentProfileCatalogHelpers';
/* ═══════════════════════════════════════════════════════════════════════
workbenchAgentsRouteHelpers — pure helpers for
diff --git a/app/workbench/src/workbenchBoardColumns.test.ts b/app/workbench/src/routes/workbenchBoardColumns.test.ts
similarity index 100%
rename from app/workbench/src/workbenchBoardColumns.test.ts
rename to app/workbench/src/routes/workbenchBoardColumns.test.ts
diff --git a/app/workbench/src/workbenchBoardColumns.ts b/app/workbench/src/routes/workbenchBoardColumns.ts
similarity index 99%
rename from app/workbench/src/workbenchBoardColumns.ts
rename to app/workbench/src/routes/workbenchBoardColumns.ts
index 7fbf6ac0c..2446633b1 100644
--- a/app/workbench/src/workbenchBoardColumns.ts
+++ b/app/workbench/src/routes/workbenchBoardColumns.ts
@@ -17,7 +17,7 @@
═══════════════════════════════════════════════════════════════════════ */
import type { AgentHubSurface } from '@shared/platform';
-import type { TaskStatus } from './pages';
+import type { TaskStatus } from '../pages/index';
export type BoardColumnTone = 'idle' | 'running' | 'review' | 'confirm' | 'done';
diff --git a/app/workbench/src/workbenchDocPreview.test.ts b/app/workbench/src/routes/workbenchDocPreview.test.ts
similarity index 96%
rename from app/workbench/src/workbenchDocPreview.test.ts
rename to app/workbench/src/routes/workbenchDocPreview.test.ts
index 54ec93fcb..c58309e82 100644
--- a/app/workbench/src/workbenchDocPreview.test.ts
+++ b/app/workbench/src/routes/workbenchDocPreview.test.ts
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest';
-import type { DocRow } from './pages';
+import type { DocRow } from '../pages/index';
import { createDocPreview } from './workbenchDocPreview';
function doc(overrides: Partial = {}): DocRow {
diff --git a/app/workbench/src/workbenchDocPreview.ts b/app/workbench/src/routes/workbenchDocPreview.ts
similarity index 93%
rename from app/workbench/src/workbenchDocPreview.ts
rename to app/workbench/src/routes/workbenchDocPreview.ts
index 49aa025d7..3ab92662b 100644
--- a/app/workbench/src/workbenchDocPreview.ts
+++ b/app/workbench/src/routes/workbenchDocPreview.ts
@@ -2,8 +2,8 @@ import {
fileTypeFromPreviewName,
previewFilenameFromTitle,
type WorkbenchDocumentPreview,
-} from './documentPreview';
-import type { DocRow } from './pages';
+} from '../documentPreview';
+import type { DocRow } from '../pages/index';
export function createDocPreview(doc: DocRow): WorkbenchDocumentPreview {
const filename = previewFilenameFromTitle(doc.title);
diff --git a/app/workbench/src/workbenchProjectPreview.test.ts b/app/workbench/src/routes/workbenchProjectPreview.test.ts
similarity index 97%
rename from app/workbench/src/workbenchProjectPreview.test.ts
rename to app/workbench/src/routes/workbenchProjectPreview.test.ts
index 62575fe1c..634f1979f 100644
--- a/app/workbench/src/workbenchProjectPreview.test.ts
+++ b/app/workbench/src/routes/workbenchProjectPreview.test.ts
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest';
-import type { ProjectArtifact } from './pages';
+import type { ProjectArtifact } from '../pages/index';
import {
createProjectArtifactPreview,
projectArtifactContent,
diff --git a/app/workbench/src/workbenchProjectPreview.ts b/app/workbench/src/routes/workbenchProjectPreview.ts
similarity index 96%
rename from app/workbench/src/workbenchProjectPreview.ts
rename to app/workbench/src/routes/workbenchProjectPreview.ts
index 9e57311fb..8cad6bf44 100644
--- a/app/workbench/src/workbenchProjectPreview.ts
+++ b/app/workbench/src/routes/workbenchProjectPreview.ts
@@ -1,8 +1,8 @@
import {
fileTypeFromPreviewName,
type WorkbenchDocumentPreview,
-} from './documentPreview';
-import type { ProjectArtifact } from './pages';
+} from '../documentPreview';
+import type { ProjectArtifact } from '../pages/index';
export function createProjectArtifactPreview(
projectId: string,
diff --git a/app/workbench/src/workbenchRoutesHelpers.test.ts b/app/workbench/src/routes/workbenchRoutesHelpers.test.ts
similarity index 100%
rename from app/workbench/src/workbenchRoutesHelpers.test.ts
rename to app/workbench/src/routes/workbenchRoutesHelpers.test.ts
diff --git a/app/workbench/src/workbenchRoutesHelpers.ts b/app/workbench/src/routes/workbenchRoutesHelpers.ts
similarity index 95%
rename from app/workbench/src/workbenchRoutesHelpers.ts
rename to app/workbench/src/routes/workbenchRoutesHelpers.ts
index ca7288a00..b504d8139 100644
--- a/app/workbench/src/workbenchRoutesHelpers.ts
+++ b/app/workbench/src/routes/workbenchRoutesHelpers.ts
@@ -1,10 +1,10 @@
import type { LocalCliDiscoveryManifest, RuntimeSessionSummary } from '@shared/platform';
-import type { ContactsPageProps } from './pages/ContactsPage';
-import type { DocsPageProps } from './pages/DocsPage';
-import type { ProjectsPageProps } from './pages/ProjectsPage';
-import type { SettingsPageProps } from './pages/SettingsPage';
-import type { WorkbenchProfileSource } from './profileRegistry';
-import { hubEmptyContacts } from './hubDataMapping';
+import type { ContactsPageProps } from '../pages/ContactsPage';
+import type { DocsPageProps } from '../pages/DocsPage';
+import type { ProjectsPageProps } from '../pages/ProjectsPage';
+import type { SettingsPageProps } from '../pages/SettingsPage';
+import type { WorkbenchProfileSource } from '../profileRegistry';
+import { hubEmptyContacts } from '../hubDataMapping';
import type { WorkbenchContactsRoute } from './useWorkbenchContactsRoute';
import type { WorkbenchDocsRoute } from './useWorkbenchDocsRoute';
import type { WorkbenchProjectsRoute } from './useWorkbenchProjectsRoute';
diff --git a/app/workbench/src/workbenchRoutesTypes.ts b/app/workbench/src/routes/workbenchRoutesTypes.ts
similarity index 92%
rename from app/workbench/src/workbenchRoutesTypes.ts
rename to app/workbench/src/routes/workbenchRoutesTypes.ts
index bb892b1ff..86b9fe49d 100644
--- a/app/workbench/src/workbenchRoutesTypes.ts
+++ b/app/workbench/src/routes/workbenchRoutesTypes.ts
@@ -3,10 +3,10 @@ import type {
DocRow,
ProjectDraft,
ProjectInfo,
-} from './pages';
-import type { AgentConfig, SkillMarketItem, MCPMarketItem } from './pages/AgentsPage';
-import type { GlobalRailPage } from './GlobalRail';
-import type { SettingsService } from './settingsService';
+} from '../pages/index';
+import type { AgentConfig, SkillMarketItem, MCPMarketItem } from '../pages/AgentsPage';
+import type { GlobalRailPage } from '../GlobalRail';
+import type { SettingsService } from '../settingsService';
import type {
WorkbenchContactsActions,
WorkbenchContactsData,
@@ -80,9 +80,9 @@ export interface WorkbenchRoutesProps {
tags?: string[];
}> | undefined;
/** cc-switch transparent proxy status from Edge API. */
- ccSwitchStatus?: import('./pages/AgentsPage').CCSwitchStatusInfo | undefined;
+ ccSwitchStatus?: import('../pages/AgentsPage').CCSwitchStatusInfo | undefined;
/** cc-switch provider model alias mappings. */
- ccSwitchProviders?: import('./pages/AgentsPage').CCSwitchProviderInfo[] | undefined;
+ ccSwitchProviders?: import('../pages/AgentsPage').CCSwitchProviderInfo[] | undefined;
/** Settings service for persistent user preferences. When provided,
* settings are read from / written to the backend adapter. */
settingsService?: SettingsService | null | undefined;
@@ -113,7 +113,7 @@ export interface WorkbenchRoutesProps {
userDisplayName?: string | undefined;
/* ── Devices / execution-target management (#1819) ── */
/** Registered execution targets; undefined = shell not Hub-connected. */
- devicesTargets?: import('./pages/DevicesPage').DevicesPageTarget[] | undefined;
+ devicesTargets?: import('../pages/DevicesPage').DevicesPageTarget[] | undefined;
devicesLoading?: boolean | undefined;
devicesError?: string | null | undefined;
onDevicesRetry?: (() => void) | undefined;
@@ -122,7 +122,7 @@ export interface WorkbenchRoutesProps {
onDevicePing?: ((targetId: string) => void) | undefined;
/* ── Token / cost usage board (#1819) ── */
/** Per-team runs with recorded token counters; undefined = not Hub-connected. */
- usageTeams?: import('./pages/TokenUsagePage').TokenUsagePageTeam[] | undefined;
+ usageTeams?: import('../pages/TokenUsagePage').TokenUsagePageTeam[] | undefined;
usageLoading?: boolean | undefined;
usageError?: string | null | undefined;
onUsageRetry?: (() => void) | undefined;
diff --git a/app/workbench/src/workbenchTaskDeepLinks.lifecycle.test.tsx b/app/workbench/src/routes/workbenchTaskDeepLinks.lifecycle.test.tsx
similarity index 97%
rename from app/workbench/src/workbenchTaskDeepLinks.lifecycle.test.tsx
rename to app/workbench/src/routes/workbenchTaskDeepLinks.lifecycle.test.tsx
index 0e6f92e85..7c1ab3026 100644
--- a/app/workbench/src/workbenchTaskDeepLinks.lifecycle.test.tsx
+++ b/app/workbench/src/routes/workbenchTaskDeepLinks.lifecycle.test.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { fireEvent, render, screen } from '@testing-library/react';
import { describe, expect, it } from 'vitest';
-import type { TaskItem } from './pages';
+import type { TaskItem } from '../pages/index';
import {
WorkbenchTaskDeepLinkProvider,
useWorkbenchTaskDeepLinkSnapshot,
diff --git a/app/workbench/src/workbenchTaskDeepLinks.test.ts b/app/workbench/src/routes/workbenchTaskDeepLinks.test.ts
similarity index 99%
rename from app/workbench/src/workbenchTaskDeepLinks.test.ts
rename to app/workbench/src/routes/workbenchTaskDeepLinks.test.ts
index 87ffa58d9..ee1920e0b 100644
--- a/app/workbench/src/workbenchTaskDeepLinks.test.ts
+++ b/app/workbench/src/routes/workbenchTaskDeepLinks.test.ts
@@ -1,5 +1,5 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';
-import type { TaskItem } from './pages';
+import type { TaskItem } from '../pages/index';
import {
backFromTaskDeepLink,
consumeWorkbenchTaskDeepLinkIntent,
diff --git a/app/workbench/src/workbenchTaskDeepLinks.ts b/app/workbench/src/routes/workbenchTaskDeepLinks.ts
similarity index 99%
rename from app/workbench/src/workbenchTaskDeepLinks.ts
rename to app/workbench/src/routes/workbenchTaskDeepLinks.ts
index c1bc77283..6c62b00cc 100644
--- a/app/workbench/src/workbenchTaskDeepLinks.ts
+++ b/app/workbench/src/routes/workbenchTaskDeepLinks.ts
@@ -8,7 +8,7 @@ import {
type ReactElement,
type ReactNode,
} from 'react';
-import type { TaskItem, TaskStatus } from './pages';
+import type { TaskItem, TaskStatus } from '../pages/index';
/* Task ↔ conversation deep links (#1963).
*
diff --git a/app/workbench/src/workbenchTaskGroups.test.ts b/app/workbench/src/routes/workbenchTaskGroups.test.ts
similarity index 97%
rename from app/workbench/src/workbenchTaskGroups.test.ts
rename to app/workbench/src/routes/workbenchTaskGroups.test.ts
index ec2a76444..b7a8b0431 100644
--- a/app/workbench/src/workbenchTaskGroups.test.ts
+++ b/app/workbench/src/routes/workbenchTaskGroups.test.ts
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest';
-import type { TaskGroup, TaskItem } from './pages';
+import type { TaskGroup, TaskItem } from '../pages/index';
import { boardColumnDisplayLabels } from './workbenchBoardColumns';
import {
DESIGN_DONE_TASK,
diff --git a/app/workbench/src/workbenchTaskGroups.ts b/app/workbench/src/routes/workbenchTaskGroups.ts
similarity index 99%
rename from app/workbench/src/workbenchTaskGroups.ts
rename to app/workbench/src/routes/workbenchTaskGroups.ts
index f75786312..23671e514 100644
--- a/app/workbench/src/workbenchTaskGroups.ts
+++ b/app/workbench/src/routes/workbenchTaskGroups.ts
@@ -1,4 +1,4 @@
-import type { TaskGroup, TaskItem, TasksPane, ViewMode } from './pages';
+import type { TaskGroup, TaskItem, TasksPane, ViewMode } from '../pages/index';
import {
BOARD_COLUMNS_IN_DISPLAY_ORDER,
TASK_STATUS_SEQUENCE,
diff --git a/app/workbench/src/workbenchTasksPageModel.test.ts b/app/workbench/src/routes/workbenchTasksPageModel.test.ts
similarity index 98%
rename from app/workbench/src/workbenchTasksPageModel.test.ts
rename to app/workbench/src/routes/workbenchTasksPageModel.test.ts
index 06b86b269..7cd7b4809 100644
--- a/app/workbench/src/workbenchTasksPageModel.test.ts
+++ b/app/workbench/src/routes/workbenchTasksPageModel.test.ts
@@ -2,7 +2,7 @@ import { beforeAll, describe, expect, it } from 'vitest';
import { getI18n } from 'react-i18next';
import { SHARED_WORKBENCH_I18N_NAMESPACE } from '@shared/i18n';
import { useTestI18nLanguage } from '@shared/testing/i18n';
-import type { TaskItem } from './pages';
+import type { TaskItem } from '../pages/index';
import {
buildTaskFieldConfigLabel,
buildTaskGroupLabel,
diff --git a/app/workbench/src/workbenchTasksPageModel.ts b/app/workbench/src/routes/workbenchTasksPageModel.ts
similarity index 98%
rename from app/workbench/src/workbenchTasksPageModel.ts
rename to app/workbench/src/routes/workbenchTasksPageModel.ts
index 6e2ff3ec5..456726e97 100644
--- a/app/workbench/src/workbenchTasksPageModel.ts
+++ b/app/workbench/src/routes/workbenchTasksPageModel.ts
@@ -1,5 +1,5 @@
import type { TFunction } from 'i18next';
-import type { TaskItem, ViewMode } from './pages';
+import type { TaskItem, ViewMode } from '../pages/index';
import type { TaskGroupMode, TaskSortMode } from './workbenchTaskGroups';
export interface TasksPageDerivedModel {
diff --git a/app/workbench/src/workbenchTasksRouteGroupHelpers.test.ts b/app/workbench/src/routes/workbenchTasksRouteGroupHelpers.test.ts
similarity index 98%
rename from app/workbench/src/workbenchTasksRouteGroupHelpers.test.ts
rename to app/workbench/src/routes/workbenchTasksRouteGroupHelpers.test.ts
index 795024739..cf0f976c6 100644
--- a/app/workbench/src/workbenchTasksRouteGroupHelpers.test.ts
+++ b/app/workbench/src/routes/workbenchTasksRouteGroupHelpers.test.ts
@@ -1,7 +1,7 @@
import { describe, expect, it } from 'vitest';
import { SHARED_WORKBENCH_I18N_NAMESPACE } from '@shared/i18n';
import { createTestI18n } from '@shared/testing/i18n';
-import type { TaskGroup, TaskItem } from './pages';
+import type { TaskGroup, TaskItem } from '../pages/index';
import {
appendCustomTaskGroup,
buildTaskEditDraft,
diff --git a/app/workbench/src/workbenchTasksRouteGroupHelpers.ts b/app/workbench/src/routes/workbenchTasksRouteGroupHelpers.ts
similarity index 97%
rename from app/workbench/src/workbenchTasksRouteGroupHelpers.ts
rename to app/workbench/src/routes/workbenchTasksRouteGroupHelpers.ts
index 27879ac5d..e375b3057 100644
--- a/app/workbench/src/workbenchTasksRouteGroupHelpers.ts
+++ b/app/workbench/src/routes/workbenchTasksRouteGroupHelpers.ts
@@ -1,7 +1,7 @@
import type { TFunction } from 'i18next';
-import type { TaskGroup, TaskItem, TaskStatus, TasksPane } from './pages';
-import type { TaskEditDraft } from './pages/TasksPage';
-import { WORKBENCH_MOCK_TASK_GROUPS } from './mockData';
+import type { TaskGroup, TaskItem, TaskStatus, TasksPane } from '../pages/index';
+import type { TaskEditDraft } from '../pages/TasksPage';
+import { WORKBENCH_MOCK_TASK_GROUPS } from '../mockData';
import {
TASK_STATUS_SEQUENCE,
type TaskGroupMode,
diff --git a/app/workbench/src/workbenchTasksRouteHelpers.test.ts b/app/workbench/src/routes/workbenchTasksRouteHelpers.test.ts
similarity index 98%
rename from app/workbench/src/workbenchTasksRouteHelpers.test.ts
rename to app/workbench/src/routes/workbenchTasksRouteHelpers.test.ts
index 29712f65f..bc74b9a80 100644
--- a/app/workbench/src/workbenchTasksRouteHelpers.test.ts
+++ b/app/workbench/src/routes/workbenchTasksRouteHelpers.test.ts
@@ -1,8 +1,8 @@
import { describe, expect, it } from 'vitest';
import { SHARED_WORKBENCH_I18N_NAMESPACE } from '@shared/i18n';
import { createTestI18n } from '@shared/testing/i18n';
-import type { TaskGroup, TaskItem, TasksPane, ViewMode } from './pages';
-import type { TaskEditDraft } from './pages/TasksPage';
+import type { TaskGroup, TaskItem, TasksPane, ViewMode } from '../pages/index';
+import type { TaskEditDraft } from '../pages/TasksPage';
import type { TaskGroupMode, TaskSortMode } from './workbenchTaskGroups';
import {
buildTaskEditDraft,
@@ -47,8 +47,8 @@ describe('workbenchTasksRouteHelpers handlers', () => {
let editingTaskDraft = null as ReturnType | null;
let taskActionLabel = '筛选已启用';
let localTaskCounter = 1;
- let tasksPane: import('./pages').TasksPane = 'owned';
- let taskViewMode: import('./pages').ViewMode = 'list';
+ let tasksPane: import('../pages/index').TasksPane = 'owned';
+ let taskViewMode: import('../pages/index').ViewMode = 'list';
let taskFilterActive = true;
let taskSortMode: 'custom' | 'due' = 'custom';
let taskGroupMode: 'custom' | 'project' | 'status' = 'custom';
diff --git a/app/workbench/src/workbenchTasksRouteHelpers.ts b/app/workbench/src/routes/workbenchTasksRouteHelpers.ts
similarity index 99%
rename from app/workbench/src/workbenchTasksRouteHelpers.ts
rename to app/workbench/src/routes/workbenchTasksRouteHelpers.ts
index 7c28eb6b8..4afd3193d 100644
--- a/app/workbench/src/workbenchTasksRouteHelpers.ts
+++ b/app/workbench/src/routes/workbenchTasksRouteHelpers.ts
@@ -1,6 +1,6 @@
-import type { TaskGroup, TaskItem, TasksPane, ViewMode } from './pages';
+import type { TaskGroup, TaskItem, TasksPane, ViewMode } from '../pages/index';
import type { WorkbenchTaskQueueSource } from './workbenchTaskDeepLinks';
-import type { TaskEditDraft } from './pages/TasksPage';
+import type { TaskEditDraft } from '../pages/TasksPage';
import {
type TaskGroupMode,
type TaskSortMode,
diff --git a/app/workbench/src/workbenchTasksRoutePlanners.test.ts b/app/workbench/src/routes/workbenchTasksRoutePlanners.test.ts
similarity index 99%
rename from app/workbench/src/workbenchTasksRoutePlanners.test.ts
rename to app/workbench/src/routes/workbenchTasksRoutePlanners.test.ts
index 361203beb..9bcb18b4f 100644
--- a/app/workbench/src/workbenchTasksRoutePlanners.test.ts
+++ b/app/workbench/src/routes/workbenchTasksRoutePlanners.test.ts
@@ -1,7 +1,7 @@
import { describe, expect, it } from 'vitest';
import { SHARED_WORKBENCH_I18N_NAMESPACE } from '@shared/i18n';
import { createTestI18n } from '@shared/testing/i18n';
-import type { TaskItem } from './pages';
+import type { TaskItem } from '../pages/index';
import { buildTaskEditDraft } from './workbenchTasksRouteGroupHelpers';
import {
buildTaskPaneChangeLabel,
diff --git a/app/workbench/src/workbenchTasksRoutePlanners.ts b/app/workbench/src/routes/workbenchTasksRoutePlanners.ts
similarity index 98%
rename from app/workbench/src/workbenchTasksRoutePlanners.ts
rename to app/workbench/src/routes/workbenchTasksRoutePlanners.ts
index e58ec36bc..e5d561688 100644
--- a/app/workbench/src/workbenchTasksRoutePlanners.ts
+++ b/app/workbench/src/routes/workbenchTasksRoutePlanners.ts
@@ -1,5 +1,5 @@
-import type { TaskItem, TaskStatus, TasksPane } from './pages';
-import type { TaskEditDraft } from './pages/TasksPage';
+import type { TaskItem, TaskStatus, TasksPane } from '../pages/index';
+import type { TaskEditDraft } from '../pages/TasksPage';
import {
type TaskSortMode,
createLocalTask,
diff --git a/app/workbench/src/workbenchUsageSummary.test.ts b/app/workbench/src/routes/workbenchUsageSummary.test.ts
similarity index 95%
rename from app/workbench/src/workbenchUsageSummary.test.ts
rename to app/workbench/src/routes/workbenchUsageSummary.test.ts
index b076c486c..e85f25882 100644
--- a/app/workbench/src/workbenchUsageSummary.test.ts
+++ b/app/workbench/src/routes/workbenchUsageSummary.test.ts
@@ -3,7 +3,7 @@
// (chip hidden), never a fake 0; pre-counter runs contribute nothing.
import { describe, expect, it } from 'vitest';
import { sumUsageTeamTokens } from './workbenchUsageSummary';
-import type { TokenUsagePageTeam } from './pages/TokenUsagePage';
+import type { TokenUsagePageTeam } from '../pages/TokenUsagePage';
function team(runs: Array<{ tokenUsageTotal?: number }>): TokenUsagePageTeam {
return {
diff --git a/app/workbench/src/workbenchUsageSummary.ts b/app/workbench/src/routes/workbenchUsageSummary.ts
similarity index 94%
rename from app/workbench/src/workbenchUsageSummary.ts
rename to app/workbench/src/routes/workbenchUsageSummary.ts
index 56f9dac2f..17f0755c8 100644
--- a/app/workbench/src/workbenchUsageSummary.ts
+++ b/app/workbench/src/routes/workbenchUsageSummary.ts
@@ -7,7 +7,7 @@
* "current session" number — the chip's semantics match the board exactly.
*/
-import type { TokenUsagePageTeam } from './pages/TokenUsagePage';
+import type { TokenUsagePageTeam } from '../pages/TokenUsagePage';
/**
* Sum the recorded token counters across every team run.
diff --git a/app/workbench/src/ChatEngineeringColumn.module.css b/app/workbench/src/transcript/ChatEngineeringColumn.module.css
similarity index 100%
rename from app/workbench/src/ChatEngineeringColumn.module.css
rename to app/workbench/src/transcript/ChatEngineeringColumn.module.css
diff --git a/app/workbench/src/ChatEngineeringColumn.test.tsx b/app/workbench/src/transcript/ChatEngineeringColumn.test.tsx
similarity index 98%
rename from app/workbench/src/ChatEngineeringColumn.test.tsx
rename to app/workbench/src/transcript/ChatEngineeringColumn.test.tsx
index aeecbc7b5..9f0e1ad62 100644
--- a/app/workbench/src/ChatEngineeringColumn.test.tsx
+++ b/app/workbench/src/transcript/ChatEngineeringColumn.test.tsx
@@ -10,8 +10,8 @@ import {
engineeringPreviewSignal,
resolveEngineeringPreview,
} from './ChatEngineeringColumn';
-import { WORKBENCH_INSPECTOR_QUICK_OPEN_EVENT } from './desktopChromeEvents';
-import { WORKBENCH_ENGINEERING_PREVIEW_FOCUS_EVENT } from './workbenchPreviewEvents';
+import { WORKBENCH_INSPECTOR_QUICK_OPEN_EVENT } from '../desktopChromeEvents';
+import { WORKBENCH_ENGINEERING_PREVIEW_FOCUS_EVENT } from '../workbenchPreviewEvents';
beforeAll(async () => {
await useTestI18nLanguage('zh');
diff --git a/app/workbench/src/ChatEngineeringColumn.tsx b/app/workbench/src/transcript/ChatEngineeringColumn.tsx
similarity index 97%
rename from app/workbench/src/ChatEngineeringColumn.tsx
rename to app/workbench/src/transcript/ChatEngineeringColumn.tsx
index 46f29218c..afd2b9bef 100644
--- a/app/workbench/src/ChatEngineeringColumn.tsx
+++ b/app/workbench/src/transcript/ChatEngineeringColumn.tsx
@@ -14,17 +14,17 @@ import {
FilePreviewRouter,
runtimeEvidenceOverviewFiles,
type PreviewFile,
-} from './inspector';
+} from '../inspector/index';
import {
AuxPanel,
resolveAvailableAuxTabs,
resolveEffectiveAuxTab,
type AuxPanelTab,
-} from './auxPanel';
-import { WORKBENCH_INSPECTOR_QUICK_OPEN_EVENT } from './desktopChromeEvents';
-import type { InspectorTranslator } from './inspector/InspectorModePanelHelpers';
-import { WORKBENCH_ENGINEERING_PREVIEW_FOCUS_EVENT, type EngineeringPreviewFocusDetail } from './workbenchPreviewEvents';
-import shellStyles from './AgentHubWorkbench.module.css';
+} from '../auxPanel/index';
+import { WORKBENCH_INSPECTOR_QUICK_OPEN_EVENT } from '../desktopChromeEvents';
+import type { InspectorTranslator } from '../inspector/InspectorModePanelHelpers';
+import { WORKBENCH_ENGINEERING_PREVIEW_FOCUS_EVENT, type EngineeringPreviewFocusDetail } from '../workbenchPreviewEvents';
+import shellStyles from '../AgentHubWorkbench.module.css';
import styles from './ChatEngineeringColumn.module.css';
export type ChatEngineeringColumnProps = {
diff --git a/app/workbench/src/ChatViewBridge.checkpoint.test.tsx b/app/workbench/src/transcript/ChatViewBridge.checkpoint.test.tsx
similarity index 100%
rename from app/workbench/src/ChatViewBridge.checkpoint.test.tsx
rename to app/workbench/src/transcript/ChatViewBridge.checkpoint.test.tsx
diff --git a/app/workbench/src/ChatViewBridge.tsx b/app/workbench/src/transcript/ChatViewBridge.tsx
similarity index 97%
rename from app/workbench/src/ChatViewBridge.tsx
rename to app/workbench/src/transcript/ChatViewBridge.tsx
index 4b09b0152..88c7596f2 100644
--- a/app/workbench/src/ChatViewBridge.tsx
+++ b/app/workbench/src/transcript/ChatViewBridge.tsx
@@ -9,14 +9,14 @@ import React, { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import type { TranscriptBlock } from '@shared/transcript';
import type { WorkbenchConversation } from '@shared/platform';
-import type { ConnectionStatusKind } from './GlobalRail';
+import type { ConnectionStatusKind } from '../GlobalRail';
import { ChatViewTranscript } from '@shared/chatview/components/ChatViewTranscript';
import type { TranscriptUserItem } from '@shared/chatview/transcript-item';
import type { UnreadDividerDescriptor } from '@shared/chatview';
import { CHATVIEW_I18N_NAMESPACE } from '@shared/chatview/i18n/resources';
import { useTypingPresence } from '@shared/chatview/typingPresence';
-import { SubagentStreamOverlay } from './team/SubagentStreamOverlay';
-import { InlineDelegationCard } from './team/InlineDelegationCard';
+import { SubagentStreamOverlay } from '../team/SubagentStreamOverlay';
+import { InlineDelegationCard } from '../team/InlineDelegationCard';
export interface ChatViewBridgeProps {
/** Filtered + optimistic transcript blocks to render. */
diff --git a/app/workbench/src/ConversationHost.checkpoint.test.tsx b/app/workbench/src/transcript/ConversationHost.checkpoint.test.tsx
similarity index 96%
rename from app/workbench/src/ConversationHost.checkpoint.test.tsx
rename to app/workbench/src/transcript/ConversationHost.checkpoint.test.tsx
index 1fbde1524..cf1463aee 100644
--- a/app/workbench/src/ConversationHost.checkpoint.test.tsx
+++ b/app/workbench/src/transcript/ConversationHost.checkpoint.test.tsx
@@ -13,7 +13,7 @@ import { createInitialComposerState } from '@shared/composer';
import { createMockPlatform } from '@shared/platform/createMockPlatform';
import type { CheckpointPort } from '@shared/platform';
import type { RowItem } from '@shared/chatview/types';
-import { WORKBENCH_ENGINEERING_PREVIEW_FOCUS_EVENT } from './workbenchPreviewEvents';
+import { WORKBENCH_ENGINEERING_PREVIEW_FOCUS_EVENT } from '../workbenchPreviewEvents';
import { useTestI18nLanguage } from '@shared/testing/i18n';
beforeAll(async () => {
@@ -30,20 +30,20 @@ vi.mock('./ChatViewBridge', () => ({
},
}));
-vi.mock('./WorkspaceHeader', () => ({
+vi.mock('../WorkspaceHeader', () => ({
WorkspaceHeader: () => ,
}));
-vi.mock('./ComposerDispatchQueue', () => ({
+vi.mock('../composer/ComposerDispatchQueue', () => ({
ComposerDispatchQueue: () => null,
}));
-vi.mock('./MessageSearchPanel', () => ({
+vi.mock('../MessageSearchPanel', () => ({
default: () => null,
}));
-vi.mock('./UnifiedComposer', () => ({
+vi.mock('../composer/UnifiedComposer', () => ({
UnifiedComposer: () => ,
}));
diff --git a/app/workbench/src/ConversationHost.goalBanner.test.tsx b/app/workbench/src/transcript/ConversationHost.goalBanner.test.tsx
similarity index 96%
rename from app/workbench/src/ConversationHost.goalBanner.test.tsx
rename to app/workbench/src/transcript/ConversationHost.goalBanner.test.tsx
index 8baae162e..99107764f 100644
--- a/app/workbench/src/ConversationHost.goalBanner.test.tsx
+++ b/app/workbench/src/transcript/ConversationHost.goalBanner.test.tsx
@@ -24,19 +24,19 @@ vi.mock('./ChatViewBridge', () => ({
ChatViewBridge: () => ,
}));
-vi.mock('./WorkspaceHeader', () => ({
+vi.mock('../WorkspaceHeader', () => ({
WorkspaceHeader: () => ,
}));
-vi.mock('./ComposerDispatchQueue', () => ({
+vi.mock('../composer/ComposerDispatchQueue', () => ({
ComposerDispatchQueue: () => null,
}));
-vi.mock('./MessageSearchPanel', () => ({
+vi.mock('../MessageSearchPanel', () => ({
default: () => null,
}));
-vi.mock('./UnifiedComposer', () => ({
+vi.mock('../composer/UnifiedComposer', () => ({
UnifiedComposer: () => ,
}));
diff --git a/app/workbench/src/ConversationHost.tsx b/app/workbench/src/transcript/ConversationHost.tsx
similarity index 97%
rename from app/workbench/src/ConversationHost.tsx
rename to app/workbench/src/transcript/ConversationHost.tsx
index 52d332a00..642064bf6 100644
--- a/app/workbench/src/ConversationHost.tsx
+++ b/app/workbench/src/transcript/ConversationHost.tsx
@@ -1,6 +1,6 @@
import React, { FormEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
-import { WORKBENCH_APPROVAL_JUMP_EVENT } from './workbenchApprovalEvents';
+import { WORKBENCH_APPROVAL_JUMP_EVENT } from '../workbenchApprovalEvents';
import type { TFunction } from 'i18next';
import type { TranscriptBlock, TextTranscriptBlock } from '@shared/transcript';
import {
@@ -22,7 +22,7 @@ import {
handleDocumentDragOver,
handleDocumentDrop,
type ComposerDocumentFileDropCallbacks,
-} from './composerDocumentFileDrop';
+} from '../composer/composerDocumentFileDrop';
import {
describePendingIntent,
enqueuePendingIntent,
@@ -38,34 +38,34 @@ import {
retryPendingIntent,
type PendingDispatchIntent,
type PendingIntentMove,
-} from './composer/pendingIntents';
+} from '../composer/pendingIntents';
import type { AgentHubPlatform, WorkbenchConversation } from '@shared/platform';
import { AppError } from '@shared/errors';
import { resolveFailedToastKey } from '@shared/chatview/failedToastKey';
import { CHATVIEW_I18N_NAMESPACE } from '@shared/chatview/i18n/resources';
-import type { AttachmentUploadState } from './UnifiedComposer';
-import type { FileItem } from './inspector';
-import type { ConnectionStatusKind } from './GlobalRail';
+import type { AttachmentUploadState } from '../composer/UnifiedComposer';
+import type { FileItem } from '../inspector/index';
+import type { ConnectionStatusKind } from '../GlobalRail';
import { ChatViewBridge } from './ChatViewBridge';
-import { ComposerDispatchQueue } from './ComposerDispatchQueue';
+import { ComposerDispatchQueue } from '../composer/ComposerDispatchQueue';
import {
countPendingApprovals,
firstPendingApprovalBlockId,
-} from './workbenchApprovalSummary';
-import { UnifiedComposer } from './UnifiedComposer';
-import { WorkspaceHeader } from './WorkspaceHeader';
-import type { WorkbenchSplitControls } from './workbenchFrameTypes';
+} from '../workbenchApprovalSummary';
+import { UnifiedComposer } from '../composer/UnifiedComposer';
+import { WorkspaceHeader } from '../WorkspaceHeader';
+import type { WorkbenchSplitControls } from '../workbenchFrameTypes';
import { WorkbenchGoalBanner } from './WorkbenchGoalBanner';
import { deriveGoalSummary } from './workbenchGoalSummary';
import type { UnreadDividerDescriptor } from '@shared/chatview';
import type { RowItem } from '@shared/chatview/types';
-import { WORKBENCH_ENGINEERING_PREVIEW_FOCUS_EVENT } from './workbenchPreviewEvents';
-import MessageSearchPanel from './MessageSearchPanel';
-import { PageErrorBoundary } from './PageErrorBoundary';
-import { useComposerSubmitBehavior } from './workbenchPreferences';
-import styles from './AgentHubWorkbench.module.css';
+import { WORKBENCH_ENGINEERING_PREVIEW_FOCUS_EVENT } from '../workbenchPreviewEvents';
+import MessageSearchPanel from '../MessageSearchPanel';
+import { PageErrorBoundary } from '../PageErrorBoundary';
+import { useComposerSubmitBehavior } from '../workbenchPreferences';
+import styles from '../AgentHubWorkbench.module.css';
-export type { MainchainSummary } from './mainchain';
+export type { MainchainSummary } from '../mainchain/index';
/**
* Map a platform/API failure to user-facing toast copy (#1826).
diff --git a/app/workbench/src/ConversationSidebar.test.tsx b/app/workbench/src/transcript/ConversationSidebar.test.tsx
similarity index 99%
rename from app/workbench/src/ConversationSidebar.test.tsx
rename to app/workbench/src/transcript/ConversationSidebar.test.tsx
index db6586a8b..f846baa85 100644
--- a/app/workbench/src/ConversationSidebar.test.tsx
+++ b/app/workbench/src/transcript/ConversationSidebar.test.tsx
@@ -4,7 +4,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vite
import type { ReactNode } from 'react';
import type { WorkbenchConversation } from '@shared/platform';
import { ConversationSidebar } from './ConversationSidebar';
-import type { TaskItem } from './pages';
+import type { TaskItem } from '../pages/index';
import {
backFromTaskDeepLink,
consumeWorkbenchTaskDeepLinkIntent,
@@ -12,7 +12,7 @@ import {
openConversationForTask,
publishWorkbenchTaskQueue,
resetWorkbenchTaskDeepLinksForTest,
-} from './workbenchTaskDeepLinks';
+} from '../routes/workbenchTaskDeepLinks';
/* ──────────────────────────────────────────────────────────────────────
ConversationSidebar actions tests (#1508): rename / copy link / delete.
diff --git a/app/workbench/src/ConversationSidebar.tsx b/app/workbench/src/transcript/ConversationSidebar.tsx
similarity index 99%
rename from app/workbench/src/ConversationSidebar.tsx
rename to app/workbench/src/transcript/ConversationSidebar.tsx
index 3887c27a2..37c511f72 100644
--- a/app/workbench/src/ConversationSidebar.tsx
+++ b/app/workbench/src/transcript/ConversationSidebar.tsx
@@ -2,17 +2,17 @@ import React, { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Virtualizer, type VirtualizerHandle } from 'virtua';
import type { WorkbenchConversation } from '@shared/platform';
-import { DesignNavIcon } from './designIcons';
-import { ContextMenu, type ContextMenuItem } from './floating';
+import { DesignNavIcon } from '../designIcons';
+import { ContextMenu, type ContextMenuItem } from '../floating/index';
import { CHATVIEW_I18N_NAMESPACE } from '@shared/chatview/i18n/resources';
import Modal from '@shared/ui/Modal';
import { Tooltip } from '@shared/ui/Tooltip';
-import type { ConversationLiveStatus } from './workbenchAttentionModel';
+import type { ConversationLiveStatus } from '../workbenchAttentionModel';
import {
useWorkbenchTaskDeepLinkActions,
useWorkbenchTaskDeepLinkSnapshot,
-} from './workbenchTaskDeepLinks';
-import styles from './AgentHubWorkbench.module.css';
+} from '../routes/workbenchTaskDeepLinks';
+import styles from '../AgentHubWorkbench.module.css';
const SORT_STORAGE_KEY = 'agenthub.conversationSort';
diff --git a/app/workbench/src/MainchainStatusStrip.test.tsx b/app/workbench/src/transcript/MainchainStatusStrip.test.tsx
similarity index 98%
rename from app/workbench/src/MainchainStatusStrip.test.tsx
rename to app/workbench/src/transcript/MainchainStatusStrip.test.tsx
index 1740faec8..8dce300fb 100644
--- a/app/workbench/src/MainchainStatusStrip.test.tsx
+++ b/app/workbench/src/transcript/MainchainStatusStrip.test.tsx
@@ -2,7 +2,7 @@ import { fireEvent, render, screen } from '@testing-library/react';
import { beforeAll, describe, expect, it, vi } from 'vitest';
import { useTestI18nLanguage } from '@shared/testing/i18n';
import { MainchainStatusStrip } from './MainchainStatusStrip';
-import type { MainchainSummary } from './mainchain';
+import type { MainchainSummary } from '../mainchain/index';
// Chip copy resolves through the real zh/en bundles (sharedWorkbench ns),
// so opt into a real language instead of the key-echo default (#1717).
diff --git a/app/workbench/src/MainchainStatusStrip.tsx b/app/workbench/src/transcript/MainchainStatusStrip.tsx
similarity index 97%
rename from app/workbench/src/MainchainStatusStrip.tsx
rename to app/workbench/src/transcript/MainchainStatusStrip.tsx
index ea90f04eb..7e0be3fd5 100644
--- a/app/workbench/src/MainchainStatusStrip.tsx
+++ b/app/workbench/src/transcript/MainchainStatusStrip.tsx
@@ -1,10 +1,10 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { CHATVIEW_I18N_NAMESPACE } from '@shared/chatview/i18n/resources';
-import styles from './AgentHubWorkbench.module.css';
-import { connectionStatusLabel, type ConnectionStatusKind } from './GlobalRail';
-import type { MainchainSummary } from './mainchain';
-import type { WorkbenchAttentionCounts } from './workbenchAttentionModel';
+import styles from '../AgentHubWorkbench.module.css';
+import { connectionStatusLabel, type ConnectionStatusKind } from '../GlobalRail';
+import type { MainchainSummary } from '../mainchain/index';
+import type { WorkbenchAttentionCounts } from '../workbenchAttentionModel';
// #2154: shared token formatter (same units as the usage board and the
// inspector overview) instead of the page-local formatTokenCount.
import { formatTokens } from '@shared/context/breakdown';
diff --git a/app/workbench/src/WorkbenchGoalBanner.module.css b/app/workbench/src/transcript/WorkbenchGoalBanner.module.css
similarity index 100%
rename from app/workbench/src/WorkbenchGoalBanner.module.css
rename to app/workbench/src/transcript/WorkbenchGoalBanner.module.css
diff --git a/app/workbench/src/WorkbenchGoalBanner.test.tsx b/app/workbench/src/transcript/WorkbenchGoalBanner.test.tsx
similarity index 100%
rename from app/workbench/src/WorkbenchGoalBanner.test.tsx
rename to app/workbench/src/transcript/WorkbenchGoalBanner.test.tsx
diff --git a/app/workbench/src/WorkbenchGoalBanner.tsx b/app/workbench/src/transcript/WorkbenchGoalBanner.tsx
similarity index 97%
rename from app/workbench/src/WorkbenchGoalBanner.tsx
rename to app/workbench/src/transcript/WorkbenchGoalBanner.tsx
index b58f86fdf..5f28435cd 100644
--- a/app/workbench/src/WorkbenchGoalBanner.tsx
+++ b/app/workbench/src/transcript/WorkbenchGoalBanner.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { CHATVIEW_I18N_NAMESPACE } from '@shared/chatview/i18n/resources';
-import chipStyles from './AgentHubWorkbench.module.css';
+import chipStyles from '../AgentHubWorkbench.module.css';
import styles from './WorkbenchGoalBanner.module.css';
import type { WorkbenchGoalStatus, WorkbenchGoalSummary } from './workbenchGoalSummary';
diff --git a/app/workbench/src/WorkbenchTranscriptOverlays.tsx b/app/workbench/src/transcript/WorkbenchTranscriptOverlays.tsx
similarity index 99%
rename from app/workbench/src/WorkbenchTranscriptOverlays.tsx
rename to app/workbench/src/transcript/WorkbenchTranscriptOverlays.tsx
index ec3475dcb..e55849dc4 100644
--- a/app/workbench/src/WorkbenchTranscriptOverlays.tsx
+++ b/app/workbench/src/transcript/WorkbenchTranscriptOverlays.tsx
@@ -7,7 +7,7 @@ import {
DemoToast,
type ContextMenuItem,
type MultiSelectBarAction,
-} from './floating';
+} from '../floating/index';
import type {
DeleteConfirmRequest,
WorkbenchContextMenuState,
diff --git a/app/workbench/src/useWorkbenchSessionChrome.test.ts b/app/workbench/src/transcript/useWorkbenchSessionChrome.test.ts
similarity index 99%
rename from app/workbench/src/useWorkbenchSessionChrome.test.ts
rename to app/workbench/src/transcript/useWorkbenchSessionChrome.test.ts
index f82c0a668..122ebfa15 100644
--- a/app/workbench/src/useWorkbenchSessionChrome.test.ts
+++ b/app/workbench/src/transcript/useWorkbenchSessionChrome.test.ts
@@ -9,8 +9,8 @@ import type {
WorkbenchConversation,
} from '@shared/platform';
import type { TranscriptBlock } from '@shared/transcript';
-import { INSPECTOR_DEFAULT_COLLAPSE_EVENT } from './workbenchLayoutConstants';
-import { WORKBENCH_MOCK_SETTINGS_DEFAULTS } from './mockData';
+import { INSPECTOR_DEFAULT_COLLAPSE_EVENT } from '../workbenchLayoutConstants';
+import { WORKBENCH_MOCK_SETTINGS_DEFAULTS } from '../mockData';
import {
LOCAL_CLI_DISCOVERY_FALLBACK,
useWorkbenchSessionChrome,
diff --git a/app/workbench/src/useWorkbenchSessionChrome.ts b/app/workbench/src/transcript/useWorkbenchSessionChrome.ts
similarity index 98%
rename from app/workbench/src/useWorkbenchSessionChrome.ts
rename to app/workbench/src/transcript/useWorkbenchSessionChrome.ts
index e92f4c0ff..632443d15 100644
--- a/app/workbench/src/useWorkbenchSessionChrome.ts
+++ b/app/workbench/src/transcript/useWorkbenchSessionChrome.ts
@@ -15,14 +15,14 @@ import {
} from '@shared/composer';
import { toggleAppliedAgentHubTheme } from '@shared/theme';
import { collectTranscriptEvidence } from '@shared/transcript';
-import { buildMainchainSummary } from './mainchain';
-import type { FileItem } from './inspector';
-import { WORKBENCH_MOCK_SETTINGS_DEFAULTS } from './mockData';
-import { createSettingsService, type SettingsService } from './settingsService';
+import { buildMainchainSummary } from '../mainchain/index';
+import type { FileItem } from '../inspector/index';
+import { WORKBENCH_MOCK_SETTINGS_DEFAULTS } from '../mockData';
+import { createSettingsService, type SettingsService } from '../settingsService';
import {
INSPECTOR_DEFAULT_COLLAPSE_EVENT,
type InspectorDefaultCollapseDetail,
-} from './workbenchLayoutConstants';
+} from '../workbenchLayoutConstants';
import {
LOCAL_CLI_DISCOVERY_FALLBACK,
buildInspectorTranscriptViews,
diff --git a/app/workbench/src/useWorkbenchTranscriptChrome.test.ts b/app/workbench/src/transcript/useWorkbenchTranscriptChrome.test.ts
similarity index 99%
rename from app/workbench/src/useWorkbenchTranscriptChrome.test.ts
rename to app/workbench/src/transcript/useWorkbenchTranscriptChrome.test.ts
index c46557cc2..53a40a190 100644
--- a/app/workbench/src/useWorkbenchTranscriptChrome.test.ts
+++ b/app/workbench/src/transcript/useWorkbenchTranscriptChrome.test.ts
@@ -4,7 +4,7 @@ import { afterEach, describe, expect, it, vi } from 'vitest';
import type { ReactElement } from 'react';
import type { WorkbenchConversation } from '@shared/platform';
import type { TranscriptBlock } from '@shared/transcript';
-import type { TranscriptContextMenuEvent, TranscriptPointerEvent } from './transcriptEventTypes';
+import type { TranscriptContextMenuEvent, TranscriptPointerEvent } from '../transcriptEventTypes';
import {
SELECTION_HOLD_CANCEL_DISTANCE,
SELECTION_HOLD_DELAY_MS,
diff --git a/app/workbench/src/useWorkbenchTranscriptChrome.ts b/app/workbench/src/transcript/useWorkbenchTranscriptChrome.ts
similarity index 98%
rename from app/workbench/src/useWorkbenchTranscriptChrome.ts
rename to app/workbench/src/transcript/useWorkbenchTranscriptChrome.ts
index 52b932f4a..152a4f0be 100644
--- a/app/workbench/src/useWorkbenchTranscriptChrome.ts
+++ b/app/workbench/src/transcript/useWorkbenchTranscriptChrome.ts
@@ -9,8 +9,8 @@ import {
} from 'react';
import type { ComposerAction } from '@shared/composer';
import type { ApprovalDecisionAction, TranscriptBlock } from '@shared/transcript';
-import type { ContextMenuItem, MultiSelectBarAction } from './floating';
-import type { TranscriptContextMenuEvent, TranscriptPointerEvent } from './transcriptEventTypes';
+import type { ContextMenuItem, MultiSelectBarAction } from '../floating/index';
+import type { TranscriptContextMenuEvent, TranscriptPointerEvent } from '../transcriptEventTypes';
import {
createTranscriptChromeController,
type DeleteConfirmRequest,
diff --git a/app/workbench/src/workbenchGoalSummary.test.ts b/app/workbench/src/transcript/workbenchGoalSummary.test.ts
similarity index 100%
rename from app/workbench/src/workbenchGoalSummary.test.ts
rename to app/workbench/src/transcript/workbenchGoalSummary.test.ts
diff --git a/app/workbench/src/workbenchGoalSummary.ts b/app/workbench/src/transcript/workbenchGoalSummary.ts
similarity index 100%
rename from app/workbench/src/workbenchGoalSummary.ts
rename to app/workbench/src/transcript/workbenchGoalSummary.ts
diff --git a/app/workbench/src/workbenchSessionChromeHelpers.test.ts b/app/workbench/src/transcript/workbenchSessionChromeHelpers.test.ts
similarity index 100%
rename from app/workbench/src/workbenchSessionChromeHelpers.test.ts
rename to app/workbench/src/transcript/workbenchSessionChromeHelpers.test.ts
diff --git a/app/workbench/src/workbenchSessionChromeHelpers.ts b/app/workbench/src/transcript/workbenchSessionChromeHelpers.ts
similarity index 98%
rename from app/workbench/src/workbenchSessionChromeHelpers.ts
rename to app/workbench/src/transcript/workbenchSessionChromeHelpers.ts
index 420c80bd2..9b5ac7435 100644
--- a/app/workbench/src/workbenchSessionChromeHelpers.ts
+++ b/app/workbench/src/transcript/workbenchSessionChromeHelpers.ts
@@ -25,10 +25,10 @@ import type {
ChildAgentTranscriptBlock,
EvidenceRef,
} from '@shared/transcript';
-import type { MainchainSummary } from './mainchain';
-import type { FileItem, RunResultInfo } from './inspector';
-import type { SettingsService } from './settingsService';
-import type { GlobalRailPage } from './GlobalRail';
+import type { MainchainSummary } from '../mainchain/index';
+import type { FileItem, RunResultInfo } from '../inspector/index';
+import type { SettingsService } from '../settingsService';
+import type { GlobalRailPage } from '../GlobalRail';
import { matchesShortcut } from '@shared/utils/keyboardUtils';
import type { KeyboardEventLike } from '@shared/utils/keyboardUtils';
import { getResolvedBinding } from '@shared/utils/keyboardShortcuts';
diff --git a/app/workbench/src/workbenchTranscriptChromeActionMappers.test.ts b/app/workbench/src/transcript/workbenchTranscriptChromeActionMappers.test.ts
similarity index 100%
rename from app/workbench/src/workbenchTranscriptChromeActionMappers.test.ts
rename to app/workbench/src/transcript/workbenchTranscriptChromeActionMappers.test.ts
diff --git a/app/workbench/src/workbenchTranscriptChromeActionMappers.ts b/app/workbench/src/transcript/workbenchTranscriptChromeActionMappers.ts
similarity index 99%
rename from app/workbench/src/workbenchTranscriptChromeActionMappers.ts
rename to app/workbench/src/transcript/workbenchTranscriptChromeActionMappers.ts
index 814a36fb9..f3446f0de 100644
--- a/app/workbench/src/workbenchTranscriptChromeActionMappers.ts
+++ b/app/workbench/src/transcript/workbenchTranscriptChromeActionMappers.ts
@@ -3,8 +3,8 @@ import type { ComposerAction } from '@shared/composer';
import type { WorkbenchConversation } from '@shared/platform';
import type { ApprovalDecisionAction, TranscriptBlock } from '@shared/transcript';
import { resolveFailedToastKey } from '@shared/chatview/failedToastKey';
-import type { ContextMenuItem, MultiSelectBarAction } from './floating';
-import { ForwardConversationPicker } from './floating/ForwardConversationPicker';
+import type { ContextMenuItem, MultiSelectBarAction } from '../floating/index';
+import { ForwardConversationPicker } from '../floating/ForwardConversationPicker';
import {
blockTitle,
buildPermissionApprovalDecision,
diff --git a/app/workbench/src/workbenchTranscriptChromeHelpers.test.ts b/app/workbench/src/transcript/workbenchTranscriptChromeHelpers.test.ts
similarity index 100%
rename from app/workbench/src/workbenchTranscriptChromeHelpers.test.ts
rename to app/workbench/src/transcript/workbenchTranscriptChromeHelpers.test.ts
diff --git a/app/workbench/src/workbenchTranscriptChromeHelpers.ts b/app/workbench/src/transcript/workbenchTranscriptChromeHelpers.ts
similarity index 99%
rename from app/workbench/src/workbenchTranscriptChromeHelpers.ts
rename to app/workbench/src/transcript/workbenchTranscriptChromeHelpers.ts
index 372f66dc2..42d8393d7 100644
--- a/app/workbench/src/workbenchTranscriptChromeHelpers.ts
+++ b/app/workbench/src/transcript/workbenchTranscriptChromeHelpers.ts
@@ -1,7 +1,7 @@
import type { ComposerAction } from '@shared/composer';
import type { WorkbenchConversation } from '@shared/platform';
import type { ApprovalDecisionAction, TranscriptBlock } from '@shared/transcript';
-import type { ContextMenuItem, MultiSelectBarAction } from './floating';
+import type { ContextMenuItem, MultiSelectBarAction } from '../floating/index';
import {
applyTranscriptChromeSideEffects,
buildTranscriptContextMenuGroups,
diff --git a/app/workbench/src/workbenchTranscriptChromeLabels.test.ts b/app/workbench/src/transcript/workbenchTranscriptChromeLabels.test.ts
similarity index 100%
rename from app/workbench/src/workbenchTranscriptChromeLabels.test.ts
rename to app/workbench/src/transcript/workbenchTranscriptChromeLabels.test.ts
diff --git a/app/workbench/src/workbenchTranscriptChromeLabels.ts b/app/workbench/src/transcript/workbenchTranscriptChromeLabels.ts
similarity index 100%
rename from app/workbench/src/workbenchTranscriptChromeLabels.ts
rename to app/workbench/src/transcript/workbenchTranscriptChromeLabels.ts
diff --git a/app/workbench/src/workbenchTranscriptChromeStateHelpers.test.ts b/app/workbench/src/transcript/workbenchTranscriptChromeStateHelpers.test.ts
similarity index 100%
rename from app/workbench/src/workbenchTranscriptChromeStateHelpers.test.ts
rename to app/workbench/src/transcript/workbenchTranscriptChromeStateHelpers.test.ts
diff --git a/app/workbench/src/workbenchTranscriptChromeStateHelpers.ts b/app/workbench/src/transcript/workbenchTranscriptChromeStateHelpers.ts
similarity index 100%
rename from app/workbench/src/workbenchTranscriptChromeStateHelpers.ts
rename to app/workbench/src/transcript/workbenchTranscriptChromeStateHelpers.ts
diff --git a/app/workbench/src/useWorkbenchGlobalShortcuts.ts b/app/workbench/src/useWorkbenchGlobalShortcuts.ts
index 2c4f8b700..498198c74 100644
--- a/app/workbench/src/useWorkbenchGlobalShortcuts.ts
+++ b/app/workbench/src/useWorkbenchGlobalShortcuts.ts
@@ -1,7 +1,7 @@
import { useEffect, useRef } from 'react';
import { getResolvedShortcutGroups } from '@shared/utils/keyboardShortcuts';
import { matchesShortcut } from '@shared/utils/keyboardUtils';
-import { isEditableKeyboardTarget } from './workbenchSessionChromeHelpers';
+import { isEditableKeyboardTarget } from './transcript/workbenchSessionChromeHelpers';
/* ═══════════════════════════════════════════════════════════════════════
useWorkbenchGlobalShortcuts — shared global keyboard dispatcher (#1822).
diff --git a/app/workbench/src/useWorkbenchTaskDeepLinks.test.ts b/app/workbench/src/useWorkbenchTaskDeepLinks.test.ts
index 105c7eaac..a39ef0530 100644
--- a/app/workbench/src/useWorkbenchTaskDeepLinks.test.ts
+++ b/app/workbench/src/useWorkbenchTaskDeepLinks.test.ts
@@ -1,6 +1,6 @@
import { act, renderHook } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
-import type { TaskItem } from './pages';
+import type { TaskItem } from './pages/index';
import {
backFromTaskDeepLink,
getWorkbenchTaskDeepLinkSnapshot,
@@ -9,7 +9,7 @@ import {
openTaskDetailForConversation,
publishWorkbenchTaskQueue,
resetWorkbenchTaskDeepLinksForTest,
-} from './workbenchTaskDeepLinks';
+} from './routes/workbenchTaskDeepLinks';
import { useWorkbenchTaskDeepLinks } from './useWorkbenchTaskDeepLinks';
function makeTask(overrides: Partial = {}): TaskItem {
diff --git a/app/workbench/src/useWorkbenchTaskDeepLinks.ts b/app/workbench/src/useWorkbenchTaskDeepLinks.ts
index eeeb45b0d..36a334f31 100644
--- a/app/workbench/src/useWorkbenchTaskDeepLinks.ts
+++ b/app/workbench/src/useWorkbenchTaskDeepLinks.ts
@@ -7,7 +7,7 @@ import {
useWorkbenchTaskDeepLinkStore,
type WorkbenchTaskDeepLinkIntent,
type WorkbenchTaskQueueSource,
-} from './workbenchTaskDeepLinks';
+} from './routes/workbenchTaskDeepLinks';
export interface UseWorkbenchTaskDeepLinksOptions {
setActivePage: (page: GlobalRailPage) => void;
diff --git a/app/workbench/src/workbenchFramePartsHelpers.ts b/app/workbench/src/workbenchFramePartsHelpers.ts
index 5eb05958b..587a059f8 100644
--- a/app/workbench/src/workbenchFramePartsHelpers.ts
+++ b/app/workbench/src/workbenchFramePartsHelpers.ts
@@ -1,8 +1,8 @@
import { useMemo } from 'react';
-import type { ConversationHostProps } from './ConversationHost';
-import type { ConversationSidebarProps } from './ConversationSidebar';
-import type { RightInspectorProps } from './rightInspectorTypes';
-import type { WorkbenchRoutesProps } from './workbenchRoutesTypes';
+import type { ConversationHostProps } from './transcript/ConversationHost';
+import type { ConversationSidebarProps } from './transcript/ConversationSidebar';
+import type { RightInspectorProps } from './inspector/rightInspectorTypes';
+import type { WorkbenchRoutesProps } from './routes/workbenchRoutesTypes';
import type {
ChatConversationHostFrameProps,
ChatInspectorFrameProps,
diff --git a/app/workbench/src/workbenchFrameTypes.ts b/app/workbench/src/workbenchFrameTypes.ts
index 4503d6b49..f14920313 100644
--- a/app/workbench/src/workbenchFrameTypes.ts
+++ b/app/workbench/src/workbenchFrameTypes.ts
@@ -6,14 +6,14 @@ import type {
} from '@shared/platform';
import type { TranscriptBlock } from '@shared/transcript';
import type { ConnectionStatusKind, GlobalRailPage } from './GlobalRail';
-import type { RuntimeEvidenceSnapshot } from './RightInspector';
+import type { RuntimeEvidenceSnapshot } from './inspector/RightInspector';
import type {
WorkbenchAgentProfilesStatus,
WorkbenchContactsActions,
WorkbenchContactsData,
WorkbenchDocumentsActions,
} from './WorkbenchRoutes';
-import type { AgentConfig, DocRow, ProjectDraft } from './pages';
+import type { AgentConfig, DocRow, ProjectDraft } from './pages/index';
import type {
CCSwitchStatusInfo,
CCSwitchProviderInfo,
@@ -22,8 +22,8 @@ import type {
} from './pages/AgentsPage';
import type { ProjectInfo } from './pages/ProjectsPage';
import type { WorkbenchPanelLayout } from './useWorkbenchPanelLayout';
-import type { WorkbenchSessionChrome } from './useWorkbenchSessionChrome';
-import type { WorkbenchTranscriptChrome } from './useWorkbenchTranscriptChrome';
+import type { WorkbenchSessionChrome } from './transcript/useWorkbenchSessionChrome';
+import type { WorkbenchTranscriptChrome } from './transcript/useWorkbenchTranscriptChrome';
import type { WorkbenchProfileChrome } from './useWorkbenchProfileChrome';
import type { ConversationLiveStatus } from './workbenchAttentionModel';
import type {
diff --git a/docs/architecture/07-design-system-ssot.md b/docs/architecture/07-design-system-ssot.md
index fce02a88b..ec410c27e 100644
--- a/docs/architecture/07-design-system-ssot.md
+++ b/docs/architecture/07-design-system-ssot.md
@@ -113,7 +113,7 @@ Applied first to AuxPanel and TerminalPanel. Respect `prefers-reduced-motion`.
| HiDPI glass | `@media (min-resolution: 192dpi)` in tokens + themes | blur ~1.4×, stronger hairline borders, focus ring 3–4px |
| Breakpoint definitions | `app/shared/src/styles/tokens-base.css` 的 `--bp-*` 变量即 SSOT,`tokens-base.test.ts` 断言取值 | minimal 420 / mobile 480 / compact 720 / narrow 768 / medium 1024 / standard 1280 / wide 1440 / xwide 1920 / ultra 2560 |
-响应式断点只定义在 `tokens-base.css` 的 `--bp-*`;剩余非 SSOT `@media` 仅 `app/shared/src/ui/Input.module.css` 与 `app/web/src/components/AuthPage.module.css` 的 legacy 760、`app/workbench/src/WorkbenchGoalBanner.module.css` 的 900,以及 Desktop `App.module.css` 的 1023/1279 成对窗口约定。
+响应式断点只定义在 `tokens-base.css` 的 `--bp-*`;剩余非 SSOT `@media` 仅 `app/shared/src/ui/Input.module.css` 与 `app/web/src/components/AuthPage.module.css` 的 legacy 760、`app/workbench/src/transcript/WorkbenchGoalBanner.module.css` 的 900,以及 Desktop `App.module.css` 的 1023/1279 成对窗口约定。
## 9. Acceptance mapping