Fixes architectural issue where snapshot logic was duplicated between
hook and store layers.
Problem Identified:
- useDocumentHistory (hook) created snapshots with duplicate logic
- timelineStore (store) created snapshots with duplicate logic
- timelineStore couldn't call useDocumentHistory (hooks can't be used in stores)
- Snapshot creation logic scattered across codebase
Root Cause:
Timeline operations happen in the store layer but history was managed
via a hook. This architectural mismatch forced duplication.
Solution:
- Add pushToHistory() method to historyStore
- Single source of truth for snapshot creation
- Both hook and store layers call historyStore.pushToHistory()
- Eliminates all snapshot creation duplication
Changes:
- Add historyStore.pushToHistory() - high-level API with snapshot creation
- Keep historyStore.pushAction() - low-level API (for future use)
- Update useDocumentHistory to call historyStore.pushToHistory()
- Update timelineStore pushDocumentHistory() to call historyStore.pushToHistory()
- Remove createDocumentSnapshot import from useDocumentHistory
- Remove createDocumentSnapshot import from timelineStore
Architecture:
Before:
Hook (useDocumentHistory) → creates snapshot → historyStore.pushAction()
Store (timelineStore) → creates snapshot → historyStore.pushAction()
[Duplication at 2 call sites]
After:
Hook (useDocumentHistory) → historyStore.pushToHistory() → creates snapshot
Store (timelineStore) → historyStore.pushToHistory() → creates snapshot
[Single implementation in historyStore]
Benefits:
- ✅ Zero snapshot creation duplication
- ✅ Proper architectural separation (store handles snapshots, not hook/store)
- ✅ Single source of truth (historyStore.pushToHistory)
- ✅ Timeline and graph operations use identical snapshot logic
- ✅ Easy to modify snapshot behavior in future (one place)
Impact:
- No breaking changes
- No behavior changes
- Better code organization
- Easier maintenance
Related: Phase 2.1 architectural improvement
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Eliminates duplicate snapshot logic between useDocumentHistory and timelineStore.
Problem:
- useDocumentHistory created snapshots reading types from document (correct)
- timelineStore created snapshots reading types from graphStore (incorrect)
- ~30 lines of duplicated snapshot creation logic
- Risk of inconsistent behavior between graph and timeline operations
Solution:
- Created createDocumentSnapshot() in documentUtils.ts
- Single source of truth for snapshot creation
- Always reads types/labels from document (correct source)
- Syncs timeline current state before snapshot (ensures latest data)
Changes:
- Add createDocumentSnapshot() to src/stores/workspace/documentUtils.ts
- Update useDocumentHistory.ts to use centralized helper
- Update timelineStore.ts pushDocumentHistory() to use centralized helper
- Remove duplicate snapshot creation code (~30 lines)
Benefits:
- ✅ Consistent snapshot behavior everywhere
- ✅ Types always read from document (source of truth)
- ✅ Easier to maintain (single implementation)
- ✅ Fixes potential bug where timelineStore had stale types
- ✅ Better code organization
Impact:
- No breaking changes
- Undo/redo behavior unchanged for users
- Timeline operations now have correct type information
- Safer - impossible for snapshot logic to diverge
Testing:
- TypeScript compilation passes
- No runtime behavior changes expected
- Snapshot structure unchanged
Related: Phase 2.1 of STATE_MANAGEMENT_REFACTORING_PLAN.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements comprehensive group minimize/maximize functionality and migrates
to React Flow v12 (@xyflow/react) with improved edge routing.
## Group Minimize/Maximize Features:
- Minimized groups render as compact 220×80px solid rectangles
- Original dimensions preserved in metadata and restored on maximize
- Child actors hidden (not filtered) to prevent React Flow state issues
- Solid color backgrounds (transparency removed for minimized state)
- Internal edges filtered out when group is minimized
- Dimension sync before minimize ensures correct size on maximize
## Floating Edges:
- Dynamic edge routing for connections to/from minimized groups
- Edges connect to closest point on minimized group border
- Regular actors maintain fixed handle connections
- Smooth transitions when toggling group state
## React Flow v12 Migration:
- Updated package from 'reactflow' to '@xyflow/react'
- Changed imports to named imports (ReactFlow is now named)
- Updated CSS imports to '@xyflow/react/dist/style.css'
- Fixed NodeProps/EdgeProps to use full Node/Edge types
- Added Record<string, unknown> to data interfaces for v12 compatibility
- Replaced useStore(state => state.connectionNodeId) with useConnection()
- Updated nodeInternals to nodeLookup (renamed in v12)
- Fixed event handler types for v12 API changes
## Edge Label Improvements:
- Added explicit z-index (1000) to edge labels via EdgeLabelRenderer
- Labels now properly render above edge paths
## Type Safety & Code Quality:
- Removed all 'any' type assertions in useDocumentHistory
- Fixed missing React Hook dependencies
- Fixed unused variable warnings
- All ESLint checks passing (0 errors, 0 warnings)
- TypeScript compilation clean
## Bug Fixes:
- Group drag positions now properly persisted to store
- Minimized group styling (removed dotted border, padding)
- Node visibility using 'hidden' property instead of array filtering
- Dimension sync prevents actors from disappearing on maximize
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements visual grouping of actors with context menu operations,
resizable containers, and complete history tracking integration.
Features:
- Create groups from multiple selected actors via context menu
- Groups visualized as resizable containers with child nodes
- Ungroup actors (non-destructive) or delete group with actors
- Right-click context menu with group-specific operations
- Dedicated GroupEditorPanel for group properties
- Smart minimum size constraint based on child node positions
- Full undo/redo support for group operations and resizes
Technical Implementation:
- GroupNode component with React Flow NodeResizer integration
- Atomic createGroupWithActors operation for consistent history
- Parent-child relationship using React Flow v11 parentId pattern
- Groups stored separately from actors in graphStore
- Fixed history tracking to sync graphStore before snapshots
- Resize tracking to prevent state sync loops during interaction
- Dynamic minimum dimensions to keep children inside bounds
- Sanitization of orphaned parentId references on state load
History Fixes:
- pushToHistory now syncs timeline with graphStore before snapshot
- Prevents missing groups/nodes in history states
- Ensures undo/redo correctly restores all graph elements
- Atomic state updates to avoid React Flow processing stale state
Storage & Persistence:
- Groups saved in timeline states and document structure
- Safe JSON serialization to prevent prototype pollution
- Cleanup utilities for removing __proto__ from localStorage
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements a comprehensive label system and completely redesigns all
filtering (labels, actor types, relation types) to use intuitive positive
filtering where empty selection shows all items.
Label System Features:
- Create, edit, delete labels with names, colors, and scope (actors/relations/both)
- Inline editing with click-to-edit UI for quick modifications
- Quick-add label forms in config modals
- Autocomplete label selector with inline label creation
- Label badges rendered on nodes and edges (no overflow limits)
- Full undo/redo support for label operations
- Label validation and cleanup when labels are deleted
- Labels stored per-document in workspace system
Filter System Redesign:
- Changed from negative to positive filtering for all filter types
- Empty selection = show all items (intuitive default)
- Selected items = show only those items (positive filter)
- Consistent behavior across actor types, relation types, and labels
- Clear visual feedback with selection counts and helper text
- Auto-zoom viewport adjustment works for all filter types including labels
Label Cleanup & Validation:
- When label deleted, automatically removed from all nodes/edges across all timeline states
- Label references validated during node/edge updates
- Unknown label IDs filtered out to maintain data integrity
UI Improvements:
- All labels rendered without overflow limits (removed +N more indicators)
- Filter checkboxes start unchecked (select to filter, not hide)
- Helper text explains current filter state
- Selection counts displayed in filter section headers
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Refactors the type management system to properly follow the
Workspace→Document→Timeline→Graph hierarchy, where nodeTypes and
edgeTypes are owned by the document rather than being independent
state in graphStore.
Changes:
- Add type management actions to workspaceStore (document-level)
- Update workspaceStore.saveDocument to stop copying types from graphStore
- Modify useActiveDocument to only track node/edge changes for dirty state
- Update useGraphWithHistory to route type operations through workspaceStore
- Update useDocumentHistory to read/restore types from document
Architecture:
- Document: Source of truth for types (persistent storage)
- graphStore: Synchronized working memory (optimized for React Flow)
- useActiveDocument: Bridge that syncs document → graphStore
- Type mutations: Always go through workspaceStore, then sync to graphStore
This ensures proper data ownership while maintaining graphStore as a
performance optimization layer for the UI.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Refactors the history system to track complete document state instead of
individual timeline states, making timeline operations fully undoable.
BREAKING CHANGE: History is now per-document instead of per-timeline-state.
Existing undo/redo stacks will be cleared on first load with this change.
Changes:
- historyStore: Track complete document snapshots (timeline + all states + types)
- useDocumentHistory: Simplified to work with document-level operations
- timelineStore: All timeline operations now record history
- createState, switchToState, deleteState, updateState, duplicateState
- Fixed redo button bug (was mutating Zustand state directly)
New capabilities:
- Undo/redo timeline state creation
- Undo/redo timeline state deletion
- Undo/redo switching between timeline states
- Undo/redo renaming timeline states
- Unified history for all document operations
Technical improvements:
- Proper Zustand state management (no direct mutations)
- Document snapshots include entire timeline structure
- History methods accept currentSnapshot parameter
- Removed TypeScript 'any' types for better type safety
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements a comprehensive timeline system that enables documents to contain
multiple constellation states with branching timelines. This allows users to
create different versions of their analysis for temporal evolution, alternative
scenarios, or what-if analysis.
Core Features:
- Timeline store managing multiple states per document with branching structure
- Visual timeline panel with React Flow-based state graph visualization
- State management: create, switch, rename, duplicate (parallel/series), delete
- Per-state undo/redo history (max 50 actions per state)
- Context menu for timeline node operations
- Collapsible timeline panel (always visible, moved toolbar to panel header)
Architecture Changes:
- Document structure: removed top-level graph field, states now only in timeline
- Global types: nodeTypes and edgeTypes are now global per document, not per state
- State graphs: only contain nodes and edges, types inherited from document
- Persistence: full timeline serialization/deserialization with all states
- History system: converted from document-level to per-state independent stacks
Timeline Components:
- TimelineView: main timeline visualization with state nodes and edges
- BottomPanel: collapsible container with timeline controls in header
- StateNode: custom node component showing state info and active indicator
- CreateStateDialog: dialog for creating new timeline states
- RenameStateDialog: dialog for renaming existing states
- Context menu: right-click operations (rename, duplicate parallel/series, delete)
Document Management:
- Documents always have timeline (initialized with root state on creation)
- Timeline persisted with document in localStorage
- Export/import includes complete timeline with all states
- Migration support for legacy single-state documents
Store Updates:
- timelineStore: manages timelines, states, and timeline operations
- historyStore: per-state history with independent undo/redo stacks
- workspaceStore: saves/loads timeline data, handles global types
- panelStore: added timeline panel visibility state
- useActiveDocument: syncs timeline state with graph editor
Context Menu Improvements:
- Smart viewport edge detection to prevent overflow
- Click-outside detection for React Flow panes
- Consistent styling across application
Files Added:
- src/types/timeline.ts - Timeline type definitions
- src/stores/timelineStore.ts - Timeline state management
- src/components/Timeline/TimelineView.tsx - Main timeline component
- src/components/Timeline/BottomPanel.tsx - Timeline panel container
- src/components/Timeline/StateNode.tsx - State node visualization
- src/components/Timeline/CreateStateDialog.tsx - State creation dialog
- src/components/Timeline/RenameStateDialog.tsx - State rename dialog
Files Removed:
- src/stores/persistence/middleware.ts - Obsolete persistence middleware
Documentation:
- Added comprehensive timeline feature documentation
- Implementation checklists and quick reference guides
- Temporal analysis concepts and UX guidelines
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>