#!/usr/bin/env node // ═══════════════════════════════════════════════════════════════════════════ // Release Gate — Verifierar att alla kriterier är uppfyllda före release // ═══════════════════════════════════════════════════════════════════════════ import { detectArchitectureDrift } from './architecture-drift.mjs'; import { readFileSync, readdirSync } from 'fs'; const RELEASE_CRITERIA = { version: '1.0', required: [ 'runtimeContract', 'policyLayer', 'decisionReplay', 'goldenFailures', 'ciIntegration', 'regressionSuite', 'architectureDrift', 'runtimeDrift', 'decisionCorrectness', 'policyRobustness' ] }; /** * Verifiera Runtime Contract */ function verifyRuntimeContract() { try { const contract = readFileSync('./RUNTIME-CONTRACT.md', 'utf8'); const hasInvariants = contract.includes('Runtime Invariants'); const hasReleaseLevels = contract.includes('Release Nivåer'); return { name: 'Runtime Contract', passed: hasInvariants && hasReleaseLevels, details: hasInvariants && hasReleaseLevels ? 'Contract verified' : 'Missing required sections' }; } catch (error) { return { name: 'Runtime Contract', passed: false, details: `Error: ${error.message}` }; } } /** * Verifiera Policy Layer */ function verifyPolicyLayer() { try { const registry = readFileSync('./policy-registry.mjs', 'utf8'); const hasPolicies = registry.includes('POL-'); const hasVersioning = registry.includes('version'); return { name: 'Policy Layer', passed: hasPolicies && hasVersioning, details: hasPolicies ? 'Policy registry found' : 'No policies found' }; } catch (error) { return { name: 'Policy Layer', passed: false, details: `Error: ${error.message}` }; } } /** * Verifiera Decision Replay */ function verifyDecisionReplay() { try { const replay = readFileSync('./decision-replay.mjs', 'utf8'); const hasRecord = replay.includes('recordDecision'); const hasReplay = replay.includes('replay'); return { name: 'Decision Replay', passed: hasRecord && hasReplay, details: hasRecord && hasReplay ? 'Replay system verified' : 'Missing replay functions' }; } catch (error) { return { name: 'Decision Replay', passed: false, details: `Error: ${error.message}` }; } } /** * Verifiera Golden Failures */ function verifyGoldenFailures() { try { const failures = JSON.parse(readFileSync('./golden-failures.json', 'utf8')); const hasFailures = failures.failures && failures.failures.length > 0; const hasPrinciples = failures.principles && failures.principles.length > 0; return { name: 'Golden Failures', passed: hasFailures && hasPrinciples, details: hasFailures ? `${failures.failures.length} golden failures documented` : 'No golden failures found' }; } catch (error) { return { name: 'Golden Failures', passed: false, details: `Error: ${error.message}` }; } } /** * Verifiera CI-integration */ function verifyCIIntegration() { try { const ci = readFileSync('./ci-config.yml', 'utf8'); const hasWorkflows = ci.includes('runtime-regression') && ci.includes('policy-regression') && ci.includes('decision-replay'); return { name: 'CI Integration', passed: hasWorkflows, details: hasWorkflows ? 'CI configuration verified' : 'Missing required workflows' }; } catch (error) { return { name: 'CI Integration', passed: false, details: `Error: ${error.message}` }; } } /** * Verifiera Regression Suite */ function verifyRegressionSuite() { try { const suite = readFileSync('./regression-suite.mjs', 'utf8'); const hasSafety = suite.includes('safety'); const hasBehaviour = suite.includes('behaviour'); const hasGolden = suite.includes('golden'); return { name: 'Regression Suite', passed: hasSafety && hasBehaviour && hasGolden, details: hasSafety && hasBehaviour && hasGolden ? 'All test categories found' : 'Missing test categories' }; } catch (error) { return { name: 'Regression Suite', passed: false, details: `Error: ${error.message}` }; } } /** * Verifiera Architecture Drift */ function verifyArchitectureDrift() { const result = detectArchitectureDrift('./agent-runtime-v10.mjs'); return { name: 'Architecture Drift', passed: result.passed, details: result.passed ? 'No drift detected' : `Drift: ${result.drift}` }; } /** * Verifiera Runtime Drift */ function verifyRuntimeDrift() { try { const logs = readdirSync('./stability-logs') .filter(f => f.startsWith('stability-') && f.endsWith('.json')) .sort(); if (logs.length < 2) { return { name: 'Runtime Drift', passed: true, details: 'Insufficient data (need 2+ days)' }; } const latest = JSON.parse(readFileSync(`./stability-logs/${logs[logs.length - 1]}`, 'utf8')); const previous = JSON.parse(readFileSync(`./stability-logs/${logs[logs.length - 2]}`, 'utf8')); const drift = latest.metrics.decisionCorrectness - previous.metrics.decisionCorrectness; return { name: 'Runtime Drift', passed: drift >= 0, details: `Drift: ${drift}% (latest: ${latest.metrics.decisionCorrectness}%, previous: ${previous.metrics.decisionCorrectness}%)` }; } catch (error) { return { name: 'Runtime Drift', passed: true, details: `No stability logs found: ${error.message}` }; } } /** * Verifiera Decision Correctness */ function verifyDecisionCorrectness() { try { const report = JSON.parse(readFileSync('./falsification-suite-report-v6.json', 'utf8')); const correctness = report.summary.overallDecisionCorrectness; return { name: 'Decision Correctness', passed: correctness >= 95, details: `${correctness}% (required: ≥95%)` }; } catch (error) { return { name: 'Decision Correctness', passed: false, details: `Error: ${error.message}` }; } } /** * Verifiera Policy Robustness */ function verifyPolicyRobustness() { try { const report = JSON.parse(readFileSync('./falsification-suite-report-v6.json', 'utf8')); const robustness = report.summary.overallRobustness; return { name: 'Policy Robustness', passed: robustness >= 95, details: `${robustness}% (required: ≥95%)` }; } catch (error) { return { name: 'Policy Robustness', passed: false, details: `Error: ${error.message}` }; } } /** * Huvudfunktion */ function runReleaseGate() { console.log('═══════════════════════════════════════════════════════════════'); console.log(' EOS RELEASE GATE'); console.log(` Version: ${RELEASE_CRITERIA.version}`); console.log('═══════════════════════════════════════════════════════════════\n'); const checks = [ verifyRuntimeContract(), verifyPolicyLayer(), verifyDecisionReplay(), verifyGoldenFailures(), verifyCIIntegration(), verifyRegressionSuite(), verifyArchitectureDrift(), verifyRuntimeDrift(), verifyDecisionCorrectness(), verifyPolicyRobustness() ]; let passed = 0; let failed = 0; for (const check of checks) { const status = check.passed ? '✅' : '❌'; console.log(`${status} ${check.name}`); console.log(` ${check.details}`); if (check.passed) { passed++; } else { failed++; } } console.log('\n═══════════════════════════════════════════════════════════════'); console.log(` RESULT: ${passed}/${checks.length} passed`); console.log('═══════════════════════════════════════════════════════════════'); if (failed > 0) { console.log('\n❌ POLICY LAYER RELEASE BLOCKED'); console.log(` ${failed} criteria not met`); process.exit(1); } else { console.log('\n✅ POLICY LAYER RELEASE APPROVED'); console.log(' Note: EOS Runtime (including Reasoning) is NOT yet released'); console.log(' Reasoning Gate R0 must be passed before full EOS Runtime release'); process.exit(0); } } runReleaseGate();