vibecodingmachine-core 2026.2.20-438 → 2026.2.26-1739

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/README.md +240 -0
  2. package/package.json +10 -2
  3. package/src/agents/Agent.js +300 -0
  4. package/src/agents/AgentAdditionService.js +311 -0
  5. package/src/agents/AgentCheckService.js +690 -0
  6. package/src/agents/AgentInstallationService.js +140 -0
  7. package/src/agents/AgentSetupService.js +467 -0
  8. package/src/agents/AgentStatus.js +183 -0
  9. package/src/agents/AgentVerificationService.js +634 -0
  10. package/src/agents/ConfigurationSchemaValidator.js +543 -0
  11. package/src/agents/EnvironmentConfigurationManager.js +602 -0
  12. package/src/agents/InstallationErrorHandler.js +372 -0
  13. package/src/agents/InstallationLog.js +363 -0
  14. package/src/agents/InstallationMethod.js +510 -0
  15. package/src/agents/InstallationOrchestrator.js +352 -0
  16. package/src/agents/InstallationProgressReporter.js +372 -0
  17. package/src/agents/InstallationRetryManager.js +322 -0
  18. package/src/agents/InstallationType.js +254 -0
  19. package/src/agents/OperationTypes.js +310 -0
  20. package/src/agents/PerformanceMetricsCollector.js +493 -0
  21. package/src/agents/SecurityValidationService.js +534 -0
  22. package/src/agents/VerificationTest.js +354 -0
  23. package/src/agents/VerificationType.js +226 -0
  24. package/src/agents/WindowsPermissionHandler.js +518 -0
  25. package/src/agents/config/AgentConfigManager.js +393 -0
  26. package/src/agents/config/AgentDefaultsRegistry.js +373 -0
  27. package/src/agents/config/ConfigValidator.js +281 -0
  28. package/src/agents/discovery/AgentDiscoveryService.js +707 -0
  29. package/src/agents/logging/AgentLogger.js +511 -0
  30. package/src/agents/status/AgentStatusManager.js +481 -0
  31. package/src/agents/storage/FileManager.js +454 -0
  32. package/src/agents/verification/AgentCommunicationTester.js +474 -0
  33. package/src/agents/verification/BaseVerifier.js +430 -0
  34. package/src/agents/verification/CommandVerifier.js +480 -0
  35. package/src/agents/verification/FileOperationVerifier.js +453 -0
  36. package/src/agents/verification/ResultAnalyzer.js +707 -0
  37. package/src/agents/verification/TestRequirementManager.js +495 -0
  38. package/src/agents/verification/VerificationRunner.js +433 -0
  39. package/src/agents/windows/BaseWindowsInstaller.js +441 -0
  40. package/src/agents/windows/ChocolateyInstaller.js +509 -0
  41. package/src/agents/windows/DirectInstaller.js +443 -0
  42. package/src/agents/windows/InstallerFactory.js +391 -0
  43. package/src/agents/windows/NpmInstaller.js +505 -0
  44. package/src/agents/windows/PowerShellInstaller.js +458 -0
  45. package/src/agents/windows/WinGetInstaller.js +390 -0
  46. package/src/analysis/analysis-reporter.js +132 -0
  47. package/src/analysis/boundary-detector.js +712 -0
  48. package/src/analysis/categorizer.js +340 -0
  49. package/src/analysis/codebase-scanner.js +384 -0
  50. package/src/analysis/line-counter.js +513 -0
  51. package/src/analysis/priority-calculator.js +679 -0
  52. package/src/analysis/report/analysis-report.js +250 -0
  53. package/src/analysis/report/package-analyzer.js +278 -0
  54. package/src/analysis/report/recommendation-generator.js +382 -0
  55. package/src/analysis/report/statistics-generator.js +515 -0
  56. package/src/analysis/reports/analysis-report-model.js +101 -0
  57. package/src/analysis/reports/recommendation-generator.js +283 -0
  58. package/src/analysis/reports/report-generators.js +191 -0
  59. package/src/analysis/reports/statistics-calculator.js +231 -0
  60. package/src/analysis/reports/trend-analyzer.js +219 -0
  61. package/src/analysis/strategy-generator.js +814 -0
  62. package/src/auto-mode/AutoModeBusinessLogic.js +836 -0
  63. package/src/config/refactoring-config.js +307 -0
  64. package/src/health-tracking/json-storage.js +38 -2
  65. package/src/ide-integration/applescript-manager-core.js +233 -0
  66. package/src/ide-integration/applescript-manager.cjs +357 -28
  67. package/src/ide-integration/applescript-manager.js +89 -3599
  68. package/src/ide-integration/cdp-manager.js +306 -0
  69. package/src/ide-integration/claude-code-cli-manager.cjs +1 -1
  70. package/src/ide-integration/continuation-handler.js +337 -0
  71. package/src/ide-integration/ide-status-checker.js +292 -0
  72. package/src/ide-integration/macos-ide-manager.js +627 -0
  73. package/src/ide-integration/macos-text-sender.js +528 -0
  74. package/src/ide-integration/response-reader.js +548 -0
  75. package/src/ide-integration/windows-automation-manager.js +121 -0
  76. package/src/ide-integration/windows-ide-manager.js +373 -0
  77. package/src/index.cjs +25 -3
  78. package/src/index.js +15 -1
  79. package/src/llm/direct-llm-manager.cjs +90 -2
  80. package/src/models/compliance-report.js +538 -0
  81. package/src/models/file-analysis.js +681 -0
  82. package/src/models/refactoring-plan.js +770 -0
  83. package/src/monitoring/alert-system.js +834 -0
  84. package/src/monitoring/compliance-progress-tracker.js +437 -0
  85. package/src/monitoring/continuous-scan-notifications.js +661 -0
  86. package/src/monitoring/continuous-scanner.js +279 -0
  87. package/src/monitoring/file-monitor/file-analyzer.js +262 -0
  88. package/src/monitoring/file-monitor/file-monitor.js +237 -0
  89. package/src/monitoring/file-monitor/watcher.js +194 -0
  90. package/src/monitoring/file-monitor.js +17 -0
  91. package/src/monitoring/notification-manager.js +437 -0
  92. package/src/monitoring/scanner-core.js +368 -0
  93. package/src/monitoring/scanner-events.js +214 -0
  94. package/src/monitoring/violation-notification-system.js +515 -0
  95. package/src/refactoring/boundaries/cohesion-analyzer.js +316 -0
  96. package/src/refactoring/boundaries/extraction-result.js +285 -0
  97. package/src/refactoring/boundaries/extraction-strategies.js +392 -0
  98. package/src/refactoring/boundaries/module-boundary.js +209 -0
  99. package/src/refactoring/boundary/boundary-detector.js +741 -0
  100. package/src/refactoring/boundary/boundary-types.js +405 -0
  101. package/src/refactoring/boundary/extraction-strategies.js +554 -0
  102. package/src/refactoring/boundary-extraction-result.js +77 -0
  103. package/src/refactoring/boundary-extraction-strategies.js +330 -0
  104. package/src/refactoring/boundary-extractor.js +384 -0
  105. package/src/refactoring/boundary-types.js +46 -0
  106. package/src/refactoring/circular/circular-dependency.js +88 -0
  107. package/src/refactoring/circular/cycle-detection.js +147 -0
  108. package/src/refactoring/circular/dependency-node.js +82 -0
  109. package/src/refactoring/circular/dependency-result.js +107 -0
  110. package/src/refactoring/circular/dependency-types.js +58 -0
  111. package/src/refactoring/circular/graph-builder.js +213 -0
  112. package/src/refactoring/circular/resolution-strategy.js +72 -0
  113. package/src/refactoring/circular/strategy-generator.js +229 -0
  114. package/src/refactoring/circular-dependency-resolver-original.js +809 -0
  115. package/src/refactoring/circular-dependency-resolver.js +200 -0
  116. package/src/refactoring/code-mover.js +761 -0
  117. package/src/refactoring/file-splitter.js +696 -0
  118. package/src/refactoring/functionality-validator.js +816 -0
  119. package/src/refactoring/import-manager.js +774 -0
  120. package/src/refactoring/module-boundary.js +107 -0
  121. package/src/refactoring/refactoring-executor.js +672 -0
  122. package/src/refactoring/refactoring-rollback.js +614 -0
  123. package/src/refactoring/test-validator.js +631 -0
  124. package/src/requirement-management/default-requirement-manager.js +321 -0
  125. package/src/requirement-management/requirement-file-parser.js +159 -0
  126. package/src/requirement-management/requirement-sequencer.js +221 -0
  127. package/src/rui/commands/AgentCommandParser.js +600 -0
  128. package/src/rui/commands/AgentCommands.js +487 -0
  129. package/src/rui/commands/AgentResponseFormatter.js +832 -0
  130. package/src/scripts/verify-full-compliance.js +269 -0
  131. package/src/sync/sync-engine-core.js +1 -0
  132. package/src/sync/sync-engine-remote-handlers.js +135 -0
  133. package/src/task-generation/automated-task-generator.js +351 -0
  134. package/src/task-generation/prioritizer.js +287 -0
  135. package/src/task-generation/task-list-updater.js +215 -0
  136. package/src/task-generation/task-management-integration.js +480 -0
  137. package/src/task-generation/task-manager-integration.js +270 -0
  138. package/src/task-generation/violation-task-generator.js +474 -0
  139. package/src/task-management/continuous-scan-integration.js +342 -0
  140. package/src/timeout-management/index.js +12 -3
  141. package/src/timeout-management/response-time-tracker.js +167 -0
  142. package/src/timeout-management/timeout-calculator.js +159 -0
  143. package/src/timeout-management/timeout-config-manager.js +172 -0
  144. package/src/utils/ast-analyzer.js +417 -0
  145. package/src/utils/current-requirement-manager.js +276 -0
  146. package/src/utils/current-requirement-operations.js +472 -0
  147. package/src/utils/dependency-mapper.js +456 -0
  148. package/src/utils/download-with-progress.js +4 -2
  149. package/src/utils/electron-update-checker.js +4 -1
  150. package/src/utils/file-size-analyzer.js +272 -0
  151. package/src/utils/import-updater.js +280 -0
  152. package/src/utils/refactoring-tools.js +512 -0
  153. package/src/utils/report-generator.js +569 -0
  154. package/src/utils/reports/report-analysis.js +218 -0
  155. package/src/utils/reports/report-types.js +55 -0
  156. package/src/utils/reports/summary-generators.js +102 -0
  157. package/src/utils/requirement-file-management.js +157 -0
  158. package/src/utils/requirement-helpers/requirement-file-ops.js +392 -0
  159. package/src/utils/requirement-helpers/requirement-mover.js +414 -0
  160. package/src/utils/requirement-helpers/requirement-parser.js +326 -0
  161. package/src/utils/requirement-helpers/requirement-status.js +320 -0
  162. package/src/utils/requirement-helpers-new.js +55 -0
  163. package/src/utils/requirement-helpers-refactored.js +367 -0
  164. package/src/utils/requirement-helpers.js +291 -1191
  165. package/src/utils/requirement-movement-operations.js +450 -0
  166. package/src/utils/requirement-movement.js +312 -0
  167. package/src/utils/requirement-parsing-helpers.js +56 -0
  168. package/src/utils/requirement-statistics.js +200 -0
  169. package/src/utils/requirement-text-utils.js +58 -0
  170. package/src/utils/rollback/rollback-handlers.js +125 -0
  171. package/src/utils/rollback/rollback-operation.js +63 -0
  172. package/src/utils/rollback/rollback-recorder.js +166 -0
  173. package/src/utils/rollback/rollback-state-manager.js +175 -0
  174. package/src/utils/rollback/rollback-types.js +33 -0
  175. package/src/utils/rollback/rollback-utils.js +110 -0
  176. package/src/utils/rollback-manager-original.js +569 -0
  177. package/src/utils/rollback-manager.js +202 -0
  178. package/src/utils/smoke-test-cli.js +362 -0
  179. package/src/utils/smoke-test-gui.js +351 -0
  180. package/src/utils/smoke-test-orchestrator.js +321 -0
  181. package/src/utils/smoke-test-runner.js +60 -0
  182. package/src/utils/smoke-test-web.js +347 -0
  183. package/src/utils/specification-helpers.js +39 -13
  184. package/src/utils/specification-migration.js +97 -0
  185. package/src/utils/test-runner.js +579 -0
  186. package/src/utils/validation-framework.js +518 -0
  187. package/src/validation/compliance-analyzer.js +197 -0
  188. package/src/validation/compliance-report-generator.js +343 -0
  189. package/src/validation/compliance-reporter.js +711 -0
  190. package/src/validation/compliance-rules.js +127 -0
  191. package/src/validation/constitution-validator-new.js +196 -0
  192. package/src/validation/constitution-validator.js +17 -0
  193. package/src/validation/file-validators.js +170 -0
  194. package/src/validation/line-limit/file-analyzer.js +201 -0
  195. package/src/validation/line-limit/line-limit-validator.js +208 -0
  196. package/src/validation/line-limit/validation-result.js +144 -0
  197. package/src/validation/line-limit-core.js +225 -0
  198. package/src/validation/line-limit-reporter.js +134 -0
  199. package/src/validation/line-limit-result.js +125 -0
  200. package/src/validation/line-limit-validator.js +41 -0
  201. package/src/validation/metrics-calculator.js +660 -0
  202. package/src/sync/sync-engine-backup.js +0 -559
