tractatus/scripts/load-lemonde-package.js
TheFlow f9ab3db284 feat(submissions): add multilingual document storage for publication packages
Extends SubmissionTracking model to support complete bilingual submission
packages with version control for multiple languages.

Schema additions:
- documents.coverLetter.versions[] - Language-versioned content
- documents.mainArticle.versions[] - With translation metadata
- documents.authorBio.versions[]
- documents.technicalBrief.versions[]

Helper methods:
- getDocument(docType, language, fallbackToDefault)
- setDocumentVersion(docType, language, content, metadata)
- getAvailableLanguages(docType)
- isPackageComplete(language)
- exportPackage(language)

Scripts:
- load-lemonde-package.js - Loads complete Le Monde submission package

Le Monde Package:
- Publication target: Rank 10, high-value French intellectual publication
- Theme: Post-Weberian organizational theory for AI age
- Content: Wittgenstein + Weber critique + indigenous data sovereignty
- Format: 187-word letter (within 150-200 requirement)
- Languages: English (original) + French (translated)
- Database ID: 68fa2abd2e6acd5691932150
- Status: Ready for submission

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 02:18:18 +13:00

142 lines
4.6 KiB
JavaScript
Executable file

#!/usr/bin/env node
/**
* Load Le Monde Submission Package
* Stores the complete bilingual submission package in the database
*/
const fs = require('fs');
const path = require('path');
const mongoose = require('mongoose');
require('dotenv').config();
const SubmissionTracking = require('../src/models/SubmissionTracking.model');
const PACKAGE_DIR = '/tmp/le-monde-package';
// Document file mappings
const DOCUMENTS = {
coverLetter: {
en: '1-cover-letter.txt',
fr: '1-cover-letter-FR.txt'
},
mainArticle: {
en: '2-letter-to-editor.txt',
fr: '2-letter-to-editor-FR.txt'
},
authorBio: {
en: '3-author-bio.txt',
fr: '3-author-bio-FR.txt'
},
technicalBrief: {
en: '4-technical-brief.txt',
fr: '4-technical-brief-FR.txt'
}
};
async function loadPackage() {
try {
// Connect to database
const mongoUri = process.env.MONGODB_URI || 'mongodb://localhost:27017/tractatus_dev';
await mongoose.connect(mongoUri);
console.log('✓ Connected to MongoDB');
// Check if package already exists
let submission = await SubmissionTracking.findOne({
publicationId: 'le-monde-lettre',
title: 'Beyond Weber: AI and the Limits of Bureaucratic Rationality'
});
if (!submission) {
// Create new submission tracking entry
submission = new SubmissionTracking({
publicationId: 'le-monde-lettre',
publicationName: 'Le Monde',
title: 'Beyond Weber: AI and the Limits of Bureaucratic Rationality',
wordCount: 187,
contentType: 'letter',
status: 'ready',
createdBy: new mongoose.Types.ObjectId('000000000000000000000000'), // System user
lastUpdatedBy: new mongoose.Types.ObjectId('000000000000000000000000')
});
console.log('✓ Created new submission tracking entry');
} else {
console.log('✓ Found existing submission tracking entry');
}
// Load and store each document type in both languages
for (const [docType, files] of Object.entries(DOCUMENTS)) {
console.log(`\nProcessing ${docType}...`);
for (const [language, filename] of Object.entries(files)) {
const filepath = path.join(PACKAGE_DIR, filename);
if (!fs.existsSync(filepath)) {
console.warn(` ⚠ File not found: ${filepath}`);
continue;
}
const content = fs.readFileSync(filepath, 'utf8');
const wordCount = content.split(/\s+/).length;
await submission.setDocumentVersion(docType, language, content, {
translatedBy: language === 'en' ? 'manual' : 'claude',
approved: true
});
console.log(` ✓ Loaded ${language}: ${wordCount} words`);
}
// Mark document type as completed
if (submission.documents[docType]) {
submission.documents[docType].completed = true;
}
}
// Save final state
await submission.save();
// Display summary
console.log('\n' + '='.repeat(60));
console.log('PACKAGE SUMMARY');
console.log('='.repeat(60));
console.log(`Publication: ${submission.publicationName} (${submission.publicationId})`);
console.log(`Title: ${submission.title}`);
console.log(`Status: ${submission.status}`);
console.log(`\nDocuments:`);
for (const docType of ['coverLetter', 'mainArticle', 'authorBio', 'technicalBrief']) {
const languages = submission.getAvailableLanguages(docType);
const completed = submission.documents[docType]?.completed ? '✓' : '✗';
console.log(` ${completed} ${docType}: ${languages.join(', ')}`);
}
console.log(`\nPackage complete (EN): ${submission.isPackageComplete('en')}`);
console.log(`Package complete (FR): ${submission.isPackageComplete('fr')}`);
// Export sample
console.log('\n' + '='.repeat(60));
console.log('FRENCH PACKAGE EXPORT (SAMPLE)');
console.log('='.repeat(60));
const frPackage = submission.exportPackage('fr');
console.log(`\nCover Letter (${frPackage.documents.coverLetter.wordCount} words):`);
console.log(frPackage.documents.coverLetter.content.substring(0, 200) + '...\n');
console.log(`Main Article (${frPackage.documents.mainArticle.wordCount} words):`);
console.log(frPackage.documents.mainArticle.content.substring(0, 200) + '...\n');
console.log(`\n✅ Le Monde submission package loaded successfully!`);
console.log(`\nSubmission ID: ${submission._id}`);
await mongoose.connection.close();
} catch (error) {
console.error('❌ Error loading package:', error);
process.exit(1);
}
}
// Run if called directly
if (require.main === module) {
loadPackage();
}
module.exports = { loadPackage };