Files
zclaw_openfang/docs/superpowers/plans/2026-03-21-phase2-domain-reorganization.md
iven 0d4fa96b82
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
refactor: 统一项目名称从OpenFang到ZCLAW
重构所有代码和文档中的项目名称,将OpenFang统一更新为ZCLAW。包括:
- 配置文件中的项目名称
- 代码注释和文档引用
- 环境变量和路径
- 类型定义和接口名称
- 测试用例和模拟数据

同时优化部分代码结构,移除未使用的模块,并更新相关依赖项。
2026-03-27 07:36:03 +08:00

1175 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ZCLAW 架构优化 - Phase 2: 领域重组 实施计划
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 按领域重组代码结构,迁移到 Valtio 状态管理,引入 XState 状态机
**Architecture:** 创建 domains/ 目录,按业务领域组织代码,使用 Valtio 替代 Zustand使用 XState 管理 Hands 状态
**Tech Stack:** TypeScript, Valtio, XState, React
**Spec Reference:** `docs/superpowers/specs/2026-03-21-architecture-optimization-design.md`
**Duration:** 4 周 (16 人日)
---
## File Structure
### New Files
```
desktop/src/
├── domains/
│ ├── chat/
│ │ ├── index.ts # 导出入口
│ │ ├── store.ts # Valtio store
│ │ ├── types.ts # 类型定义
│ │ ├── api.ts # API 调用
│ │ └── hooks.ts # React hooks
│ ├── hands/
│ │ ├── index.ts # 导出入口
│ │ ├── store.ts # Valtio store
│ │ ├── machine.ts # XState 状态机
│ │ ├── types.ts # 类型定义
│ │ └── hooks.ts # React hooks
│ ├── intelligence/
│ │ ├── index.ts # 导出入口
│ │ ├── client.ts # 统一客户端
│ │ ├── cache.ts # 缓存策略
│ │ └── types.ts # 类型定义
│ └── skills/
│ ├── index.ts # 导出入口
│ ├── store.ts # Valtio store
│ └── types.ts # 类型定义
└── shared/
├── index.ts # 导出入口
├── error-handling.ts # 统一错误处理
├── logging.ts # 统一日志
└── types.ts # 共享类型
```
### Modified Files
```
desktop/
├── package.json # 添加 Valtio, XState 依赖
├── src/store/chatStore.ts # 重导出 domains/chat
├── src/store/handStore.ts # 重导出 domains/hands
└── src/components/ # 更新导入路径
```
---
## Chunk 1: 依赖安装和目录结构
### Task 1.1: 安装 Valtio 和 XState
**Files:**
- Modify: `desktop/package.json`
- [ ] **Step 1: 安装 Valtio**
Run:
```bash
cd g:/ZClaw_zclaw/desktop && pnpm add valtio
```
Expected: valtio 安装成功
- [ ] **Step 2: 安装 XState**
Run:
```bash
cd g:/ZClaw_zclaw/desktop && pnpm add xstate @xstate/react
```
Expected: xstate 和 @xstate/react 安装成功
- [ ] **Step 3: 验证安装**
Run:
```bash
cd g:/ZClaw_zclaw/desktop && pnpm list valtio xstate @xstate/react
```
Expected: 显示已安装版本
- [ ] **Step 4: 提交依赖更新**
```bash
cd g:/ZClaw_zclaw && git add desktop/package.json desktop/pnpm-lock.yaml
git commit -m "$(cat <<'EOF'
feat(deps): add Valtio and XState for Phase 2
- Add valtio for Proxy-based state management
- Add xstate and @xstate/react for state machines
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"
```
---
### Task 1.2: 创建领域目录结构
**Files:**
- Create: `desktop/src/domains/chat/` directory
- Create: `desktop/src/domains/hands/` directory
- Create: `desktop/src/domains/intelligence/` directory
- Create: `desktop/src/domains/skills/` directory
- Create: `desktop/src/shared/` directory
- [ ] **Step 1: 创建目录**
Run:
```bash
cd g:/ZClaw_zclaw/desktop/src && mkdir -p domains/chat domains/hands domains/intelligence domains/skills shared
```
- [ ] **Step 2: 提交目录结构**
```bash
cd g:/ZClaw_zclaw && git add desktop/src/domains desktop/src/shared
git commit -m "$(cat <<'EOF'
refactor: create domains directory structure
- Create domains/chat for chat system
- Create domains/hands for automation
- Create domains/intelligence for AI layer
- Create domains/skills for skill system
- Create shared for common utilities
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"
```
---
## Chunk 2: Chat Domain 迁移
### Task 2.1: 创建 Chat Domain 类型定义
**Files:**
- Create: `desktop/src/domains/chat/types.ts`
- [ ] **Step 1: 提取类型定义**
Create `desktop/src/domains/chat/types.ts`:
```typescript
/**
* Chat Domain Types
*
* Core types for the chat system.
*/
export interface MessageFile {
name: string;
path?: string;
size?: number;
type?: string;
}
export interface CodeBlock {
language?: string;
filename?: string;
content?: string;
}
export interface Message {
id: string;
role: 'user' | 'assistant' | 'tool' | 'hand' | 'workflow';
content: string;
timestamp: Date;
runId?: string;
streaming?: boolean;
toolName?: string;
toolInput?: string;
toolOutput?: string;
error?: string;
handName?: string;
handStatus?: string;
handResult?: unknown;
workflowId?: string;
workflowStep?: string;
workflowStatus?: string;
workflowResult?: unknown;
files?: MessageFile[];
codeBlocks?: CodeBlock[];
}
export interface Conversation {
id: string;
title: string;
messages: Message[];
sessionKey: string | null;
agentId: string | null;
createdAt: Date;
updatedAt: Date;
}
export interface Agent {
id: string;
name: string;
icon: string;
color: string;
lastMessage: string;
time: string;
}
export interface AgentProfileLike {
id: string;
name: string;
nickname?: string;
role?: string;
}
export interface ChatState {
messages: Message[];
conversations: Conversation[];
currentConversationId: string | null;
agents: Agent[];
currentAgent: Agent | null;
isStreaming: boolean;
currentModel: string;
sessionKey: string | null;
}
```
- [ ] **Step 2: 提交类型定义**
```bash
cd g:/ZClaw_zclaw && git add desktop/src/domains/chat/types.ts
git commit -m "$(cat <<'EOF'
refactor(chat): extract chat domain types
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"
```
---
### Task 2.2: 创建 Valtio Chat Store
**Files:**
- Create: `desktop/src/domains/chat/store.ts`
- [ ] **Step 1: 创建 Valtio Store**
Create `desktop/src/domains/chat/store.ts`:
```typescript
/**
* Chat Domain Store
*
* Valtio-based state management for chat.
* Replaces Zustand for better performance with fine-grained reactivity.
*/
import { proxy, subscribe } from 'valtio';
import type { Message, Conversation, Agent, AgentProfileLike, ChatState } from './types';
// Default agent
const DEFAULT_AGENT: Agent = {
id: '1',
name: 'ZCLAW',
icon: '🦞',
color: 'bg-gradient-to-br from-orange-500 to-red-500',
lastMessage: '发送消息开始对话',
time: '',
};
// Helper functions
function generateConvId(): string {
return `conv_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
}
function deriveTitle(messages: Message[]): string {
const firstUser = messages.find(m => m.role === 'user');
if (firstUser) {
const text = firstUser.content.trim();
return text.length > 30 ? text.slice(0, 30) + '...' : text;
}
return '新对话';
}
export function toChatAgent(profile: AgentProfileLike): Agent {
return {
id: profile.id,
name: profile.name,
icon: profile.nickname?.slice(0, 1) || '🦞',
color: 'bg-gradient-to-br from-orange-500 to-red-500',
lastMessage: profile.role || '新分身',
time: '',
};
}
// State interface with actions
interface ChatStore extends ChatState {
// Actions
addMessage: (message: Message) => void;
updateMessage: (id: string, updates: Partial<Message>) => void;
setCurrentAgent: (agent: Agent) => void;
syncAgents: (profiles: AgentProfileLike[]) => void;
setCurrentModel: (model: string) => void;
newConversation: () => void;
switchConversation: (id: string) => void;
deleteConversation: (id: string) => void;
clearMessages: () => void;
}
// Create proxy state
export const chatStore = proxy<ChatStore>({
// Initial state
messages: [],
conversations: [],
currentConversationId: null,
agents: [DEFAULT_AGENT],
currentAgent: DEFAULT_AGENT,
isStreaming: false,
currentModel: 'glm-5',
sessionKey: null,
// Actions
addMessage: (message: Message) => {
chatStore.messages.push(message);
},
updateMessage: (id: string, updates: Partial<Message>) => {
const msg = chatStore.messages.find(m => m.id === id);
if (msg) {
Object.assign(msg, updates);
}
},
setCurrentAgent: (agent: Agent) => {
chatStore.currentAgent = agent;
},
syncAgents: (profiles: AgentProfileLike[]) => {
if (profiles.length === 0) {
chatStore.agents = [DEFAULT_AGENT];
} else {
chatStore.agents = profiles.map(toChatAgent);
}
},
setCurrentModel: (model: string) => {
chatStore.currentModel = model;
},
newConversation: () => {
// Save current conversation if has messages
if (chatStore.messages.length > 0) {
const conversation: Conversation = {
id: chatStore.currentConversationId || generateConvId(),
title: deriveTitle(chatStore.messages),
messages: [...chatStore.messages],
sessionKey: chatStore.sessionKey,
agentId: chatStore.currentAgent?.id || null,
createdAt: new Date(),
updatedAt: new Date(),
};
chatStore.conversations.unshift(conversation);
}
// Reset for new conversation
chatStore.messages = [];
chatStore.sessionKey = null;
chatStore.isStreaming = false;
chatStore.currentConversationId = null;
},
switchConversation: (id: string) => {
const conv = chatStore.conversations.find(c => c.id === id);
if (conv) {
// Save current first
if (chatStore.messages.length > 0) {
const currentConv: Conversation = {
id: chatStore.currentConversationId || generateConvId(),
title: deriveTitle(chatStore.messages),
messages: [...chatStore.messages],
sessionKey: chatStore.sessionKey,
agentId: chatStore.currentAgent?.id || null,
createdAt: new Date(),
updatedAt: new Date(),
};
const existingIndex = chatStore.conversations.findIndex(
c => c.id === chatStore.currentConversationId
);
if (existingIndex >= 0) {
chatStore.conversations[existingIndex] = currentConv;
} else {
chatStore.conversations.unshift(currentConv);
}
}
// Switch to new
chatStore.messages = [...conv.messages];
chatStore.sessionKey = conv.sessionKey;
chatStore.currentConversationId = conv.id;
}
},
deleteConversation: (id: string) => {
const index = chatStore.conversations.findIndex(c => c.id === id);
if (index >= 0) {
chatStore.conversations.splice(index, 1);
// If deleting current, clear messages
if (chatStore.currentConversationId === id) {
chatStore.messages = [];
chatStore.sessionKey = null;
chatStore.currentConversationId = null;
}
}
},
clearMessages: () => {
chatStore.messages = [];
},
});
// Optional: Subscribe to changes for debugging
if (import.meta.env.DEV) {
subscribe(chatStore, (ops) => {
console.log('[ChatStore] Changes:', ops);
});
}
```
- [ ] **Step 2: 提交 Valtio Store**
```bash
cd g:/ZClaw_zclaw && git add desktop/src/domains/chat/store.ts
git commit -m "$(cat <<'EOF'
refactor(chat): create Valtio-based chat store
- Replace Zustand with Valtio for fine-grained reactivity
- Implement core actions: addMessage, updateMessage, etc.
- Add conversation management: new, switch, delete
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"
```
---
### Task 2.3: 创建 Chat Domain Hooks
**Files:**
- Create: `desktop/src/domains/chat/hooks.ts`
- [ ] **Step 1: 创建 React Hooks**
Create `desktop/src/domains/chat/hooks.ts`:
```typescript
/**
* Chat Domain Hooks
*
* React hooks for accessing chat state with Valtio.
*/
import { useSnapshot } from 'valtio';
import { chatStore } from './store';
import type { Message, Agent, Conversation } from './types';
/**
* Hook to access the full chat state.
* Only re-renders when accessed properties change.
*/
export function useChatState() {
return useSnapshot(chatStore);
}
/**
* Hook to access messages only.
* Only re-renders when messages change.
*/
export function useMessages(): readonly Message[] {
const { messages } = useSnapshot(chatStore);
return messages;
}
/**
* Hook to access streaming state.
* Only re-renders when isStreaming changes.
*/
export function useIsStreaming(): boolean {
const { isStreaming } = useSnapshot(chatStore);
return isStreaming;
}
/**
* Hook to access current agent.
*/
export function useCurrentAgent(): Agent | null {
const { currentAgent } = useSnapshot(chatStore);
return currentAgent;
}
/**
* Hook to access conversations.
*/
export function useConversations(): readonly Conversation[] {
const { conversations } = useSnapshot(chatStore);
return conversations;
}
/**
* Hook to access chat actions.
* Returns the store directly for calling actions.
*/
export function useChatActions() {
return chatStore;
}
```
- [ ] **Step 2: 创建 Domain Index**
Create `desktop/src/domains/chat/index.ts`:
```typescript
/**
* Chat Domain
*
* Public API for the chat system.
*/
// Types
export type {
Message,
MessageFile,
CodeBlock,
Conversation,
Agent,
AgentProfileLike,
ChatState,
} from './types';
// Store
export { chatStore, toChatAgent } from './store';
// Hooks
export {
useChatState,
useMessages,
useIsStreaming,
useCurrentAgent,
useConversations,
useChatActions,
} from './hooks';
```
- [ ] **Step 3: 提交 Hooks 和 Index**
```bash
cd g:/ZClaw_zclaw && git add desktop/src/domains/chat/hooks.ts desktop/src/domains/chat/index.ts
git commit -m "$(cat <<'EOF'
refactor(chat): add chat domain hooks and public API
- Add useChatState, useMessages, useIsStreaming hooks
- Export types, store, and hooks from domain index
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"
```
---
## Chunk 3: Hands Domain 迁移
### Task 3.1: 创建 Hands Domain 类型定义
**Files:**
- Create: `desktop/src/domains/hands/types.ts`
- [ ] **Step 1: 创建类型定义**
Create `desktop/src/domains/hands/types.ts`:
```typescript
/**
* Hands Domain Types
*
* Core types for the automation/hands system.
*/
export interface HandRequirement {
description: string;
met: boolean;
details?: string;
}
export interface Hand {
id: string;
name: string;
description: string;
status: HandStatus;
currentRunId?: string;
requirements_met?: boolean;
category?: string;
icon?: string;
provider?: string;
model?: string;
requirements?: HandRequirement[];
tools?: string[];
metrics?: string[];
toolCount?: number;
metricCount?: number;
}
export type HandStatus =
| 'idle'
| 'running'
| 'needs_approval'
| 'error'
| 'unavailable'
| 'setup_needed';
export interface HandRun {
runId: string;
status: string;
startedAt: string;
completedAt?: string;
result?: unknown;
error?: string;
}
export interface Trigger {
id: string;
type: string;
enabled: boolean;
}
export interface ApprovalRequest {
id: string;
handName: string;
action: string;
params: Record<string, unknown>;
createdAt: Date;
}
export interface HandsState {
hands: Hand[];
runs: Record<string, HandRun>;
triggers: Trigger[];
approvalQueue: ApprovalRequest[];
isLoading: boolean;
error: string | null;
}
// XState Events
export type HandsEvent =
| { type: 'START'; handId: string }
| { type: 'APPROVE'; requestId: string }
| { type: 'REJECT'; requestId: string }
| { type: 'COMPLETE'; runId: string; result: unknown }
| { type: 'ERROR'; runId: string; error: string }
| { type: 'RESET' };
```
- [ ] **Step 2: 提交类型定义**
```bash
cd g:/ZClaw_zclaw && git add desktop/src/domains/hands/types.ts
git commit -m "$(cat <<'EOF'
refactor(hands): extract hands domain types
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"
```
---
### Task 3.2: 创建 XState 状态机
**Files:**
- Create: `desktop/src/domains/hands/machine.ts`
- [ ] **Step 1: 创建状态机**
Create `desktop/src/domains/hands/machine.ts`:
```typescript
/**
* Hands State Machine
*
* XState machine for managing hand execution lifecycle.
*/
import { setup, assign } from 'xstate';
import type { HandStatus, HandsEvent, Hand } from './types';
export interface HandContext {
handId: string;
handName: string;
runId: string | null;
error: string | null;
result: unknown;
}
export type HandState =
| { value: 'idle'; context: HandContext }
| { value: 'running'; context: HandContext }
| { value: 'needs_approval'; context: HandContext }
| { value: 'success'; context: HandContext }
| { value: 'error'; context: HandContext };
export const handMachine = setup({
types: {
context: {} as HandContext,
events: {} as HandsEvent,
},
actions: {
setRunId: assign({
runId: (_, params: { runId: string }) => params.runId,
}),
setError: assign({
error: (_, params: { error: string }) => params.error,
}),
setResult: assign({
result: (_, params: { result: unknown }) => params.result,
}),
clearError: assign({
error: null,
}),
},
}).createMachine({
id: 'hand',
initial: 'idle',
context: {
handId: '',
handName: '',
runId: null,
error: null,
result: null,
},
states: {
idle: {
on: {
START: {
target: 'running',
actions: {
type: 'setRunId',
params: ({ event }) => ({ runId: `run_${Date.now()}` }),
},
},
},
},
running: {
on: {
APPROVE: 'needs_approval',
COMPLETE: {
target: 'success',
actions: {
type: 'setResult',
params: ({ event }) => ({ result: event.result }),
},
},
ERROR: {
target: 'error',
actions: {
type: 'setError',
params: ({ event }) => ({ error: event.error }),
},
},
},
},
needs_approval: {
on: {
APPROVE: 'running',
REJECT: 'idle',
},
},
success: {
on: {
RESET: {
target: 'idle',
actions: 'clearError',
},
},
},
error: {
on: {
RESET: {
target: 'idle',
actions: 'clearError',
},
START: 'running',
},
},
},
});
```
- [ ] **Step 2: 提交状态机**
```bash
cd g:/ZClaw_zclaw && git add desktop/src/domains/hands/machine.ts
git commit -m "$(cat <<'EOF'
refactor(hands): create XState machine for hand execution
- Define states: idle, running, needs_approval, success, error
- Define events: START, APPROVE, REJECT, COMPLETE, ERROR, RESET
- Add context for tracking runId, error, result
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"
```
---
### Task 3.3: 创建 Hands Valtio Store
**Files:**
- Create: `desktop/src/domains/hands/store.ts`
- Create: `desktop/src/domains/hands/hooks.ts`
- Create: `desktop/src/domains/hands/index.ts`
- [ ] **Step 1: 创建 Store**
Create `desktop/src/domains/hands/store.ts`:
```typescript
/**
* Hands Domain Store
*
* Valtio-based state management for hands/automation.
*/
import { proxy } from 'valtio';
import type { Hand, HandRun, Trigger, ApprovalRequest, HandsState } from './types';
interface HandsStore extends HandsState {
// Actions
setHands: (hands: Hand[]) => void;
updateHand: (id: string, updates: Partial<Hand>) => void;
addRun: (run: HandRun) => void;
updateRun: (runId: string, updates: Partial<HandRun>) => void;
setTriggers: (triggers: Trigger[]) => void;
addApproval: (request: ApprovalRequest) => void;
removeApproval: (id: string) => void;
setLoading: (loading: boolean) => void;
setError: (error: string | null) => void;
}
export const handsStore = proxy<HandsStore>({
// Initial state
hands: [],
runs: {},
triggers: [],
approvalQueue: [],
isLoading: false,
error: null,
// Actions
setHands: (hands: Hand[]) => {
handsStore.hands = hands;
},
updateHand: (id: string, updates: Partial<Hand>) => {
const hand = handsStore.hands.find(h => h.id === id);
if (hand) {
Object.assign(hand, updates);
}
},
addRun: (run: HandRun) => {
handsStore.runs[run.runId] = run;
},
updateRun: (runId: string, updates: Partial<HandRun>) => {
if (handsStore.runs[runId]) {
Object.assign(handsStore.runs[runId], updates);
}
},
setTriggers: (triggers: Trigger[]) => {
handsStore.triggers = triggers;
},
addApproval: (request: ApprovalRequest) => {
handsStore.approvalQueue.push(request);
},
removeApproval: (id: string) => {
const index = handsStore.approvalQueue.findIndex(a => a.id === id);
if (index >= 0) {
handsStore.approvalQueue.splice(index, 1);
}
},
setLoading: (loading: boolean) => {
handsStore.isLoading = loading;
},
setError: (error: string | null) => {
handsStore.error = error;
},
});
```
- [ ] **Step 2: 创建 Hooks**
Create `desktop/src/domains/hands/hooks.ts`:
```typescript
/**
* Hands Domain Hooks
*/
import { useSnapshot } from 'valtio';
import { handsStore } from './store';
export function useHandsState() {
return useSnapshot(handsStore);
}
export function useHands() {
const { hands } = useSnapshot(handsStore);
return hands;
}
export function useApprovalQueue() {
const { approvalQueue } = useSnapshot(handsStore);
return approvalQueue;
}
export function useHandsActions() {
return handsStore;
}
```
- [ ] **Step 3: 创建 Index**
Create `desktop/src/domains/hands/index.ts`:
```typescript
/**
* Hands Domain
*/
export * from './types';
export { handMachine } from './machine';
export { handsStore } from './store';
export { useHandsState, useHands, useApprovalQueue, useHandsActions } from './hooks';
```
- [ ] **Step 4: 提交 Hands Domain**
```bash
cd g:/ZClaw_zclaw && git add desktop/src/domains/hands/
git commit -m "$(cat <<'EOF'
refactor(hands): complete hands domain migration
- Add Valtio store for hands state
- Add React hooks for hands access
- Export all from domain index
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"
```
---
## Chunk 4: Shared Module 提取
### Task 4.1: 创建共享错误处理
**Files:**
- Create: `desktop/src/shared/error-handling.ts`
- Create: `desktop/src/shared/types.ts`
- Create: `desktop/src/shared/index.ts`
- [ ] **Step 1: 创建错误处理工具**
Create `desktop/src/shared/error-handling.ts`:
```typescript
/**
* Shared Error Handling
*
* Unified error handling utilities.
*/
export class AppError extends Error {
constructor(
message: string,
public code: string,
public cause?: Error
) {
super(message);
this.name = 'AppError';
}
}
export function isError(error: unknown): error is Error {
return error instanceof Error;
}
export function getErrorMessage(error: unknown): string {
if (isError(error)) {
return error.message;
}
return String(error);
}
export function wrapError(error: unknown, code: string): AppError {
if (error instanceof AppError) {
return error;
}
return new AppError(getErrorMessage(error), code, isError(error) ? error : undefined);
}
```
- [ ] **Step 2: 创建共享类型**
Create `desktop/src/shared/types.ts`:
```typescript
/**
* Shared Types
*/
export type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E };
export type AsyncResult<T, E = Error> = Promise<Result<T, E>>;
export interface PaginatedResponse<T> {
items: T[];
total: number;
page: number;
pageSize: number;
}
```
- [ ] **Step 3: 创建 Index**
Create `desktop/src/shared/index.ts`:
```typescript
/**
* Shared Module
*/
export * from './error-handling';
export * from './types';
```
- [ ] **Step 4: 提交共享模块**
```bash
cd g:/ZClaw_zclaw && git add desktop/src/shared/
git commit -m "$(cat <<'EOF'
refactor(shared): create shared module
- Add AppError class for unified error handling
- Add Result type for functional error handling
- Add PaginatedResponse type
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"
```
---
## Chunk 5: 集成和验证
### Task 5.1: 创建向后兼容层
**Files:**
- Modify: `desktop/src/store/chatStore.ts`
- [ ] **Step 1: 更新旧 Store 重导出**
Update `desktop/src/store/chatStore.ts` to re-export from domain:
```typescript
/**
* Chat Store - Backward Compatibility Layer
*
* This file re-exports from the new domains/chat module.
* Import from '@/domains/chat' for new code.
*/
export * from '../domains/chat';
```
- [ ] **Step 2: 提交兼容层**
```bash
cd g:/ZClaw_zclaw && git add desktop/src/store/chatStore.ts
git commit -m "$(cat <<'EOF'
refactor(chat): add backward compatibility layer
- Re-export from domains/chat for backward compatibility
- Maintains existing import paths
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"
```
---
### Task 5.2: 运行测试验证
- [ ] **Step 1: 运行 Chat Store 测试**
Run:
```bash
cd g:/ZClaw_zclaw/desktop && pnpm test tests/store/chatStore.test.ts
```
Expected: Tests pass with new Valtio store
- [ ] **Step 2: 运行所有测试**
Run:
```bash
cd g:/ZClaw_zclaw/desktop && pnpm test
```
Expected: No new test failures
---
### Task 5.3: 更新文档
- [ ] **Step 1: 创建 Phase 2 变更日志**
Create `docs/changelogs/2026-03-21-phase2-domain-reorganization.md`
---
## Verification Checklist
### Domain Structure
- [ ] domains/chat/ created with types, store, hooks
- [ ] domains/hands/ created with types, machine, store, hooks
- [ ] shared/ created with error-handling, types
### State Management
- [ ] Valtio installed and configured
- [ ] Chat store migrated to Valtio
- [ ] Hands store migrated to Valtio
- [ ] XState machine created for hands
### Compatibility
- [ ] Backward compatibility layer in place
- [ ] Existing imports still work
- [ ] Tests passing
---
## Next Steps (Phase 3)
- Valtio 性能优化
- XState 状态机完整集成
- Intelligence 缓存增强
- 组件迁移到新 Hooks