faf-cli
Version:
š½ TURBO-CAT: The Rapid Catalytic Converter ⢠Project DNA ⨠for ANY AI ⢠Fully Integrated with React, Next.js, Svelte, TypeScript, Vite & n8n ⢠FREE FOREVER ⢠10,000+ developers ⢠Championship Edition
148 lines ⢠6.48 kB
JavaScript
;
/**
* š faf audit - Audit Command
* Check .faf file freshness and completeness gaps
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.auditFafFile = auditFafFile;
const colors_1 = require("../fix-once/colors");
const fs_1 = require("fs");
const yaml_1 = require("../fix-once/yaml");
const file_utils_1 = require("../utils/file-utils");
const faf_compiler_1 = require("../compiler/faf-compiler");
async function auditFafFile(file, options = {}) {
try {
const fafPath = file || (await (0, file_utils_1.findFafFile)());
if (!fafPath) {
console.log(colors_1.chalk.red("ā No .faf file found"));
console.log(colors_1.chalk.yellow('š” Run "faf init" to create one'));
process.exit(1);
}
console.log(colors_1.chalk.blue(`š Auditing: ${fafPath}`));
// Read and parse .faf file
const content = await fs_1.promises.readFile(fafPath, "utf-8");
const fafData = (0, yaml_1.parse)(content);
const warnDays = parseInt(options.warnDays || "7");
const errorDays = parseInt(options.errorDays || "30");
let auditScore = 100;
const issues = [];
const warnings = [];
// 1. File Age Audit
const modTime = await (0, file_utils_1.getFileModTime)(fafPath);
if (modTime) {
const daysSincemod = (0, file_utils_1.daysSinceModified)(modTime);
if (daysSincemod >= errorDays) {
issues.push(`File is ${daysSincemod} days old (critical staleness)`);
auditScore -= 30;
}
else if (daysSincemod >= warnDays) {
warnings.push(`File is ${daysSincemod} days old (consider refresh)`);
auditScore -= 10;
}
}
// 2. Generated Timestamp Audit
if (fafData.generated) {
try {
const generatedDate = new Date(fafData.generated);
const daysSinceGenerated = (0, file_utils_1.daysSinceModified)(generatedDate);
if (daysSinceGenerated >= errorDays) {
issues.push(`Generated timestamp is ${daysSinceGenerated} days old`);
auditScore -= 20;
}
else if (daysSinceGenerated >= warnDays) {
warnings.push(`Generated timestamp is ${daysSinceGenerated} days old`);
auditScore -= 5;
}
}
catch {
issues.push("Invalid generated timestamp format");
auditScore -= 15;
}
}
else {
issues.push("Missing generated timestamp");
auditScore -= 20;
}
// 3. Completeness Audit
const compiler = new faf_compiler_1.FafCompiler();
const scoreResult = await compiler.compile(fafPath);
const completenessScore = scoreResult.score || 0;
if (completenessScore < 50) {
issues.push(`Low completeness score: ${Math.round(completenessScore)}%`);
auditScore -= 25;
}
else if (completenessScore < 70) {
warnings.push(`Moderate completeness score: ${Math.round(completenessScore)}%`);
auditScore -= 10;
}
// 4. Critical Sections Audit
const criticalSections = ["project", "ai_instructions", "scores"];
criticalSections.forEach((section) => {
if (!fafData[section] || Object.keys(fafData[section]).length === 0) {
issues.push(`Missing critical section: ${section}`);
auditScore -= 15;
}
});
// 5. Quality Indicators Audit
const hasAiInstructions = fafData.ai_instructions && Object.keys(fafData.ai_instructions).length > 0;
if (!hasAiInstructions) {
warnings.push("Missing AI instructions for context handoff");
auditScore -= 5;
}
const hasHumanContext = fafData.human_context &&
(fafData.human_context.who || fafData.human_context.what || fafData.human_context.why);
if (!hasHumanContext) {
warnings.push("Missing human context (6 Ws) for deeper understanding");
auditScore -= 10;
}
// Display Results
auditScore = Math.max(0, Math.min(100, auditScore));
if (auditScore >= 90) {
console.log(colors_1.chalk.green(`āļø Audit Score: ${auditScore}% - Excellent`));
}
else if (auditScore >= 70) {
console.log(colors_1.chalk.yellow(`ā ļø Audit Score: ${auditScore}% - Good`));
}
else {
console.log(colors_1.chalk.red(`šØ Audit Score: ${auditScore}% - Needs Attention`));
}
// Show Issues
if (issues.length > 0) {
console.log(colors_1.chalk.red("\nšØ Critical Issues:"));
issues.forEach((issue, index) => {
console.log(colors_1.chalk.red(` ${index + 1}. ${issue}`));
});
}
// Show Warnings
if (warnings.length > 0) {
console.log(colors_1.chalk.yellow("\nā ļø Warnings:"));
warnings.forEach((warning, index) => {
console.log(colors_1.chalk.yellow(` ${index + 1}. ${warning}`));
});
}
// Recommendations
if (auditScore < 100) {
console.log(colors_1.chalk.blue("\nš” Recommendations:"));
if (auditScore < 70) {
console.log(colors_1.chalk.blue(' ⢠Run "faf sync" to update with latest project changes'));
console.log(colors_1.chalk.blue(' ⢠Run "faf score --details" to identify missing context'));
}
if (issues.some((i) => i.includes("days old"))) {
console.log(colors_1.chalk.blue(' ⢠Consider regenerating .faf file with "faf init --force"'));
}
if (completenessScore < 70) {
console.log(colors_1.chalk.blue(" ⢠Add missing context sections to improve AI understanding"));
}
}
// Exit with appropriate code
if (issues.length > 0) {
process.exit(1);
}
}
catch (error) {
console.log(colors_1.chalk.red("š„ Audit failed:"));
console.log(colors_1.chalk.red(error instanceof Error ? error.message : String(error)));
process.exit(1);
}
}
//# sourceMappingURL=audit.js.map