#!/usr/bin/env node /** * Scan Response Templates for Governance Violations * Checks all existing templates for inst_016/017/018/079 violations * * Usage: * node scripts/scan-response-templates.js * node scripts/scan-response-templates.js --fix # Mark violating templates as inactive */ const { getCollection } = require('../src/utils/db.util'); const ContentGovernanceChecker = require('../src/services/ContentGovernanceChecker.service'); async function main() { try { const args = process.argv.slice(2); const fixMode = args.includes('--fix'); console.log('╔══════════════════════════════════════════════════════╗'); console.log('║ Response Template Governance Scanner ║'); console.log('╚══════════════════════════════════════════════════════╝'); console.log(''); const collection = await getCollection('response_templates'); // Get all active templates const templates = await collection.find({ active: true }).toArray(); console.log(`Found ${templates.length} active templates to scan\n`); const results = { scanned: 0, passed: 0, failed: 0, violations: [] }; for (const template of templates) { results.scanned++; // Scan template content const fullText = [template.subject, template.content].filter(Boolean).join('\n'); const check = await ContentGovernanceChecker.scanContent(fullText, { type: 'response_template', context: { template_id: template._id.toString(), name: template.name, category: template.category } }); if (check.success) { results.passed++; console.log(`✅ ${template.name} (${template.category})`); } else { results.failed++; console.log(`\n❌ ${template.name} (${template.category})`); console.log(` ID: ${template._id}`); console.log(` Violations: ${check.violations.length}`); check.violations.forEach((v, idx) => { console.log(` ${idx + 1}. [${v.severity}] ${v.rule}`); console.log(` "${v.match}"`); console.log(` ${v.message}`); }); results.violations.push({ template_id: template._id, name: template.name, category: template.category, violations: check.violations }); // Update template with governance check results await collection.updateOne( { _id: template._id }, { $set: { 'governance_check.passed': false, 'governance_check.scanned_at': check.scannedAt, 'governance_check.violations': check.violations, 'governance_check.summary': check.summary, updated_at: new Date() } } ); // Mark as inactive if in fix mode if (fixMode) { await collection.updateOne( { _id: template._id }, { $set: { active: false, deactivated_reason: 'Governance violations detected', deactivated_at: new Date() } } ); console.log(` 🔒 Template marked as inactive`); } console.log(''); } } // Summary console.log(''); console.log('╔══════════════════════════════════════════════════════╗'); console.log('║ Scan Summary ║'); console.log('╚══════════════════════════════════════════════════════╝'); console.log(''); console.log(`Total Scanned: ${results.scanned}`); console.log(`✅ Passed: ${results.passed}`); console.log(`❌ Failed: ${results.failed}`); console.log(''); if (results.failed > 0) { console.log('Violations by Rule:'); const violationsByRule = {}; results.violations.forEach(v => { v.violations.forEach(violation => { violationsByRule[violation.instruction] = (violationsByRule[violation.instruction] || 0) + 1; }); }); Object.entries(violationsByRule).forEach(([rule, count]) => { console.log(` • ${rule}: ${count}`); }); console.log(''); if (fixMode) { console.log(`🔒 ${results.failed} violating template(s) marked as inactive`); } else { console.log('💡 Run with --fix to mark violating templates as inactive'); } } console.log(''); process.exit(results.failed > 0 ? 1 : 0); } catch (error) { console.error('Error scanning templates:', error); process.exit(1); } } // Run if called directly if (require.main === module) { main(); } module.exports = { main };