/**
* Concurrent Load Test for Hot-Reload Race Conditions
*
* This script will be called by Claude to test concurrent tool calls
* during infrastructure hot-reload.
*
* Test Protocol:
* 1. Make 20 rapid sequential tool calls
* 2. Mix of actions: identity, greet, write-file
* 3. Track success/failure rate
* 4. Report any inconsistencies
*/
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
// Test configuration
const TEST_CALLS = 20;
const CALL_DELAY_MS = 50; // 50ms between calls = 20 calls/second
// Results tracking
const results = [];
let testPhase = 'unknown';
/**
* Simulate a tool call by checking tool output
*/
function callTool(action) {
const startTime = Date.now();
try {
// We can't actually call the MCP tool from Node.js directly
// This is a placeholder that Claude will replace with actual tool calls
console.log(` [Call] ${action}`);
results.push({
action,
success: true,
latency: Date.now() - startTime,
phase: testPhase,
});
return { success: true, action };
} catch (error) {
console.log(` [FAIL] ${action}: ${error.message}`);
results.push({
action,
success: false,
error: error.message,
latency: Date.now() - startTime,
phase: testPhase,
});
return { success: false, action, error };
}
}
/**
* Sleep utility
*/
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* Trigger hot-reload
*/
function triggerHotReload() {
console.log('\nš„ TRIGGERING HOT-RELOAD š„');
const filePath = path.join(__dirname, 'src', 'core', 'conversation-manager.ts');
const content = fs.readFileSync(filePath, 'utf8');
// Add timestamp marker
const modified = content.replace(
'class ConversationManager {',
`class ConversationManager {\n // Concurrent load test: ${Date.now()}`
);
fs.writeFileSync(filePath, modified);
// Build
console.log(' Building...');
try {
execSync('npm run build', { cwd: __dirname, stdio: 'pipe' });
console.log(' ā
Build complete\n');
} catch (err) {
console.log(' ā Build failed\n');
}
testPhase = 'during-reload';
}
/**
* Revert changes
*/
function revertChanges() {
console.log('\nš Reverting changes');
const filePath = path.join(__dirname, 'src', 'core', 'conversation-manager.ts');
const content = fs.readFileSync(filePath, 'utf8');
const clean = content.replace(/\n \/\/ Concurrent load test: \d+/, '');
fs.writeFileSync(filePath, clean);
execSync('npm run build', { cwd: __dirname, stdio: 'pipe' });
console.log(' ā
Reverted\n');
}
/**
* Analyze results
*/
function analyzeResults() {
console.log('\n' + '='.repeat(60));
console.log('CONCURRENT LOAD TEST RESULTS');
console.log('='.repeat(60));
const total = results.length;
const successful = results.filter(r => r.success).length;
const failed = results.filter(r => !r.success).length;
const preReload = results.filter(r => r.phase === 'pre-reload').length;
const duringReload = results.filter(r => r.phase === 'during-reload').length;
const postReload = results.filter(r => r.phase === 'post-reload').length;
console.log(`Total Calls: ${total}`);
console.log(`Successful: ${successful} (${(successful/total*100).toFixed(1)}%)`);
console.log(`Failed: ${failed} (${(failed/total*100).toFixed(1)}%)`);
console.log(`\nPhase Breakdown:`);
console.log(` Pre-Reload: ${preReload}`);
console.log(` During Reload: ${duringReload}`);
console.log(` Post-Reload: ${postReload}`);
if (failed > 0) {
console.log('\nā FAILURES DETECTED:');
results.filter(r => !r.success).forEach((r, i) => {
console.log(` ${i + 1}. ${r.action} (${r.phase}): ${r.error}`);
});
}
console.log('\n' + '='.repeat(60) + '\n');
}
/**
* Main test
*/
async function runTest() {
console.log('Concurrent Load Test for Hot-Reload');
console.log('====================================\n');
console.log('ā ļø NOTE: This script provides test infrastructure.');
console.log(' Claude must make actual MCP tool calls.\n');
testPhase = 'pre-reload';
console.log('Phase 1: Pre-reload baseline (5 calls)');
for (let i = 0; i < 5; i++) {
callTool('identity');
await sleep(CALL_DELAY_MS);
}
console.log('\nPhase 2: Triggering hot-reload');
triggerHotReload();
console.log('Phase 3: Calls during reload window (10 calls)');
for (let i = 0; i < 10; i++) {
callTool(i % 2 === 0 ? 'identity' : 'greet');
await sleep(CALL_DELAY_MS);
}
testPhase = 'post-reload';
console.log('\nPhase 4: Post-reload verification (5 calls)');
for (let i = 0; i < 5; i++) {
callTool('identity');
await sleep(CALL_DELAY_MS);
}
console.log('\nPhase 5: Cleanup');
revertChanges();
analyzeResults();
}
// Export for use
module.exports = {
runTest,
triggerHotReload,
revertChanges,
};
// Run if called directly
if (require.main === module) {
runTest().catch(console.error);
}