elsabro 2.3.0 → 3.8.0

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 (71) hide show
  1. package/README.md +698 -20
  2. package/bin/install.js +0 -0
  3. package/flows/development-flow.json +452 -0
  4. package/flows/quick-flow.json +118 -0
  5. package/hooks/hooks-config-updated.json +285 -0
  6. package/hooks/skill-discovery.sh +539 -0
  7. package/package.json +3 -2
  8. package/references/SYSTEM_INDEX.md +400 -5
  9. package/references/agent-marketplace.md +2274 -0
  10. package/references/agent-protocol.md +1126 -0
  11. package/references/ai-code-suggestions.md +2413 -0
  12. package/references/checkpointing.md +595 -0
  13. package/references/collaboration-patterns.md +851 -0
  14. package/references/collaborative-sessions.md +1081 -0
  15. package/references/configuration-management.md +1810 -0
  16. package/references/cost-tracking.md +1095 -0
  17. package/references/enterprise-sso.md +2001 -0
  18. package/references/error-contracts-v2.md +968 -0
  19. package/references/event-driven.md +1031 -0
  20. package/references/flow-orchestration.md +940 -0
  21. package/references/flow-visualization.md +1557 -0
  22. package/references/ide-integrations.md +3513 -0
  23. package/references/interrupt-system.md +681 -0
  24. package/references/kubernetes-deployment.md +3099 -0
  25. package/references/memory-system.md +683 -0
  26. package/references/mobile-companion.md +3236 -0
  27. package/references/multi-llm-providers.md +2494 -0
  28. package/references/multi-project-memory.md +1182 -0
  29. package/references/observability.md +793 -0
  30. package/references/output-schemas.md +858 -0
  31. package/references/performance-profiler.md +955 -0
  32. package/references/plugin-system.md +1526 -0
  33. package/references/prompt-management.md +292 -0
  34. package/references/sandbox-execution.md +303 -0
  35. package/references/security-system.md +1253 -0
  36. package/references/skill-marketplace-integration.md +3901 -0
  37. package/references/streaming.md +696 -0
  38. package/references/testing-framework.md +1151 -0
  39. package/references/time-travel.md +802 -0
  40. package/references/tool-registry.md +886 -0
  41. package/references/voice-commands.md +3296 -0
  42. package/templates/agent-marketplace-config.json +220 -0
  43. package/templates/agent-protocol-config.json +136 -0
  44. package/templates/ai-suggestions-config.json +100 -0
  45. package/templates/checkpoint-state.json +61 -0
  46. package/templates/collaboration-config.json +157 -0
  47. package/templates/collaborative-sessions-config.json +153 -0
  48. package/templates/configuration-config.json +245 -0
  49. package/templates/cost-tracking-config.json +148 -0
  50. package/templates/enterprise-sso-config.json +438 -0
  51. package/templates/events-config.json +148 -0
  52. package/templates/flow-visualization-config.json +196 -0
  53. package/templates/ide-integrations-config.json +442 -0
  54. package/templates/kubernetes-config.json +764 -0
  55. package/templates/memory-state.json +84 -0
  56. package/templates/mobile-companion-config.json +600 -0
  57. package/templates/multi-llm-config.json +544 -0
  58. package/templates/multi-project-memory-config.json +145 -0
  59. package/templates/observability-config.json +109 -0
  60. package/templates/performance-profiler-config.json +125 -0
  61. package/templates/plugin-config.json +170 -0
  62. package/templates/prompt-management-config.json +86 -0
  63. package/templates/sandbox-config.json +185 -0
  64. package/templates/schemas-config.json +65 -0
  65. package/templates/security-config.json +120 -0
  66. package/templates/skill-marketplace-config.json +441 -0
  67. package/templates/streaming-config.json +72 -0
  68. package/templates/testing-config.json +81 -0
  69. package/templates/timetravel-config.json +62 -0
  70. package/templates/tool-registry-config.json +109 -0
  71. package/templates/voice-commands-config.json +658 -0
