/ docs / architecture / epic-1-implementation.md
epic-1-implementation.md
  1  # Epic 1: Plugin Infrastructure Implementation
  2  
  3  This document captures the actual implementation details from Epic 1, serving as the technical reference for the foundation of the InterBrain Obsidian plugin.
  4  
  5  ## Overview
  6  
  7  Epic 1 established the complete plugin infrastructure with modern tooling, reactive state management, and comprehensive testing. This foundation supports all future development with a clean, maintainable architecture.
  8  
  9  ## Build System: Vite Dual Workflow
 10  
 11  ### Configuration
 12  - **Development**: `vite.dev.config.ts` for browser development with React hot reload
 13  - **Production**: `vite.config.ts` for Obsidian plugin builds
 14  - **Key Decision**: Replaced esbuild with Vite for superior development experience
 15  
 16  ### Build Process
 17  ```json
 18  {
 19    "scripts": {
 20      "dev": "vite --config vite.dev.config.ts",      // Browser development
 21      "plugin-build": "vite build && cp dist/main.js ." // Plugin build + copy
 22    }
 23  }
 24  ```
 25  
 26  **Why the copy step?**
 27  - Vite outputs to `dist/` (standard practice)
 28  - Obsidian expects `main.js` at plugin root
 29  - Simple `cp` command bridges this gap cleanly
 30  
 31  ## Command-Driven Architecture
 32  
 33  ### Command Registration Pattern
 34  All functionality exposed through Obsidian's command palette:
 35  
 36  ```typescript
 37  this.addCommand({
 38    id: 'save-dreamnode',
 39    name: 'Save DreamNode (commit changes)',
 40    callback: async () => {
 41      const loadingNotice = this.uiService.showLoading('Saving DreamNode...');
 42      try {
 43        const currentNode = this.dreamNodeService.getCurrentNode();
 44        if (!currentNode) {
 45          throw new Error('No DreamNode selected');
 46        }
 47        await this.gitService.commitWithAI(currentNode.path);
 48        this.uiService.showSuccess('DreamNode saved successfully');
 49      } catch (error) {
 50        this.uiService.showError(error instanceof Error ? error.message : 'Unknown error occurred');
 51      } finally {
 52        loadingNotice.hide();
 53      }
 54    }
 55  });
 56  ```
 57  
 58  ### Implemented Commands
 59  1. **Open DreamSpace** - Opens 3D spatial visualization view
 60  2. **Save DreamNode** - Commits changes with AI assistance
 61  3. **Create new DreamNode** - Creates Dream or Dreamer node
 62  4. **Weave Dreams** - Combines nodes via git submodules
 63  5. **Toggle DreamNode selection** - Multi-select for operations
 64  6. **Share DreamNode** - Coherence Beacon sharing
 65  
 66  ### Test Commands (Development)
 67  - `[TEST] Select Mock DreamNode` - Verifies state synchronization
 68  - `[TEST] Clear DreamNode Selection` - Tests state clearing
 69  
 70  ## Service Layer Architecture
 71  
 72  ### Design Philosophy
 73  Clean separation of concerns with dedicated service classes:
 74  
 75  ```typescript
 76  export class InterBrainPlugin extends Plugin {
 77    private uiService: UIService;
 78    private gitService: GitService;
 79    private dreamNodeService: DreamNodeService;
 80    private vaultService: VaultService;
 81    
 82    async onload() {
 83      this.initializeServices();
 84      this.registerCommands();
 85      this.addRibbonIcon('brain', 'InterBrain', () => {
 86        this.uiService.showPlaceholder('Opening DreamSpace...');
 87      });
 88    }
 89  }
 90  ```
 91  
 92  ### Service Responsibilities
 93  
 94  **UIService**: User notifications and feedback
 95  ```typescript
 96  showSuccess(message: string): void
 97  showError(message: string): void
 98  showPlaceholder(message: string): void
 99  showLoading(message: string): Notice
100  ```
101  
102  **GitService**: Git operations abstraction
103  ```typescript
104  async commitWithAI(path: string): Promise<void>
105  async createDreamNode(name: string, type: 'dream' | 'dreamer'): Promise<string>
106  async weaveDreams(nodes: DreamNode[], name: string): Promise<void>
107  ```
108  
109  **DreamNodeService**: State and selection management
110  ```typescript
111  getCurrentNode(): DreamNode | null
112  setCurrentNode(node: DreamNode | null): void
113  toggleNodeSelection(nodeId: string): void
114  getSelectedNodes(): DreamNode[]
115  ```
116  
117  **VaultService**: Obsidian file system operations
118  ```typescript
119  async createFolder(path: string): Promise<void>
120  async fileExists(path: string): Promise<boolean>
121  async readFile(path: string): Promise<string>
122  async writeFile(path: string, content: string): Promise<void>
123  ```
124  
125  ## State Management: Zustand
126  
127  ### Store Structure
128  Centralized reactive state for future UI components:
129  
130  ```typescript
131  interface InterBrainState {
132    selectedNode: DreamNode | null;
133    searchResults: DreamNode[];
134    spatialLayout: 'constellation' | 'search' | 'focused';
135    
136    setSelectedNode: (node: DreamNode | null) => void;
137    setSearchResults: (results: DreamNode[]) => void;
138    setSpatialLayout: (layout: SpatialLayout) => void;
139  }
140  ```
141  
142  ### Integration Pattern
143  Services update both internal state and Zustand store:
144  
145  ```typescript
146  setCurrentNode(node: DreamNode | null): void {
147    this.currentNode = node; // Internal state
148    useInterBrainStore.getState().setSelectedNode(node); // Reactive state
149  }
150  ```
151  
152  ## Testing Framework: Vitest
153  
154  ### Configuration
155  Complete testing setup with Obsidian API mocking:
156  
157  ```typescript
158  // vitest.config.ts
159  export default defineConfig({
160    plugins: [react()],
161    test: {
162      environment: 'jsdom',
163      setupFiles: ['./tests/setup.ts'],
164    },
165    resolve: {
166      alias: {
167        'obsidian': resolve(__dirname, 'tests/mocks/obsidian-module.ts'),
168      },
169    },
170  });
171  ```
172  
173  ### Test Organization
174  Co-located tests following vertical slice architecture:
175  ```
176  src/
177  ├── services/
178  │   ├── dreamnode-service.ts
179  │   ├── dreamnode-service.test.ts    // 10 tests
180  │   ├── ui-service.ts
181  │   ├── ui-service.test.ts           // 8 tests
182  │   └── vault-service.test.ts        // 15 tests
183  └── store/
184      ├── interbrain-store.ts
185      └── interbrain-store.test.ts     // 14 tests
186  ```
187  
188  ### Test Results
189  **47 tests passing** across all core services and state management.
190  
191  ## Development Workflow
192  
193  ### Local Development
194  1. `npm run dev` - Browser development with hot reload
195  2. `npm run plugin-build` - Build for Obsidian
196  3. Use Plugin Reloader hotkey in Obsidian development vault
197  
198  ### Quality Assurance
199  ```bash
200  npm run lint          # ESLint checks
201  npm run typecheck     # TypeScript validation
202  npm run test          # Run test suite
203  npm run check-all     # All checks combined
204  ```
205  
206  ## Key Architectural Decisions
207  
208  1. **Vite over esbuild**: Superior DX with hot reload and dual workflows
209  2. **Command-first design**: All features accessible via command palette
210  3. **Service layer pattern**: Clean separation between UI and business logic
211  4. **Zustand for state**: Preparation for complex React UI in Epic 2
212  5. **Vitest over Jest**: Better Vite integration and ESM support
213  6. **Co-located tests**: Tests live next to implementation files
214  
215  ## Epic 1 Deliverables
216  
217  - ✅ Complete Obsidian plugin foundation
218  - ✅ Modern build system with dual workflows
219  - ✅ Command palette integration (8 commands)
220  - ✅ Service layer architecture (4 services)
221  - ✅ Reactive state management
222  - ✅ Comprehensive testing (47 tests)
223  - ✅ Development workflow documentation
224  
225  ## Next: Epic 2
226  
227  With this foundation, Epic 2 can focus entirely on building the 3D spatial visualization system using React Three Fiber, knowing that all infrastructure concerns have been addressed.