tractatus/scripts/migrate-documents-final.js
TheFlow a04521713a feat(docs): documentation curation infrastructure (scripts + sidebar)
INFRASTRUCTURE COMPLETE (22 public documents from 129 total):

CATEGORY CONSOLIDATION (12 → 5):
- Eliminated chaotic category proliferation
- Defined 5 canonical categories with icons, descriptions
- Updated frontend sidebar (public/js/docs-app.js)
- Categories: getting-started, research-theory, technical-reference,
  advanced-topics, business-leadership

SCRIPTS CREATED:
- comprehensive-document-audit.js: Systematic audit of all 129 docs
- generate-public-pdfs.js: Puppeteer-based PDF generation (22 PDFs)
- migrate-documents-final.js: DB migration (22 updated, 104 archived)
- export-for-production.js: Export 22 docs for production
- import-from-export.js: Import documents to production DB
- analyze-categories.js: Category analysis tool
- prepare-public-docs.js: Document preparation validator

AUDIT RESULTS:
- docs/DOCUMENT_AUDIT_REPORT.json: Full analysis with recommendations
- 22 documents recommended for public visibility
- 104 documents to archive (internal/obsolete/poor quality)

REMAINING WORK:
- Fix inst_016/017/018 violations in 22 public documents (85 violations)
  • inst_016: Statistics need citations or [NEEDS VERIFICATION]
  • inst_017: Replace absolute assurance terms with evidence-based language
  • inst_018: Remove maturity claims or add documented evidence
- Regenerate PDFs after content fixes
- Regenerate production export file (compliant version)
- Deploy to production

Database migration already executed in dev (22 updated, 104 archived).

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 21:36:54 +13:00

