snapkitty
agents
python
holy-agents / src /twins /performance.ts
SNAPKITTYWEST's picture
push from SNAPKITTYWEST/holy-agents
662ceed verified
Raw History Blame Contribute Delete
2.68 kB
import type { TwinAudit, Finding } from './types.js';
export function auditPerformance(sourceFiles: { name: string; content: string }[]): TwinAudit {
const findings: Finding[] = [];
let idCounter = 0;
for (const file of sourceFiles) {
const lines = file.content.split('\n');
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (/while\s*\(\s*true\s*\)/.test(line) && !line.includes('break')) {
findings.push({
id: `PERF-${String(++idCounter).padStart(3, '0')}`,
severity: 'high',
category: 'infinite_loop',
description: `${file.name}:${i + 1} — Potential infinite loop without break`,
file: file.name, line: i + 1,
remediation: 'Add termination condition or timeout'
});
}
if (/JSON\.parse/.test(line) && !line.includes('try')) {
const surrounding = lines.slice(Math.max(0, i - 2), Math.min(lines.length, i + 3)).join('\n');
if (!surrounding.includes('try')) {
findings.push({
id: `PERF-${String(++idCounter).padStart(3, '0')}`,
severity: 'medium',
category: 'uncaught_parse',
description: `${file.name}:${i + 1} — JSON.parse without try/catch`,
file: file.name, line: i + 1,
remediation: 'Wrap JSON.parse in try/catch'
});
}
}
if (/fs\.readFileSync/.test(line)) {
findings.push({
id: `PERF-${String(++idCounter).padStart(3, '0')}`,
severity: 'low',
category: 'sync_io',
description: `${file.name}:${i + 1} — Synchronous file read`,
file: file.name, line: i + 1,
remediation: 'Consider async file operations'
});
}
if (line.length > 200) {
findings.push({
id: `PERF-${String(++idCounter).padStart(3, '0')}`,
severity: 'info',
category: 'long_line',
description: `${file.name}:${i + 1} — Line exceeds 200 characters (${line.length})`,
file: file.name, line: i + 1,
remediation: 'Consider breaking long lines'
});
}
}
}
const high = findings.filter(f => f.severity === 'high').length;
const medium = findings.filter(f => f.severity === 'medium').length;
const low = findings.filter(f => f.severity === 'low').length;
return {
twin: 'performance',
verdict: high > 0 ? 'fail' : medium > 0 ? 'warn' : 'pass',
findings,
passed: sourceFiles.length - (high > 0 ? 1 : 0),
failed: high,
warnings: medium + low,
duration_ms: 0
};
}