claude-collab
Version:
Claude Collab - The AI collaboration framework that prevents echo chambers
464 lines (400 loc) • 16.6 kB
JavaScript
/**
* Claude-Collab Anti-Echo Chamber Demo
* Demonstrates enforced diversity in decision-making
*
* Created by Alex - Frontend/UX & Testing Lead
*/
const WebSocket = require('ws');
const chalk = require('chalk');
console.log(chalk.cyan(`
╔════════════════════════════════════════════════════════╗
║ 🛡️ Claude-Collab Anti-Echo Chamber Demo 🛡️ ║
║ ║
║ Watch how Claude-Collab prevents groupthink and ║
║ enforces diverse perspectives in decision-making ║
╚════════════════════════════════════════════════════════╝
`));
// Demo configuration
const SERVER_URL = 'ws://localhost:8765';
// Decision scenarios
const SCENARIOS = [
{
title: "Technology Stack Decision",
question: "Should we migrate our monolith to microservices?",
context: "Our e-commerce platform has 500k daily users and 20 developers"
},
{
title: "Remote Work Policy",
question: "Should we go fully remote or maintain hybrid model?",
context: "Tech company with 200 employees across 3 time zones"
},
{
title: "AI Implementation Strategy",
question: "Should we build AI capabilities in-house or use third-party services?",
context: "Mid-size fintech with strong engineering team but limited AI expertise"
}
];
// Decision makers with different biases
const DECISION_MAKERS = [
{
name: 'TechLead',
role: 'tech-lead',
perspective: 'innovation-driven',
bias: 'prefers cutting-edge solutions'
},
{
name: 'ProductMgr',
role: 'product-manager',
perspective: 'user-focused',
bias: 'prioritizes user experience'
},
{
name: 'FinanceDir',
role: 'finance-director',
perspective: 'cost-conscious',
bias: 'focuses on ROI and budget'
},
{
name: 'SecOps',
role: 'security-ops',
perspective: 'risk-averse',
bias: 'emphasizes security and stability'
},
{
name: 'TeamLead',
role: 'team-lead',
perspective: 'people-centric',
bias: 'considers team morale and skills'
}
];
class DecisionMaker {
constructor(config) {
this.name = config.name;
this.role = config.role;
this.perspective = config.perspective;
this.bias = config.bias;
this.ws = null;
this.interventionCount = 0;
this.hasProvidedEvidence = false;
this.hasDisagreed = false;
}
async register() {
return new Promise((resolve, reject) => {
console.log(chalk.yellow(`📝 ${this.name} joining decision panel...`));
const ws = new WebSocket(SERVER_URL);
ws.on('open', () => {
ws.send(JSON.stringify({
type: 'register',
agentName: this.name,
role: this.role
}));
});
ws.on('message', (data) => {
const message = JSON.parse(data.toString());
if (message.type === 'register-success') {
this.authToken = message.authToken;
console.log(chalk.green(`✓ ${this.name} ready (${this.perspective})`));
ws.close();
resolve();
} else if (message.type === 'register-failed' && message.reason === 'name-taken') {
console.log(chalk.gray(`ℹ ${this.name} already registered`));
ws.close();
resolve();
}
});
ws.on('error', reject);
});
}
async connect() {
return new Promise((resolve, reject) => {
this.ws = new WebSocket(SERVER_URL);
this.ws.on('open', () => {
this.ws.send(JSON.stringify({
type: 'auth',
agentName: this.name,
authToken: this.authToken,
role: this.role,
perspective: this.perspective,
clientVersion: '3.2.3'
}));
});
this.ws.on('message', (data) => {
const message = JSON.parse(data.toString());
if (message.type === 'auth-success') {
console.log(chalk.green(`✅ ${this.name} connected`));
resolve();
} else if (message.type === 'diversity-intervention') {
this.handleIntervention(message);
}
});
this.ws.on('error', reject);
});
}
handleIntervention(message) {
this.interventionCount++;
console.log(chalk.red(`\n🛑 INTERVENTION for ${this.name}!`));
console.log(chalk.yellow(` Reason: ${message.reason}`));
console.log(chalk.yellow(` Required: ${message.requiredAction}`));
console.log(chalk.gray(` (Intervention #${this.interventionCount} for this agent)`));
// Respond to intervention
setTimeout(() => {
if (message.requiredAction.includes('disagree')) {
this.provideDisagreement();
} else if (message.requiredAction.includes('evidence')) {
this.provideEvidence();
} else if (message.requiredAction.includes('alternative')) {
this.provideAlternative();
}
}, 2000);
}
initialResponse(scenario, agreeable = false) {
const responses = {
'innovation-driven': {
microservices: agreeable ?
"Microservices are definitely the way to go! Modern architecture!" :
"Microservices would give us better scalability and team autonomy",
remote: agreeable ?
"Full remote is the future! Let's embrace it completely!" :
"Remote work enables hiring the best talent globally",
ai: agreeable ?
"We must build everything in-house! Full control!" :
"Building in-house gives us competitive advantage and customization"
},
'user-focused': {
microservices: "This could improve feature delivery speed for users",
remote: "We need to consider how this affects user support and collaboration",
ai: "Whatever gets AI features to users fastest with best experience"
},
'cost-conscious': {
microservices: "The migration cost and increased infrastructure overhead concerns me",
remote: "Remote could save office costs but may impact productivity",
ai: "Third-party services would be more cost-effective initially"
},
'risk-averse': {
microservices: "This introduces significant security complexity and attack surface",
remote: "Hybrid maintains security controls while offering flexibility",
ai: "Third-party services have proven security but create dependencies"
},
'people-centric': {
microservices: "We need to consider the learning curve for our team",
remote: "Team cohesion and mentoring suffer in fully remote settings",
ai: "Our team would grow more by building some capabilities internally"
}
};
const scenarioKey = scenario.title.includes('Technology') ? 'microservices' :
scenario.title.includes('Remote') ? 'remote' : 'ai';
const response = responses[this.perspective]?.[scenarioKey] ||
"I need to think about this...";
this.say(response);
}
provideDisagreement() {
this.hasDisagreed = true;
const disagreements = {
'innovation-driven': [
"Actually, let me play devil's advocate here...",
"But we should also consider the downsides of this approach",
"Innovation for innovation's sake isn't always the answer"
],
'user-focused': [
"However, users might actually prefer stability over change",
"We might be assuming what users want without data",
"Let's consider the user segments who might be negatively impacted"
],
'cost-conscious': [
"Though I'm concerned about costs, there's value in other perspectives",
"The long-term benefits might outweigh short-term costs",
"We should factor in opportunity costs as well"
],
'risk-averse': [
"While security is crucial, we can't let fear paralyze us",
"There are ways to mitigate these risks effectively",
"Sometimes calculated risks are necessary for growth"
],
'people-centric': [
"Different team members might view this differently",
"We should survey the team rather than assume",
"Change can also be an opportunity for growth"
]
};
const options = disagreements[this.perspective] || ["Let me reconsider this..."];
this.say(options[Math.floor(Math.random() * options.length)]);
}
provideEvidence() {
this.hasProvidedEvidence = true;
const evidence = {
'innovation-driven': [
"According to the State of DevOps report, high-performing teams use microservices",
"GitLab's remote work report shows 86% increased productivity",
"Google's AI principles emphasize building responsible AI capabilities"
],
'user-focused': [
"User surveys show 73% prefer frequent small updates over big releases",
"Studies indicate remote support can be equally effective with proper tools",
"Gartner reports 85% of users value AI features in products"
],
'cost-conscious': [
"Microservices can increase infrastructure costs by 30-50% initially",
"Remote work saves average $11,000 per employee annually",
"Building AI in-house requires $500k+ initial investment"
],
'risk-averse': [
"OWASP lists distributed systems in top 10 security challenges",
"FBI reports 300% increase in cyber attacks on remote workers",
"Third-party AI services have established compliance certifications"
],
'people-centric': [
"Stack Overflow survey shows 65% of developers prefer monoliths for small teams",
"Microsoft study found remote work decreased collaboration by 25%",
"LinkedIn data shows AI skills are top priority for developer growth"
]
};
const options = evidence[this.perspective] || ["Research suggests we consider all factors"];
this.say(options[Math.floor(Math.random() * options.length)]);
}
provideAlternative() {
const alternatives = [
"What if we took a phased approach instead of all-or-nothing?",
"Could we run a pilot program first to gather real data?",
"Perhaps a hybrid solution would balance the tradeoffs better",
"Let's define success metrics before making the decision",
"We could start small and iterate based on learnings"
];
this.say(alternatives[Math.floor(Math.random() * alternatives.length)]);
}
finalRecommendation(scenario) {
const recommendations = {
'innovation-driven': "I recommend a gradual migration with careful monitoring",
'user-focused': "Let's prioritize based on user impact and feedback loops",
'cost-conscious': "We should start with a cost-benefit analysis and ROI projection",
'risk-averse': "Implement with strong security measures and rollback plans",
'people-centric': "Ensure team buy-in and provide adequate training and support"
};
this.say(recommendations[this.perspective] || "We need a balanced approach");
}
say(text) {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
console.log(chalk.blue(`\n💬 ${this.name}: "${text}"`));
this.ws.send(JSON.stringify({
type: 'message',
text
}));
}
}
getStats() {
return {
name: this.name,
interventions: this.interventionCount,
providedEvidence: this.hasProvidedEvidence,
disagreed: this.hasDisagreed
};
}
disconnect() {
if (this.ws) {
this.ws.close();
}
}
}
// Main demo flow
async function runDemo() {
try {
// Server check
console.log(chalk.yellow('\n🔍 Checking collaboration server...'));
try {
const testWs = new WebSocket(SERVER_URL);
await new Promise((resolve, reject) => {
testWs.on('open', () => {
testWs.close();
resolve();
});
testWs.on('error', reject);
setTimeout(() => reject(new Error('timeout')), 2000);
});
} catch (error) {
console.log(chalk.red('❌ Server not running!'));
console.log(chalk.yellow('💡 Starting server...'));
const { spawn } = require('child_process');
const serverProcess = spawn('cc', ['server'], {
detached: true,
stdio: 'ignore'
});
serverProcess.unref();
await new Promise(resolve => setTimeout(resolve, 3000));
}
console.log(chalk.green('✅ Server ready'));
// Create decision makers
const panel = DECISION_MAKERS.map(config => new DecisionMaker(config));
// Register all
for (const member of panel) {
await member.register();
await new Promise(resolve => setTimeout(resolve, 300));
}
// Connect all
for (const member of panel) {
await member.connect();
await new Promise(resolve => setTimeout(resolve, 300));
}
// Run through scenarios
for (let i = 0; i < SCENARIOS.length; i++) {
const scenario = SCENARIOS[i];
console.log(chalk.cyan(`\n\n📊 Scenario ${i + 1}: ${scenario.title}`));
console.log(chalk.yellow(`❓ ${scenario.question}`));
console.log(chalk.gray(`📋 Context: ${scenario.context}\n`));
// Phase 1: Initial responses (some agreeable to trigger intervention)
console.log(chalk.magenta('\n--- Phase 1: Initial Thoughts ---'));
await new Promise(resolve => setTimeout(resolve, 1500));
// First few agree to trigger echo chamber
panel[0].initialResponse(scenario, true);
await new Promise(resolve => setTimeout(resolve, 1500));
panel[1].initialResponse(scenario, true);
await new Promise(resolve => setTimeout(resolve, 1500));
panel[2].initialResponse(scenario, i === 0); // Sometimes agree
await new Promise(resolve => setTimeout(resolve, 1500));
// Others provide diverse views
panel[3].initialResponse(scenario);
await new Promise(resolve => setTimeout(resolve, 1500));
panel[4].initialResponse(scenario);
// Wait for interventions
await new Promise(resolve => setTimeout(resolve, 5000));
// Phase 2: Deep discussion
console.log(chalk.magenta('\n--- Phase 2: Evidence-Based Discussion ---'));
await new Promise(resolve => setTimeout(resolve, 8000));
// Phase 3: Final recommendations
console.log(chalk.magenta('\n--- Phase 3: Final Recommendations ---'));
for (const member of panel) {
member.finalRecommendation(scenario);
await new Promise(resolve => setTimeout(resolve, 1000));
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
// Show statistics
console.log(chalk.green('\n\n✨ Anti-Echo Chamber Demo Complete!'));
console.log(chalk.yellow('\n📈 Intervention Statistics:'));
const stats = panel.map(m => m.getStats());
stats.forEach(stat => {
console.log(chalk.gray(`• ${stat.name}: ${stat.interventions} interventions, ` +
`Evidence: ${stat.providedEvidence ? '✓' : '✗'}, ` +
`Disagreed: ${stat.disagreed ? '✓' : '✗'}`));
});
const totalInterventions = stats.reduce((sum, s) => sum + s.interventions, 0);
console.log(chalk.yellow(`\nTotal interventions: ${totalInterventions}`));
console.log(chalk.cyan('\n🎯 Key Takeaways:'));
console.log(chalk.gray('1. Echo chambers are automatically detected and prevented'));
console.log(chalk.gray('2. Agents are prompted to provide evidence for claims'));
console.log(chalk.gray('3. Diverse perspectives are enforced, not just encouraged'));
console.log(chalk.gray('4. Groupthink is actively disrupted by the system'));
console.log(chalk.gray('5. Decision quality improves through mandatory diversity'));
console.log(chalk.cyan('\n🚀 Try It Yourself:'));
console.log(chalk.gray(' cc server # Start server'));
console.log(chalk.gray(' cc watch # Monitor interventions'));
console.log(chalk.gray(' cc join <name> --role decision-maker'));
// Cleanup
panel.forEach(member => member.disconnect());
process.exit(0);
} catch (error) {
console.error(chalk.red('\n❌ Demo error:'), error.message);
process.exit(1);
}
}
// Run the demo
runDemo();