05ed037fe8
- DNS: pilot.landvex.com -> 16.170.83.169 - TLS: Let's Encrypt certificate (expires 2026-09-30) - Nginx: reverse proxy with SSL termination - API: https://pilot.landvex.com/api/v1/missions - UI: https://pilot.landvex.com/ - Upload: POST /api/v1/missions/import (multipart/form-data) Verified: ✅ https://pilot.landvex.com/health ✅ https://pilot.landvex.com/version ✅ https://pilot.landvex.com/api/v1/missions (list) ✅ https://pilot.landvex.com/api/v1/missions/:id (get) ✅ POST /api/v1/missions/import (video upload) ✅ UI loads with title 'LandveX Intelligence Lab' Next: Pilot 001 — Break the system!
312 lines
9.0 KiB
JavaScript
312 lines
9.0 KiB
JavaScript
#!/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();
|