File size: 3,739 Bytes
33f2414
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import fs from 'fs';
import path from 'path';
import { EventEmitter } from 'events';

// DEFINITION: Path to the Single Source of Truth
// Assuming running from apps/backend/src or similar structure in Docker
const HANDOVER_LOG_PATH = path.join(process.cwd(), '..', '..', 'docs', 'HANDOVER_LOG.md');

export class HandoverWatchdog extends EventEmitter {
    private static instance: HandoverWatchdog;
    private isWatching: boolean = false;
    private lastProcessedTime: number = 0;

    private constructor() {
        super();
    }

    public static getInstance(): HandoverWatchdog {
        if (!HandoverWatchdog.instance) {
            HandoverWatchdog.instance = new HandoverWatchdog();
        }
        return HandoverWatchdog.instance;
    }

    /**
     * Starts the surveillance of the Blackboard Protocol.
     */
    public startWatch(): void {
        if (this.isWatching) {
            console.log('πŸ‘οΈ [WATCHDOG] Already active.');
            return;
        }

        console.log(`πŸ‘οΈ [WATCHDOG] Initializing Blackboard Protocol surveillance...`);
        console.log(`πŸ“ [WATCHDOG] Target: ${HANDOVER_LOG_PATH}`);

        // Verify existence of the Truth Document
        if (!fs.existsSync(HANDOVER_LOG_PATH)) {
            console.warn(`⚠️ [WATCHDOG] Critical Failure: Handover log not found at ${HANDOVER_LOG_PATH}`);
            // Retry logic could be added here, but for now we warn
            return;
        }

        try {
            // We use watchFile for better Docker volume compatibility than fs.watch
            fs.watchFile(HANDOVER_LOG_PATH, { interval: 2000 }, (curr, prev) => {
                // Only trigger if modified time changed and it's newer than last process
                if (curr.mtimeMs !== prev.mtimeMs) {
                    console.log('⚑ [WATCHDOG] Detect: Blackboard updated. Analyzing...');
                    this.analyzeBlackboard();
                }
            });

            this.isWatching = true;
            console.log('🟒 [WATCHDOG] Active and Waiting for Signals.');
        } catch (error) {
            console.error('❌ [WATCHDOG] Failed to initialize:', error);
        }
    }

    /**
     * Reads the Blackboard and looks for "READY FOR [AGENT]" signals.
     */
    private analyzeBlackboard(): void {
        try {
            const content = fs.readFileSync(HANDOVER_LOG_PATH, 'utf-8');

            // REGEX LOGIC:
            // We look for: **Status:** [BOLD/EMOJI?] READY FOR [AGENT_NAME]
            // Captures the agent name. Case insensitive.
            const statusRegex = /\*\*Status:\*\*\s*(?:βœ…|πŸ”΄|🟒|\*\*)?\s*READY FOR\s*\[?(.*?)\]?/i;

            // We only scan the last 2000 characters to be efficient
            const recentContent = content.slice(-2000);
            const match = statusRegex.exec(recentContent);

            if (match && match[1]) {
                const targetAgent = match[1].trim().replace(/\*|\]|\[/g, ''); // Cleanup cleanup

                console.log(`πŸš€ [WATCHDOG] SIGNAL VERIFIED: Handover to Agent [${targetAgent}]`);

                // Emit the signal for the Orchestrator to pick up
                this.emit('handover_signal', {
                    target: targetAgent,
                    timestamp: new Date(),
                    source: 'Blackboard'
                });
            } else {
                // Debug log to confirm scan happened (can be removed later for silence)
                // console.log('πŸ” [WATCHDOG] Scanned. No active handover signal found.');
            }

        } catch (error) {
            console.error('❌ [WATCHDOG] Read error:', error);
        }
    }
}

export const handoverWatchdog = HandoverWatchdog.getInstance();