Files
boc/SIL/failure-review.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

288 lines
9.7 KiB
JavaScript

#!/usr/bin/env node
// ═══════════════════════════════════════════════════════════════════════════
// SIL Failure Review — Klassificera varje fel
// Erik-krav: "Varje gång SIL har fel ska ni inte bara logga det. Ni ska klassificera felet."
// ═══════════════════════════════════════════════════════════════════════════
import { readFileSync, writeFileSync, existsSync, appendFileSync } from 'fs';
const FAILURE_LOG = '/home/bernt/.openclaw/workspace/SIL/validation/failure-log.jsonl';
/**
* Feltyper som SIL kan göra
*/
const FAILURE_TYPES = {
KNOWLEDGE_ERROR: {
description: 'Grafen saknade en relation',
example: 'SIL visste inte att Wallet påverkar Payout',
action: 'Uppdatera kunskapsgrafen'
},
PARSING_ERROR: {
description: 'AST missade en import',
example: 'SIL såg inte att filen importerade Stripe',
action: 'Förbättra AST-parser'
},
RUNTIME_DRIFT: {
description: 'Driftmiljön skiljde sig från modellen',
example: 'Produktion hade en feature flag som grafen inte kände till',
action: 'Uppdatera observer'
},
POLICY_ERROR: {
description: 'Arkitekturregel felaktigt formulerad',
example: 'Regeln var för strikt och flaggade giltig kod',
action: 'Justera arkitekturpolicy'
},
LLM_ERROR: {
description: 'Felaktig inferens',
example: 'SIL drog fel slutsats från korrekt data',
action: 'Förbättra resonemangsmodell'
},
CONFIDENCE_ERROR: {
description: 'För hög confidence trots svag evidens',
example: 'SIL sa 95% confidence men hade fel',
action: 'Kalibrera om confidence-modell'
},
OBSERVATION_ERROR: {
description: 'Felaktig eller ofullständig observation',
example: 'Git diff missade en fil',
action: 'Förbättra observer'
},
REASONING_ERROR: {
description: 'Felaktigt resonemang från korrekt data',
example: 'Korrekt data men fel slutsats',
action: 'Granska resonemangsregler'
}
};
class FailureReview {
constructor() {
this.failures = this.loadFailures();
}
loadFailures() {
if (!existsSync(FAILURE_LOG)) return [];
return readFileSync(FAILURE_LOG, 'utf8')
.split('\n')
.filter(line => line.trim())
.map(line => {
try { return JSON.parse(line); } catch { return null; }
})
.filter(Boolean);
}
/**
* Logga ett nytt fel med klassificering
*/
logFailure(failure) {
const entry = {
timestamp: new Date().toISOString(),
analysisId: failure.analysisId,
pr: failure.pr,
// Vad SIL sa
silPrediction: failure.silPrediction,
silConfidence: failure.silConfidence,
// Vad som var sant
actualOutcome: failure.actualOutcome,
// Klassificering
failureType: failure.failureType,
failureTypeDescription: FAILURE_TYPES[failure.failureType]?.description,
// Kontext
component: failure.component,
evidence: failure.evidence,
// Root cause
rootCause: failure.rootCause,
// Åtgärd
action: failure.action || FAILURE_TYPES[failure.failureType]?.action,
// Allvarlighet
severity: failure.severity || 'MEDIUM',
// Lärande
lesson: failure.lesson
};
appendFileSync(FAILURE_LOG, JSON.stringify(entry) + '\n', 'utf8');
console.log(`✅ Fel loggat: ${failure.failureType}`);
console.log(` ${FAILURE_TYPES[failure.failureType]?.description}`);
console.log(` Åtgärd: ${entry.action}\n`);
return entry;
}
/**
* Analysera felmönster
*/
analyzePatterns() {
const byType = {};
const byComponent = {};
const bySeverity = {};
for (const failure of this.failures) {
// Per typ
byType[failure.failureType] = (byType[failure.failureType] || 0) + 1;
// Per komponent
if (failure.component) {
byComponent[failure.component] = (byComponent[failure.component] || 0) + 1;
}
// Per allvarlighet
bySeverity[failure.severity] = (bySeverity[failure.severity] || 0) + 1;
}
return {
total: this.failures.length,
byType: Object.entries(byType)
.sort((a, b) => b[1] - a[1])
.map(([type, count]) => ({
type,
count,
percentage: Math.round(count / this.failures.length * 100) + '%',
description: FAILURE_TYPES[type]?.description,
action: FAILURE_TYPES[type]?.action
})),
byComponent: Object.entries(byComponent)
.sort((a, b) => b[1] - a[1])
.slice(0, 10)
.map(([component, count]) => ({ component, count })),
bySeverity
};
}
/**
* Generera rapport
*/
generateReport() {
const patterns = this.analyzePatterns();
const report = {
timestamp: new Date().toISOString(),
totalFailures: patterns.total,
patterns,
// Dominant feltyp
dominantFailure: patterns.byType[0],
// Rekommendationer
recommendations: this.generateRecommendations(patterns)
};
this.printReport(report);
return report;
}
generateRecommendations(patterns) {
const recs = [];
// Om en feltyp dominerar → prioritera den
if (patterns.byType.length > 0) {
const dominant = patterns.byType[0];
if (parseFloat(dominant.percentage) > 30) {
recs.push({
priority: 'HIGH',
issue: `${dominant.type} dominerar (${dominant.percentage})`,
action: dominant.action
});
}
}
// Om vissa komponenter har många fel → granska dem
for (const comp of patterns.byComponent.slice(0, 3)) {
if (comp.count > 3) {
recs.push({
priority: 'MEDIUM',
issue: `Komponent ${comp.component} har ${comp.count} fel`,
action: `Granska och uppdatera graf för ${comp.component}`
});
}
}
return recs;
}
printReport(report) {
console.log('╔═══════════════════════════════════════════════════════════════╗');
console.log('║ FAILURE REVIEW ║');
console.log('║ Klassificering av SIL:s fel ║');
console.log('╚═══════════════════════════════════════════════════════════════╝');
console.log();
console.log(`📊 TOTALT: ${report.totalFailures} fel\n`);
console.log('📋 PER TYP\n');
for (const type of report.patterns.byType) {
console.log(` ${type.count}x ${type.type}`);
console.log(` ${type.description}`);
console.log(` ${type.percentage} av alla fel`);
console.log(` Åtgärd: ${type.action}`);
console.log();
}
console.log('📋 PER KOMPONENT (top 10)\n');
for (const comp of report.patterns.byComponent) {
console.log(` ${comp.component}: ${comp.count} fel`);
}
console.log();
console.log('📋 PER ALLVARLIGHET\n');
for (const [sev, count] of Object.entries(report.patterns.bySeverity)) {
console.log(` ${sev}: ${count}`);
}
console.log();
if (report.recommendations.length > 0) {
console.log('💡 REKOMMENDATIONER\n');
for (const rec of report.recommendations) {
const icon = rec.priority === 'HIGH' ? '🔴' : '🟡';
console.log(` ${icon} [${rec.priority}] ${rec.issue}`);
console.log(`${rec.action}`);
}
console.log();
}
console.log('═══════════════════════════════════════════════════════════════\n');
}
/**
* Lista alla feltyper
*/
listTypes() {
console.log('📋 FELTYPER\n');
for (const [type, info] of Object.entries(FAILURE_TYPES)) {
console.log(` ${type}:`);
console.log(` ${info.description}`);
console.log(` Exempel: ${info.example}`);
console.log(` Åtgärd: ${info.action}`);
console.log();
}
}
}
// ── Main ──────────────────────────────────────────────────────────────────
const review = new FailureReview();
const command = process.argv[2] || '--report';
if (command === '--report') {
review.generateReport();
} else if (command === '--log') {
// Exempel på att logga ett fel
const failure = {
analysisId: process.argv[3] || 'unknown',
pr: process.argv[4] || 'PR-123',
silPrediction: process.argv[5] || 'Wallet påverkar inte Payout',
silConfidence: 0.85,
actualOutcome: 'Wallet påverkar Payout',
failureType: process.argv[6] || 'KNOWLEDGE_ERROR',
component: process.argv[7] || 'wallet',
evidence: 'Git diff visade ändring i payout.ts',
rootCause: 'Grafen saknade kant Wallet → Payout',
severity: 'HIGH',
lesson: 'Måste uppdatera graf när nya beroenden läggs till'
};
review.logFailure(failure);
} else if (command === '--types') {
review.listTypes();
} else {
console.log('Användning:');
console.log(' node failure-review.mjs --report # Generera rapport');
console.log(' node failure-review.mjs --log <id> <pr> <pred> <type> <comp> # Logga fel');
console.log(' node failure-review.mjs --types # Lista feltyper');
}