@@ -1,559 +0,0 @@
1
- const fs = require('fs-extra');
2
- const path = require('path');
3
- const os = require('os');
4
- const crypto = require('crypto');
5
- const EventEmitter = require('events');
6
- const RemoteControlServer = require('./remote-control-server');
7
- const SyncEngineCore = require('./sync-engine-core');
8
- const SyncEngineFileOperations = require('./sync-engine-file-ops');
9
- const SyncEngineConflictResolution = require('./sync-engine-conflicts');
10
-
11
- /**
12
- * SyncEngine - Handles bidirectional sync between local files and AWS DynamoDB
13
- *
14
- * Features:
15
- * - Real-time change detection using file watchers
16
- * - Conflict resolution strategies
17
- * - Offline queue for disconnected state
18
- * - Change history tracking
19
- * - Delta sync for efficiency
20
- */
21
- class SyncEngine extends SyncEngineCore {
22
- constructor(options = {}) {
23
- super(options);
24
-
25
- // Enhanced options
26
- this.options = {
27
- syncInterval: options.syncInterval || 30000, // 30 seconds
28
- conflictStrategy: options.conflictStrategy || 'last-write-wins',
29
- offlineMode: options.offlineMode || false,
30
- enableRemoteControl: options.enableRemoteControl !== false, // Default to true
31
- remoteControlPort: options.remoteControlPort || 3457,
32
- ...options
33
- };
34
-
35
- // Initialize components
36
- this.fileOperations = new SyncEngineFileOperations(this);
37
- this.conflictResolution = new SyncEngineConflictResolution(this);
38
-
39
- // Remote control server
40
- this.remoteControlServer = null;
41
-
42
- // Start remote control server if enabled
43
- if (this.options.enableRemoteControl) {
44
- this.remoteControlServer = new RemoteControlServer({
45
- port: this.options.remoteControlPort,
46
- region: options.region,
47
- syncEngine: this
48
- });
49
- }
50
- }
51
- userPoolId: options.cognitoUserPoolId
52
- });
53
-
54
- // Set up remote control event handlers
55
- this.setupRemoteControlHandlers();
56
- }
57
- }
58
-
59
- /**
60
- * Setup remote control event handlers
61
- */
62
- setupRemoteControlHandlers() {
63
- if (!this.remoteControlServer) return;
64
-
65
- // Handle remote control commands
66
- this.remoteControlServer.on('command', async (command) => {
67
- console.log('🎮 Remote control command received:', command);
68
-
69
- try {
70
- switch (command.type) {
71
- case 'start-auto':
72
- await this.handleStartAutoCommand(command);
73
- break;
74
- case 'stop-auto':
75
- await this.handleStopAutoCommand(command);
76
- break;
77
- case 'get-status':
78
- await this.handleGetStatusCommand(command);
79
- break;
80
- default:
81
- console.warn('⚠️ Unknown remote control command:', command.type);
82
- }
83
- } catch (error) {
84
- console.error('❌ Error handling remote control command:', error);
85
- this.remoteControlServer.sendToClientById(command.clientId, 'command-error', {
86
- command: command.type,
87
- error: error.message
88
- });
89
- }
90
- });
91
-
92
- // Handle client authentication
93
- this.remoteControlServer.on('client-authenticated', (data) => {
94
- console.log('🔐 Remote control client authenticated:', data.userInfo.username);
95
- this.emit('remote-client-authenticated', data);
96
- });
97
-
98
- // Handle client disconnection
99
- this.remoteControlServer.on('client-disconnected', (data) => {
100
- console.log('🔌 Remote control client disconnected:', data.clientId);
101
- this.emit('remote-client-disconnected', data);
102
- });
103
- }
104
-
105
- /**
106
- * Handle start-auto command
107
- */
108
- async handleStartAutoCommand(command) {
109
- console.log('🚀 Starting auto mode via remote control');
110
-
111
- // Emit event for main application to handle
112
- this.emit('remote-start-auto', {
113
- clientId: command.clientId,
114
- userInfo: command.userInfo,
115
- data: command.data
116
- });
117
-
118
- // Send confirmation back to client
119
- this.remoteControlServer.sendToClientById(command.clientId, 'command-success', {
120
- command: 'start-auto',
121
- message: 'Auto mode started successfully'
122
- });
123
- }
124
-
125
- /**
126
- * Handle stop-auto command
127
- */
128
- async handleStopAutoCommand(command) {
129
- console.log('🛑 Stopping auto mode via remote control');
130
-
131
- // Emit event for main application to handle
132
- this.emit('remote-stop-auto', {
133
- clientId: command.clientId,
134
- userInfo: command.userInfo,
135
- data: command.data
136
- });
137
-
138
- // Send confirmation back to client
139
- this.remoteControlServer.sendToClientById(command.clientId, 'command-success', {
140
- command: 'stop-auto',
141
- message: 'Auto mode stopped successfully'
142
- });
143
- }
144
-
145
- /**
146
- * Handle get-status command
147
- */
148
- async handleGetStatusCommand(command) {
149
- console.log('📊 Getting status via remote control');
150
-
151
- // Get current status
152
- const status = {
153
- computerId: this.computerId,
154
- isOnline: this.isOnline,
155
- isSyncing: this.isSyncing,
156
- lastSyncTime: this.lastSyncTime,
157
- offlineQueueSize: this.offlineQueue.length,
158
- changeHistorySize: this.changeHistory.length,
159
- syncEngineStatus: 'running'
160
- };
161
-
162
- // Send status back to client
163
- this.remoteControlServer.sendToClientById(command.clientId, 'status-response', {
164
- command: 'get-status',
165
- status
166
- });
167
- }
168
-
169
- /**
170
- * Get unique computer ID
171
- */
172
- _getComputerId() {
173
- const hostname = os.hostname();
174
- return hostname;
175
- }
176
-
177
- /**
178
- * Initialize AWS clients
179
- */
180
- async initialize() {
181
- try {
182
- // Initialize DynamoDB client
183
- const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
184
- const { DynamoDBDocumentClient } = require('@aws-sdk/lib-dynamodb');
185
-
186
- const region = process.env.AWS_REGION || 'us-east-1';
187
- const client = new DynamoDBClient({ region });
188
- this.dynamoClient = DynamoDBDocumentClient.from(client);
189
-
190
- // Initialize WebSocket client for real-time updates
191
- await this._initializeWebSocket();
192
-
193
- this.emit('initialized');
194
- return true;
195
- } catch (error) {
196
- // If AWS SDK is not installed in this environment (common in local dev),
197
- // fall back to offline mode instead of throwing so the CLI remains usable.
198
- if (error && error.code === 'MODULE_NOT_FOUND' && /@aws-sdk\//.test(error.message)) {
199
- this.options.offlineMode = true;
200
- this.isOnline = false;
201
- this.emit('warning', { type: 'offline-fallback', message: 'AWS SDK not available, running in offline mode', error });
202
- this.emit('initialized');
203
- return false;
204
- }
205
-
206
- this.emit('error', { type: 'initialization', error });
207
- throw error;
208
- }
209
- }
210
-
211
- /**
212
- * Initialize WebSocket connection for real-time updates
213
- */
214
- async _initializeWebSocket() {
215
- // TODO: Implement WebSocket connection to AWS IoT Core or API Gateway WebSocket
216
- // For now, we'll use polling
217
- this.emit('websocket-status', { connected: false, reason: 'not-implemented' });
218
- }
219
-
220
- /**
221
- * Start sync engine
222
- */
223
- async start() {
224
- if (!this.dynamoClient) {
225
- await this.initialize();
226
- }
227
-
228
- // Start remote control server
229
- if (this.remoteControlServer && !this.remoteControlServer.isRunning) {
230
- try {
231
- await this.remoteControlServer.start();
232
- console.log('🚀 Remote control server started');
233
- } catch (error) {
234
- console.error('❌ Failed to start remote control server:', error);
235
- this.emit('error', { type: 'remote-control-start', error });
236
- }
237
- }
238
-
239
- // Start periodic sync
240
- this.syncInterval = setInterval(() => {
241
- this.sync().catch(error => {
242
- this.emit('error', { type: 'sync', error });
243
- });
244
- }, this.options.syncInterval);
245
-
246
- // Do initial sync
247
- await this.sync();
248
-
249
- this.emit('started');
250
- }
251
-
252
- /**
253
- * Stop sync engine
254
- */
255
- async stop() {
256
- // Stop remote control server
257
- if (this.remoteControlServer && this.remoteControlServer.isRunning) {
258
- try {
259
- await this.remoteControlServer.stop();
260
- console.log('🛑 Remote control server stopped');
261
- } catch (error) {
262
- console.error('❌ Failed to stop remote control server:', error);
263
- }
264
- }
265
-
266
- if (this.syncInterval) {
267
- clearInterval(this.syncInterval);
268
- this.syncInterval = null;
269
- }
270
-
271
- this.emit('stopped');
272
- }
273
-
274
- /**
275
- * Perform sync operation
276
- */
277
- async sync() {
278
- if (this.isSyncing) {
279
- return; // Already syncing
280
- }
281
-
282
- this.isSyncing = true;
283
- this.emit('sync-start');
284
-
285
- try {
286
- // Check if online
287
- if (!this.isOnline) {
288
- this.emit('sync-complete', { status: 'offline', queued: this.offlineQueue.length });
289
- return;
290
- }
291
-
292
- // Process offline queue first
293
- if (this.offlineQueue.length > 0) {
294
- await this._processOfflineQueue();
295
- }
296
-
297
- // Fetch remote changes
298
- const remoteChanges = await this._fetchRemoteChanges();
299
-
300
- // Detect local changes
301
- const localChanges = await this._detectLocalChanges();
302
-
303
- // Resolve conflicts
304
- const conflicts = this._detectConflicts(localChanges, remoteChanges);
305
- if (conflicts.length > 0) {
306
- await this._resolveConflicts(conflicts);
307
- }
308
-
309
- // Apply remote changes locally
310
- if (remoteChanges.length > 0) {
311
- await this._applyRemoteChanges(remoteChanges);
312
- }
313
-
314
- // Push local changes to remote
315
- if (localChanges.length > 0) {
316
- await this._pushLocalChanges(localChanges);
317
- }
318
-
319
- this.lastSyncTime = Date.now();
320
- this.emit('sync-complete', {
321
- status: 'success',
322
- remoteChanges: remoteChanges.length,
323
- localChanges: localChanges.length,
324
- conflicts: conflicts.length
325
- });
326
- } catch (error) {
327
- this.emit('sync-complete', { status: 'error', error: error.message });
328
- // Don't throw - just emit error event
329
- this.emit('error', { type: 'sync', error: error.message });
330
- } finally {
331
- this.isSyncing = false;
332
- }
333
- }
334
-
335
- /**
336
- * Fetch remote changes from DynamoDB
337
- */
338
- async _fetchRemoteChanges() {
339
- if (!this.dynamoClient) {
340
- this.emit('warning', { type: 'no-dynamo', message: 'DynamoDB client not initialized, skipping remote fetch' });
341
- return [];
342
- }
343
-
344
- const { ScanCommand } = require('@aws-sdk/lib-dynamodb');
345
-
346
- const tableName = process.env.DYNAMODB_TABLE_NAME || 'vibecodingmachine-requirements';
347
- const lastSync = this.lastSyncTime || 0;
348
-
349
- try {
350
- // Use Scan with filter instead of Query since we need to check all items
351
- // In production, consider using DynamoDB Streams for real-time updates
352
- const command = new ScanCommand({
353
- TableName: tableName,
354
- FilterExpression: '#ts > :lastSync',
355
- ExpressionAttributeNames: {
356
- '#ts': 'timestamp'
357
- },
358
- ExpressionAttributeValues: {
359
- ':lastSync': lastSync
360
- }
361
- });
362
-
363
- const response = await this.dynamoClient.send(command);
364
- return response.Items || [];
365
- } catch (error) {
366
- this.emit('error', { type: 'fetch-remote', error });
367
- return [];
368
- }
369
- }
370
-
371
- /**
372
- * Detect local changes
373
- */
374
- async _detectLocalChanges() {
375
- // TODO: Implement file watching and change detection
376
- // For now, return empty array
377
- return [];
378
- }
379
-
380
- /**
381
- * Detect conflicts between local and remote changes
382
- */
383
- _detectConflicts(localChanges, remoteChanges) {
384
- const conflicts = [];
385
-
386
- for (const local of localChanges) {
387
- for (const remote of remoteChanges) {
388
- if (local.requirementId === remote.requirementId) {
389
- // Same requirement modified both locally and remotely
390
- if (local.timestamp !== remote.timestamp) {
391
- conflicts.push({ local, remote });
392
- }
393
- }
394
- }
395
- }
396
-
397
- return conflicts;
398
- }
399
-
400
- /**
401
- * Resolve conflicts based on strategy
402
- */
403
- async _resolveConflicts(conflicts) {
404
- for (const conflict of conflicts) {
405
- this.emit('conflict', conflict);
406
-
407
- let resolution;
408
- switch (this.options.conflictStrategy) {
409
- case 'last-write-wins':
410
- resolution = conflict.local.timestamp > conflict.remote.timestamp
411
- ? conflict.local
412
- : conflict.remote;
413
- break;
414
-
415
- case 'manual':
416
- // Emit event for manual resolution
417
- resolution = await new Promise((resolve) => {
418
- this.once('conflict-resolved', resolve);
419
- });
420
- break;
421
-
422
- case 'auto-merge':
423
- resolution = this._autoMerge(conflict.local, conflict.remote);
424
- break;
425
-
426
- default:
427
- resolution = conflict.remote; // Default to remote
428
- }
429
-
430
- // Log conflict resolution
431
- this.changeHistory.push({
432
- type: 'conflict-resolution',
433
- timestamp: Date.now(),
434
- conflict,
435
- resolution
436
- });
437
- }
438
- }
439
-
440
- /**
441
- * Auto-merge non-overlapping changes
442
- */
443
- _autoMerge(local, remote) {
444
- // Simple merge: combine changes from both
445
- return {
446
- ...remote,
447
- ...local,
448
- timestamp: Math.max(local.timestamp, remote.timestamp)
449
- };
450
- }
451
-
452
- /**
453
- * Apply remote changes locally
454
- */
455
- async _applyRemoteChanges(changes) {
456
- for (const change of changes) {
457
- try {
458
- // TODO: Apply change to local requirements file
459
- this.emit('remote-change-applied', change);
460
- } catch (error) {
461
- this.emit('error', { type: 'apply-remote', change, error });
462
- }
463
- }
464
- }
465
-
466
- /**
467
- * Push local changes to remote
468
- */
469
- async _pushLocalChanges(changes) {
470
- if (!this.dynamoClient) {
471
- this.emit('warning', { type: 'no-dynamo', message: 'DynamoDB client not initialized, queuing local changes' });
472
- // Queue all changes for later push
473
- this.offlineQueue.push(...changes);
474
- return;
475
- }
476
-
477
- const { PutCommand } = require('@aws-sdk/lib-dynamodb');
478
-
479
- const tableName = process.env.DYNAMODB_TABLE_NAME || 'vibecodingmachine-requirements';
480
-
481
- for (const change of changes) {
482
- try {
483
- const command = new PutCommand({
484
- TableName: tableName,
485
- Item: {
486
- computerId: this.computerId,
487
- timestamp: Date.now(),
488
- ...change
489
- }
490
- });
491
-
492
- await this.dynamoClient.send(command);
493
- this.emit('local-change-pushed', change);
494
- } catch (error) {
495
- this.emit('error', { type: 'push-local', change, error });
496
-
497
- // Add to offline queue if push fails
498
- if (!this.isOnline) {
499
- this.offlineQueue.push(change);
500
- }
501
- }
502
- }
503
- }
504
-
505
- /**
506
- * Process offline queue
507
- */
508
- async _processOfflineQueue() {
509
- const queue = [...this.offlineQueue];
510
- this.offlineQueue = [];
511
-
512
- for (const change of queue) {
513
- try {
514
- await this._pushLocalChanges([change]);
515
- } catch (error) {
516
- // Re-add to queue if still failing
517
- this.offlineQueue.push(change);
518
- }
519
- }
520
- }
521
-
522
- /**
523
- * Get sync status
524
- */
525
- getStatus() {
526
- return {
527
- computerId: this.computerId,
528
- isOnline: this.isOnline,
529
- isSyncing: this.isSyncing,
530
- lastSyncTime: this.lastSyncTime,
531
- queuedChanges: this.offlineQueue.length,
532
- conflictStrategy: this.options.conflictStrategy
533
- };
534
- }
535
-
536
- /**
537
- * Get change history
538
- */
539
- getHistory(limit = 100) {
540
- return this.changeHistory.slice(-limit);
541
- }
542
-
543
- /**
544
- * Set online/offline mode
545
- */
546
- setOnlineMode(isOnline) {
547
- this.isOnline = isOnline;
548
- this.emit('online-status-changed', { isOnline });
549
-
550
- if (isOnline && this.offlineQueue.length > 0) {
551
- // Trigger sync to process offline queue
552
- this.sync().catch(error => {
553
- this.emit('error', { type: 'sync', error });
554
- });
555
- }
556
- }
557
- }
558
-
559
- module.exports = SyncEngine;