tractatus/scripts/update-five-component-banner.js
TheFlow 2298d36bed fix(submissions): restructure Economist package and fix article display
- Create Economist SubmissionTracking package correctly:
  * mainArticle = full blog post content
  * coverLetter = 216-word SIR— letter
  * Links to blog post via blogPostId
- Archive 'Letter to The Economist' from blog posts (it's the cover letter)
- Fix date display on article cards (use published_at)
- Target publication already displaying via blue badge

Database changes:
- Make blogPostId optional in SubmissionTracking model
- Economist package ID: 68fa85ae49d4900e7f2ecd83
- Le Monde package ID: 68fa2abd2e6acd5691932150

Next: Enhanced modal with tabs, validation, export

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 08:47:42 +13:00

122 lines
5.1 KiB
JavaScript

/**
* Update "Five-Component Architecture" Banner
* Add note about framework evolution from 5 to 6 components
*/
const { MongoClient } = require('mongodb');
const DEV_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017';
const DEV_DB = process.env.MONGODB_DB || 'tractatus_dev';
const SLUG = 'five-component-tractatus-architecture';
const ENHANCED_BANNER = `
<div class="bg-amber-50 border-l-4 border-amber-500 p-4 mb-6">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-amber-400" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z"/>
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-amber-800">Framework Evolution Notice</h3>
<div class="mt-2 text-sm text-amber-700">
<p><strong>Framework Update:</strong> This blog describes the original <em>five-component</em> architecture from early October 2025. The framework has since evolved to <strong>six components</strong> with the addition of <strong>PluralisticDeliberationOrchestrator</strong> for values-sensitive decisions requiring multi-stakeholder input.</p>
<p class="mt-2">When we ran this blog through updated governance rules in late October 2025, the framework flagged language that violated newly-added instructions:</p>
<ul class="list-disc ml-5 mt-2 space-y-1">
<li><strong>inst_017 (No Absolute Assurances):</strong> Detected use of "guarantees" - now requires evidence-based language</li>
<li><strong>inst_018 (Honest Testing Status):</strong> Flags "production-ready" claims without multi-project validation</li>
</ul>
<p class="mt-2"><strong>This is the framework working as designed.</strong> As governance rules and components evolve, they catch content that previously passed review. Rather than silently revise, we're leaving this as a live demonstration of how architectural governance improves over time.</p>
<p class="mt-2">Read our <a href="/blog-post.html?slug=when-frameworks-fail-case-study" class="underline font-semibold hover:text-amber-900">framework failure case study</a> for more on transparent error handling.</p>
<p class="mt-2 text-xs italic">Note: This blog describes early-stage research (single-project validation). The framework components exist and function, but have not been validated across multiple production deployments.</p>
</div>
</div>
</div>
</div>`;
async function updateBanner() {
const client = new MongoClient(DEV_URI);
try {
console.log('🔧 Updating "Five-Component Architecture" Banner\n');
console.log('═'.repeat(70));
await client.connect();
const db = client.db(DEV_DB);
const collection = db.collection('blog_posts');
// Fetch the blog
const blog = await collection.findOne({ slug: SLUG });
if (!blog) {
console.log(`\n❌ Blog not found: ${SLUG}`);
return false;
}
console.log(`\n✅ Found blog: "${blog.title}"`);
// Check if banner exists
if (!blog.content.includes('Framework Evolution Notice')) {
console.log('⚠️ No existing banner found - add banner first with add-governance-banners-to-blogs.js');
return false;
}
// Replace existing banner with enhanced version
// Find the banner div (from <div class="bg-amber-50" to its closing </div>)
const bannerRegex = /<div class="bg-amber-50 border-l-4 border-amber-500[^>]*>[\s\S]*?<\/div>\s*<\/div>\s*<\/div>/;
if (!bannerRegex.test(blog.content)) {
console.log('⚠️ Could not find banner pattern to replace');
return false;
}
const updatedContent = blog.content.replace(bannerRegex, ENHANCED_BANNER);
// Update the blog
const result = await collection.updateOne(
{ slug: SLUG },
{ $set: { content: updatedContent } }
);
if (result.modifiedCount === 1) {
console.log('\n═'.repeat(70));
console.log(`\n✨ Banner updated successfully!`);
console.log(`\nEnhancements:`);
console.log(` • Added note about 6th component (PluralisticDeliberationOrchestrator)`);
console.log(` • Explains framework evolution from 5 to 6 components`);
console.log(` • Maintains existing governance violation notices`);
console.log(`\nNext steps:`);
console.log(`1. Review at: http://localhost:9000/blog-post.html?slug=${SLUG}`);
console.log(`2. Deploy to production\n`);
return true;
} else {
console.log('❌ Failed to update blog in database');
return false;
}
} catch (error) {
console.error('❌ Error:', error.message);
throw error;
} finally {
await client.close();
}
}
// Run if called directly
if (require.main === module) {
updateBanner()
.then((success) => {
process.exit(success ? 0 : 1);
})
.catch(error => {
console.error('\n💥 Failed:', error);
process.exit(1);
});
}
module.exports = { updateBanner };