重构所有代码和文档中的项目名称,将OpenFang统一更新为ZCLAW。包括: - 配置文件中的项目名称 - 代码注释和文档引用 - 环境变量和路径 - 类型定义和接口名称 - 测试用例和模拟数据 同时优化部分代码结构,移除未使用的模块,并更新相关依赖项。
26 KiB
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:
cd g:/ZClaw_zclaw/desktop && pnpm add valtio
Expected: valtio 安装成功
- Step 2: 安装 XState
Run:
cd g:/ZClaw_zclaw/desktop && pnpm add xstate @xstate/react
Expected: xstate 和 @xstate/react 安装成功
- Step 3: 验证安装
Run:
cd g:/ZClaw_zclaw/desktop && pnpm list valtio xstate @xstate/react
Expected: 显示已安装版本
- Step 4: 提交依赖更新
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:
cd g:/ZClaw_zclaw/desktop/src && mkdir -p domains/chat domains/hands domains/intelligence domains/skills shared
- Step 2: 提交目录结构
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:
/**
* 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: 提交类型定义
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:
/**
* 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
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:
/**
* 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:
/**
* 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
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:
/**
* 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: 提交类型定义
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:
/**
* 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: 提交状态机
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:
/**
* 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:
/**
* 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:
/**
* Hands Domain
*/
export * from './types';
export { handMachine } from './machine';
export { handsStore } from './store';
export { useHandsState, useHands, useApprovalQueue, useHandsActions } from './hooks';
- Step 4: 提交 Hands Domain
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:
/**
* 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:
/**
* 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:
/**
* Shared Module
*/
export * from './error-handling';
export * from './types';
- Step 4: 提交共享模块
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:
/**
* 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: 提交兼容层
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:
cd g:/ZClaw_zclaw/desktop && pnpm test tests/store/chatStore.test.ts
Expected: Tests pass with new Valtio store
- Step 2: 运行所有测试
Run:
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