229 lines
7.5 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Final Document Migration Script
*
* Migrates 22 curated public documents to production with:
* - Correct categories (5 total: getting-started, research-theory, technical-reference, advanced-topics, business-leadership)
* - Proper ordering (1-10 range)
* - Archives remaining documents
* - Migrates research paper to production
*
* Usage: node scripts/migrate-documents-final.js [--dry-run] [--dev-only] [--prod-only]
*/
const { MongoClient } = require('mongodb');
const DEV_URI = 'mongodb://localhost:27017';
const PROD_URI = 'mongodb://localhost:27017'; // Production uses auth, will need SSH tunnel
// 22 curated public documents with final categories and orders
const PUBLIC_DOCUMENTS = {
'getting-started': [
{ slug: 'introduction', order: 1 },
{ slug: 'core-concepts', order: 2 },
{ slug: 'executive-summary-tractatus-inflection-point', order: 3 },
{ slug: 'implementation-guide-v1.1', order: 4 },
{ slug: 'implementation-guide', order: 5 },
{ slug: 'implementation-guide-python-examples', order: 6 }
],
'research-theory': [
{ slug: 'tractatus-framework-research', order: 1 }, // Working Paper v0.1
{ slug: 'pluralistic-values-research-foundations', order: 2 },
{ slug: 'the-27027-incident-a-case-study-in-pattern-recognition-bias', order: 3 },
{ slug: 'real-world-ai-governance-a-case-study-in-framework-failure-and-recovery', order: 4 },
{ slug: 'llm-integration-feasibility-research-scope', order: 5 },
{ slug: 'research-topic-concurrent-session-architecture', order: 6 },
{ slug: 'research-topic-rule-proliferation-transactional-overhead', order: 7 }
],
'technical-reference': [
{ slug: 'technical-architecture', order: 1 },
{ slug: 'api-reference-complete', order: 2 },
{ slug: 'api-javascript-examples', order: 3 },
{ slug: 'api-python-examples', order: 4 },
{ slug: 'openapi-specification', order: 5 }
],
'advanced-topics': [
{ slug: 'value-pluralism-faq', order: 1 },
{ slug: 'tractatus-ai-safety-framework-core-values-and-principles', order: 2 },
{ slug: 'organizational-theory-foundations', order: 3 }
],
'business-leadership': [
{ slug: 'business-case-tractatus-framework', order: 1 }
]
};
async function migrateDatabase(dbName, client, dryRun = false) {
console.log(`\n${'═'.repeat(70)}`);
console.log(` MIGRATING DATABASE: ${dbName}`);
console.log(`${'═'.repeat(70)}\n`);
const db = client.db(dbName);
const collection = db.collection('documents');
const stats = {
updated: 0,
archived: 0,
errors: [],
notFound: []
};
// Get all public slugs
const allPublicSlugs = Object.values(PUBLIC_DOCUMENTS).flat().map(d => d.slug);
console.log(`Public documents to migrate: ${allPublicSlugs.length}\n`);
// Update each public document
for (const [category, docs] of Object.entries(PUBLIC_DOCUMENTS)) {
console.log(`\n📁 Category: ${category} (${docs.length} documents)`);
for (const { slug, order } of docs) {
try {
const doc = await collection.findOne({ slug });
if (!doc) {
console.log(` ⚠️ NOT FOUND: ${slug}`);
stats.notFound.push(slug);
continue;
}
if (dryRun) {
console.log(` [DRY RUN] Would update: ${doc.title}`);
console.log(` Category: ${doc.category}${category}`);
console.log(` Order: ${doc.order}${order}`);
console.log(` Visibility: ${doc.visibility} → public`);
} else {
await collection.updateOne(
{ slug },
{
$set: {
category,
order,
visibility: 'public',
updated_at: new Date()
}
}
);
console.log(` ✓ Updated: ${doc.title}`);
stats.updated++;
}
} catch (error) {
console.error(` ✗ Error updating ${slug}: ${error.message}`);
stats.errors.push({ slug, error: error.message });
}
}
}
// Archive all other documents
console.log(`\n\n📦 Archiving documents not in public list...\n`);
try {
if (dryRun) {
const toArchive = await collection.countDocuments({
slug: { $nin: allPublicSlugs },
visibility: { $ne: 'archived' }
});
console.log(` [DRY RUN] Would archive: ${toArchive} documents`);
} else {
const result = await collection.updateMany(
{
slug: { $nin: allPublicSlugs },
visibility: { $ne: 'archived' }
},
{
$set: {
visibility: 'archived',
archiveNote: 'Archived during final documentation curation - 2025-10-25',
updated_at: new Date()
}
}
);
stats.archived = result.modifiedCount;
console.log(` ✓ Archived: ${stats.archived} documents`);
}
} catch (error) {
console.error(` ✗ Error archiving documents: ${error.message}`);
stats.errors.push({ task: 'archiving', error: error.message });
}
// Summary
console.log(`\n${'═'.repeat(70)}`);
console.log(` MIGRATION SUMMARY - ${dbName}`);
console.log(`${'═'.repeat(70)}\n`);
console.log(` ✅ Updated: ${stats.updated}`);
console.log(` 📦 Archived: ${stats.archived}`);
console.log(` ⚠️ Not found: ${stats.notFound.length}`);
console.log(` ✗ Errors: ${stats.errors.length}\n`);
if (stats.notFound.length > 0) {
console.log(` Not found slugs:`);
stats.notFound.forEach(slug => console.log(` - ${slug}`));
console.log('');
}
if (stats.errors.length > 0) {
console.log(` Errors:`);
stats.errors.forEach(e => console.log(` - ${e.slug || e.task}: ${e.error}`));
console.log('');
}
return stats;
}
async function run() {
const args = process.argv.slice(2);
const dryRun = args.includes('--dry-run');
const devOnly = args.includes('--dev-only');
const prodOnly = args.includes('--prod-only');
console.log('═'.repeat(70));
console.log(' FINAL DOCUMENT MIGRATION');
console.log('═'.repeat(70));
console.log(`\nMode: ${dryRun ? 'DRY RUN (no changes)' : 'LIVE MIGRATION'}`);
console.log(`Target: ${devOnly ? 'Development only' : prodOnly ? 'Production only' : 'Both databases'}\n`);
if (dryRun) {
console.log('⚠️ DRY RUN MODE - No changes will be made\n');
}
const client = new MongoClient(DEV_URI);
try {
await client.connect();
// Migrate development database
if (!prodOnly) {
await migrateDatabase('tractatus_dev', client, dryRun);
}
// Migrate production database
if (!devOnly) {
console.log('\n\n⚠ PRODUCTION MIGRATION REQUIRES SSH TUNNEL');
console.log('Run this command first:');
console.log(' ssh -i ~/.ssh/tractatus_deploy -L 27018:localhost:27017 ubuntu@vps-93a693da.vps.ovh.net -N\n');
console.log('Then run this script with production connection\n');
// TODO: Add production migration when SSH tunnel is ready
// For now, we'll export the data and import on production
}
await client.close();
console.log('\n✅ Migration complete!\n');
if (!dryRun && !prodOnly) {
console.log('Next steps:');
console.log(' 1. Review changes in development database');
console.log(' 2. Test http://localhost:9000/docs.html');
console.log(' 3. Export research paper for production:');
console.log(' node scripts/export-research-paper.js');
console.log(' 4. Deploy to production\n');
}
process.exit(0);
} catch (error) {
console.error('Migration error:', error);
await client.close();
process.exit(1);
}
}
run();