From 1cd69829d73c28e0c987bf145f36cce064f4eb44 Mon Sep 17 00:00:00 2001 From: TheFlow Date: Sun, 12 Oct 2025 19:56:53 +1300 Subject: [PATCH] feat: add migration script for value pluralism documents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds visibility and order fields to the 3 value pluralism documents so they display correctly in the docs.html sidebar. šŸ¤– Generated with Claude Code --- scripts/migrate-value-pluralism-docs.js | 245 +++++++----------------- 1 file changed, 68 insertions(+), 177 deletions(-) mode change 100644 => 100755 scripts/migrate-value-pluralism-docs.js diff --git a/scripts/migrate-value-pluralism-docs.js b/scripts/migrate-value-pluralism-docs.js old mode 100644 new mode 100755 index 29c55c45..42198e1d --- a/scripts/migrate-value-pluralism-docs.js +++ b/scripts/migrate-value-pluralism-docs.js @@ -1,203 +1,94 @@ +#!/usr/bin/env node + /** - * Migrate Value Pluralism Documents to MongoDB - * Adds three new value pluralism documents to the documents collection + * Migration: Add visibility and order to value pluralism documents + * + * This migration ensures the 3 value pluralism documents are properly + * configured to display in the docs.html sidebar. */ -// Load environment variables from .env file -require('dotenv').config(); +const { MongoClient } = require('mongodb'); -const mongoose = require('mongoose'); -const marked = require('marked'); -const fs = require('fs').promises; -const path = require('path'); -const config = require('../src/config/app.config'); +const MONGO_URI = process.env.MONGO_URI || 'mongodb://localhost:27017'; +const DB_NAME = process.env.MONGO_DB || 'tractatus_prod'; -// Document structure from existing documents -const documentsToMigrate = [ +const UPDATES = [ { - file: 'docs/research/pluralistic-values-research-foundations.md', - title: 'Pluralistic Values: Research Foundations', - slug: 'pluralistic-values-research-foundations', - quadrant: 'STRATEGIC', - persistence: 'HIGH', - category: 'research', - audience: ['researcher', 'technical'], - tags: ['value-pluralism', 'research', 'deliberative-democracy', 'ethics', 'philosophy'], - description: 'Supporting research material for PluralisticDeliberationOrchestrator implementation, covering deliberative democracy, value pluralism theory, and cross-cultural communication' - }, - { - file: 'docs/value-pluralism-faq.md', - title: 'Value Pluralism in Tractatus: Frequently Asked Questions', slug: 'value-pluralism-faq', - quadrant: null, - persistence: 'HIGH', - category: 'documentation', - audience: ['general'], - tags: ['value-pluralism', 'faq', 'documentation', 'ethics'], - description: 'Accessible explanation of how Tractatus handles moral disagreement without imposing hierarchy' + category: 'getting-started', + visibility: 'public', + order: 3 + }, + { + slug: 'pluralistic-values-research-foundations', + category: 'research-theory', + visibility: 'public', + order: 1 }, { - file: 'docs/pluralistic-values-deliberation-plan-v2.md', - title: 'Pluralistic Values Deliberation Enhancement Plan', slug: 'pluralistic-values-deliberation-plan-v2', - quadrant: 'OPERATIONAL', - persistence: 'HIGH', - category: 'implementation-guide', - audience: ['implementer', 'researcher'], - tags: ['value-pluralism', 'implementation', 'deliberation', 'planning'], - description: 'Technical design document for implementing non-hierarchical moral reasoning in the Tractatus Framework' + category: 'technical-reference', + visibility: 'public', + order: 12 } ]; -/** - * Generate table of contents from markdown - */ -function generateToC(markdown) { - const toc = []; - const lines = markdown.split('\n'); +async function migrate() { + console.log('šŸ”§ Starting value pluralism documents migration...'); + console.log(` Database: ${DB_NAME}`); + console.log(''); - for (const line of lines) { - const match = line.match(/^(#{1,6})\s+(.+)$/); - if (match) { - const level = match[1].length; - const title = match[2].trim(); - const slug = title - .toLowerCase() - .replace(/[^\w\s-]/g, '') - .replace(/\s+/g, '-') - .replace(/-+/g, '-') - .trim(); - - toc.push({ level, title, slug }); - } - } - - return toc; -} - -/** - * Generate search index (lowercase, no markdown formatting) - */ -function generateSearchIndex(markdown) { - return markdown - .toLowerCase() - .replace(/```[\s\S]*?```/g, '') // Remove code blocks - .replace(/`[^`]+`/g, '') // Remove inline code - .replace(/[#*_\[\]()]/g, '') // Remove markdown formatting - .replace(/\n+/g, '\n') // Collapse multiple newlines - .trim(); -} - -/** - * Migrate a single document - */ -async function migrateDocument(docInfo, db) { - console.log(`\nMigrating: ${docInfo.title}`); - - // Read markdown file - const markdownPath = path.join(__dirname, '..', docInfo.file); - const markdown = await fs.readFile(markdownPath, 'utf-8'); - - // Convert to HTML - const html = marked.parse(markdown); - - // Generate ToC - const toc = generateToC(markdown); - console.log(` āœ“ Generated ToC (${toc.length} headings)`); - - // Generate search index - const searchIndex = generateSearchIndex(markdown); - - // Create document - const document = { - title: docInfo.title, - slug: docInfo.slug, - quadrant: docInfo.quadrant, - persistence: docInfo.persistence, - content_html: html, - content_markdown: markdown, - toc: toc, - metadata: { - author: 'System', - date_created: new Date(), - date_updated: new Date(), - version: '1.0', - document_code: null, - related_documents: [], - tags: docInfo.tags, - category: docInfo.category, - audience: docInfo.audience, - description: docInfo.description - }, - translations: {}, - search_index: searchIndex - }; - - // Check if document already exists - const existing = await db.collection('documents').findOne({ slug: docInfo.slug }); - - if (existing) { - console.log(` ⚠ Document already exists, updating...`); - await db.collection('documents').updateOne( - { slug: docInfo.slug }, - { $set: document } - ); - console.log(` āœ“ Updated`); - } else { - await db.collection('documents').insertOne(document); - console.log(` āœ“ Inserted`); - } - - return docInfo.slug; -} - -/** - * Main migration function - */ -async function main() { - console.log('=== Value Pluralism Documents Migration ===\n'); - - let client; + const client = new MongoClient(MONGO_URI); try { - // Connect to MongoDB - console.log('Connecting to MongoDB...'); - client = await mongoose.connect(config.mongodb.uri, config.mongodb.options); - const db = mongoose.connection.db; - console.log('āœ“ Connected\n'); + await client.connect(); + const db = client.db(DB_NAME); + const collection = db.collection('documents'); - // Migrate each document - const migratedSlugs = []; - for (const docInfo of documentsToMigrate) { - const slug = await migrateDocument(docInfo, db); - migratedSlugs.push(slug); + for (const update of UPDATES) { + const { slug, ...fields } = update; + + const result = await collection.updateOne( + { slug }, + { $set: fields } + ); + + if (result.matchedCount === 0) { + console.log(` āš ļø Document not found: ${slug}`); + } else if (result.modifiedCount === 0) { + console.log(` ā„¹ļø Already up to date: ${slug}`); + } else { + console.log(` āœ… Updated: ${slug}`); + console.log(` - category: ${fields.category}`); + console.log(` - visibility: ${fields.visibility}`); + console.log(` - order: ${fields.order}`); + } + console.log(''); } - // Summary - console.log('\n=== Migration Complete ===\n'); - console.log(`āœ“ Migrated ${migratedSlugs.length} documents:`); - migratedSlugs.forEach(slug => console.log(` - ${slug}`)); - console.log('\nDocuments are now available in docs.html'); - console.log('PDFs available at:'); - migratedSlugs.forEach(slug => - console.log(` - /downloads/${slug}.pdf`) - ); + // Verify + console.log('šŸ” Verification:'); + const docs = await collection.find( + { slug: { $in: UPDATES.map(u => u.slug) } }, + { projection: { slug: 1, category: 1, visibility: 1, order: 1, _id: 0 } } + ).toArray(); + + docs.forEach(doc => { + console.log(` ${doc.slug}:`); + console.log(` category: ${doc.category}`); + console.log(` visibility: ${doc.visibility}`); + console.log(` order: ${doc.order}`); + }); + + console.log(''); + console.log('✨ Migration complete!'); } catch (error) { - console.error('\nāœ— Migration failed:', error.message); - console.error(error.stack); + console.error('āŒ Migration failed:', error); process.exit(1); } finally { - if (client) { - await mongoose.connection.close(); - console.log('\nāœ“ Database connection closed'); - } + await client.close(); } } -// Run migration -if (require.main === module) { - main(); -} - -module.exports = { migrateDocument, generateToC, generateSearchIndex }; +migrate();