File size: 3,342 Bytes
34367da
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/**

 * ProjectMemory - In-memory project lifecycle tracking

 *

 * Uses in-memory storage for development.

 * In production, events are also sent to Neo4j via EventBus.

 */

import { eventBus } from '../../mcp/EventBus.js';

export interface LifecycleEvent {
    id?: number;
    eventType: 'build' | 'test' | 'deploy' | 'feature' | 'other';
    status: 'success' | 'failure' | 'in_progress';
    details: any;
    createdAt?: string;
}

export interface ProjectFeature {
    id?: number;
    name: string;
    description: string;
    status: 'planned' | 'in_progress' | 'completed' | 'deprecated';
    createdAt?: string;
    updatedAt?: string;
}

class ProjectMemoryService {
    private events: LifecycleEvent[] = [];
    private features: Map<string, ProjectFeature> = new Map();
    private eventIdCounter = 1;
    private featureIdCounter = 1;

    constructor() {
        this.setupEventListeners();
        console.log('📚 ProjectMemory initialized (in-memory mode)');
    }

    private setupEventListeners() {
        // Listen for system alerts and log them as 'other' events
        eventBus.onEvent('system.alert', (event) => {
            this.logLifecycleEvent({
                eventType: 'other',
                status: 'failure', // Alerts are usually bad
                details: { source: 'system.alert', payload: event.payload }
            });
        });
    }

    public logLifecycleEvent(event: LifecycleEvent): void {
        const now = new Date().toISOString();
        const newEvent: LifecycleEvent = {
            ...event,
            id: this.eventIdCounter++,
            createdAt: now
        };

        this.events.unshift(newEvent); // Add to front for newest-first ordering

        // Keep only last 1000 events in memory
        if (this.events.length > 1000) {
            this.events = this.events.slice(0, 1000);
        }

        console.log(`[ProjectMemory] Logged event: ${event.eventType} - ${event.status}`);
    }

    public getLifecycleEvents(limit = 50): LifecycleEvent[] {
        return this.events.slice(0, limit);
    }

    public addFeature(feature: ProjectFeature): void {
        const now = new Date().toISOString();
        const newFeature: ProjectFeature = {
            ...feature,
            id: this.featureIdCounter++,
            createdAt: now,
            updatedAt: now
        };

        this.features.set(feature.name, newFeature);
        console.log(`[ProjectMemory] Added feature: ${feature.name}`);
    }

    public getFeatures(): ProjectFeature[] {
        return Array.from(this.features.values())
            .sort((a, b) => (b.updatedAt || '').localeCompare(a.updatedAt || ''));
    }

    public updateFeatureStatus(name: string, status: ProjectFeature['status']): void {
        const existing = this.features.get(name);

        if (existing) {
            existing.status = status;
            existing.updatedAt = new Date().toISOString();
        } else {
            this.addFeature({
                name,
                description: name,
                status
            });
        }

        console.log(`[ProjectMemory] Updated feature ${name} to ${status}`);
    }
}

export const projectMemory = new ProjectMemoryService();