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!
200 lines
7.0 KiB
JavaScript
200 lines
7.0 KiB
JavaScript
#!/usr/bin/env node
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// EOS Dependency Budget — Precis som prestandabudgetar
|
|
// Erik-krav: "Om någon PR ökar komplexiteten bryter EOS budgeten"
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
import { readFileSync, existsSync } from 'fs';
|
|
import { execSync } from 'child_process';
|
|
|
|
const REGISTRY_PATH = '/home/bernt/.openclaw/workspace/EOS/capability-registry.json';
|
|
|
|
class DependencyBudget {
|
|
constructor() {
|
|
this.capabilities = this.loadCapabilities();
|
|
}
|
|
|
|
loadCapabilities() {
|
|
if (existsSync(REGISTRY_PATH)) {
|
|
return JSON.parse(readFileSync(REGISTRY_PATH, 'utf8'));
|
|
}
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* Analysera en PR mot dependency-budget
|
|
*/
|
|
analyzePR(pr) {
|
|
console.log(`🔍 Analyserar PR: ${pr.title}\n`);
|
|
|
|
const results = [];
|
|
let totalViolations = 0;
|
|
|
|
for (const file of pr.files) {
|
|
const cap = this.findCapabilityForFile(file);
|
|
if (!cap) continue;
|
|
|
|
const analysis = this.analyzeFile(file, cap);
|
|
results.push(analysis);
|
|
|
|
if (!analysis.withinBudget) {
|
|
totalViolations++;
|
|
}
|
|
}
|
|
|
|
const report = {
|
|
pr: pr.title,
|
|
totalFiles: pr.files.length,
|
|
analyzedFiles: results.length,
|
|
violations: totalViolations,
|
|
results
|
|
};
|
|
|
|
this.printReport(report);
|
|
return report;
|
|
}
|
|
|
|
findCapabilityForFile(file) {
|
|
// Matcha fil mot capability baserat på sökväg
|
|
for (const cap of this.capabilities) {
|
|
for (const service of cap.services) {
|
|
if (file.includes(service.toLowerCase().replace(' ', '-'))) {
|
|
return cap;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
analyzeFile(file, cap) {
|
|
// Simulera analys av fil
|
|
const currentDeps = cap.dependencies.length;
|
|
const newDeps = this.countNewDependencies(file);
|
|
const currentApis = cap.apis.filter(a => a.includes('stripe') || a.includes('external')).length;
|
|
const newApis = this.countNewExternalApis(file);
|
|
|
|
const totalDeps = currentDeps + newDeps;
|
|
const totalApis = currentApis + newApis;
|
|
|
|
const withinBudget =
|
|
totalDeps <= cap.budget.maxDirectDeps &&
|
|
totalApis <= cap.budget.maxExternalApis;
|
|
|
|
return {
|
|
file,
|
|
capability: cap.name,
|
|
currentDeps,
|
|
newDeps,
|
|
totalDeps,
|
|
maxDeps: cap.budget.maxDirectDeps,
|
|
currentApis,
|
|
newApis,
|
|
totalApis,
|
|
maxApis: cap.budget.maxExternalApis,
|
|
withinBudget,
|
|
issues: []
|
|
.concat(totalDeps > cap.budget.maxDirectDeps
|
|
? [`För många beroenden: ${totalDeps}/${cap.budget.maxDirectDeps}`]
|
|
: [])
|
|
.concat(totalApis > cap.budget.maxExternalApis
|
|
? [`För många externa API:er: ${totalApis}/${cap.budget.maxExternalApis}`]
|
|
: [])
|
|
};
|
|
}
|
|
|
|
countNewDependencies(file) {
|
|
// Simulering — i verkligheten skulle detta analysera import-satser
|
|
return 0;
|
|
}
|
|
|
|
countNewExternalApis(file) {
|
|
// Simulering — i verkligheten skulle detta analysera API-anrop
|
|
return 0;
|
|
}
|
|
|
|
printReport(report) {
|
|
console.log('╔═══════════════════════════════════════════════════════════════╗');
|
|
console.log('║ DEPENDENCY BUDGET ║');
|
|
console.log('║ PR-analys ║');
|
|
console.log('╚═══════════════════════════════════════════════════════════════╝');
|
|
console.log();
|
|
|
|
console.log(`📊 PR: ${report.pr}\n`);
|
|
console.log(` Filer: ${report.totalFiles}`);
|
|
console.log(` Analyserade: ${report.analyzedFiles}`);
|
|
console.log(` Överträdelser: ${report.violations}\n`);
|
|
|
|
for (const result of report.results) {
|
|
const icon = result.withinBudget ? '✅' : '🔴';
|
|
console.log(`${icon} ${result.file}`);
|
|
console.log(` Capability: ${result.capability}`);
|
|
console.log(` Beroenden: ${result.totalDeps}/${result.maxDeps}`);
|
|
console.log(` Externa API:er: ${result.totalApis}/${result.maxApis}`);
|
|
|
|
if (!result.withinBudget) {
|
|
console.log(' 🔴 Överträdelser:');
|
|
for (const issue of result.issues) {
|
|
console.log(` • ${issue}`);
|
|
}
|
|
}
|
|
|
|
console.log();
|
|
}
|
|
|
|
if (report.violations > 0) {
|
|
console.log('🔴 BUDGET ÖVERSKRIDEN\n');
|
|
console.log(' PR:en kan inte mergeas utan att budgeten justeras eller');
|
|
console.log(' komplexiteten minskas.\n');
|
|
} else {
|
|
console.log('✅ BUDGET RESPEKTERAD\n');
|
|
console.log(' PR:en är inom budget.\n');
|
|
}
|
|
|
|
console.log('═══════════════════════════════════════════════════════════════\n');
|
|
}
|
|
|
|
/**
|
|
* Visa budget-status för alla capabilities
|
|
*/
|
|
showBudgetStatus() {
|
|
console.log('💰 DEPENDENCY BUDGET — Status\n');
|
|
|
|
for (const cap of this.capabilities) {
|
|
const depCount = cap.dependencies.length;
|
|
const apiCount = cap.apis.filter(a => a.includes('stripe') || a.includes('external')).length;
|
|
|
|
const depStatus = depCount > cap.budget.maxDirectDeps ? '🔴' :
|
|
depCount > cap.budget.maxDirectDeps * 0.8 ? '⚠️' : '✅';
|
|
const apiStatus = apiCount > cap.budget.maxExternalApis ? '🔴' :
|
|
apiCount > cap.budget.maxExternalApis * 0.8 ? '⚠️' : '✅';
|
|
|
|
console.log(`${depStatus}${apiStatus} ${cap.name}`);
|
|
console.log(` Beroenden: ${depCount}/${cap.budget.maxDirectDeps}`);
|
|
console.log(` Externa API:er: ${apiCount}/${cap.budget.maxExternalApis}`);
|
|
console.log();
|
|
}
|
|
}
|
|
}
|
|
|
|
// ── Main ──────────────────────────────────────────────────────────────────
|
|
|
|
const budget = new DependencyBudget();
|
|
const command = process.argv[2] || '--status';
|
|
|
|
if (command === '--status') {
|
|
budget.showBudgetStatus();
|
|
} else if (command === '--analyze') {
|
|
const pr = {
|
|
title: process.argv[3] || 'Lägg till Stripe-integration',
|
|
files: process.argv.slice(4).length > 0 ? process.argv.slice(4) : [
|
|
'src/services/payment/stripe-adapter.ts',
|
|
'src/services/mission/mission-service.ts'
|
|
]
|
|
};
|
|
budget.analyzePR(pr);
|
|
} else {
|
|
console.log('Användning:');
|
|
console.log(' node dependency-budget.mjs --status # Visa budget-status');
|
|
console.log(' node dependency-budget.mjs --analyze <pr-title> [files...] # Analysera PR');
|
|
}
|