/**
 * Bollharness Integration for Bolloon
 *
 * Main integration class that combines:
 * - Gate State Machine (8-gate workflow governance)
 * - Guard Checker (code quality checks)
 * - Context Router (automatic context injection)
 * - Skill Adapter (bollharness skills in Bolloon)
 */
import { GateStateMachine } from './gate-state-machine.js';
import { GuardChecker, runGuards } from './guard-checker.js';
import { ContextRouter } from './context-router.js';
import { createSkillAdapter } from './skill-adapter.js';
/**
 * Main integration class
 */
export class BollharnessIntegration {
    config;
    gateMachine;
    guardChecker;
    contextRouter;
    skillAdapter;
    sessionArchives = [];
    currentSessionId = '';
    constructor(config = {}) {
        this.config = {
            enabled: config.enabled ?? true,
            guardsEnabled: config.guardsEnabled ?? true,
            contextEnabled: config.contextEnabled ?? true,
            skillsEnabled: config.skillsEnabled ?? true,
            gatesEnabled: config.gatesEnabled ?? true,
        };
        this.gateMachine = new GateStateMachine();
        this.guardChecker = new GuardChecker();
        this.contextRouter = new ContextRouter();
        this.skillAdapter = createSkillAdapter();
    }
    /**
     * Process a file edit with all enabled checks
     */
    async processFileEdit(filePath) {
        const errors = [];
        let guards;
        let context;
        // Run guards if enabled
        if (this.config.guardsEnabled) {
            try {
                guards = await runGuards(filePath);
                if (!guards.passed) {
                    errors.push(...guards.findings.map(f => f.message));
                }
            }
            catch (error) {
                errors.push(`Guard check failed: ${error}`);
            }
        }
        // Get context fragments if enabled
        if (this.config.contextEnabled) {
            try {
                context = this.contextRouter.match(filePath);
            }
            catch (error) {
                errors.push(`Context routing failed: ${error}`);
            }
        }
        return {
            success: errors.length === 0,
            guards,
            context,
            errors,
        };
    }
    /**
     * Check file before edit (pre-check)
     */
    async preEditCheck(filePath) {
        const errors = [];
        let guards;
        if (this.config.guardsEnabled) {
            try {
                guards = await runGuards(filePath);
                if (!guards.passed && guards.blockingCount > 0) {
                    errors.push(...guards.findings
                        .filter(f => f.blocking)
                        .map(f => `BLOCKING: ${f.message}`));
                }
            }
            catch (error) {
                errors.push(`Pre-check failed: ${error}`);
            }
        }
        return {
            success: errors.length === 0,
            guards,
            errors,
        };
    }
    /**
     * Get context for a file
     */
    getContext(filePath) {
        if (!this.config.contextEnabled) {
            return '';
        }
        return this.contextRouter.getContext(filePath);
    }
    /**
     * Get fragments for a file
     */
    getFragments(filePath) {
        return this.contextRouter.match(filePath);
    }
    // ==================== Gate Methods ====================
    /**
     * Get current gate state
     */
    getCurrentGate() {
        return this.gateMachine.getCurrentGate();
    }
    /**
     * Get gate pack for output
     */
    getGatePack() {
        return this.gateMachine.getGatePack();
    }
    /**
     * Submit artifact to current gate
     */
    submitGateArtifact(name, artifact) {
        this.gateMachine.submitArtifact(name, artifact);
    }
    /**
     * Attempt gate transition
     */
    async transitionGate(reviewResult) {
        const transition = await this.gateMachine.transition(reviewResult);
        return {
            success: transition.blockers.length === 0,
            transition,
        };
    }
    /**
     * Classify change type
     */
    classifyChange(description) {
        const isPolicy = description.includes('policy') || description.includes('boundary');
        const isContract = description.includes('API') || description.includes('contract');
        const isImplementation = !isPolicy && !isContract;
        return {
            classification: isPolicy ? 'policy' : isContract ? 'contract' : 'implementation',
            minimum_gates: isPolicy ? '0→8' : isContract ? '0→8' : '0→7',
            fast_track: isImplementation,
        };
    }
    // ==================== Skill Methods ====================
    /**
     * Execute a bollharness skill
     */
    async executeSkill(skillName, params) {
        try {
            const result = await this.skillAdapter.executeSkill(skillName, params);
            return { success: true, result };
        }
        catch (error) {
            return { success: false, error: String(error) };
        }
    }
    /**
     * List available skills
     */
    listSkills() {
        return this.skillAdapter.listSkills().map(s => ({
            name: s.name,
            description: s.description,
        }));
    }
    /**
     * Get skill registry
     */
    getSkillAdapter() {
        return this.skillAdapter;
    }
    /**
     * List harness-native skills (metadata from SKILL.md files)
     */
    listHarnessSkills() {
        return this.skillAdapter.listHarnessSkills().map(s => ({
            name: s.name,
            description: s.description,
            tier: s.tier,
        }));
    }
    // ==================== Configuration Methods ====================
    /**
     * Update configuration
     */
    updateConfig(config) {
        this.config = { ...this.config, ...config };
    }
    /**
     * Get current configuration
     */
    getConfig() {
        return { ...this.config };
    }
    /**
     * Enable/disable specific checks
     */
    enableCheck(checkName) {
        this.guardChecker.enableCheck(checkName);
    }
    disableCheck(checkName) {
        this.guardChecker.disableCheck(checkName);
    }
    // ==================== Metrics ====================
    /**
     * Get integration metrics
     */
    getMetrics() {
        return {
            config: this.config,
            currentGate: this.gateMachine.getCurrentGate(),
            enabledChecks: 'multiple',
            availableSkills: this.skillAdapter.listSkills().length,
            sessionArchives: this.sessionArchives.length,
        };
    }
    // ==================== Session Archive Methods ====================
    /**
     * Archive current session operations with compression
     */
    archiveSession(logs, options) {
        const id = `session_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
        const gate = this.gateMachine.getCurrentGate();
        const compressed = this.compressLogs(logs);
        const summary = options?.summary || this.generateSessionSummary(logs);
        const keyDecisions = options?.keyDecisions || this.extractKeyDecisions(logs);
        const archive = {
            id,
            timestamp: Date.now(),
            gate,
            summary,
            actionCount: logs.length,
            compressed,
            keyDecisions,
        };
        this.sessionArchives.push(archive);
        this.currentSessionId = id;
        return archive;
    }
    /**
     * Compress logs by removing redundancy
     */
    compressLogs(logs) {
        if (logs.length === 0)
            return '';
        const lines = [];
        const seenActions = new Set();
        const recentTime = logs.length > 10 ? logs[logs.length - 10].timestamp : logs[0].timestamp;
        lines.push(`## Session Archive (${logs.length} actions)`);
        lines.push(`Gate: ${this.gateMachine.getCurrentGate()}`);
        lines.push('');
        for (const log of logs.slice(-50)) {
            const time = new Date(log.timestamp).toISOString();
            const action = log.action.padEnd(30);
            if (seenActions.has(log.action) && log.status === 'ok') {
                lines.push(`  ${time} [RPT] ${action}`);
            }
            else {
                lines.push(`  ${time} [${log.status.padEnd(4)}] ${action}`);
                seenActions.add(log.action);
            }
            if (log.timestamp < recentTime) {
                lines.push(`    ^ ${log.details ? JSON.stringify(log.details).substring(0, 100) : ''}`);
            }
        }
        return lines.join('\n');
    }
    /**
     * Generate a brief summary of the session
     */
    generateSessionSummary(logs) {
        const actions = logs.map(l => l.action);
        const unique = [...new Set(actions)];
        const okCount = logs.filter(l => l.status === 'ok').length;
        return `${this.gateMachine.getCurrentGate()}G: ${unique.slice(0, 3).join(', ')}${unique.length > 3 ? '...' : ''} (${okCount}/${logs.length} OK)`;
    }
    /**
     * Extract key decisions from logs
     */
    extractKeyDecisions(logs) {
        const decisions = [];
        for (const log of logs) {
            if (log.action.includes('decision') || log.action.includes('approve') || log.action.includes('commit')) {
                decisions.push(log.action);
            }
        }
        return decisions.slice(0, 10);
    }
    /**
     * Get session context for skills
     */
    getSessionContext(sessionId) {
        if (sessionId) {
            const archive = this.sessionArchives.find(a => a.id === sessionId);
            if (archive) {
                return `## Session ${archive.id}\nGate: ${archive.gate}\n${archive.compressed}`;
            }
        }
        if (this.sessionArchives.length === 0) {
            return 'No session archives available.';
        }
        const recent = this.sessionArchives.slice(-3);
        const lines = ['## Recent Sessions'];
        for (const archive of recent) {
            lines.push(`\n### ${archive.id}`);
            lines.push(`Gate: ${archive.gate} | Actions: ${archive.actionCount}`);
            lines.push(`Summary: ${archive.summary}`);
            if (archive.keyDecisions.length > 0) {
                lines.push(`Decisions: ${archive.keyDecisions.join(', ')}`);
            }
        }
        return lines.join('\n');
    }
    /**
     * Get all session archives
     */
    getSessionArchives() {
        return [...this.sessionArchives];
    }
    /**
     * Start a new session
     */
    startNewSession() {
        this.currentSessionId = `session_${Date.now()}`;
        return this.currentSessionId;
    }
    /**
     * Link current harness session to Pi SDK session
     */
    linkSession(sessionId) {
        this.currentSessionId = sessionId;
    }
}
/**
 * Create a default integration instance
 */
