Files
boc/EOS/dependency-budget.mjs
T
Bernt 05ed037fe8 pilot.landvex.com: HTTPS + Full Stack Verified
- 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!
2026-07-02 17:34:19 +00:00

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');
}