Browse Source
Phase 16: Store Modularization - 3 plans created - 9 total tasks defined - Ready for execution Plans: - 16-01: Extract localStorage helpers and node defaults - 16-02: Extract execution logic into dedicated modules - 16-03: Create Zustand slices and compose storehandoff-20260429-1057
3 changed files with 519 additions and 0 deletions
@ -0,0 +1,139 @@ |
|||||
|
--- |
||||
|
phase: 16-store-modularization |
||||
|
plan: 01 |
||||
|
type: execute |
||||
|
--- |
||||
|
|
||||
|
<objective> |
||||
|
Extract localStorage helpers and configuration utilities from workflowStore.ts into dedicated modules. |
||||
|
|
||||
|
Purpose: Begin store modularization by extracting pure utility functions that don't depend on Zustand state, making them easier to test and reducing the main store file size. |
||||
|
Output: New utility modules for localStorage operations and default node data creation, with workflowStore.ts importing from these modules. |
||||
|
</objective> |
||||
|
|
||||
|
<execution_context> |
||||
|
~/.claude/get-shit-done/workflows/execute-phase.md |
||||
|
~/.claude/get-shit-done/templates/summary.md |
||||
|
</execution_context> |
||||
|
|
||||
|
<context> |
||||
|
@.planning/PROJECT.md |
||||
|
@.planning/ROADMAP.md |
||||
|
@.planning/STATE.md |
||||
|
@.planning/phases/15-test-infrastructure/15-01-SUMMARY.md |
||||
|
@src/store/workflowStore.ts |
||||
|
|
||||
|
**From Phase 15 Summary:** |
||||
|
- Vitest and React Testing Library configured |
||||
|
- Zustand store mocking patterns established |
||||
|
- Test infrastructure ready for validating refactored modules |
||||
|
|
||||
|
**Current Store Analysis (2786 lines):** |
||||
|
The workflowStore.ts contains several pure utility functions at the top that don't depend on Zustand state: |
||||
|
- localStorage helpers for workflow configs (~40 lines) |
||||
|
- localStorage helpers for cost tracking (~40 lines) |
||||
|
- localStorage helpers for GenerateImage defaults (~40 lines) |
||||
|
- localStorage helpers for provider settings (~50 lines) |
||||
|
- createDefaultNodeData function (~90 lines) |
||||
|
- GROUP_COLORS and GROUP_COLOR_ORDER constants (~15 lines) |
||||
|
- generateWorkflowId utility (~3 lines) |
||||
|
</context> |
||||
|
|
||||
|
<tasks> |
||||
|
|
||||
|
<task type="auto"> |
||||
|
<name>Task 1: Create store utilities module</name> |
||||
|
<files>src/store/utils/localStorage.ts</files> |
||||
|
<action> |
||||
|
Extract all localStorage helpers into a new module: |
||||
|
1. Create src/store/utils/localStorage.ts |
||||
|
2. Move these functions/constants: |
||||
|
- STORAGE_KEY constant |
||||
|
- COST_DATA_STORAGE_KEY constant |
||||
|
- GENERATE_IMAGE_DEFAULTS_KEY constant |
||||
|
- PROVIDER_SETTINGS_KEY constant |
||||
|
- loadSaveConfigs() |
||||
|
- saveSaveConfig() |
||||
|
- loadWorkflowCostData() |
||||
|
- saveWorkflowCostData() |
||||
|
- loadGenerateImageDefaults() (rename from loadNanoBananaDefaults) |
||||
|
- saveGenerateImageDefaults() (existing export, keep as-is) |
||||
|
- getProviderSettings() |
||||
|
- saveProviderSettings() |
||||
|
- defaultProviderSettings constant |
||||
|
- GenerateImageDefaults interface |
||||
|
3. Export all functions and types |
||||
|
4. Keep backward-compatible aliases (NanoBananaDefaults, saveNanoBananaDefaults) in workflowStore.ts but have them re-export from the new module |
||||
|
|
||||
|
Note: These functions use localStorage directly and don't depend on Zustand state, making them safe to extract. |
||||
|
</action> |
||||
|
<verify>npm run build succeeds with no TypeScript errors</verify> |
||||
|
<done>All localStorage helpers extracted, workflowStore.ts imports from new module, build passes</done> |
||||
|
</task> |
||||
|
|
||||
|
<task type="auto"> |
||||
|
<name>Task 2: Create node defaults module</name> |
||||
|
<files>src/store/utils/nodeDefaults.ts</files> |
||||
|
<action> |
||||
|
Extract node creation utilities: |
||||
|
1. Create src/store/utils/nodeDefaults.ts |
||||
|
2. Move these items: |
||||
|
- createDefaultNodeData() function (~90 lines) |
||||
|
- defaultDimensions record (duplicated in addNode and createGroup - consolidate) |
||||
|
- GROUP_COLORS record |
||||
|
- GROUP_COLOR_ORDER array |
||||
|
- GroupColor type import from @/types |
||||
|
3. The createDefaultNodeData function calls loadGenerateImageDefaults() - update import to use new localStorage module |
||||
|
4. Export createDefaultNodeData, defaultNodeDimensions, GROUP_COLORS, GROUP_COLOR_ORDER |
||||
|
5. Update workflowStore.ts to import these from the new module |
||||
|
</action> |
||||
|
<verify>npm run build succeeds, npm test passes all 112+ tests</verify> |
||||
|
<done>Node defaults extracted, GROUP_COLORS exported from new location, all imports updated, tests pass</done> |
||||
|
</task> |
||||
|
|
||||
|
<task type="auto"> |
||||
|
<name>Task 3: Add unit tests for extracted modules</name> |
||||
|
<files>src/store/utils/__tests__/localStorage.test.ts, src/store/utils/__tests__/nodeDefaults.test.ts</files> |
||||
|
<action> |
||||
|
Create tests for the extracted modules: |
||||
|
1. Create src/store/utils/__tests__/localStorage.test.ts: |
||||
|
- Test loadSaveConfigs returns empty object when localStorage empty |
||||
|
- Test saveSaveConfig stores and retrieves config |
||||
|
- Test loadWorkflowCostData handles missing data |
||||
|
- Test loadGenerateImageDefaults returns defaults when localStorage empty |
||||
|
- Test getProviderSettings merges with defaults for new providers |
||||
|
- Mock localStorage using vi.stubGlobal or in-memory implementation |
||||
|
|
||||
|
2. Create src/store/utils/__tests__/nodeDefaults.test.ts: |
||||
|
- Test createDefaultNodeData for each node type returns correct structure |
||||
|
- Test defaultNodeDimensions has all expected node types |
||||
|
- Test GROUP_COLORS has expected color keys |
||||
|
- Mock localStorage for createDefaultNodeData's loadGenerateImageDefaults call |
||||
|
</action> |
||||
|
<verify>npm test passes with new tests included, coverage for new modules</verify> |
||||
|
<done>Unit tests added for both modules, all tests pass including new ones</done> |
||||
|
</task> |
||||
|
|
||||
|
</tasks> |
||||
|
|
||||
|
<verification> |
||||
|
Before declaring plan complete: |
||||
|
- [ ] `npm run build` succeeds without errors |
||||
|
- [ ] `npm test` passes all tests (existing + new) |
||||
|
- [ ] workflowStore.ts is reduced by ~280 lines |
||||
|
- [ ] New modules are properly typed with exports |
||||
|
- [ ] Backward compatibility maintained (saveNanoBananaDefaults still works) |
||||
|
</verification> |
||||
|
|
||||
|
<success_criteria> |
||||
|
|
||||
|
- All tasks completed |
||||
|
- All verification checks pass |
||||
|
- No TypeScript errors |
||||
|
- workflowStore.ts imports from new utility modules |
||||
|
- New modules have test coverage |
||||
|
</success_criteria> |
||||
|
|
||||
|
<output> |
||||
|
After completion, create `.planning/phases/16-store-modularization/16-01-SUMMARY.md` |
||||
|
</output> |
||||
@ -0,0 +1,168 @@ |
|||||
|
--- |
||||
|
phase: 16-store-modularization |
||||
|
plan: 02 |
||||
|
type: execute |
||||
|
--- |
||||
|
|
||||
|
<objective> |
||||
|
Extract workflow execution logic from workflowStore.ts into a dedicated execution module. |
||||
|
|
||||
|
Purpose: The execution logic (~800 lines) is the largest section and most complex. Extracting it enables focused testing and cleaner separation of concerns between state management and execution orchestration. |
||||
|
Output: New execution module with executeWorkflow, regenerateNode, and supporting execution utilities. |
||||
|
</objective> |
||||
|
|
||||
|
<execution_context> |
||||
|
~/.claude/get-shit-done/workflows/execute-phase.md |
||||
|
~/.claude/get-shit-done/templates/summary.md |
||||
|
</execution_context> |
||||
|
|
||||
|
<context> |
||||
|
@.planning/PROJECT.md |
||||
|
@.planning/ROADMAP.md |
||||
|
@.planning/STATE.md |
||||
|
@.planning/phases/16-store-modularization/16-01-PLAN.md |
||||
|
@src/store/workflowStore.ts |
||||
|
|
||||
|
**Dependencies from 16-01:** |
||||
|
- localStorage utilities extracted |
||||
|
- nodeDefaults module exists |
||||
|
|
||||
|
**Execution Logic Analysis (~800 lines):** |
||||
|
The executeWorkflow and regenerateNode functions are tightly coupled to store state but can be extracted as action creators that receive state getters/setters. Key components: |
||||
|
- Topological sort algorithm (~30 lines) |
||||
|
- Node execution switch statement (~600 lines for all node types) |
||||
|
- API call patterns (repeated for each provider) |
||||
|
- Logger calls throughout |
||||
|
- State updates via updateNodeData |
||||
|
</context> |
||||
|
|
||||
|
<tasks> |
||||
|
|
||||
|
<task type="auto"> |
||||
|
<name>Task 1: Extract execution utilities</name> |
||||
|
<files>src/store/execution/utils.ts</files> |
||||
|
<action> |
||||
|
Create src/store/execution/utils.ts with reusable execution utilities: |
||||
|
|
||||
|
1. Extract topologicalSort function: |
||||
|
- Takes nodes and edges as input |
||||
|
- Returns sorted WorkflowNode array |
||||
|
- Throws on cycle detection |
||||
|
|
||||
|
2. Extract buildProviderHeaders function: |
||||
|
- Takes provider type and providerSettings |
||||
|
- Returns headers object with API key headers |
||||
|
- Consolidates the repeated header building logic from executeWorkflow/regenerateNode |
||||
|
|
||||
|
3. Extract getSourceOutput helper: |
||||
|
- Takes a WorkflowNode |
||||
|
- Returns { type: "image" | "text" | "video", value: string | null } |
||||
|
- Currently duplicated in getConnectedInputs |
||||
|
|
||||
|
4. Export types: |
||||
|
- ExecutionResult = { success: boolean; error?: string; data?: unknown } |
||||
|
- NodeExecutionContext = { nodeId: string; get: () => StoreState; set: (partial: Partial<StoreState>) => void } |
||||
|
|
||||
|
These are pure functions that don't directly depend on Zustand, making them testable. |
||||
|
</action> |
||||
|
<verify>npm run build succeeds, new module compiles without errors</verify> |
||||
|
<done>Execution utilities extracted, types defined, build passes</done> |
||||
|
</task> |
||||
|
|
||||
|
<task type="auto"> |
||||
|
<name>Task 2: Extract node executors</name> |
||||
|
<files>src/store/execution/nodeExecutors.ts</files> |
||||
|
<action> |
||||
|
Create src/store/execution/nodeExecutors.ts with individual node type executors: |
||||
|
|
||||
|
1. Create executor type: |
||||
|
```typescript |
||||
|
type NodeExecutor = ( |
||||
|
node: WorkflowNode, |
||||
|
context: { |
||||
|
getConnectedInputs: (nodeId: string) => ConnectedInputs; |
||||
|
updateNodeData: (nodeId: string, data: Partial<WorkflowNodeData>) => void; |
||||
|
get: () => WorkflowStoreState; |
||||
|
set: (partial: Partial<WorkflowStoreState>) => void; |
||||
|
providerSettings: ProviderSettings; |
||||
|
} |
||||
|
) => Promise<{ continue: boolean; error?: string }>; |
||||
|
``` |
||||
|
|
||||
|
2. Extract executors for each node type: |
||||
|
- executeImageInput (no-op, returns continue: true) |
||||
|
- executeAnnotation |
||||
|
- executePrompt (no-op) |
||||
|
- executeNanoBanana (image generation) |
||||
|
- executeGenerateVideo (video generation) |
||||
|
- executeLlmGenerate (text generation) |
||||
|
- executeSplitGrid |
||||
|
- executeOutput |
||||
|
|
||||
|
3. Create nodeExecutorMap: |
||||
|
```typescript |
||||
|
const nodeExecutorMap: Record<NodeType, NodeExecutor> = { ... } |
||||
|
``` |
||||
|
|
||||
|
4. Export executeNode function that dispatches to the correct executor |
||||
|
|
||||
|
This keeps the individual node logic but allows testing each executor in isolation. |
||||
|
</action> |
||||
|
<verify>npm run build succeeds, no TypeScript errors</verify> |
||||
|
<done>Node executors extracted as individual functions with shared interface</done> |
||||
|
</task> |
||||
|
|
||||
|
<task type="auto"> |
||||
|
<name>Task 3: Refactor executeWorkflow to use extracted modules</name> |
||||
|
<files>src/store/workflowStore.ts</files> |
||||
|
<action> |
||||
|
Update executeWorkflow in workflowStore.ts to use the extracted modules: |
||||
|
|
||||
|
1. Import from execution/utils.ts: |
||||
|
- topologicalSort |
||||
|
- buildProviderHeaders |
||||
|
|
||||
|
2. Import from execution/nodeExecutors.ts: |
||||
|
- executeNode |
||||
|
|
||||
|
3. Refactor executeWorkflow to use the imported utilities: |
||||
|
- Replace inline topological sort with topologicalSort() |
||||
|
- Replace switch statement with executeNode() calls |
||||
|
- Keep the overall orchestration logic (pause handling, locked groups, logging) in the store |
||||
|
|
||||
|
4. Refactor regenerateNode similarly: |
||||
|
- Use buildProviderHeaders |
||||
|
- Could call individual executors but for now keep inline (regenerate has slightly different flow) |
||||
|
|
||||
|
5. Ensure getConnectedInputs stays in the store (it needs edge state) |
||||
|
|
||||
|
The goal is to reduce executeWorkflow from ~800 lines to ~200 lines of orchestration logic. |
||||
|
</action> |
||||
|
<verify>npm run build succeeds, npm test passes, manual test of workflow execution works</verify> |
||||
|
<done>executeWorkflow refactored to ~200 lines, uses extracted modules, all tests pass</done> |
||||
|
</task> |
||||
|
|
||||
|
</tasks> |
||||
|
|
||||
|
<verification> |
||||
|
Before declaring plan complete: |
||||
|
- [ ] `npm run build` succeeds without errors |
||||
|
- [ ] `npm test` passes all tests |
||||
|
- [ ] executeWorkflow function reduced from ~800 to ~200 lines |
||||
|
- [ ] Workflow execution still works (test with a simple prompt -> generate -> output flow) |
||||
|
- [ ] regenerateNode still works |
||||
|
- [ ] Error handling preserved |
||||
|
</verification> |
||||
|
|
||||
|
<success_criteria> |
||||
|
|
||||
|
- All tasks completed |
||||
|
- All verification checks pass |
||||
|
- executeWorkflow is significantly shorter and more readable |
||||
|
- Node execution logic is isolated and testable |
||||
|
- No regression in workflow execution behavior |
||||
|
</success_criteria> |
||||
|
|
||||
|
<output> |
||||
|
After completion, create `.planning/phases/16-store-modularization/16-02-SUMMARY.md` |
||||
|
</output> |
||||
@ -0,0 +1,212 @@ |
|||||
|
--- |
||||
|
phase: 16-store-modularization |
||||
|
plan: 03 |
||||
|
type: execute |
||||
|
--- |
||||
|
|
||||
|
<objective> |
||||
|
Extract remaining store slices into focused modules using Zustand slice pattern. |
||||
|
|
||||
|
Purpose: Break up the remaining monolithic store into logical slices (groups, clipboard, persistence, providers) that can be developed and tested independently while maintaining a single unified store. |
||||
|
Output: Zustand slices for groups, clipboard, persistence, and provider settings, composed into the main store. |
||||
|
</objective> |
||||
|
|
||||
|
<execution_context> |
||||
|
~/.claude/get-shit-done/workflows/execute-phase.md |
||||
|
~/.claude/get-shit-done/templates/summary.md |
||||
|
</execution_context> |
||||
|
|
||||
|
<context> |
||||
|
@.planning/PROJECT.md |
||||
|
@.planning/ROADMAP.md |
||||
|
@.planning/STATE.md |
||||
|
@.planning/phases/16-store-modularization/16-01-PLAN.md |
||||
|
@.planning/phases/16-store-modularization/16-02-PLAN.md |
||||
|
@src/store/workflowStore.ts |
||||
|
|
||||
|
**Dependencies from 16-01 and 16-02:** |
||||
|
- localStorage utilities extracted to src/store/utils/localStorage.ts |
||||
|
- Node defaults extracted to src/store/utils/nodeDefaults.ts |
||||
|
- Execution logic extracted to src/store/execution/ |
||||
|
|
||||
|
**Remaining Store Sections:** |
||||
|
After 16-01 and 16-02, the store still contains: |
||||
|
- Group operations (~200 lines): createGroup, deleteGroup, addNodesToGroup, etc. |
||||
|
- Clipboard operations (~100 lines): copySelectedNodes, pasteNodes, clearClipboard |
||||
|
- Persistence operations (~300 lines): saveWorkflow, loadWorkflow, auto-save |
||||
|
- Provider settings (~100 lines): updateProviderSettings, updateProviderApiKey |
||||
|
- Core node/edge operations (~200 lines): These stay in main store |
||||
|
- UI state (~50 lines): modal count, quickstart - stays in main store |
||||
|
</context> |
||||
|
|
||||
|
<tasks> |
||||
|
|
||||
|
<task type="auto"> |
||||
|
<name>Task 1: Create group operations slice</name> |
||||
|
<files>src/store/slices/groupSlice.ts</files> |
||||
|
<action> |
||||
|
Create src/store/slices/groupSlice.ts using Zustand slice pattern: |
||||
|
|
||||
|
1. Define GroupSlice interface: |
||||
|
```typescript |
||||
|
interface GroupSlice { |
||||
|
groups: Record<string, NodeGroup>; |
||||
|
createGroup: (nodeIds: string[]) => string; |
||||
|
deleteGroup: (groupId: string) => void; |
||||
|
addNodesToGroup: (nodeIds: string[], groupId: string) => void; |
||||
|
removeNodesFromGroup: (nodeIds: string[]) => void; |
||||
|
updateGroup: (groupId: string, updates: Partial<NodeGroup>) => void; |
||||
|
toggleGroupLock: (groupId: string) => void; |
||||
|
moveGroupNodes: (groupId: string, delta: { x: number; y: number }) => void; |
||||
|
setNodeGroupId: (nodeId: string, groupId: string | undefined) => void; |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
2. Create slice creator function: |
||||
|
```typescript |
||||
|
export const createGroupSlice: StateCreator< |
||||
|
WorkflowStore, |
||||
|
[], |
||||
|
[], |
||||
|
GroupSlice |
||||
|
> = (set, get) => ({ |
||||
|
groups: {}, |
||||
|
createGroup: (nodeIds) => { ... }, |
||||
|
// ... other methods |
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
3. Import GROUP_COLORS and GROUP_COLOR_ORDER from utils/nodeDefaults |
||||
|
4. Import defaultNodeDimensions for bounding box calculation |
||||
|
5. Manage groupIdCounter within the slice |
||||
|
|
||||
|
The slice needs access to nodes for createGroup bounding box calculation, which it gets via get(). |
||||
|
</action> |
||||
|
<verify>npm run build succeeds, slice compiles without errors</verify> |
||||
|
<done>Group slice created with all group operations</done> |
||||
|
</task> |
||||
|
|
||||
|
<task type="auto"> |
||||
|
<name>Task 2: Create persistence slice</name> |
||||
|
<files>src/store/slices/persistenceSlice.ts</files> |
||||
|
<action> |
||||
|
Create src/store/slices/persistenceSlice.ts: |
||||
|
|
||||
|
1. Define PersistenceSlice interface: |
||||
|
```typescript |
||||
|
interface PersistenceSlice { |
||||
|
// State |
||||
|
workflowId: string | null; |
||||
|
workflowName: string | null; |
||||
|
saveDirectoryPath: string | null; |
||||
|
generationsPath: string | null; |
||||
|
lastSavedAt: number | null; |
||||
|
hasUnsavedChanges: boolean; |
||||
|
autoSaveEnabled: boolean; |
||||
|
isSaving: boolean; |
||||
|
useExternalImageStorage: boolean; |
||||
|
|
||||
|
// Actions |
||||
|
setWorkflowMetadata: (id: string, name: string, path: string, generationsPath?: string | null) => void; |
||||
|
setWorkflowName: (name: string) => void; |
||||
|
setGenerationsPath: (path: string | null) => void; |
||||
|
setAutoSaveEnabled: (enabled: boolean) => void; |
||||
|
setUseExternalImageStorage: (enabled: boolean) => void; |
||||
|
markAsUnsaved: () => void; |
||||
|
saveToFile: () => Promise<boolean>; |
||||
|
initializeAutoSave: () => void; |
||||
|
cleanupAutoSave: () => void; |
||||
|
saveWorkflow: (name?: string) => void; |
||||
|
loadWorkflow: (workflow: WorkflowFile, workflowPath?: string) => Promise<void>; |
||||
|
clearWorkflow: () => void; |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
2. Move autoSaveIntervalId to slice file scope |
||||
|
3. Import localStorage helpers from utils/localStorage |
||||
|
4. Import externalizeWorkflowImages, hydrateWorkflowImages from @/utils/imageStorage |
||||
|
5. Keep nodeIdCounter and groupIdCounter management in main store (loadWorkflow needs to update them) |
||||
|
|
||||
|
Note: loadWorkflow also needs to reset execution state (isRunning, currentNodeId) which stays in main store. The slice's loadWorkflow will need to call through to main store's set(). |
||||
|
</action> |
||||
|
<verify>npm run build succeeds, slice compiles without errors</verify> |
||||
|
<done>Persistence slice created with save/load/auto-save logic</done> |
||||
|
</task> |
||||
|
|
||||
|
<task type="auto"> |
||||
|
<name>Task 3: Compose slices into main store</name> |
||||
|
<files>src/store/workflowStore.ts</files> |
||||
|
<action> |
||||
|
Refactor workflowStore.ts to compose the slices: |
||||
|
|
||||
|
1. Import slices: |
||||
|
```typescript |
||||
|
import { createGroupSlice, GroupSlice } from './slices/groupSlice'; |
||||
|
import { createPersistenceSlice, PersistenceSlice } from './slices/persistenceSlice'; |
||||
|
``` |
||||
|
|
||||
|
2. Define combined store type: |
||||
|
```typescript |
||||
|
type WorkflowStore = CoreSlice & GroupSlice & PersistenceSlice & ExecutionSlice; |
||||
|
``` |
||||
|
|
||||
|
3. Update store creation using spread: |
||||
|
```typescript |
||||
|
export const useWorkflowStore = create<WorkflowStore>()((...args) => ({ |
||||
|
// Core state and actions inline |
||||
|
nodes: [], |
||||
|
edges: [], |
||||
|
// ... |
||||
|
|
||||
|
// Spread slices |
||||
|
...createGroupSlice(...args), |
||||
|
...createPersistenceSlice(...args), |
||||
|
})); |
||||
|
``` |
||||
|
|
||||
|
4. Keep in main store (CoreSlice): |
||||
|
- nodes, edges, edgeStyle state |
||||
|
- Node CRUD: addNode, updateNodeData, removeNode, onNodesChange |
||||
|
- Edge operations: onEdgesChange, onConnect, addEdgeWithType, removeEdge, toggleEdgePause |
||||
|
- getNodeById, getConnectedInputs, validateWorkflow |
||||
|
- UI state: openModalCount, isModalOpen, showQuickstart |
||||
|
- Execution state: isRunning, currentNodeId, pausedAtNodeId |
||||
|
- executeWorkflow, regenerateNode, stopWorkflow (uses extracted execution modules) |
||||
|
- globalImageHistory, incurredCost state and actions |
||||
|
- Provider settings state and actions |
||||
|
- Model search dialog state |
||||
|
|
||||
|
5. Export backward-compatible aliases (GROUP_COLORS, saveNanoBananaDefaults, etc.) |
||||
|
|
||||
|
Target: Main store file reduced from ~2800 to ~1500 lines. |
||||
|
</action> |
||||
|
<verify>npm run build succeeds, npm test passes all tests, manual test of group creation and save/load works</verify> |
||||
|
<done>Store composed from slices, main file significantly reduced, all functionality preserved</done> |
||||
|
</task> |
||||
|
|
||||
|
</tasks> |
||||
|
|
||||
|
<verification> |
||||
|
Before declaring plan complete: |
||||
|
- [ ] `npm run build` succeeds without errors |
||||
|
- [ ] `npm test` passes all tests |
||||
|
- [ ] workflowStore.ts reduced from ~2800 to ~1500 lines |
||||
|
- [ ] Group operations work (create, lock, delete) |
||||
|
- [ ] Save/load workflow works |
||||
|
- [ ] Auto-save works |
||||
|
- [ ] All exports maintained for backward compatibility |
||||
|
</verification> |
||||
|
|
||||
|
<success_criteria> |
||||
|
|
||||
|
- All tasks completed |
||||
|
- All verification checks pass |
||||
|
- Store properly composed from slices |
||||
|
- Each slice is focused and cohesive |
||||
|
- No regression in any store functionality |
||||
|
- Phase 16 complete: Store Modularization achieved |
||||
|
</success_criteria> |
||||
|
|
||||
|
<output> |
||||
|
After completion, create `.planning/phases/16-store-modularization/16-03-SUMMARY.md` |
||||
|
</output> |
||||
Loading…
Reference in new issue