export class UnifiedOrchestrator {
    results = [];
    findings = [];
    listeners = new Set();
    onEvent(callback) {
        this.listeners.add(callback);
        return () => this.listeners.delete(callback);
    }
    emit(event) {
        for (const cb of this.listeners) {
            try {
                cb(event);
            }
            catch {
                // Ignore listener failures to avoid breaking orchestration
            }
        }
    }
    async execute(config) {
        const start = Date.now();
        const report = this.generateReport(config.objective ?? '');
        const end = Date.now();
        return {
            ...report,
            id: report.id ?? `report-${start}`,
            objective: config.objective ?? '',
            startTime: start,
            endTime: end,
            duration: end - start,
        };
    }
    generateReport(objective) {
        const dedupedFindings = [];
        const recSet = new Set();
        const seen = new Map();
        for (const finding of this.findings) {
            const key = `${finding.title}|${finding.recommendation ?? ''}`;
            const existing = seen.get(key);
            if (existing) {
                const evidence = [
                    ...(Array.isArray(existing.evidence) ? existing.evidence : existing.evidence ? [existing.evidence] : []),
                    ...(Array.isArray(finding.evidence) ? finding.evidence : finding.evidence ? [finding.evidence] : []),
                ];
                existing.evidence = Array.from(new Set(evidence));
                continue;
            }
            const clone = { ...finding };
            seen.set(key, clone);
            dedupedFindings.push(clone);
            if (clone.recommendation) {
                recSet.add(clone.recommendation);
            }
        }
        // Derive recommendations if none are present
        if (recSet.size === 0) {
            const lower = objective.toLowerCase();
            if (lower.includes('ml') || lower.includes('model') || lower.includes('train')) {
                recSet.add('Validate model outputs against a held-out set');
                recSet.add('Document evaluation metrics and risks');
            }
            else if (lower.includes('research') || lower.includes('cure')) {
                recSet.add('Peer review findings with a subject-matter expert');
                recSet.add('Validate data provenance and ethics approvals');
            }
            else {
                recSet.add('Review results with a teammate');
                recSet.add('Verify outputs and rerun if needed');
            }
        }
        const failedCommands = this.results.filter((r) => r && !r.success);
        const hasCritical = dedupedFindings.some((f) => f.severity === 'critical');
        let exitReason = 'success';
        let success = true;
        if (failedCommands.length) {
            exitReason = 'failed-commands';
            success = false;
        }
        else if (hasCritical) {
            exitReason = 'critical-findings';
            success = false;
        }
        const statusSummary = [
            `${this.results.length} command(s)`,
            failedCommands.length ? `${failedCommands.length} failed` : 'all passed',
            dedupedFindings.length ? `${dedupedFindings.length} finding(s)` : 'no findings',
        ].join(' | ');
        return {
            id: `report-${Date.now()}`,
            objective,
            startTime: Date.now(),
            endTime: Date.now(),
            duration: 0,
            results: this.results.slice(),
            findings: dedupedFindings,
            recommendations: Array.from(recSet),
            summary: statusSummary,
            success,
            exitReason,
            statusSummary,
        };
    }
}
//# sourceMappingURL=unifiedOrchestrator.js.map