/** * Comprehensive Document Audit * Analyzes all documents in development database for: * 1. Public suitability * 2. Category assignment * 3. Quality assessment * 4. Archive/removal recommendations */ const { MongoClient } = require('mongodb'); // Audit criteria const AUDIT_CRITERIA = { PUBLIC_SUITABLE: { // Documents that should be public-facing REQUIRED: [ 'Introduction', 'Getting Started', 'Core Concepts', 'Executive Brief', 'Framework Overview', 'Implementation Guide' ], RESEARCH: ['Research', 'Working Paper', 'Study', 'Analysis'], TECHNICAL: ['API', 'Technical', 'Architecture', 'Integration'], BUSINESS: ['Business Case', 'ROI', 'Leadership'], EDUCATIONAL: ['Case Study', 'Values', 'Pluralism', 'Theory'] }, INTERNAL_ONLY: { SESSIONS: ['Session Handoff', 'Session Init', 'Session Summary', 'Part 1', 'Part 2', 'Part 3', 'Part 4'], PROCESS: ['Workflow', 'Process', 'Checklist', 'Progress Report'], PLANNING: ['Plan', 'Roadmap', 'Assessment', 'Advisory'], DEVELOPMENT: ['PoC', 'Proof of Concept', 'Week 1', 'Week 2', 'Week 3'], INTERNAL_TECH: ['Benchmark', 'Audit Report', 'Deployment Guide', 'Setup Guide'] }, QUALITY_MARKERS: { HIGH: ['has sections', 'complete', 'published', 'reviewed'], MEDIUM: ['draft', 'in progress'], LOW: ['incomplete', 'obsolete', 'deprecated', 'old'] } }; async function auditDocument(doc) { const audit = { title: doc.title, slug: doc.slug, category: doc.category, order: doc.order, visibility: doc.visibility, hasSections: doc.sections && doc.sections.length > 0, sectionCount: doc.sections ? doc.sections.length : 0, recommendation: 'ANALYZE', // PUBLIC, ARCHIVE, REMOVE, REVISE suggestedCategory: null, reasoning: [], quality: 'UNKNOWN' // HIGH, MEDIUM, LOW }; const titleLower = doc.title.toLowerCase(); const slugLower = doc.slug.toLowerCase(); // Check if internal-only document for (const [type, patterns] of Object.entries(AUDIT_CRITERIA.INTERNAL_ONLY)) { if (patterns.some(p => titleLower.includes(p.toLowerCase()))) { audit.recommendation = 'ARCHIVE'; audit.reasoning.push(`Internal document (${type})`); audit.quality = 'N/A'; return audit; } } // Check if public-suitable let isPublicSuitable = false; for (const [type, patterns] of Object.entries(AUDIT_CRITERIA.PUBLIC_SUITABLE)) { if (patterns.some(p => titleLower.includes(p.toLowerCase()))) { isPublicSuitable = true; // Suggest category based on type if (type === 'REQUIRED') audit.suggestedCategory = 'getting-started'; else if (type === 'RESEARCH') audit.suggestedCategory = 'research-theory'; else if (type === 'TECHNICAL') audit.suggestedCategory = 'technical-reference'; else if (type === 'BUSINESS') audit.suggestedCategory = 'business-leadership'; else if (type === 'EDUCATIONAL') { if (titleLower.includes('case study')) audit.suggestedCategory = 'case-studies'; else audit.suggestedCategory = 'advanced-topics'; } audit.reasoning.push(`Public-suitable (${type})`); break; } } // Quality assessment if (audit.hasSections && audit.sectionCount >= 5) { audit.quality = 'HIGH'; audit.reasoning.push(`Well-structured (${audit.sectionCount} sections)`); } else if (audit.hasSections) { audit.quality = 'MEDIUM'; audit.reasoning.push(`Structured (${audit.sectionCount} sections)`); } else { audit.quality = 'LOW'; audit.reasoning.push('No sections (may need revision)'); } // Check current category if (doc.category === 'none' || !doc.category) { audit.reasoning.push('⚠️ Uncategorized'); } if (doc.order === 999) { audit.reasoning.push('⚠️ Default order (not prioritized)'); } // Final recommendation if (isPublicSuitable && audit.quality !== 'LOW') { audit.recommendation = 'PUBLIC'; } else if (isPublicSuitable && audit.quality === 'LOW') { audit.recommendation = 'REVISE'; audit.reasoning.push('Needs content improvement before public'); } else if (!isPublicSuitable) { audit.recommendation = 'ARCHIVE'; } return audit; } async function run() { const client = new MongoClient('mongodb://localhost:27017'); try { await client.connect(); const db = client.db('tractatus_dev'); const collection = db.collection('documents'); const allDocs = await collection.find({}).sort({ category: 1, order: 1 }).toArray(); console.log('═══════════════════════════════════════════════════════════'); console.log(' COMPREHENSIVE DOCUMENT AUDIT'); console.log('═══════════════════════════════════════════════════════════\n'); console.log(`Total documents: ${allDocs.length}\n`); const audits = []; for (const doc of allDocs) { const audit = await auditDocument(doc); audits.push(audit); } // Group by recommendation const byRecommendation = { PUBLIC: audits.filter(a => a.recommendation === 'PUBLIC'), REVISE: audits.filter(a => a.recommendation === 'REVISE'), ARCHIVE: audits.filter(a => a.recommendation === 'ARCHIVE'), REMOVE: audits.filter(a => a.recommendation === 'REMOVE') }; // Summary console.log('═══════════════════════════════════════════════════════════'); console.log(' SUMMARY'); console.log('═══════════════════════════════════════════════════════════\n'); console.log(`PUBLIC (should be on /docs.html): ${byRecommendation.PUBLIC.length}`); console.log(`REVISE (needs work before public): ${byRecommendation.REVISE.length}`); console.log(`ARCHIVE (internal, keep but hide): ${byRecommendation.ARCHIVE.length}`); console.log(`REMOVE (obsolete, delete): ${byRecommendation.REMOVE.length}\n`); // Detailed recommendations console.log('═══════════════════════════════════════════════════════════'); console.log(' 1. RECOMMENDED FOR PUBLIC (/docs.html)'); console.log('═══════════════════════════════════════════════════════════\n'); const byCategory = {}; byRecommendation.PUBLIC.forEach(a => { const cat = a.suggestedCategory || a.category || 'uncategorized'; if (!byCategory[cat]) byCategory[cat] = []; byCategory[cat].push(a); }); Object.keys(byCategory).sort().forEach(cat => { console.log(`\n${cat.toUpperCase()} (${byCategory[cat].length} documents):`); byCategory[cat].forEach(a => { console.log(` ✓ ${a.title}`); console.log(` Quality: ${a.quality} | Sections: ${a.sectionCount}`); if (a.category !== a.suggestedCategory && a.suggestedCategory) { console.log(` ⚠️ Move from "${a.category}" to "${a.suggestedCategory}"`); } }); }); console.log('\n\n═══════════════════════════════════════════════════════════'); console.log(' 2. NEEDS REVISION BEFORE PUBLIC'); console.log('═══════════════════════════════════════════════════════════\n'); byRecommendation.REVISE.forEach(a => { console.log(` ⚠️ ${a.title}`); console.log(` Current: ${a.category} | Suggested: ${a.suggestedCategory}`); console.log(` Reason: ${a.reasoning.join(', ')}\n`); }); console.log('\n═══════════════════════════════════════════════════════════'); console.log(' 3. RECOMMENDED FOR ARCHIVE'); console.log('═══════════════════════════════════════════════════════════\n'); const archiveGroups = {}; byRecommendation.ARCHIVE.forEach(a => { const reason = a.reasoning[0] || 'Other'; if (!archiveGroups[reason]) archiveGroups[reason] = []; archiveGroups[reason].push(a.title); }); Object.keys(archiveGroups).forEach(reason => { console.log(`\n${reason} (${archiveGroups[reason].length}):`); archiveGroups[reason].slice(0, 5).forEach(title => { console.log(` - ${title}`); }); if (archiveGroups[reason].length > 5) { console.log(` ... and ${archiveGroups[reason].length - 5} more`); } }); // Save detailed audit to file const fs = require('fs'); const auditReport = { timestamp: new Date().toISOString(), totalDocuments: allDocs.length, recommendations: byRecommendation, categorySuggestions: byCategory }; fs.writeFileSync( 'docs/DOCUMENT_AUDIT_REPORT.json', JSON.stringify(auditReport, null, 2) ); console.log('\n\n═══════════════════════════════════════════════════════════'); console.log(' Full audit report saved to: docs/DOCUMENT_AUDIT_REPORT.json'); console.log('═══════════════════════════════════════════════════════════\n'); await client.close(); process.exit(0); } catch (error) { console.error('Error:', error); await client.close(); process.exit(1); } } run();