"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConsequenceForecaster = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const crypto = __importStar(require("crypto"));
const AtomicWriter_1 = require("./util/AtomicWriter");
class ConsequenceForecaster {
    forecast(goal, governanceRisk, basePolicy, executors) {
        const normalizedGoal = goal.toLowerCase();
        const paths = [
            this.buildConservativePath(basePolicy, executors, governanceRisk, normalizedGoal),
            this.buildBalancedPath(basePolicy, executors, governanceRisk, normalizedGoal),
            this.buildAggressivePath(basePolicy, executors, governanceRisk, normalizedGoal)
        ];
        const selectedPath = this.pickBest(paths);
        const executiveSummary = this.buildExecutiveSummary(selectedPath, governanceRisk, normalizedGoal);
        const valueScores = this.scoreValues(selectedPath, governanceRisk, normalizedGoal);
        const horizons = this.buildHorizons(selectedPath, governanceRisk, normalizedGoal);
        return { selectedPath, consideredPaths: paths, executiveSummary, valueScores, horizons };
    }
    /**
     * Story 14.3 (v1.5) — Brain-enriched forecast with persistent cache.
     *
     * Calls `forecast()` first, then layers a Brain-derived
     * `BrainForecastEnrichment` on top (riskAmplifiers / opportunityFactors /
     * overallVerdict / rationale). The enrichment is cached at
     * `.openlife/forecasts/<sha256(goal)>.json` keyed by goalHash + governanceRisk
     * so repeated forecasts for the same goal don't burn tokens.
     *
     * Falls back gracefully:
     *   • Cache hit fresher than TTL (default 24h) → cached enrichment, source='cache'
     *   • Brain key absent → no enrichment attached; pure heuristic forecast
     *   • Brain available + parseable → fresh enrichment cached, source='brain'
     *   • Brain available + garbage → no enrichment attached
     *
     * Disable cache via OPENLIFE_FORECAST_CACHE=off. Custom TTL via
     * OPENLIFE_FORECAST_CACHE_TTL_HOURS.
     */
    async forecastWithBrain(goal, governanceRisk, basePolicy, executors) {
        const base = this.forecast(goal, governanceRisk, basePolicy, executors);
        const goalHash = crypto.createHash('sha256').update(goal).digest('hex');
        const cacheKey = `${goalHash}_${governanceRisk}`;
        const cached = this.readForecastCache(cacheKey);
        if (cached)
            return { ...base, brain: { ...cached, source: 'cache' } };
        try {
            // eslint-disable-next-line @typescript-eslint/no-var-requires
            const { Brain } = require('./Brain');
            const brain = new Brain();
            if (!brain.isAnyProviderAvailable())
                return base;
            const systemPrompt = [
                'You are a risk forecaster for an autonomous orchestrator.',
                'Given a mission goal, governance risk level, and selected execution path,',
                'output ONE LINE of JSON: { "riskAmplifiers": [string,...], "opportunityFactors": [string,...], "overallVerdict": "safe"|"caution"|"block", "rationale": string }',
                'Max 5 entries per array. No markdown, no preamble.',
            ].join(' ');
            const userMessage = [
                `Goal: ${goal}`,
                `Governance risk: ${governanceRisk}`,
                `Selected path: ${base.selectedPath.id} (${base.selectedPath.description})`,
                `Considered consequences: ${base.selectedPath.consequences.join(' | ')}`,
            ].join('\n');
            const raw = await brain.think(systemPrompt, userMessage);
            const parsed = this.parseBrainEnrichment(raw);
            if (!parsed)
                return base;
            const enrichment = { ...parsed, source: 'brain', cachedAt: new Date().toISOString() };
            this.writeForecastCache(cacheKey, enrichment);
            return { ...base, brain: enrichment };
        }
        catch {
            return base;
        }
    }
    parseBrainEnrichment(raw) {
        try {
            const start = raw.indexOf('{');
            const end = raw.lastIndexOf('}');
            if (start < 0 || end <= start)
                return null;
            const obj = JSON.parse(raw.slice(start, end + 1));
            const amp = Array.isArray(obj.riskAmplifiers)
                ? obj.riskAmplifiers.filter((s) => typeof s === 'string').slice(0, 5)
                : null;
            const opp = Array.isArray(obj.opportunityFactors)
                ? obj.opportunityFactors.filter((s) => typeof s === 'string').slice(0, 5)
                : null;
            const verdict = obj.overallVerdict === 'safe' || obj.overallVerdict === 'caution' || obj.overallVerdict === 'block'
                ? obj.overallVerdict
                : null;
            const rationale = typeof obj.rationale === 'string' ? obj.rationale.slice(0, 400) : '';
            if (!amp || !opp || !verdict)
                return null;
            return { riskAmplifiers: amp, opportunityFactors: opp, overallVerdict: verdict, rationale };
        }
        catch {
            return null;
        }
    }
    readForecastCache(cacheKey) {
        if (process.env.OPENLIFE_FORECAST_CACHE === 'off')
            return null;
        const file = this.cacheFile(cacheKey);
        if (!fs.existsSync(file))
            return null;
        try {
            const entry = JSON.parse(fs.readFileSync(file, 'utf-8'));
            const ttlHours = Number(process.env.OPENLIFE_FORECAST_CACHE_TTL_HOURS || 24);
            if (!entry.cachedAt)
                return null;
            const ageMs = Date.now() - new Date(entry.cachedAt).getTime();
            if (ageMs > ttlHours * 60 * 60 * 1000)
                return null;
            return entry;
        }
        catch {
            return null;
        }
    }
    writeForecastCache(cacheKey, entry) {
        if (process.env.OPENLIFE_FORECAST_CACHE === 'off')
            return;
        try {
            const file = this.cacheFile(cacheKey);
            fs.mkdirSync(path.dirname(file), { recursive: true });
            (0, AtomicWriter_1.writeJsonAtomic)(file, entry);
        }
        catch { /* non-fatal */ }
    }
    cacheFile(cacheKey) {
        const stateDir = process.env.OPENLIFE_STATE_DIR || path.join(process.cwd(), '.openlife');
        return path.join(stateDir, 'forecasts', `${cacheKey}.json`);
    }
    buildConservativePath(basePolicy, executors, risk, normalizedGoal) {
        const policy = {
            executionMode: 'balanced',
            swarmMode: 'none',
            maxBranches: 1,
            rationale: 'Conservador: minimizar risco de efeitos colaterais.'
        };
        const score = this.scorePath(risk, policy, executors, normalizedGoal, true);
        return {
            id: 'conservative',
            description: 'Executa com baixa superfície e validação estrita.',
            policy,
            executors,
            consequences: [
                'Reduz chance de bloqueio por governança',
                'Pode aumentar tempo total de execução',
                'Preserva previsibilidade do serviço'
            ],
            score
        };
    }
    buildBalancedPath(basePolicy, executors, risk, normalizedGoal) {
        const policy = {
            ...basePolicy,
            executionMode: 'balanced',
            swarmMode: basePolicy.swarmMode === 'consensus' ? 'parallel' : basePolicy.swarmMode,
            maxBranches: Math.max(1, Math.min(basePolicy.maxBranches, 3)),
            rationale: 'Balanceado: manter qualidade com risco controlado.'
        };
        const score = this.scorePath(risk, policy, executors, normalizedGoal, false) + 1;
        return {
            id: 'balanced',
            description: 'Combina execução robusta com fallback e revisão.',
            policy,
            executors,
            consequences: [
                'Boa relação entre velocidade e segurança',
                'Mantém chance alta de serviço completo',
                'Risco moderado de retrabalho'
            ],
            score
        };
    }
    buildAggressivePath(basePolicy, executors, risk, normalizedGoal) {
        const policy = {
            executionMode: 'performance',
            swarmMode: 'consensus',
            maxBranches: 4,
            rationale: 'Agressivo: maximizar throughput e paralelismo.'
        };
        const score = this.scorePath(risk, policy, executors, normalizedGoal, false) - 2;
        return {
            id: 'aggressive',
            description: 'Força paralelismo para velocidade máxima.',
            policy,
            executors,
            consequences: [
                'Aumenta velocidade em cenários favoráveis',
                'Eleva superfície de risco e custo',
                'Maior probabilidade de bloqueio em risco alto'
            ],
            score
        };
    }
    pickBest(paths) {
        return paths.reduce((best, current) => {
            if (current.score > best.score)
                return current;
            if (current.score < best.score)
                return best;
            const stabilityRank = {
                conservative: 3,
                balanced: 2,
                aggressive: 1
            };
            return stabilityRank[current.id] > stabilityRank[best.id] ? current : best;
        });
    }
    buildExecutiveSummary(selectedPath, risk, normalizedGoal) {
        const goalHint = this.goalBias(normalizedGoal);
        return `Rota escolhida: ${selectedPath.id}. Risk=${risk}. Viés do objetivo=${goalHint}. Consequências previstas: ${selectedPath.consequences.join(' | ')}`;
    }
    goalBias(normalizedGoal) {
        const speedTokens = ['deploy', 'urgente', 'hotfix', 'incident', 'performance', 'rápido', 'rapido'];
        const safetyTokens = ['prod', 'produção', 'producao', 'governança', 'governanca', 'compliance', 'security', 'segurança', 'seguranca'];
        const speed = speedTokens.some((token) => normalizedGoal.includes(token));
        const safety = safetyTokens.some((token) => normalizedGoal.includes(token));
        if (speed && !safety)
            return 'speed';
        if (safety)
            return 'safety';
        return 'neutral';
    }
    scoreValues(selectedPath, risk, normalizedGoal) {
        const safety = risk === 'high' && selectedPath.id === 'conservative' ? 9 : risk === 'high' ? 5 : 7;
        const usefulness = selectedPath.id === 'aggressive' ? 8 : selectedPath.id === 'balanced' ? 8 : 6;
        const reversibility = normalizedGoal.includes('delete') || normalizedGoal.includes('remove') || normalizedGoal.includes('produção') || normalizedGoal.includes('production') ? 5 : 8;
        const cost = selectedPath.policy.maxBranches > 2 ? 5 : 8;
        return [
            { criterion: 'safety', score: safety, rationale: 'Prioriza risco governado e superfície de execução.' },
            { criterion: 'usefulness', score: usefulness, rationale: 'Estima probabilidade de entregar valor útil ao usuário.' },
            { criterion: 'reversibility', score: reversibility, rationale: 'Avalia facilidade de desfazer ou pausar a ação.' },
            { criterion: 'cost', score: cost, rationale: 'Penaliza fan-out e paralelismo quando aumentam custo operacional.' },
        ];
    }
    buildHorizons(selectedPath, risk, normalizedGoal) {
        const safeAction = risk === 'high' ? 'exigir validação explícita antes de efeitos externos' : 'executar com validação padrão';
        return {
            now: { impact: `Rota ${selectedPath.id} selecionada; ${selectedPath.consequences[0]}.`, recommendedAction: safeAction, risk },
            '24h': { impact: 'Evidências e logs devem confirmar ausência de regressão operacional.', recommendedAction: 'revisar serviceEvidence e eventos de governança', risk: risk === 'low' ? 'low' : 'medium' },
            '7d': { impact: 'Padrões de falha ou retrabalho começam a aparecer nos KPIs do serviço.', recommendedAction: 'avaliar scorecard e ajustar capability/workflow se necessário', risk: 'medium' },
            '30d': { impact: 'Efeito acumulado em custo, confiabilidade e confiança do operador fica mensurável.', recommendedAction: 'promover, pausar ou refatorar a capacidade com base em evidência', risk: normalizedGoal.includes('production') || normalizedGoal.includes('produção') ? 'high' : 'medium' },
        };
    }
    scorePath(risk, policy, executors, normalizedGoal, conservative) {
        let score = 0;
        if (executors.length > 1)
            score += 2;
        if (policy.swarmMode === 'none')
            score += 1;
        if (policy.swarmMode === 'light')
            score += 1;
        if (policy.swarmMode === 'parallel')
            score += 1;
        if (policy.swarmMode === 'consensus')
            score -= 1;
        if (risk === 'high')
            score += conservative ? 4 : -3;
        if (risk === 'medium')
            score += conservative ? 1 : 0;
        if (risk === 'low')
            score += conservative ? 0 : 2;
        const bias = this.goalBias(normalizedGoal);
        if (bias === 'speed' && !conservative)
            score += 2;
        if (bias === 'safety' && conservative)
            score += 2;
        return score;
    }
}
exports.ConsequenceForecaster = ConsequenceForecaster;