export function createBollharnessIntegration(config) {
    return new BollharnessIntegration(config);
}
/**
 * Integration hooks for Bolloon's execution pipeline
 */
export class BollharnessHooks {
    integration;
    constructor(integration) {
        this.integration = integration || new BollharnessIntegration();
    }
    /**
     * Pre-tool-use hook
     */
    async preToolUse(context) {
        // Check for dangerous operations
        if (context.tool === 'Bash') {
            const cmd = context.input?.command;
            if (cmd?.includes('rm -rf') || cmd?.includes('sudo')) {
                return {
                    allowed: false,
                    blockReason: 'Dangerous command detected',
                };
            }
        }
        // Check guards if file is being edited
        if (context.filePath && ['Edit', 'Write'].includes(context.tool)) {
            const result = await this.integration.preEditCheck(context.filePath);
            if (!result.success) {
                return {
                    allowed: false,
                    findings: result.guards?.findings.map(f => ({
                        severity: f.severity,
                        message: f.message,
                    })),
                    blockReason: 'Guard checks failed',
                };
            }
        }
        return { allowed: true };
    }
    /**
     * Post-tool-use hook
     */
    async postToolUse(context) {
        if (!context.filePath) {
            return { allowed: true };
        }
        const result = await this.integration.processFileEdit(context.filePath);
        return {
            allowed: result.success,
            context: result.context,
            findings: result.guards?.findings.map(f => ({
                severity: f.severity,
                message: f.message,
            })),
        };
    }
    /**
     * Session start hook
     */
    async sessionStart() {
        // Reset state if needed
        console.log('[Bollharness] Session started with governance enabled');
    }
    /**
     * Session end hook
     */
    async sessionEnd() {
        const metrics = this.integration.getMetrics();
        console.log('[Bollharness] Session ended', JSON.stringify(metrics, null, 2));
    }
}
