/**
 * Operation Log Service
 *
 * Provides persistent, queryable operation logs for observability.
 * Writes structured log entries to the operation_log SQLite table so that
 * events survive session restarts and can be queried later via the CLI.
 *
 * Categories:
 * - dispatch: Task dispatch events, poll errors
 * - session: Session spawn/terminate/failure
 * - merge: Test results, merge outcomes
 * - rate-limit: Rate limit detection and recovery
 * - steward: Steward execution events
 * - recovery: Orphan recovery events
 *
 * @module
 */
// ============================================================================
// Types
// ============================================================================
/**
 * Log levels for operation log entries
 */
export const OperationLogLevel = {
    INFO: 'info',
    WARN: 'warn',
    ERROR: 'error',
};
/**
 * Categories for operation log entries
 */
export const OperationLogCategory = {
    DISPATCH: 'dispatch',
    MERGE: 'merge',
    SESSION: 'session',
    RATE_LIMIT: 'rate-limit',
    STEWARD: 'steward',
    RECOVERY: 'recovery',
};
// ============================================================================
// Implementation
// ============================================================================
/**
 * Generate a unique ID for an operation log entry.
 * Format: oplog-{timestamp}-{random}
 */
function generateLogId() {
    const ts = Date.now().toString(36);
    const rand = Math.random().toString(36).slice(2, 8);
    return `oplog-${ts}-${rand}`;
}
/**
 * Creates an OperationLogService backed by the given StorageBackend.
 *
 * @param storage - The SQLite storage backend with the operation_log table
 * @returns An OperationLogService instance
 */
export function createOperationLogService(storage) {
    return {
        write(level, category, message, details) {
            const id = generateLogId();
            const timestamp = new Date().toISOString();
            const agentId = details?.agentId ?? null;
            const taskId = details?.taskId ?? null;
            // Build a clean details object without agentId/taskId (they have their own columns)
            let detailsJson = null;
            if (details) {
                const { agentId: _a, taskId: _t, ...rest } = details;
                if (Object.keys(rest).length > 0) {
                    detailsJson = JSON.stringify(rest);
                }
            }
            storage.run(`INSERT INTO operation_log (id, timestamp, level, category, agent_id, task_id, message, details)
         VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [id, timestamp, level, category, agentId, taskId, message, detailsJson]);
        },
        query(filters = {}) {
            const conditions = [];
            const params = [];
            if (filters.level) {
                conditions.push('level = ?');
                params.push(filters.level);
            }
            if (filters.category) {
                conditions.push('category = ?');
                params.push(filters.category);
            }
            if (filters.since) {
                conditions.push('timestamp >= ?');
                params.push(filters.since);
            }
            if (filters.taskId) {
                conditions.push('task_id = ?');
                params.push(filters.taskId);
            }
            if (filters.agentId) {
                conditions.push('agent_id = ?');
                params.push(filters.agentId);
            }
            const limit = filters.limit ?? 20;
            const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
            const rows = storage.query(`SELECT id, timestamp, level, category, agent_id, task_id, message, details
         FROM operation_log
         ${whereClause}
         ORDER BY timestamp DESC
         LIMIT ?`, [...params, limit]);
            return rows.map((row) => ({
                id: row.id,
                timestamp: row.timestamp,
                level: row.level,
                category: row.category,
                agentId: row.agent_id ?? undefined,
                taskId: row.task_id ?? undefined,
                message: row.message,
                details: row.details ? JSON.parse(row.details) : undefined,
            }));
        },
    };
}
//# sourceMappingURL=operation-log-service.js.map