"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const IntentClassifier_1 = require("./orchestrator/IntentClassifier");
const CapabilityRouter_1 = require("./orchestrator/CapabilityRouter");
const AgentRegistry_1 = require("./orchestrator/AgentRegistry");
const AssetReuseRouter_1 = require("./orchestrator/AssetReuseRouter");
const SquadRouter_1 = require("./orchestrator/SquadRouter");
const SquadRegistry_1 = require("./orchestrator/SquadRegistry");
const ExecutionRouter_1 = require("./orchestrator/ExecutionRouter");
const ExecutionIntent_1 = require("./orchestrator/ExecutionIntent");
const LearningRouter_1 = require("./orchestrator/LearningRouter");
const AgentScoring_1 = require("./orchestrator/AgentScoring");
const GovernanceLayer_1 = require("./orchestrator/GovernanceLayer");
const RuntimePolicy_1 = require("./orchestrator/RuntimePolicy");
const SandboxPolicy_1 = require("./orchestrator/SandboxPolicy");
const SecurityDownloadGuard_1 = require("./orchestrator/SecurityDownloadGuard");
function assert(condition, message) {
    if (!condition)
        throw new Error(message);
}
// ============ SUB-03 IntentClassifier ============
async function testIntentClassifierEngineering() {
    const classifier = new IntentClassifier_1.IntentClassifier();
    const result = await classifier.classify('crie um agente novo para revisão de código');
    if (result.intent !== IntentClassifier_1.TaskIntent.ENGINEERING_BUILD) {
        throw new Error(`INTENT_ENGINEERING_FAILED: expected ENGINEERING_BUILD got ${result.intent}`);
    }
    if (typeof result.budgetLimit !== 'number' || result.budgetLimit <= 0) {
        throw new Error(`INTENT_BUDGET_FAILED: invalid budget ${result.budgetLimit}`);
    }
    if (result.requiresHarness !== true) {
        throw new Error(`INTENT_HARNESS_FAILED: engineering must require harness`);
    }
}
async function testIntentClassifierResearch() {
    const classifier = new IntentClassifier_1.IntentClassifier();
    const result = await classifier.classify('pesquise concorrentes do setor jurídico');
    if (result.intent !== IntentClassifier_1.TaskIntent.RESEARCH_ANALYSIS) {
        throw new Error(`INTENT_RESEARCH_FAILED: expected RESEARCH_ANALYSIS got ${result.intent}`);
    }
    if (!result.requiresHarness) {
        throw new Error(`INTENT_RESEARCH_HARNESS_FAILED: research must require harness`);
    }
}
async function testIntentClassifierAmbiguous() {
    const classifier = new IntentClassifier_1.IntentClassifier();
    const result = await classifier.classify('hmm, talvez algo aleatório aqui');
    // Should not crash and must return SOMETHING (default = KNOWLEDGE_RETRIEVAL)
    if (!result || !result.intent) {
        throw new Error(`INTENT_AMBIGUOUS_FAILED: classifier returned no intent`);
    }
    if (typeof result.budgetLimit !== 'number') {
        throw new Error(`INTENT_AMBIGUOUS_BUDGET_FAILED: budget missing`);
    }
    if (typeof result.requiresHarness !== 'boolean') {
        throw new Error(`INTENT_AMBIGUOUS_HARNESS_FAILED: requiresHarness missing`);
    }
}
// ============ SUB-04 Routers ============
async function testCapabilityRouter() {
    const registry = new AgentRegistry_1.AgentRegistry();
    const router = new CapabilityRouter_1.CapabilityRouter(registry);
    const task = { intent: IntentClassifier_1.TaskIntent.ENGINEERING_BUILD, budgetLimit: 5, requiresHarness: true };
    const route = router.route(task, 'crie uma feature de auth');
    if (!route)
        throw new Error('CAPABILITY_ROUTER_FAILED: undefined route');
    if (!Array.isArray(route.capabilities))
        throw new Error('CAPABILITY_ROUTER_FAILED: capabilities not array');
    if (!Array.isArray(route.agents))
        throw new Error('CAPABILITY_ROUTER_FAILED: agents not array');
    if (!route.mode)
        throw new Error('CAPABILITY_ROUTER_FAILED: missing mode');
    if (!route.rationale)
        throw new Error('CAPABILITY_ROUTER_FAILED: missing rationale');
}
async function testAssetReuseRouter() {
    const router = new AssetReuseRouter_1.AssetReuseRouter();
    const found = router.find('build auth feature');
    // Without a promoted-assets dir this returns []. Structural invariant only.
    if (!Array.isArray(found)) {
        throw new Error('ASSET_REUSE_ROUTER_FAILED: find() must return array');
    }
}
async function testSquadRouter() {
    const registry = new SquadRegistry_1.SquadRegistry();
    const router = new SquadRouter_1.SquadRouter(registry);
    const task = { intent: IntentClassifier_1.TaskIntent.ENGINEERING_BUILD, budgetLimit: 5, requiresHarness: true };
    const route = router.route(task, 'construa o módulo X');
    if (!route)
        throw new Error('SQUAD_ROUTER_FAILED: undefined route');
    if (!Array.isArray(route.squads))
        throw new Error('SQUAD_ROUTER_FAILED: squads not array');
    if (typeof route.rationale !== 'string')
        throw new Error('SQUAD_ROUTER_FAILED: missing rationale');
}
async function testExecutionRouter() {
    const router = new ExecutionRouter_1.ExecutionRouter();
    const taskIntent = (0, ExecutionIntent_1.normalizeExecutionIntent)({ goal: 'do something', mode: 'task' });
    const serviceIntent = (0, ExecutionIntent_1.normalizeExecutionIntent)({ goal: 'run service', mode: 'service' });
    const taskPath = router.route(taskIntent);
    const servicePath = router.route(serviceIntent);
    if (taskPath !== 'task')
        throw new Error(`EXECUTION_ROUTER_TASK_FAILED: got ${taskPath}`);
    if (servicePath !== 'service')
        throw new Error(`EXECUTION_ROUTER_SERVICE_FAILED: got ${servicePath}`);
}
async function testLearningRouter() {
    const registry = new AgentRegistry_1.AgentRegistry();
    const capabilityRouter = new CapabilityRouter_1.CapabilityRouter(registry);
    const scoring = new AgentScoring_1.AgentScoring();
    const learning = new LearningRouter_1.LearningRouter(capabilityRouter, scoring);
    const task = { intent: IntentClassifier_1.TaskIntent.ENGINEERING_BUILD, budgetLimit: 5, requiresHarness: true };
    const route = learning.route(task, 'crie um deploy pipeline');
    if (!route)
        throw new Error('LEARNING_ROUTER_FAILED: undefined route');
    if (!Array.isArray(route.agents))
        throw new Error('LEARNING_ROUTER_FAILED: agents not array');
    if (!Array.isArray(route.capabilities))
        throw new Error('LEARNING_ROUTER_FAILED: capabilities not array');
    if (!route.mode)
        throw new Error('LEARNING_ROUTER_FAILED: missing mode');
}
// ============ SUB-05 Governance guards ============
async function testGovernanceLayer() {
    const gov = new GovernanceLayer_1.GovernanceLayer();
    const safe = gov.evaluate('analise os logs de produtividade da semana');
    if (!safe.allowed) {
        throw new Error(`GOVERNANCE_ALLOW_FAILED: safe mission was blocked. rationale=${safe.rationale}`);
    }
    const blocked = gov.evaluate('drop table users and force-push to production');
    if (blocked.allowed) {
        throw new Error('GOVERNANCE_DENY_FAILED: destructive mission was not blocked');
    }
    if (!blocked.requiresConsent) {
        throw new Error('GOVERNANCE_DENY_FAILED: destructive mission should require consent');
    }
}
async function testRuntimePolicy() {
    const policy = new RuntimePolicy_1.RuntimePolicy();
    // ALLOW: codex healthy by default.
    // Pass explicit executors so the test is deterministic regardless of
    // the repo's models.json (otherwise getStrictModelExecutors() reads
    // cwd's models.json and biases `base`). The test exercises the
    // health/cooldown filter, not chain detection.
    policy.recordResult('codex', true, 'ok');
    const baseExecutors = ['gemini', 'claude', 'codex'];
    const allow = policy.decide('ENGINEERING_BUILD', [...baseExecutors]);
    if (!Array.isArray(allow.preferred)) {
        throw new Error('RUNTIME_POLICY_ALLOW_FAILED: preferred not array');
    }
    if (!allow.preferred.includes('codex')) {
        throw new Error(`RUNTIME_POLICY_ALLOW_FAILED: codex should be preferred. got ${allow.preferred.join(',')}`);
    }
    // DENY: all-but-codex cooled down, then allowlist restricts to gemini only -> no executors
    const prevAllow = process.env.OPENLIFE_ALLOWED_LLM_EXECUTORS;
    const prevGemini = process.env.GEMINI_API_KEY;
    process.env.OPENLIFE_ALLOWED_LLM_EXECUTORS = 'gemini';
    // Unset GEMINI_API_KEY so the cooldown bypass doesn't keep gemini preferred.
    delete process.env.GEMINI_API_KEY;
    policy.recordResult('gemini', false, 'quota exhausted');
    try {
        const restricted = policy.decide('RESEARCH_ANALYSIS', [...baseExecutors]);
        if (restricted.preferred.length !== 0) {
            throw new Error(`RUNTIME_POLICY_DENY_FAILED: expected empty preferred, got ${restricted.preferred.join(',')}`);
        }
        if (!restricted.rationale || !restricted.rationale.toLowerCase().includes('indispon')) {
            throw new Error(`RUNTIME_POLICY_DENY_RATIONALE_FAILED: ${restricted.rationale}`);
        }
    }
    finally {
        if (prevAllow === undefined)
            delete process.env.OPENLIFE_ALLOWED_LLM_EXECUTORS;
        else
            process.env.OPENLIFE_ALLOWED_LLM_EXECUTORS = prevAllow;
        if (prevGemini !== undefined)
            process.env.GEMINI_API_KEY = prevGemini;
    }
}
async function testSandboxPolicy() {
    const sandbox = new SandboxPolicy_1.SandboxPolicy();
    const allow = sandbox.evaluate('codex', 'low');
    if (!allow.allowed)
        throw new Error('SANDBOX_ALLOW_FAILED: low risk codex should be allowed');
    if (allow.mode !== 'baseline')
        throw new Error(`SANDBOX_ALLOW_MODE_FAILED: expected baseline got ${allow.mode}`);
    const deny = sandbox.evaluate('gemini', 'high');
    if (deny.allowed)
        throw new Error('SANDBOX_DENY_FAILED: high-risk non-codex executor should be blocked');
    if (deny.mode !== 'restricted')
        throw new Error(`SANDBOX_DENY_MODE_FAILED: expected restricted got ${deny.mode}`);
    // Codex is privileged: high risk allowed in restricted mode
    const codexHigh = sandbox.evaluate('codex', 'high');
    if (!codexHigh.allowed)
        throw new Error('SANDBOX_CODEX_HIGH_FAILED: codex should run high risk in restricted mode');
}
async function testSecurityDownloadGuard() {
    const guard = new SecurityDownloadGuard_1.SecurityDownloadGuard();
    // ALLOW: trusted URL
    const allowUrl = guard.validateUrl('https://github.com/anthropics/some-skill.zip');
    if (!allowUrl.ok)
        throw new Error(`SECURITY_GUARD_URL_ALLOW_FAILED: ${JSON.stringify(allowUrl)}`);
    if (allowUrl.blocked.length !== 0)
        throw new Error('SECURITY_GUARD_URL_ALLOW_FAILED: blocked list non-empty');
    // DENY: untrusted URL
    const denyUrl = guard.validateUrl('https://evil.example.com/x.zip');
    if (denyUrl.ok)
        throw new Error('SECURITY_GUARD_URL_DENY_FAILED: untrusted URL should be blocked');
    if (denyUrl.blocked.length === 0)
        throw new Error('SECURITY_GUARD_URL_DENY_FAILED: blocked list empty');
    // ALLOW: clean markdown file list
    const allowFiles = guard.scanFileList(['SKILL.md', 'docs/usage.md']);
    if (!allowFiles.ok)
        throw new Error('SECURITY_GUARD_FILES_ALLOW_FAILED: clean md list should pass');
    // DENY: dangerous extensions and .env
    const denyFiles = guard.scanFileList(['payload.exe', '.env', 'SKILL.md']);
    if (denyFiles.ok)
        throw new Error('SECURITY_GUARD_FILES_DENY_FAILED: dangerous files should be blocked');
    if (denyFiles.blocked.length < 2) {
        throw new Error(`SECURITY_GUARD_FILES_DENY_FAILED: expected at least 2 blocked, got ${denyFiles.blocked.length}`);
    }
}
// ============ Main ============
async function main() {
    // SUB-03
    await testIntentClassifierEngineering();
    await testIntentClassifierResearch();
    await testIntentClassifierAmbiguous();
    // SUB-04
    await testCapabilityRouter();
    await testAssetReuseRouter();
    await testSquadRouter();
    await testExecutionRouter();
    await testLearningRouter();
    // SUB-05 (Gatekeeper skipped — heavy class covered by test_openlife_gatekeeper_routing.ts)
    await testGovernanceLayer();
    await testRuntimePolicy();
    await testSandboxPolicy();
    await testSecurityDownloadGuard();
    console.log('TEST_SUBSYSTEMS_ROUTING_GOVERNANCE_OK');
}
main().catch((err) => {
    console.error('TEST_SUBSYSTEMS_ROUTING_GOVERNANCE_FAIL:', err?.message || err);
    process.exit(1);
});