@@ -0,0 +1,802 @@
1
+ ---
2
+ name: time-travel
3
+ description: Sistema de time-travel debugging para análisis y replay de sesiones
4
+ version: 1.0.0
5
+ ---
6
+
7
+ # ELSABRO Time-Travel Debugging System
8
+
9
+ ## Vision General
10
+
11
+ El sistema de Time-Travel Debugging permite navegar por la historia de ejecución, analizar decisiones pasadas, y explorar caminos alternativos ("what-if" analysis).
12
+
13
+ ```
14
+ ┌──────────────────────────────────────────────────────────────────────────┐
15
+ │ TIME-TRAVEL ARCHITECTURE │
16
+ ├──────────────────────────────────────────────────────────────────────────┤
17
+ │ │
18
+ │ TIMELINE │
19
+ │ ═══════════════════════════════════════════════════════════════ │
20
+ │ │ │
21
+ │ ▼ │
22
+ │ [CP1]────[CP2]────[CP3]────[CP4]────[CP5]────[CURRENT] │
23
+ │ │ │ │ │ │ │
24
+ │ │ │ │ │ └── Review complete │
25
+ │ │ │ │ └── Implementation done │
26
+ │ │ │ └── Plan approved │
27
+ │ │ └── Analysis complete │
28
+ │ └── Session started │
29
+ │ │
30
+ │ OPERATIONS │
31
+ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
32
+ │ │ REPLAY │ │ JUMP │ │ BRANCH │ │ COMPARE │ │
33
+ │ │ (watch) │ │ (goto) │ │ (fork) │ │ (diff) │ │
34
+ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
35
+ │ │
36
+ │ WHAT-IF ANALYSIS │
37
+ │ ┌──────────────────────────────────────────────────────────────┐ │
38
+ │ │ Original: CP3 ─── [Decision A] ─── CP4 ─── CP5 │ │
39
+ │ │ │ │ │
40
+ │ │ Branch: CP3 ─── [Decision B] ─── CP4' ─── ? │ │
41
+ │ │ (alternative) │ │
42
+ │ └──────────────────────────────────────────────────────────────┘ │
43
+ │ │
44
+ └──────────────────────────────────────────────────────────────────────────┘
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Componentes del Sistema
50
+
51
+ ### 1. Timeline Manager
52
+
53
+ Gestiona la línea de tiempo de ejecución.
54
+
55
+ ```javascript
56
+ /**
57
+ * TimelineManager
58
+ * Gestiona la línea de tiempo de ejecución para time-travel
59
+ */
60
+ class TimelineManager {
61
+ constructor(checkpointManager) {
62
+ this.checkpointManager = checkpointManager;
63
+ this.timeline = [];
64
+ this.currentPosition = -1;
65
+ this.branches = new Map();
66
+ this.mainBranch = 'main';
67
+ this.activeBranch = 'main';
68
+ }
69
+
70
+ /**
71
+ * Construye timeline desde checkpoints
72
+ */
73
+ async buildTimeline(sessionId) {
74
+ const checkpoints = await this.checkpointManager.listCheckpoints(sessionId, {
75
+ limit: 1000
76
+ });
77
+
78
+ this.timeline = checkpoints.map((cp, index) => ({
79
+ index,
80
+ checkpointId: cp.checkpointId,
81
+ timestamp: cp.createdAt,
82
+ event: cp.event,
83
+ phase: cp.phase,
84
+ summary: this.generateSummary(cp),
85
+ branch: 'main'
86
+ }));
87
+
88
+ this.currentPosition = this.timeline.length - 1;
89
+
90
+ return this.timeline;
91
+ }
92
+
93
+ /**
94
+ * Genera resumen legible de un checkpoint
95
+ */
96
+ generateSummary(checkpoint) {
97
+ const summaries = {
98
+ 'FLOW_START': 'Session started',
99
+ 'PHASE_START': `Started phase: ${checkpoint.phase}`,
100
+ 'PHASE_COMPLETE': `Completed phase: ${checkpoint.phase}`,
101
+ 'NODE_COMPLETE': `Completed node: ${checkpoint.nodeId}`,
102
+ 'AGENT_COMPLETE': `Agent finished: ${checkpoint.agentId}`,
103
+ 'INTERRUPT': `Waiting for input: ${checkpoint.reason}`,
104
+ 'DECISION': `Decision made: ${checkpoint.decision}`,
105
+ 'ERROR': `Error occurred: ${checkpoint.error}`,
106
+ 'ROLLBACK': `Rolled back to: ${checkpoint.targetId}`
107
+ };
108
+
109
+ return summaries[checkpoint.event] || checkpoint.event;
110
+ }
111
+
112
+ /**
113
+ * Obtiene posición actual en timeline
114
+ */
115
+ getCurrentPosition() {
116
+ return {
117
+ index: this.currentPosition,
118
+ checkpoint: this.timeline[this.currentPosition],
119
+ total: this.timeline.length,
120
+ isLatest: this.currentPosition === this.timeline.length - 1,
121
+ branch: this.activeBranch
122
+ };
123
+ }
124
+
125
+ /**
126
+ * Salta a una posición específica
127
+ */
128
+ async jumpTo(position) {
129
+ if (position < 0 || position >= this.timeline.length) {
130
+ throw new Error(`Invalid position: ${position}`);
131
+ }
132
+
133
+ const checkpoint = this.timeline[position];
134
+ await this.checkpointManager.loadCheckpoint(checkpoint.checkpointId);
135
+
136
+ this.currentPosition = position;
137
+
138
+ return {
139
+ position: this.currentPosition,
140
+ checkpoint,
141
+ state: await this.checkpointManager.getStateAt(checkpoint.checkpointId)
142
+ };
143
+ }
144
+
145
+ /**
146
+ * Avanza un paso
147
+ */
148
+ async stepForward() {
149
+ if (this.currentPosition >= this.timeline.length - 1) {
150
+ return { atEnd: true };
151
+ }
152
+
153
+ return this.jumpTo(this.currentPosition + 1);
154
+ }
155
+
156
+ /**
157
+ * Retrocede un paso
158
+ */
159
+ async stepBackward() {
160
+ if (this.currentPosition <= 0) {
161
+ return { atBeginning: true };
162
+ }
163
+
164
+ return this.jumpTo(this.currentPosition - 1);
165
+ }
166
+
167
+ /**
168
+ * Crea una rama alternativa desde la posición actual
169
+ */
170
+ async createBranch(branchName) {
171
+ if (this.branches.has(branchName)) {
172
+ throw new Error(`Branch ${branchName} already exists`);
173
+ }
174
+
175
+ const branchPoint = this.timeline[this.currentPosition];
176
+
177
+ this.branches.set(branchName, {
178
+ name: branchName,
179
+ createdAt: new Date().toISOString(),
180
+ branchPoint: branchPoint.checkpointId,
181
+ branchPosition: this.currentPosition,
182
+ timeline: []
183
+ });
184
+
185
+ this.activeBranch = branchName;
186
+
187
+ return {
188
+ branch: branchName,
189
+ branchPoint: branchPoint,
190
+ position: this.currentPosition
191
+ };
192
+ }
193
+
194
+ /**
195
+ * Cambia a una rama
196
+ */
197
+ async switchBranch(branchName) {
198
+ if (branchName === 'main') {
199
+ this.activeBranch = 'main';
200
+ return { branch: 'main', timeline: this.timeline };
201
+ }
202
+
203
+ if (!this.branches.has(branchName)) {
204
+ throw new Error(`Branch ${branchName} not found`);
205
+ }
206
+
207
+ const branch = this.branches.get(branchName);
208
+ this.activeBranch = branchName;
209
+
210
+ // Combinar timeline principal hasta branch point + branch timeline
211
+ const combinedTimeline = [
212
+ ...this.timeline.slice(0, branch.branchPosition + 1),
213
+ ...branch.timeline
214
+ ];
215
+
216
+ return {
217
+ branch: branchName,
218
+ timeline: combinedTimeline,
219
+ branchPoint: branch.branchPosition
220
+ };
221
+ }
222
+
223
+ /**
224
+ * Lista todas las ramas
225
+ */
226
+ listBranches() {
227
+ const branches = [
228
+ {
229
+ name: 'main',
230
+ isActive: this.activeBranch === 'main',
231
+ length: this.timeline.length,
232
+ branchPoint: null
233
+ }
234
+ ];
235
+
236
+ for (const [name, branch] of this.branches) {
237
+ branches.push({
238
+ name,
239
+ isActive: this.activeBranch === name,
240
+ length: branch.timeline.length,
241
+ branchPoint: branch.branchPosition,
242
+ createdAt: branch.createdAt
243
+ });
244
+ }
245
+
246
+ return branches;
247
+ }
248
+ }
249
+ ```
250
+
251
+ ### 2. Replay Engine
252
+
253
+ Motor para reproducir ejecuciones pasadas.
254
+
255
+ ```javascript
256
+ /**
257
+ * ReplayEngine
258
+ * Reproduce ejecuciones pasadas step-by-step
259
+ */
260
+ class ReplayEngine {
261
+ constructor(timelineManager, options = {}) {
262
+ this.timeline = timelineManager;
263
+ this.config = {
264
+ speed: options.speed || 1.0, // 1.0 = tiempo real
265
+ autoPlay: options.autoPlay || false,
266
+ pauseOnDecision: options.pauseOnDecision || true,
267
+ pauseOnError: options.pauseOnError || true
268
+ };
269
+
270
+ this.state = {
271
+ isPlaying: false,
272
+ isPaused: false,
273
+ currentStep: 0,
274
+ totalSteps: 0
275
+ };
276
+
277
+ this.listeners = new Set();
278
+ }
279
+
280
+ /**
281
+ * Inicia replay desde posición actual
282
+ */
283
+ async startReplay(options = {}) {
284
+ const startPosition = options.from || 0;
285
+ const endPosition = options.to || this.timeline.timeline.length - 1;
286
+
287
+ this.state = {
288
+ isPlaying: true,
289
+ isPaused: false,
290
+ currentStep: startPosition,
291
+ totalSteps: endPosition - startPosition + 1,
292
+ startPosition,
293
+ endPosition
294
+ };
295
+
296
+ await this.timeline.jumpTo(startPosition);
297
+ this.emit('replay_started', { position: startPosition });
298
+
299
+ if (this.config.autoPlay) {
300
+ await this.play();
301
+ }
302
+
303
+ return this.state;
304
+ }
305
+
306
+ /**
307
+ * Reproduce automáticamente
308
+ */
309
+ async play() {
310
+ while (this.state.isPlaying && !this.state.isPaused) {
311
+ const result = await this.step();
312
+
313
+ if (result.atEnd) {
314
+ this.state.isPlaying = false;
315
+ this.emit('replay_complete', { steps: this.state.currentStep });
316
+ break;
317
+ }
318
+
319
+ // Pausa en decisiones si está configurado
320
+ if (this.config.pauseOnDecision && result.checkpoint.event === 'DECISION') {
321
+ this.pause();
322
+ this.emit('paused_on_decision', result);
323
+ break;
324
+ }
325
+
326
+ // Pausa en errores si está configurado
327
+ if (this.config.pauseOnError && result.checkpoint.event === 'ERROR') {
328
+ this.pause();
329
+ this.emit('paused_on_error', result);
330
+ break;
331
+ }
332
+
333
+ // Delay basado en velocidad
334
+ const delay = this.calculateDelay(result);
335
+ await this.sleep(delay);
336
+ }
337
+ }
338
+
339
+ /**
340
+ * Avanza un paso en el replay
341
+ */
342
+ async step() {
343
+ if (this.state.currentStep >= this.state.endPosition) {
344
+ return { atEnd: true };
345
+ }
346
+
347
+ const result = await this.timeline.stepForward();
348
+ this.state.currentStep++;
349
+
350
+ this.emit('step', {
351
+ step: this.state.currentStep,
352
+ total: this.state.totalSteps,
353
+ checkpoint: result.checkpoint,
354
+ state: result.state
355
+ });
356
+
357
+ return result;
358
+ }
359
+
360
+ /**
361
+ * Retrocede un paso
362
+ */
363
+ async stepBack() {
364
+ if (this.state.currentStep <= this.state.startPosition) {
365
+ return { atBeginning: true };
366
+ }
367
+
368
+ const result = await this.timeline.stepBackward();
369
+ this.state.currentStep--;
370
+
371
+ this.emit('step_back', {
372
+ step: this.state.currentStep,
373
+ checkpoint: result.checkpoint
374
+ });
375
+
376
+ return result;
377
+ }
378
+
379
+ /**
380
+ * Pausa el replay
381
+ */
382
+ pause() {
383
+ this.state.isPaused = true;
384
+ this.emit('paused', { step: this.state.currentStep });
385
+ }
386
+
387
+ /**
388
+ * Reanuda el replay
389
+ */
390
+ async resume() {
391
+ this.state.isPaused = false;
392
+ this.emit('resumed', { step: this.state.currentStep });
393
+ await this.play();
394
+ }
395
+
396
+ /**
397
+ * Detiene el replay
398
+ */
399
+ stop() {
400
+ this.state.isPlaying = false;
401
+ this.state.isPaused = false;
402
+ this.emit('stopped', { step: this.state.currentStep });
403
+ }
404
+
405
+ /**
406
+ * Cambia velocidad de replay
407
+ */
408
+ setSpeed(speed) {
409
+ this.config.speed = speed;
410
+ this.emit('speed_changed', { speed });
411
+ }
412
+
413
+ /**
414
+ * Calcula delay entre pasos
415
+ */
416
+ calculateDelay(result) {
417
+ // Base delay de 500ms, ajustado por velocidad
418
+ const baseDelay = 500;
419
+ return baseDelay / this.config.speed;
420
+ }
421
+
422
+ /**
423
+ * Event emitter
424
+ */
425
+ on(event, callback) {
426
+ this.listeners.add({ event, callback });
427
+ return () => this.listeners.delete({ event, callback });
428
+ }
429
+
430
+ emit(event, data) {
431
+ for (const listener of this.listeners) {
432
+ if (listener.event === event) {
433
+ listener.callback(data);
434
+ }
435
+ }
436
+ }
437
+
438
+ sleep(ms) {
439
+ return new Promise(resolve => setTimeout(resolve, ms));
440
+ }
441
+ }
442
+ ```
443
+
444
+ ### 3. What-If Analyzer
445
+
446
+ Analizador de escenarios alternativos.
447
+
448
+ ```javascript
449
+ /**
450
+ * WhatIfAnalyzer
451
+ * Analiza escenarios alternativos ("what-if")
452
+ */
453
+ class WhatIfAnalyzer {
454
+ constructor(timelineManager, flowEngine) {
455
+ this.timeline = timelineManager;
456
+ this.flowEngine = flowEngine;
457
+ this.scenarios = new Map();
458
+ }
459
+
460
+ /**
461
+ * Crea un escenario what-if desde un punto
462
+ */
463
+ async createScenario(name, options = {}) {
464
+ const { fromPosition, alternativeDecision, alternativeInputs } = options;
465
+
466
+ // Crear branch
467
+ await this.timeline.jumpTo(fromPosition);
468
+ await this.timeline.createBranch(`whatif_${name}`);
469
+
470
+ const scenario = {
471
+ id: `scenario_${Date.now()}`,
472
+ name,
473
+ createdAt: new Date().toISOString(),
474
+ branchPoint: fromPosition,
475
+ originalDecision: this.timeline.timeline[fromPosition],
476
+ alternativeDecision,
477
+ alternativeInputs,
478
+ status: 'created',
479
+ results: null
480
+ };
481
+
482
+ this.scenarios.set(scenario.id, scenario);
483
+
484
+ return scenario;
485
+ }
486
+
487
+ /**
488
+ * Ejecuta un escenario what-if
489
+ */
490
+ async runScenario(scenarioId) {
491
+ const scenario = this.scenarios.get(scenarioId);
492
+
493
+ if (!scenario) {
494
+ throw new Error(`Scenario ${scenarioId} not found`);
495
+ }
496
+
497
+ scenario.status = 'running';
498
+ scenario.startedAt = new Date().toISOString();
499
+
500
+ try {
501
+ // Restaurar estado en branch point
502
+ const state = await this.timeline.checkpointManager.getStateAt(
503
+ this.timeline.timeline[scenario.branchPoint].checkpointId
504
+ );
505
+
506
+ // Aplicar decisión/inputs alternativos
507
+ const modifiedState = this.applyAlternatives(state, scenario);
508
+
509
+ // Ejecutar flow desde ese punto
510
+ const result = await this.flowEngine.executeFromState(modifiedState, {
511
+ branchName: `whatif_${scenario.name}`,
512
+ dryRun: false
513
+ });
514
+
515
+ scenario.status = 'completed';
516
+ scenario.completedAt = new Date().toISOString();
517
+ scenario.results = result;
518
+
519
+ return scenario;
520
+
521
+ } catch (error) {
522
+ scenario.status = 'failed';
523
+ scenario.error = error.message;
524
+ throw error;
525
+ }
526
+ }
527
+
528
+ /**
529
+ * Aplica alternativas al estado
530
+ */
531
+ applyAlternatives(state, scenario) {
532
+ const modified = JSON.parse(JSON.stringify(state));
533
+
534
+ if (scenario.alternativeDecision) {
535
+ // Reemplazar decisión
536
+ modified.decisions = modified.decisions || [];
537
+ modified.decisions.push({
538
+ original: scenario.originalDecision,
539
+ alternative: scenario.alternativeDecision,
540
+ appliedAt: new Date().toISOString()
541
+ });
542
+ }
543
+
544
+ if (scenario.alternativeInputs) {
545
+ // Merge inputs alternativos
546
+ modified.variables = {
547
+ ...modified.variables,
548
+ ...scenario.alternativeInputs
549
+ };
550
+ }
551
+
552
+ return modified;
553
+ }
554
+
555
+ /**
556
+ * Compara dos escenarios
557
+ */
558
+ async compareScenarios(scenarioId1, scenarioId2) {
559
+ const s1 = this.scenarios.get(scenarioId1);
560
+ const s2 = this.scenarios.get(scenarioId2);
561
+
562
+ if (!s1 || !s2) {
563
+ throw new Error('One or both scenarios not found');
564
+ }
565
+
566
+ if (s1.status !== 'completed' || s2.status !== 'completed') {
567
+ throw new Error('Both scenarios must be completed');
568
+ }
569
+
570
+ return {
571
+ scenario1: {
572
+ id: s1.id,
573
+ name: s1.name,
574
+ decision: s1.alternativeDecision || 'original'
575
+ },
576
+ scenario2: {
577
+ id: s2.id,
578
+ name: s2.name,
579
+ decision: s2.alternativeDecision || 'original'
580
+ },
581
+ comparison: {
582
+ filesCreated: this.compareLists(
583
+ s1.results.filesCreated,
584
+ s2.results.filesCreated
585
+ ),
586
+ filesModified: this.compareLists(
587
+ s1.results.filesModified,
588
+ s2.results.filesModified
589
+ ),
590
+ duration: {
591
+ scenario1: s1.results.duration,
592
+ scenario2: s2.results.duration,
593
+ difference: s2.results.duration - s1.results.duration
594
+ },
595
+ success: {
596
+ scenario1: s1.results.success,
597
+ scenario2: s2.results.success
598
+ },
599
+ errors: {
600
+ scenario1: s1.results.errors?.length || 0,
601
+ scenario2: s2.results.errors?.length || 0
602
+ }
603
+ }
604
+ };
605
+ }
606
+
607
+ /**
608
+ * Compara dos listas
609
+ */
610
+ compareLists(list1, list2) {
611
+ const set1 = new Set(list1?.map(f => f.path || f) || []);
612
+ const set2 = new Set(list2?.map(f => f.path || f) || []);
613
+
614
+ return {
615
+ onlyIn1: [...set1].filter(x => !set2.has(x)),
616
+ onlyIn2: [...set2].filter(x => !set1.has(x)),
617
+ inBoth: [...set1].filter(x => set2.has(x))
618
+ };
619
+ }
620
+
621
+ /**
622
+ * Lista todos los escenarios
623
+ */
624
+ listScenarios() {
625
+ return Array.from(this.scenarios.values()).map(s => ({
626
+ id: s.id,
627
+ name: s.name,
628
+ status: s.status,
629
+ branchPoint: s.branchPoint,
630
+ createdAt: s.createdAt
631
+ }));
632
+ }
633
+ }
634
+ ```
635
+
636
+ ---
637
+
638
+ ## Interfaz de Usuario
639
+
640
+ ### Timeline Visualization
641
+
642
+ ```
643
+ ╔══════════════════════════════════════════════════════════════════════════╗
644
+ ║ TIME-TRAVEL DEBUGGER ║
645
+ ╠══════════════════════════════════════════════════════════════════════════╣
646
+ ║ ║
647
+ ║ TIMELINE (Branch: main) ║
648
+ ║ ═══════════════════════════════════════════════════════════════════ ║
649
+ ║ ║
650
+ ║ [1]──[2]──[3]──[4]──[5]──[6]──[7]──►[8] ║
651
+ ║ │ │ │ │ │ │ │ │ ║
652
+ ║ │ │ │ │ │ │ │ └─ Current: Review complete ║
653
+ ║ │ │ │ │ │ │ └─────── Implementation done ║
654
+ ║ │ │ │ │ │ └──────────── Tests written ║
655
+ ║ │ │ │ │ └───────────────── Code generated ║
656
+ ║ │ │ │ └────────────────────── Plan approved ║
657
+ ║ │ │ └─────────────────────────── Analysis complete ║
658
+ ║ │ └──────────────────────────────── Started analysis ║
659
+ ║ └───────────────────────────────────── Session started ║
660
+ ║ ║
661
+ ║ Position: 8/8 (latest) ║
662
+ ║ ║
663
+ ╠══════════════════════════════════════════════════════════════════════════╣
664
+ ║ CONTROLS ║
665
+ ║ [◄◄] First [◄] Back [▶] Forward [►►] Last [▶▶] Play [⏸] Pause ║
666
+ ║ ║
667
+ ║ BRANCHES ║
668
+ ║ • main (active) - 8 checkpoints ║
669
+ ║ • whatif_different_auth - 5 checkpoints (branched from #4) ║
670
+ ║ ║
671
+ ╠══════════════════════════════════════════════════════════════════════════╣
672
+ ║ CHECKPOINT #8 DETAILS ║
673
+ ║ ┌────────────────────────────────────────────────────────────────────┐ ║
674
+ ║ │ Event: PHASE_COMPLETE │ ║
675
+ ║ │ Phase: review │ ║
676
+ ║ │ Timestamp: 2024-01-20T15:45:32.123Z │ ║
677
+ ║ │ Duration since start: 2m 34s │ ║
678
+ ║ │ │ ║
679
+ ║ │ State: │ ║
680
+ ║ │ • Files created: 3 │ ║
681
+ ║ │ • Files modified: 2 │ ║
682
+ ║ │ • Tests: 12 passing │ ║
683
+ ║ │ • Review: approved │ ║
684
+ ║ └────────────────────────────────────────────────────────────────────┘ ║
685
+ ║ ║
686
+ ╚══════════════════════════════════════════════════════════════════════════╝
687
+ ```
688
+
689
+ ### Comparison View
690
+
691
+ ```
692
+ ╔══════════════════════════════════════════════════════════════════════════╗
693
+ ║ SCENARIO COMPARISON ║
694
+ ╠══════════════════════════════════════════════════════════════════════════╣
695
+ ║ ║
696
+ ║ Scenario A: Original (NextAuth) │ Scenario B: Alternative (Clerk) ║
697
+ ║ ───────────────────────────────── │ ─────────────────────────────────║
698
+ ║ │ ║
699
+ ║ Decision at checkpoint #4: │ Decision at checkpoint #4: ║
700
+ ║ "Use NextAuth.js for auth" │ "Use Clerk for auth" ║
701
+ ║ │ ║
702
+ ║ Files Created: 5 │ Files Created: 3 ║
703
+ ║ • src/auth/[...nextauth].ts │ • src/middleware.ts ║
704
+ ║ • src/auth/providers.ts │ • src/lib/clerk.ts ║
705
+ ║ • src/auth/callbacks.ts │ • src/components/ClerkProvider.tsx║
706
+ ║ • src/lib/auth.ts │ ║
707
+ ║ • src/types/next-auth.d.ts │ ║
708
+ ║ │ ║
709
+ ║ Duration: 45s │ Duration: 28s ║
710
+ ║ Tests: 8 passing │ Tests: 5 passing ║
711
+ ║ Complexity: Medium │ Complexity: Low ║
712
+ ║ │ ║
713
+ ╠══════════════════════════════════════════════════════════════════════════╣
714
+ ║ ANALYSIS ║
715
+ ║ • Clerk approach is 38% faster to implement ║
716
+ ║ • NextAuth has more flexibility but more boilerplate ║
717
+ ║ • Clerk has better DX but vendor lock-in ║
718
+ ╚══════════════════════════════════════════════════════════════════════════╝
719
+ ```
720
+
721
+ ---
722
+
723
+ ## Comandos de Usuario
724
+
725
+ ### /elsabro:timetravel
726
+
727
+ ```bash
728
+ /elsabro:timetravel show # Mostrar timeline actual
729
+ /elsabro:timetravel goto <position> # Saltar a posición
730
+ /elsabro:timetravel back # Retroceder un paso
731
+ /elsabro:timetravel forward # Avanzar un paso
732
+ /elsabro:timetravel replay [from] [to] # Replay de rango
733
+ /elsabro:timetravel branch <name> # Crear branch alternativo
734
+ /elsabro:timetravel branches # Listar branches
735
+ /elsabro:timetravel switch <branch> # Cambiar de branch
736
+ /elsabro:timetravel whatif <name> # Crear escenario what-if
737
+ /elsabro:timetravel compare <s1> <s2> # Comparar escenarios
738
+ /elsabro:timetravel diff <cp1> <cp2> # Diff entre checkpoints
739
+ ```
740
+
741
+ ---
742
+
743
+ ## Integración con Checkpointing
744
+
745
+ El sistema de time-travel se construye sobre el sistema de checkpointing existente:
746
+
747
+ ```javascript
748
+ // Inicialización
749
+ const checkpointManager = new CheckpointManager();
750
+ const timelineManager = new TimelineManager(checkpointManager);
751
+ const replayEngine = new ReplayEngine(timelineManager);
752
+ const whatIfAnalyzer = new WhatIfAnalyzer(timelineManager, flowEngine);
753
+
754
+ // Construir timeline desde sesión
755
+ await timelineManager.buildTimeline(sessionId);
756
+
757
+ // Navegar
758
+ await timelineManager.jumpTo(5);
759
+ await timelineManager.stepBackward();
760
+
761
+ // Replay
762
+ await replayEngine.startReplay({ from: 0, to: 10 });
763
+
764
+ // What-if analysis
765
+ const scenario = await whatIfAnalyzer.createScenario('try_clerk', {
766
+ fromPosition: 4,
767
+ alternativeDecision: 'Use Clerk instead of NextAuth'
768
+ });
769
+ await whatIfAnalyzer.runScenario(scenario.id);
770
+ ```
771
+
772
+ ---
773
+
774
+ ## Configuración
775
+
776
+ ### .planning/timetravel-config.json
777
+
778
+ ```json
779
+ {
780
+ "timeTravel": {
781
+ "enabled": true,
782
+ "maxTimelineLength": 1000,
783
+ "maxBranches": 10,
784
+ "replay": {
785
+ "defaultSpeed": 1.0,
786
+ "pauseOnDecision": true,
787
+ "pauseOnError": true,
788
+ "autoPlay": false
789
+ },
790
+ "whatIf": {
791
+ "enabled": true,
792
+ "maxScenarios": 20,
793
+ "autoCompare": true
794
+ },
795
+ "visualization": {
796
+ "showTimestamps": true,
797
+ "showDurations": true,
798
+ "compactMode": false
799
+ }
800
+ }
801
+ }
802
+ ```