- 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>
208 lines
8.6 KiB
JavaScript
208 lines
8.6 KiB
JavaScript
/**
|
|
* Test Script: DeliberationSession Model
|
|
* Validates MongoDB schema and all model methods work correctly
|
|
*/
|
|
|
|
const { DeliberationSession } = require('../src/models');
|
|
|
|
async function testDeliberationSession() {
|
|
console.log('╔════════════════════════════════════════════════════════════════╗');
|
|
console.log('║ Testing DeliberationSession Model ║');
|
|
console.log('╚════════════════════════════════════════════════════════════════╝\n');
|
|
|
|
let sessionId = null;
|
|
|
|
try {
|
|
// Test 1: Create session
|
|
console.log('Test 1: Creating test deliberation session...');
|
|
const session = await DeliberationSession.create({
|
|
decision: {
|
|
description: 'Test decision for model validation',
|
|
scenario: 'test_scenario',
|
|
context: {
|
|
geographic: 'United States',
|
|
temporal: 'test'
|
|
}
|
|
},
|
|
stakeholders: [
|
|
{
|
|
id: 'stakeholder-test-001',
|
|
name: 'Test Stakeholder 1',
|
|
type: 'individual',
|
|
represents: 'Test Stakeholder 1',
|
|
contact: { email: 'test1@example.com' }
|
|
},
|
|
{
|
|
id: 'stakeholder-test-002',
|
|
name: 'Test Stakeholder 2',
|
|
type: 'organization',
|
|
represents: 'Test Stakeholder 2',
|
|
contact: { email: 'test2@example.com' }
|
|
}
|
|
],
|
|
configuration: {
|
|
format: 'hybrid',
|
|
ai_role: 'ai_led',
|
|
visibility: 'private_to_public',
|
|
output_framing: 'pluralistic_accommodation'
|
|
}
|
|
});
|
|
|
|
sessionId = session.session_id;
|
|
console.log('✅ Session created:', sessionId);
|
|
console.log(' Status:', session.status);
|
|
console.log(' Stakeholders:', session.stakeholders.length);
|
|
console.log(' Created at:', session.created_at.toISOString());
|
|
|
|
// Test 2: Record AI facilitation action
|
|
console.log('\nTest 2: Recording AI facilitation action...');
|
|
await DeliberationSession.recordFacilitationAction(sessionId, {
|
|
actor: 'ai',
|
|
action_type: 'round_opening',
|
|
round_number: 1,
|
|
content: 'Test Round 1 opening by AI facilitator',
|
|
reason: 'Starting deliberation Round 1'
|
|
});
|
|
console.log('✅ AI action logged (round_opening)');
|
|
|
|
// Test 3: Record another AI action
|
|
console.log('\nTest 3: Recording stakeholder invitation...');
|
|
await DeliberationSession.recordFacilitationAction(sessionId, {
|
|
actor: 'ai',
|
|
action_type: 'stakeholder_invitation',
|
|
round_number: 1,
|
|
content: 'Invited stakeholder-test-001 to present',
|
|
reason: 'Facilitating position statement presentation'
|
|
});
|
|
console.log('✅ AI action logged (stakeholder_invitation)');
|
|
|
|
// Test 4: Record human intervention
|
|
console.log('\nTest 4: Recording human intervention...');
|
|
await DeliberationSession.recordHumanIntervention(sessionId, {
|
|
intervener: 'Test Observer',
|
|
trigger: 'pattern_bias',
|
|
round_number: 1,
|
|
description: 'AI used stigmatizing framing toward test stakeholder',
|
|
ai_action_overridden: 'Original AI prompt that was problematic',
|
|
corrective_action: 'Reframed neutrally',
|
|
stakeholder_informed: true,
|
|
resolution: 'AI resumed with corrected framing'
|
|
});
|
|
console.log('✅ Human intervention logged');
|
|
|
|
// Test 5: Record safety escalation
|
|
console.log('\nTest 5: Recording safety escalation...');
|
|
await DeliberationSession.recordSafetyEscalation(sessionId, {
|
|
detected_by: 'human',
|
|
escalation_type: 'pattern_bias',
|
|
severity: 'moderate',
|
|
round_number: 1,
|
|
description: 'Pattern bias detected in AI framing',
|
|
stakeholders_affected: ['stakeholder-test-001'],
|
|
immediate_action_taken: 'Human intervened and reframed',
|
|
requires_session_pause: false,
|
|
resolved: true,
|
|
resolution_details: 'Reframed successfully, deliberation continued'
|
|
});
|
|
console.log('✅ Safety escalation logged');
|
|
|
|
// Test 6: Add deliberation round
|
|
console.log('\nTest 6: Adding deliberation round...');
|
|
await DeliberationSession.addRound(sessionId, {
|
|
round_number: 1,
|
|
round_type: 'position_statements',
|
|
facilitator: 'ai',
|
|
contributions: [
|
|
{
|
|
stakeholder_id: 'stakeholder-test-001',
|
|
stakeholder_name: 'Test Stakeholder 1',
|
|
content: 'Test contribution from stakeholder 1',
|
|
timestamp: new Date()
|
|
}
|
|
]
|
|
});
|
|
console.log('✅ Round 1 added');
|
|
|
|
// Test 7: Retrieve session
|
|
console.log('\nTest 7: Retrieving session...');
|
|
const retrieved = await DeliberationSession.findBySessionId(sessionId);
|
|
console.log('✅ Session retrieved');
|
|
console.log(' Facilitation log entries:', retrieved.facilitation_log.length);
|
|
console.log(' Human interventions:', retrieved.human_interventions.length);
|
|
console.log(' Safety escalations:', retrieved.safety_escalations.length);
|
|
console.log(' Deliberation rounds:', retrieved.deliberation_rounds.length);
|
|
|
|
// Test 8: Get AI safety metrics
|
|
console.log('\nTest 8: Getting AI safety metrics...');
|
|
const metrics = await DeliberationSession.getAISafetyMetrics(sessionId);
|
|
console.log('✅ Safety metrics retrieved');
|
|
console.log(' Total interventions:', metrics.total_interventions);
|
|
console.log(' Total escalations:', metrics.total_escalations);
|
|
console.log(' Recommendation level:', metrics.recommendation.level);
|
|
|
|
// Test 9: Set outcome
|
|
console.log('\nTest 9: Setting deliberation outcome...');
|
|
await DeliberationSession.setOutcome(sessionId, {
|
|
decision_made: 'Test decision reached',
|
|
values_prioritized: ['fairness', 'transparency'],
|
|
values_deprioritized: ['efficiency'],
|
|
deliberation_summary: 'Test deliberation summary',
|
|
consensus_level: 'strong_accommodation',
|
|
dissenting_perspectives: [],
|
|
justification: 'Test justification',
|
|
moral_remainder: 'Some values could not be fully satisfied',
|
|
generated_by: 'ai'
|
|
});
|
|
console.log('✅ Outcome set');
|
|
|
|
// Test 10: Verify status changed to completed
|
|
const final = await DeliberationSession.findBySessionId(sessionId);
|
|
console.log('✅ Final status:', final.status);
|
|
|
|
console.log('\n╔════════════════════════════════════════════════════════════════╗');
|
|
console.log('║ ✅ ALL TESTS PASSED ║');
|
|
console.log('║ DeliberationSession model working correctly ║');
|
|
console.log('╚════════════════════════════════════════════════════════════════╝\n');
|
|
|
|
// Clean up
|
|
console.log('Cleaning up test data...');
|
|
const { getCollection } = require('../src/utils/db.util');
|
|
const collection = await getCollection('deliberation_sessions');
|
|
await collection.deleteOne({ session_id: sessionId });
|
|
console.log('✅ Test data cleaned up\n');
|
|
|
|
return true;
|
|
|
|
} catch (error) {
|
|
console.error('\n╔════════════════════════════════════════════════════════════════╗');
|
|
console.error('║ ❌ TEST FAILED ║');
|
|
console.error('╚════════════════════════════════════════════════════════════════╝\n');
|
|
console.error('Error:', error.message);
|
|
console.error('Stack:', error.stack);
|
|
|
|
// Clean up even on failure
|
|
if (sessionId) {
|
|
try {
|
|
const { getCollection } = require('../src/utils/db.util');
|
|
const collection = await getCollection('deliberation_sessions');
|
|
await collection.deleteOne({ session_id: sessionId });
|
|
console.log('✅ Test data cleaned up after failure\n');
|
|
} catch (cleanupError) {
|
|
console.error('❌ Cleanup failed:', cleanupError.message);
|
|
}
|
|
}
|
|
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// Run test
|
|
testDeliberationSession()
|
|
.then(() => {
|
|
console.log('Test script completed successfully');
|
|
process.exit(0);
|
|
})
|
|
.catch((error) => {
|
|
console.error('Test script failed:', error);
|
|
process.exit(1);
|
|
});
|