#!/usr/bin/env node /** * Framework Blog Content Checker * Scans blog posts for governance violations before publication * * Checks: * - inst_016: Fabricated statistics * - inst_017: Absolute guarantees * - inst_018: Unverified production claims * - inst_079: Dark patterns * - inst_080: Open source violations * - inst_081: Values framework impositions * * Usage: * node scripts/framework-check-blog-content.js --post-id * node scripts/framework-check-blog-content.js --content "blog text..." */ const mongoose = require('mongoose'); const path = require('path'); function parseArgs() { const args = process.argv.slice(2); const parsed = {}; for (let i = 0; i < args.length; i += 2) { const key = args[i].replace(/^--/, ''); const value = args[i + 1]; parsed[key] = value; } return parsed; } // Pattern definitions from inst_016/017/018 const contentPatterns = { inst_016_fabricated_stats: { patterns: [ /\b\d+%\s+(?:faster|better|improvement|increase|decrease|reduction|more|less)\b(?!\s*\[NEEDS VERIFICATION\]|\s*\(source:|\s*\[source:)/gi, /\b(?:faster|better|improvement)\s+of\s+\d+%\b(?!\s*\[NEEDS VERIFICATION\]|\s*\(source:|\s*\[source:)/gi ], severity: 'HIGH', message: 'Statistics require citation or [NEEDS VERIFICATION] marker' }, inst_017_absolute_guarantees: { patterns: [ /\bguarantee(?:s|d|ing)?\b/gi, /\b100%\s+(?:secure|safe|reliable|effective)\b/gi, /\bcompletely\s+prevents?\b/gi, /\bnever\s+fails?\b/gi, /\balways\s+works?\b/gi, /\beliminates?\s+all\b/gi ], severity: 'HIGH', message: 'Absolute guarantees prohibited - use evidence-based language' }, inst_018_unverified_claims: { patterns: [ /\bproduction-ready\b(?!\s+development\s+tool|\s+proof-of-concept)/gi, /\bbattle-tested\b/gi, /\benterprise-proven\b/gi, /\bwidespread\s+adoption\b/gi ], severity: 'MEDIUM', message: 'Production claims require evidence (this is proof-of-concept)' }, inst_079_dark_patterns: { patterns: [ /\bclick\s+here\s+now\b/gi, /\blimited\s+time\s+offer\b/gi, /\bonly\s+\d+\s+spots?\s+left\b/gi, /\bact\s+fast\b/gi ], severity: 'MEDIUM', message: 'Possible manipulative urgency detected' } }; async function scanContent(text) { const violations = []; for (const [ruleId, config] of Object.entries(contentPatterns)) { for (const pattern of config.patterns) { const matches = text.match(pattern); if (matches) { matches.forEach(match => { violations.push({ rule: ruleId, severity: config.severity, match, message: config.message, position: text.indexOf(match) }); }); } } } return violations; } async function main() { const args = parseArgs(); const { 'post-id': postId, content, title } = args; if (!postId && !content) { console.error('Error: --post-id or --content required'); process.exit(1); } // Connect to MongoDB try { await mongoose.connect('mongodb://localhost:27017/tractatus_dev', { serverSelectionTimeoutMS: 2000 }); } catch (err) { console.error('MongoDB connection failed:', err.message); process.exit(1); } let postContent = content; let postTitle = title || ''; let postMeta = null; // Fetch from DB if post-id provided if (postId) { const { ObjectId } = require('mongodb'); const db = require('../src/utils/db.util'); const collection = await db.getCollection('blog_posts'); const post = await collection.findOne({ _id: new ObjectId(postId) }); if (!post) { console.error('Error: Post not found'); await mongoose.disconnect(); process.exit(1); } postContent = post.content; postTitle = post.title; postMeta = { id: postId, status: post.status, author: post.author }; } // Scan content const contentViolations = await scanContent(postContent + ' ' + postTitle); // Invoke framework services const BoundaryEnforcer = require('../src/services/BoundaryEnforcer.service'); const MetacognitiveVerifier = require('../src/services/MetacognitiveVerifier.service'); const ContextPressureMonitor = require('../src/services/ContextPressureMonitor.service'); await BoundaryEnforcer.initialize(); await MetacognitiveVerifier.initialize(); await ContextPressureMonitor.initialize('blog-content-check'); const sessionId = `blog-check-${Date.now()}`; // BoundaryEnforcer: Check if content makes values claims const action = { type: 'blog_post_publication', description: `Publish blog post: ${postTitle}`, content_length: postContent.length, has_violations: contentViolations.length > 0 }; const context = { sessionId, tool: 'blog_publication', post_id: postMeta?.id, author_type: postMeta?.author?.type }; const boundaryResult = BoundaryEnforcer.enforce(action, context); // MetacognitiveVerifier: Check reasoning quality in arguments const reasoning = postContent.substring(0, 500); const verifyResult = MetacognitiveVerifier.verify(action, reasoning, context); // Wait for async audit logging await new Promise(resolve => setTimeout(resolve, 500)); await mongoose.disconnect(); // Output results const output = { success: contentViolations.length === 0, post: postMeta || { content_length: postContent.length }, violations: contentViolations, framework_checks: { boundary: { allowed: boundaryResult.allowed, message: boundaryResult.message }, verification: { decision: verifyResult.decision, confidence: verifyResult.confidence } }, summary: { total_violations: contentViolations.length, high_severity: contentViolations.filter(v => v.severity === 'HIGH').length, publication_recommended: contentViolations.length === 0 && boundaryResult.allowed } }; console.log(JSON.stringify(output, null, 2)); process.exit(output.success ? 0 : 1); } main().catch(err => { console.error('Fatal error:', err.message); process.exit(1); });