universal-agent-memory
Advanced tools
| #!/usr/bin/env npx tsx | ||
| /** | ||
| * Terminal-Bench 2.0 Comparison Report Generator | ||
| * | ||
| * Parses Harbor result.json files from baseline and UAM benchmark runs, | ||
| * computes per-model deltas, category breakdowns, and task-level diffs. | ||
| * | ||
| * Usage: | ||
| * npx tsx scripts/generate-comparison-report.ts \ | ||
| * --baseline benchmark-results/baseline_opus45_<ts> \ | ||
| * --uam benchmark-results/uam_opus45_<ts> \ | ||
| * --baseline benchmark-results/baseline_gpt52_<ts> \ | ||
| * --uam benchmark-results/uam_gpt52_<ts> \ | ||
| * --output benchmark-results/FULL_COMPARISON_<ts>.md \ | ||
| * --timestamp <ts> | ||
| */ | ||
| import { readFileSync, writeFileSync, existsSync, readdirSync } from 'fs'; | ||
| import { join, basename } from 'path'; | ||
| // ============================================================================ | ||
| // Types | ||
| // ============================================================================ | ||
| interface HarborResult { | ||
| id: string; | ||
| started_at: string; | ||
| finished_at: string | null; | ||
| n_total_trials: number; | ||
| stats: { | ||
| n_trials: number; | ||
| n_errors: number; | ||
| evals: Record<string, { | ||
| n_trials: number; | ||
| n_errors: number; | ||
| metrics: Array<{ mean: number }>; | ||
| reward_stats: { | ||
| reward: Record<string, string[]>; | ||
| }; | ||
| }>; | ||
| }; | ||
| } | ||
| interface TaskStatus { | ||
| taskName: string; | ||
| passed: boolean; | ||
| trialId: string; | ||
| } | ||
| interface RunSummary { | ||
| jobName: string; | ||
| model: string; | ||
| config: 'baseline' | 'uam'; | ||
| totalTrials: number; | ||
| errors: number; | ||
| passed: TaskStatus[]; | ||
| failed: TaskStatus[]; | ||
| passRate: number; | ||
| } | ||
| interface ModelComparison { | ||
| model: string; | ||
| baseline: RunSummary | null; | ||
| uam: RunSummary | null; | ||
| uamWins: string[]; | ||
| baselineWins: string[]; | ||
| bothPass: string[]; | ||
| bothFail: string[]; | ||
| delta: number; | ||
| } | ||
| // ============================================================================ | ||
| // Parse CLI args | ||
| // ============================================================================ | ||
| function parseArgs(): { baselineDirs: string[]; uamDirs: string[]; output: string; timestamp: string } { | ||
| const args = process.argv.slice(2); | ||
| const baselineDirs: string[] = []; | ||
| const uamDirs: string[] = []; | ||
| let output = ''; | ||
| let timestamp = new Date().toISOString().replace(/[:.]/g, '-'); | ||
| for (let i = 0; i < args.length; i++) { | ||
| switch (args[i]) { | ||
| case '--baseline': baselineDirs.push(args[++i]); break; | ||
| case '--uam': uamDirs.push(args[++i]); break; | ||
| case '--output': output = args[++i]; break; | ||
| case '--timestamp': timestamp = args[++i]; break; | ||
| case '--help': | ||
| console.log('Usage: npx tsx generate-comparison-report.ts --baseline <dir> --uam <dir> [--output <file>] [--timestamp <ts>]'); | ||
| process.exit(0); | ||
| } | ||
| } | ||
| if (baselineDirs.length === 0 && uamDirs.length === 0) { | ||
| console.error('Error: Provide at least one --baseline or --uam directory'); | ||
| process.exit(1); | ||
| } | ||
| if (!output) { | ||
| output = `benchmark-results/FULL_COMPARISON_${timestamp}.md`; | ||
| } | ||
| return { baselineDirs, uamDirs, output, timestamp }; | ||
| } | ||
| // ============================================================================ | ||
| // Parse Harbor results | ||
| // ============================================================================ | ||
| function extractModelFromJobName(jobName: string): string { | ||
| // Job names follow pattern: (baseline|uam)_<model_short>_<timestamp> | ||
| // e.g. baseline_opus45_20260213_120000, uam_gpt52_20260213_120000 | ||
| // Also handles legacy names like uam_v200_optb_full89, opus45_baseline_no_uam | ||
| const modelAliases: Record<string, string> = { | ||
| opus45: 'claude-opus-4-5', | ||
| opus_4_5: 'claude-opus-4-5', | ||
| 'claude-opus': 'claude-opus-4-5', | ||
| gpt52: 'gpt-5.2-codex', | ||
| 'gpt-5': 'gpt-5.2-codex', | ||
| glm47: 'glm-4.7', | ||
| 'glm-4': 'glm-4.7', | ||
| }; | ||
| for (const [alias, fullName] of Object.entries(modelAliases)) { | ||
| if (jobName.includes(alias)) return fullName; | ||
| } | ||
| // For UAM version runs without model in name, default to Opus 4.5 (most common) | ||
| if (/^uam_v\d+/.test(jobName)) return 'claude-opus-4-5'; | ||
| return 'unknown'; | ||
| } | ||
| function extractModelFromEvalKey(evalKey: string): string { | ||
| // Format can be: agent__model__dataset (3 parts) or agent__dataset (2 parts) | ||
| const parts = evalKey.split('__'); | ||
| if (parts.length >= 3) return parts[1]; | ||
| return ''; | ||
| } | ||
| function parseResultDir(dir: string, config: 'baseline' | 'uam'): RunSummary | null { | ||
| const resultPath = join(dir, 'result.json'); | ||
| if (!existsSync(resultPath)) { | ||
| console.warn(` Warning: ${resultPath} not found`); | ||
| return null; | ||
| } | ||
| const data: HarborResult = JSON.parse(readFileSync(resultPath, 'utf-8')); | ||
| const jobName = basename(dir); | ||
| const evalKeys = Object.keys(data.stats.evals); | ||
| if (evalKeys.length === 0) { | ||
| console.warn(` Warning: No evals in ${resultPath}`); | ||
| return null; | ||
| } | ||
| const evalKey = evalKeys[0]; | ||
| // Try model from eval key first, fall back to job name | ||
| const model = extractModelFromEvalKey(evalKey) || extractModelFromJobName(jobName); | ||
| const evalData = data.stats.evals[evalKey]; | ||
| const rewards = evalData.reward_stats?.reward || {}; | ||
| const passedTrials = rewards['1.0'] || []; | ||
| const failedTrials = rewards['0.0'] || []; | ||
| const passed: TaskStatus[] = passedTrials.map((t: string) => ({ | ||
| taskName: t.split('__')[0], | ||
| passed: true, | ||
| trialId: t, | ||
| })); | ||
| const failed: TaskStatus[] = failedTrials.map((t: string) => ({ | ||
| taskName: t.split('__')[0], | ||
| passed: false, | ||
| trialId: t, | ||
| })); | ||
| const total = passed.length + failed.length; | ||
| const passRate = total > 0 ? (passed.length / total) * 100 : 0; | ||
| return { | ||
| jobName, | ||
| model, | ||
| config, | ||
| totalTrials: data.stats.n_trials, | ||
| errors: data.stats.n_errors, | ||
| passed, | ||
| failed, | ||
| passRate, | ||
| }; | ||
| } | ||
| function extractTaskNames(tasks: TaskStatus[]): Set<string> { | ||
| return new Set(tasks.map(t => t.taskName)); | ||
| } | ||
| // ============================================================================ | ||
| // Build comparisons | ||
| // ============================================================================ | ||
| function buildModelComparison(baseline: RunSummary | null, uam: RunSummary | null): ModelComparison { | ||
| const model = baseline?.model || uam?.model || 'unknown'; | ||
| const bPassed = baseline ? extractTaskNames(baseline.passed) : new Set<string>(); | ||
| const bFailed = baseline ? extractTaskNames(baseline.failed) : new Set<string>(); | ||
| const uPassed = uam ? extractTaskNames(uam.passed) : new Set<string>(); | ||
| const uFailed = uam ? extractTaskNames(uam.failed) : new Set<string>(); | ||
| const uamWins = [...uPassed].filter(t => !bPassed.has(t)).sort(); | ||
| const baselineWins = [...bPassed].filter(t => !uPassed.has(t)).sort(); | ||
| const bothPass = [...bPassed].filter(t => uPassed.has(t)).sort(); | ||
| const bothFail = [...bFailed].filter(t => uFailed.has(t)).sort(); | ||
| const bRate = baseline?.passRate || 0; | ||
| const uRate = uam?.passRate || 0; | ||
| const delta = uRate - bRate; | ||
| return { model, baseline, uam, uamWins, baselineWins, bothPass, bothFail, delta }; | ||
| } | ||
| // ============================================================================ | ||
| // Binomial test (approximate) | ||
| // ============================================================================ | ||
| function binomialPValue(wins: number, losses: number): string { | ||
| const n = wins + losses; | ||
| if (n === 0) return 'N/A'; | ||
| // Simple sign test approximation | ||
| const p = Math.min(wins, losses); | ||
| // Use normal approximation for binomial test | ||
| const expected = n / 2; | ||
| const stddev = Math.sqrt(n * 0.25); | ||
| if (stddev === 0) return 'N/A'; | ||
| const z = Math.abs(p - expected) / stddev; | ||
| // Rough 2-sided p-value from z-score | ||
| if (z < 1.645) return '>0.10'; | ||
| if (z < 1.96) return '<0.10'; | ||
| if (z < 2.576) return '<0.05'; | ||
| return '<0.01'; | ||
| } | ||
| // ============================================================================ | ||
| // Generate markdown report | ||
| // ============================================================================ | ||
| function generateReport( | ||
| comparisons: ModelComparison[], | ||
| timestamp: string, | ||
| ): string { | ||
| const lines: string[] = []; | ||
| lines.push('# Terminal-Bench 2.0 Full Comparison: UAM v3.1.0 vs Baseline'); | ||
| lines.push(''); | ||
| lines.push(`**Generated:** ${new Date().toISOString()}`); | ||
| lines.push(`**Dataset:** Terminal-Bench 2.0 (89 tasks)`); | ||
| lines.push(`**UAM Version:** 3.1.0`); | ||
| lines.push(`**Benchmark ID:** ${timestamp}`); | ||
| lines.push(''); | ||
| // Executive summary | ||
| lines.push('## Executive Summary'); | ||
| lines.push(''); | ||
| lines.push('| Model | Baseline | UAM | Delta | UAM Wins | Baseline Wins | p-value |'); | ||
| lines.push('|-------|----------|-----|-------|----------|---------------|---------|'); | ||
| for (const c of comparisons) { | ||
| const bRate = c.baseline ? `${c.baseline.passRate.toFixed(1)}% (${c.baseline.passed.length}/${c.baseline.passed.length + c.baseline.failed.length})` : 'N/A'; | ||
| const uRate = c.uam ? `${c.uam.passRate.toFixed(1)}% (${c.uam.passed.length}/${c.uam.passed.length + c.uam.failed.length})` : 'N/A'; | ||
| const delta = c.baseline && c.uam ? `${c.delta >= 0 ? '+' : ''}${c.delta.toFixed(1)}%` : 'N/A'; | ||
| const pval = binomialPValue(c.uamWins.length, c.baselineWins.length); | ||
| lines.push(`| ${c.model} | ${bRate} | ${uRate} | **${delta}** | ${c.uamWins.length} | ${c.baselineWins.length} | ${pval} |`); | ||
| } | ||
| lines.push(''); | ||
| // Aggregate stats | ||
| const totalUamWins = comparisons.reduce((s, c) => s + c.uamWins.length, 0); | ||
| const totalBaselineWins = comparisons.reduce((s, c) => s + c.baselineWins.length, 0); | ||
| const netTasks = totalUamWins - totalBaselineWins; | ||
| lines.push(`**Across all models:** UAM wins ${totalUamWins} tasks, Baseline wins ${totalBaselineWins} tasks, Net: ${netTasks >= 0 ? '+' : ''}${netTasks} tasks for UAM.`); | ||
| lines.push(''); | ||
| // Per-model detailed sections | ||
| for (const c of comparisons) { | ||
| lines.push(`---`); | ||
| lines.push(''); | ||
| lines.push(`## ${c.model}`); | ||
| lines.push(''); | ||
| if (c.baseline) { | ||
| lines.push(`- **Baseline:** ${c.baseline.passRate.toFixed(1)}% (${c.baseline.passed.length} passed, ${c.baseline.failed.length} failed, ${c.baseline.errors} errors)`); | ||
| } | ||
| if (c.uam) { | ||
| lines.push(`- **UAM:** ${c.uam.passRate.toFixed(1)}% (${c.uam.passed.length} passed, ${c.uam.failed.length} failed, ${c.uam.errors} errors)`); | ||
| } | ||
| if (c.baseline && c.uam) { | ||
| lines.push(`- **Net Delta:** ${c.delta >= 0 ? '+' : ''}${c.delta.toFixed(1)}% (${c.uamWins.length - c.baselineWins.length >= 0 ? '+' : ''}${c.uamWins.length - c.baselineWins.length} tasks)`); | ||
| } | ||
| lines.push(''); | ||
| // UAM wins | ||
| if (c.uamWins.length > 0) { | ||
| lines.push('### Tasks UAM Wins (pass with UAM, fail without)'); | ||
| lines.push(''); | ||
| for (const t of c.uamWins) { | ||
| lines.push(`- \`${t}\``); | ||
| } | ||
| lines.push(''); | ||
| } | ||
| // Baseline wins | ||
| if (c.baselineWins.length > 0) { | ||
| lines.push('### Tasks Baseline Wins (pass without UAM, fail with)'); | ||
| lines.push(''); | ||
| for (const t of c.baselineWins) { | ||
| lines.push(`- \`${t}\``); | ||
| } | ||
| lines.push(''); | ||
| } | ||
| // Full task-level diff table | ||
| if (c.baseline && c.uam) { | ||
| const allTasks = new Set([ | ||
| ...c.baseline.passed.map(t => t.taskName), | ||
| ...c.baseline.failed.map(t => t.taskName), | ||
| ...c.uam.passed.map(t => t.taskName), | ||
| ...c.uam.failed.map(t => t.taskName), | ||
| ]); | ||
| const bPassSet = extractTaskNames(c.baseline.passed); | ||
| const uPassSet = extractTaskNames(c.uam.passed); | ||
| lines.push('### Full Task Comparison'); | ||
| lines.push(''); | ||
| lines.push('| Task | Baseline | UAM | Delta |'); | ||
| lines.push('|------|----------|-----|-------|'); | ||
| for (const t of [...allTasks].sort()) { | ||
| const bStatus = bPassSet.has(t) ? 'PASS' : 'FAIL'; | ||
| const uStatus = uPassSet.has(t) ? 'PASS' : 'FAIL'; | ||
| let delta = '='; | ||
| if (bStatus === 'FAIL' && uStatus === 'PASS') delta = '**+UAM**'; | ||
| if (bStatus === 'PASS' && uStatus === 'FAIL') delta = '**-UAM**'; | ||
| lines.push(`| ${t} | ${bStatus} | ${uStatus} | ${delta} |`); | ||
| } | ||
| lines.push(''); | ||
| } | ||
| } | ||
| // Cross-model analysis | ||
| if (comparisons.length > 1) { | ||
| lines.push('---'); | ||
| lines.push(''); | ||
| lines.push('## Cross-Model Analysis'); | ||
| lines.push(''); | ||
| // Which tasks does UAM help consistently across models? | ||
| const uamWinSets = comparisons.map(c => new Set(c.uamWins)); | ||
| const baselineWinSets = comparisons.map(c => new Set(c.baselineWins)); | ||
| if (uamWinSets.length >= 2) { | ||
| const consistentUamWins = [...uamWinSets[0]].filter(t => uamWinSets.every(s => s.has(t))); | ||
| const consistentBaselineWins = [...baselineWinSets[0]].filter(t => baselineWinSets.every(s => s.has(t))); | ||
| if (consistentUamWins.length > 0) { | ||
| lines.push(`**Tasks where UAM helps across ALL models:** ${consistentUamWins.join(', ')}`); | ||
| lines.push(''); | ||
| } | ||
| if (consistentBaselineWins.length > 0) { | ||
| lines.push(`**Tasks where UAM hurts across ALL models:** ${consistentBaselineWins.join(', ')}`); | ||
| lines.push(''); | ||
| } | ||
| } | ||
| // Which model benefits most from UAM? | ||
| const sorted = [...comparisons].sort((a, b) => b.delta - a.delta); | ||
| lines.push('**Model benefit ranking (most to least improvement from UAM):**'); | ||
| lines.push(''); | ||
| for (const c of sorted) { | ||
| lines.push(`1. **${c.model}**: ${c.delta >= 0 ? '+' : ''}${c.delta.toFixed(1)}% (${c.uamWins.length} wins, ${c.baselineWins.length} losses)`); | ||
| } | ||
| lines.push(''); | ||
| } | ||
| // Methodology | ||
| lines.push('---'); | ||
| lines.push(''); | ||
| lines.push('## Methodology'); | ||
| lines.push(''); | ||
| lines.push('- **Baseline:** `harbor run` with `--ak "system_prompt="` to clear UAM context'); | ||
| lines.push('- **UAM:** `harbor run` with default CLAUDE.md and UAM memory system active'); | ||
| lines.push('- **Dataset:** Terminal-Bench 2.0 (89 tasks across systems, ML, security, algorithms)'); | ||
| lines.push('- **Scoring:** Binary pass/fail per task based on Harbor reward (1.0 = pass, 0.0 = fail)'); | ||
| lines.push('- **Statistical test:** Sign test on UAM-wins vs Baseline-wins (binomial, 2-sided)'); | ||
| lines.push(''); | ||
| lines.push('---'); | ||
| lines.push(`*Report generated by \`scripts/generate-comparison-report.ts\` at ${new Date().toISOString()}*`); | ||
| return lines.join('\n'); | ||
| } | ||
| // ============================================================================ | ||
| // Main | ||
| // ============================================================================ | ||
| function main(): void { | ||
| const { baselineDirs, uamDirs, output, timestamp } = parseArgs(); | ||
| console.log('Parsing benchmark results...'); | ||
| const baselineRuns: RunSummary[] = []; | ||
| const uamRuns: RunSummary[] = []; | ||
| for (const dir of baselineDirs) { | ||
| const run = parseResultDir(dir, 'baseline'); | ||
| if (run) { | ||
| baselineRuns.push(run); | ||
| console.log(` Baseline: ${run.model} - ${run.passRate.toFixed(1)}% (${run.passed.length}/${run.passed.length + run.failed.length})`); | ||
| } | ||
| } | ||
| for (const dir of uamDirs) { | ||
| const run = parseResultDir(dir, 'uam'); | ||
| if (run) { | ||
| uamRuns.push(run); | ||
| console.log(` UAM: ${run.model} - ${run.passRate.toFixed(1)}% (${run.passed.length}/${run.passed.length + run.failed.length})`); | ||
| } | ||
| } | ||
| // Match baseline and UAM runs by model | ||
| const modelSet = new Set([ | ||
| ...baselineRuns.map(r => r.model), | ||
| ...uamRuns.map(r => r.model), | ||
| ]); | ||
| const comparisons: ModelComparison[] = []; | ||
| for (const model of modelSet) { | ||
| const baseline = baselineRuns.find(r => r.model === model) || null; | ||
| const uam = uamRuns.find(r => r.model === model) || null; | ||
| comparisons.push(buildModelComparison(baseline, uam)); | ||
| } | ||
| // Sort by model name for consistent output | ||
| comparisons.sort((a, b) => a.model.localeCompare(b.model)); | ||
| // Generate report | ||
| const report = generateReport(comparisons, timestamp); | ||
| writeFileSync(output, report + '\n'); | ||
| console.log(`\nReport written to: ${output}`); | ||
| console.log(`Models compared: ${comparisons.length}`); | ||
| for (const c of comparisons) { | ||
| const sym = c.delta >= 0 ? '+' : ''; | ||
| console.log(` ${c.model}: ${sym}${c.delta.toFixed(1)}% (UAM wins ${c.uamWins.length}, Baseline wins ${c.baselineWins.length})`); | ||
| } | ||
| } | ||
| main(); |
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
| # Colors | ||
| GREEN='\033[0;32m' | ||
| YELLOW='\033[1;33m' | ||
| RED='\033[0;31m' | ||
| NC='\033[0m' # No Color | ||
| REPO_URL="https://github.com/DammianMiller/universal-agent-memory" | ||
| echo -e "${GREEN}Universal Agent Memory - Desktop Installation${NC}" | ||
| echo "============================================" | ||
| echo "" | ||
| # Check for Node.js | ||
| if ! command -v node &> /dev/null; then | ||
| echo -e "${RED}Error: Node.js is not installed${NC}" | ||
| echo "Please install Node.js 18+ from https://nodejs.org/" | ||
| exit 1 | ||
| fi | ||
| NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1) | ||
| if [ "$NODE_VERSION" -lt 18 ]; then | ||
| echo -e "${RED}Error: Node.js 18+ required (you have $(node -v))${NC}" | ||
| exit 1 | ||
| fi | ||
| echo -e "${GREEN}✓${NC} Node.js $(node -v) detected" | ||
| # Check for npm | ||
| if ! command -v npm &> /dev/null; then | ||
| echo -e "${RED}Error: npm is not installed${NC}" | ||
| exit 1 | ||
| fi | ||
| echo -e "${GREEN}✓${NC} npm $(npm -v) detected" | ||
| # Check for Docker (optional) | ||
| if command -v docker &> /dev/null; then | ||
| echo -e "${GREEN}✓${NC} Docker detected - local Qdrant available" | ||
| DOCKER_AVAILABLE=true | ||
| else | ||
| echo -e "${YELLOW}⚠${NC} Docker not found - will use cloud backends only" | ||
| DOCKER_AVAILABLE=false | ||
| fi | ||
| # Install the CLI globally | ||
| echo "" | ||
| echo "Installing universal-agent-memory..." | ||
| # Try npm install first, fall back to git clone if package not published yet | ||
| if npm install -g universal-agent-memory 2>/dev/null; then | ||
| echo -e "${GREEN}✓${NC} Installed from npm registry" | ||
| else | ||
| echo -e "${YELLOW}Package not yet on npm, installing from GitHub...${NC}" | ||
| # Install to user's local directory | ||
| INSTALL_DIR="${HOME}/.universal-agent-memory" | ||
| # Remove old installation if exists | ||
| if [ -d "$INSTALL_DIR" ]; then | ||
| echo "Removing previous installation..." | ||
| rm -rf "$INSTALL_DIR" | ||
| fi | ||
| # Clone and install | ||
| git clone --depth 1 "$REPO_URL.git" "$INSTALL_DIR" | ||
| cd "$INSTALL_DIR" | ||
| npm install --production=false | ||
| npm run build | ||
| npm link | ||
| echo -e "${GREEN}✓${NC} Installed from GitHub to $INSTALL_DIR" | ||
| fi | ||
| echo "" | ||
| echo -e "${GREEN}Installation complete!${NC}" | ||
| echo "" | ||
| echo "Next steps:" | ||
| echo " 1. Initialize UAM in your project:" | ||
| echo " $ cd /path/to/your/project" | ||
| echo " $ uam init" | ||
| echo "" | ||
| echo " 2. Review the generated CLAUDE.md" | ||
| echo "" | ||
| echo " 3. Start working - your AI assistant will follow the workflows!" | ||
| echo "" | ||
| if [ "$DOCKER_AVAILABLE" = true ]; then | ||
| echo " 2. Start local memory services (optional):" | ||
| echo " $ uam memory start" | ||
| echo "" | ||
| echo " Or use cloud backends:" | ||
| else | ||
| echo " 2. Configure cloud memory backends:" | ||
| fi | ||
| echo " - GitHub: export GITHUB_TOKEN=your_token" | ||
| echo " - Qdrant Cloud: export QDRANT_API_KEY=your_key && export QDRANT_URL=your_url" | ||
| echo "" | ||
| echo " 3. Generate CLAUDE.md for your project:" | ||
| echo " $ uam generate" | ||
| echo "" | ||
| echo "Documentation: ${REPO_URL}#readme" |
| #!/bin/bash | ||
| set -e | ||
| REPO_URL="https://github.com/DammianMiller/universal-agent-memory" | ||
| echo "🚀 Universal Agent Memory - Web Platform Setup" | ||
| echo "" | ||
| # Check for required tools | ||
| if ! command -v node &> /dev/null; then | ||
| echo "❌ Node.js is required. Install from https://nodejs.org" | ||
| exit 1 | ||
| fi | ||
| if ! command -v npm &> /dev/null; then | ||
| echo "❌ npm is required. Install from https://nodejs.org" | ||
| exit 1 | ||
| fi | ||
| echo "✅ Node.js $(node -v) detected" | ||
| echo "✅ npm $(npm -v) detected" | ||
| # Install CLI globally | ||
| echo "" | ||
| echo "📦 Installing universal-agent-memory CLI..." | ||
| # Try npm install first, fall back to git clone if package not published yet | ||
| if npm install -g universal-agent-memory 2>/dev/null; then | ||
| echo "✅ Installed from npm registry" | ||
| else | ||
| echo "⚠️ Package not yet on npm, installing from GitHub..." | ||
| # Install to user's local directory | ||
| INSTALL_DIR="${HOME}/.universal-agent-memory" | ||
| # Remove old installation if exists | ||
| if [ -d "$INSTALL_DIR" ]; then | ||
| echo "Removing previous installation..." | ||
| rm -rf "$INSTALL_DIR" | ||
| fi | ||
| # Clone and install | ||
| git clone --depth 1 "$REPO_URL.git" "$INSTALL_DIR" | ||
| cd "$INSTALL_DIR" | ||
| npm install --production=false | ||
| npm run build | ||
| npm link | ||
| echo "✅ Installed from GitHub to $INSTALL_DIR" | ||
| fi | ||
| # Initialize in current directory | ||
| echo "" | ||
| echo "⚙️ Initializing project..." | ||
| uam init --web --interactive | ||
| echo "" | ||
| echo "✅ Setup complete!" | ||
| echo "" | ||
| echo "Next steps:" | ||
| echo " 1. Initialize UAM in your project:" | ||
| echo " uam init" | ||
| echo "" | ||
| echo " 2. Review the generated CLAUDE.md" | ||
| echo "" | ||
| echo " 3. Start working - your AI assistant will follow the workflows!" | ||
| echo "" | ||
| echo "Optional: Set up cloud memory backends" | ||
| echo " export GITHUB_TOKEN=your_token" | ||
| echo " export QDRANT_API_KEY=your_key" | ||
| echo " export QDRANT_URL=your_url" | ||
| echo "" | ||
| echo "Documentation: ${REPO_URL}#readme" |
| # Setup Scripts | ||
| This directory contains automated setup and installation scripts for UAM. | ||
| ## Scripts | ||
| ### `setup.sh` - Complete Setup | ||
| ```bash | ||
| npm run setup | ||
| ``` | ||
| Performs a comprehensive setup including: | ||
| - ✅ Dependency checking (Node.js, npm, git, npx) | ||
| - ✅ Optional dependency recommendations (Docker, Python, pre-commit) | ||
| - ✅ npm install (if node_modules missing) | ||
| - ✅ TypeScript build | ||
| - ✅ Git hooks configuration: | ||
| - `pre-commit` - Secrets detection, linting | ||
| - `commit-msg` - Conventional commits validation | ||
| - `pre-push` - Test execution before push | ||
| - ✅ GitHub PR template (if gh CLI available) | ||
| ### `install-web.sh` - Web Platform Setup | ||
| ```bash | ||
| npm run install:web | ||
| ``` | ||
| Installs UAM for web platform usage (claude.ai, Factory.AI): | ||
| - Installs CLI globally or from GitHub | ||
| - Initializes web platform configuration | ||
| - Sets up for web-based AI assistants | ||
| ### `install-desktop.sh` - Desktop Setup | ||
| ```bash | ||
| npm run install:desktop | ||
| ``` | ||
| Installs UAM for desktop usage: | ||
| - Installs CLI globally or from GitHub | ||
| - Detects Docker for local Qdrant | ||
| - Initializes desktop platform configuration | ||
| - Provides setup guidance | ||
| ## Usage | ||
| ### Quick Setup | ||
| ```bash | ||
| # Install UAM globally | ||
| npm install -g universal-agent-memory | ||
| # Run comprehensive setup | ||
| npm run setup | ||
| # Initialize in your project | ||
| uam init | ||
| ``` | ||
| ### Platform-Specific Setup | ||
| ```bash | ||
| # For web platforms (claude.ai, Factory.AI) | ||
| npm run install:web | ||
| # For desktop (Claude Code, opencode) | ||
| npm run install:desktop | ||
| ``` | ||
| ## Git Hooks | ||
| The `setup.sh` script configures three git hooks: | ||
| ### Pre-commit Hook | ||
| - **Purpose**: Prevent secrets from being committed | ||
| - **Checks**: | ||
| - Scans for API keys, passwords, tokens in code | ||
| - Runs linter with zero warnings allowed | ||
| - **Bypass**: `git commit --no-verify` | ||
| ### Commit-msg Hook | ||
| - **Purpose**: Enforce conventional commits format | ||
| - **Validates**: `type(scope): description` format | ||
| - **Types**: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert | ||
| - **Bypass**: Confirm with 'y' when prompted | ||
| ### Pre-push Hook | ||
| - **Purpose**: Ensure tests pass before pushing | ||
| - **Runs**: `npm test` | ||
| - **Bypass**: None (tests must pass) | ||
| ## Troubleshooting | ||
| ### Hooks not executing | ||
| ```bash | ||
| # Make hooks executable | ||
| chmod +x .git/hooks/* | ||
| # Verify hooks exist | ||
| ls -la .git/hooks/ | grep -v sample | ||
| ``` | ||
| ### Setup script fails | ||
| ```bash | ||
| # Check Node.js version | ||
| node --version # Should be >= 18.0.0 | ||
| # Check npm | ||
| npm --version | ||
| # Clear and reinstall | ||
| rm -rf node_modules package-lock.json | ||
| npm install | ||
| ``` | ||
| ### Manual hook installation | ||
| If automatic setup fails, manually create hooks: | ||
| ```bash | ||
| # Pre-commit | ||
| cat > .git/hooks/pre-commit << 'EOF' | ||
| #!/bin/bash | ||
| npm run lint -- --max-warnings=0 | ||
| exit $? | ||
| EOF | ||
| chmod +x .git/hooks/pre-commit | ||
| # Commit-msg | ||
| cat > .git/hooks/commit-msg << 'EOF' | ||
| #!/bin/bash | ||
| # Conventional commits validation | ||
| exit 0 | ||
| EOF | ||
| chmod +x .git/hooks/commit-msg | ||
| ``` | ||
| ## Best Practices | ||
| 1. **Always run `npm run setup`** after cloning or updating UAM | ||
| 2. **Review generated hooks** before committing | ||
| 3. **Keep hooks in sync** with project requirements | ||
| 4. **Document custom hooks** in project README | ||
| 5. **Test hooks** with `git commit --no-verify` first | ||
| ## Security Notes | ||
| - Git hooks run locally and cannot access remote repositories | ||
| - Pre-commit hook only scans TypeScript/JavaScript/JSON files | ||
| - Secrets detection is best-effort (not exhaustive) | ||
| - Always use environment variables for sensitive data |
| #!/bin/bash | ||
| # | ||
| # Full Terminal-Bench 2.0 Benchmark: UAM v3.1.0 vs Baseline | ||
| # Runs all 3 models x 2 configs = 6 total benchmark runs | ||
| # | ||
| # Models: Claude Opus 4.5, GPT 5.2 Codex, GLM 4.7 | ||
| # Configs: Baseline (no UAM), With UAM | ||
| # | ||
| # Usage: | ||
| # export FACTORY_API_KEY="your-key" | ||
| # ./scripts/run-full-benchmark.sh [options] | ||
| # | ||
| # Options: | ||
| # --model <model> Run only this model (e.g. anthropic/claude-opus-4-5) | ||
| # --baseline-only Skip UAM runs | ||
| # --uam-only Skip baseline runs | ||
| # --concurrency <n> Parallel tasks per run (default: 4) | ||
| # --timeout-mult <f> Timeout multiplier (default: 2.0) | ||
| # --dry-run Print commands without executing | ||
| # --resume <timestamp> Resume a previous run using its timestamp | ||
| # --help Show help | ||
| # | ||
| set -euo pipefail | ||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" | ||
| RESULTS_DIR="$PROJECT_ROOT/benchmark-results" | ||
| TIMESTAMP=$(date +%Y%m%d_%H%M%S) | ||
| # Models in Harbor format | ||
| declare -A MODEL_MAP=( | ||
| ["anthropic/claude-opus-4-5"]="opus45" | ||
| ["openai/gpt-5.2-codex"]="gpt52" | ||
| ["zhipu/glm-4.7"]="glm47" | ||
| ) | ||
| ALL_MODELS=("anthropic/claude-opus-4-5" "openai/gpt-5.2-codex" "zhipu/glm-4.7") | ||
| # Defaults | ||
| CONCURRENCY=4 | ||
| TIMEOUT_MULT=2.0 | ||
| DATASET="terminal-bench@2.0" | ||
| RUN_BASELINE=true | ||
| RUN_UAM=true | ||
| DRY_RUN=false | ||
| SELECTED_MODELS=("${ALL_MODELS[@]}") | ||
| RESUME_TS="" | ||
| # Track run results for summary | ||
| declare -A RUN_STATUS | ||
| declare -A RUN_JOBS | ||
| usage() { | ||
| sed -n '2,/^$/p' "$0" | sed 's/^#//' | sed 's/^ //' | ||
| exit 0 | ||
| } | ||
| parse_args() { | ||
| while [[ $# -gt 0 ]]; do | ||
| case $1 in | ||
| --model) SELECTED_MODELS=("$2"); shift 2 ;; | ||
| --baseline-only) RUN_UAM=false; shift ;; | ||
| --uam-only) RUN_BASELINE=false; shift ;; | ||
| --concurrency) CONCURRENCY="$2"; shift 2 ;; | ||
| --timeout-mult) TIMEOUT_MULT="$2"; shift 2 ;; | ||
| --dry-run) DRY_RUN=true; shift ;; | ||
| --resume) RESUME_TS="$2"; TIMESTAMP="$2"; shift 2 ;; | ||
| --help) usage ;; | ||
| *) echo "Unknown option: $1"; exit 1 ;; | ||
| esac | ||
| done | ||
| } | ||
| check_prerequisites() { | ||
| if ! command -v harbor &>/dev/null; then | ||
| echo "Error: 'harbor' CLI not found. Install from https://github.com/laude-institute/harbor" | ||
| exit 1 | ||
| fi | ||
| if [[ -z "${FACTORY_API_KEY:-}" ]] && [[ -z "${DROID_API_KEY:-}" ]] && [[ -z "${ANTHROPIC_API_KEY:-}" ]]; then | ||
| echo "Error: No API key found. Set FACTORY_API_KEY, DROID_API_KEY, or ANTHROPIC_API_KEY" | ||
| echo "Get your Factory key at: https://app.factory.ai/settings/api-keys" | ||
| exit 1 | ||
| fi | ||
| } | ||
| log() { | ||
| local level="$1"; shift | ||
| local ts | ||
| ts=$(date +"%H:%M:%S") | ||
| case "$level" in | ||
| INFO) echo -e "[$ts] \033[36mINFO\033[0m $*" ;; | ||
| OK) echo -e "[$ts] \033[32mOK\033[0m $*" ;; | ||
| WARN) echo -e "[$ts] \033[33mWARN\033[0m $*" ;; | ||
| ERROR) echo -e "[$ts] \033[31mERROR\033[0m $*" ;; | ||
| RUN) echo -e "[$ts] \033[35mRUN\033[0m $*" ;; | ||
| esac | ||
| } | ||
| run_harbor() { | ||
| local config_type="$1" # "baseline" or "uam" | ||
| local model="$2" | ||
| local model_short="${MODEL_MAP[$model]}" | ||
| local job_name="${config_type}_${model_short}_${TIMESTAMP}" | ||
| local log_file="$RESULTS_DIR/${job_name}.log" | ||
| local run_key="${config_type}_${model_short}" | ||
| # Skip if already completed (resume mode) | ||
| if [[ -n "$RESUME_TS" ]] && [[ -f "$RESULTS_DIR/${job_name}/result.json" ]]; then | ||
| log INFO "Skipping $job_name (already completed)" | ||
| RUN_STATUS[$run_key]="skipped" | ||
| RUN_JOBS[$run_key]="$job_name" | ||
| return 0 | ||
| fi | ||
| log RUN "$config_type | $model | job=$job_name" | ||
| local cmd=( | ||
| harbor run | ||
| -d "$DATASET" | ||
| -m "$model" | ||
| -n "$CONCURRENCY" | ||
| --timeout-multiplier "$TIMEOUT_MULT" | ||
| --job-name "$job_name" | ||
| --jobs-dir "$RESULTS_DIR" | ||
| ) | ||
| if [[ "$config_type" == "baseline" ]]; then | ||
| # Baseline: vanilla claude-code agent with no UAM context | ||
| cmd+=(-a claude-code --ak "system_prompt=") | ||
| else | ||
| # UAM: custom agent with classified preamble and pre-execution hooks | ||
| cmd+=(--agent-import-path "uam_harbor.uam_agent:UAMAgent") | ||
| fi | ||
| if [[ "$DRY_RUN" == true ]]; then | ||
| echo " [DRY RUN] ${cmd[*]}" | ||
| RUN_STATUS[$run_key]="dry-run" | ||
| RUN_JOBS[$run_key]="$job_name" | ||
| return 0 | ||
| fi | ||
| mkdir -p "$RESULTS_DIR" | ||
| local start_time | ||
| start_time=$(date +%s) | ||
| if "${cmd[@]}" 2>&1 | tee "$log_file"; then | ||
| RUN_STATUS[$run_key]="success" | ||
| else | ||
| RUN_STATUS[$run_key]="failed" | ||
| log WARN "$job_name exited with non-zero status" | ||
| fi | ||
| RUN_JOBS[$run_key]="$job_name" | ||
| local end_time | ||
| end_time=$(date +%s) | ||
| local duration=$(( end_time - start_time )) | ||
| local hours=$(( duration / 3600 )) | ||
| local minutes=$(( (duration % 3600) / 60 )) | ||
| log OK "$job_name completed in ${hours}h ${minutes}m" | ||
| } | ||
| print_summary() { | ||
| echo "" | ||
| echo "================================================================" | ||
| echo " BENCHMARK SUMMARY" | ||
| echo "================================================================" | ||
| echo "" | ||
| printf " %-12s %-30s %-10s %s\n" "Config" "Model" "Status" "Job Name" | ||
| printf " %-12s %-30s %-10s %s\n" "------" "-----" "------" "--------" | ||
| for model in "${SELECTED_MODELS[@]}"; do | ||
| local model_short="${MODEL_MAP[$model]}" | ||
| for config in baseline uam; do | ||
| local key="${config}_${model_short}" | ||
| local status="${RUN_STATUS[$key]:-not-run}" | ||
| local job="${RUN_JOBS[$key]:-N/A}" | ||
| printf " %-12s %-30s %-10s %s\n" "$config" "$model" "$status" "$job" | ||
| done | ||
| done | ||
| echo "" | ||
| echo " Results directory: $RESULTS_DIR" | ||
| echo " Timestamp: $TIMESTAMP" | ||
| echo "" | ||
| } | ||
| generate_report() { | ||
| log INFO "Generating comparison report..." | ||
| local report_script="$SCRIPT_DIR/generate-comparison-report.ts" | ||
| if [[ ! -f "$report_script" ]]; then | ||
| log WARN "Report generator not found at $report_script" | ||
| log INFO "Generating basic summary instead..." | ||
| generate_basic_report | ||
| return | ||
| fi | ||
| # Run the TypeScript report generator | ||
| local report_output | ||
| report_output="$RESULTS_DIR/FULL_COMPARISON_${TIMESTAMP}.md" | ||
| local job_args="" | ||
| for model in "${SELECTED_MODELS[@]}"; do | ||
| local model_short="${MODEL_MAP[$model]}" | ||
| if [[ "$RUN_BASELINE" == true ]]; then | ||
| local bj="${RUN_JOBS[baseline_${model_short}]:-}" | ||
| if [[ -n "$bj" ]]; then | ||
| job_args="$job_args --baseline $RESULTS_DIR/$bj" | ||
| fi | ||
| fi | ||
| if [[ "$RUN_UAM" == true ]]; then | ||
| local uj="${RUN_JOBS[uam_${model_short}]:-}" | ||
| if [[ -n "$uj" ]]; then | ||
| job_args="$job_args --uam $RESULTS_DIR/$uj" | ||
| fi | ||
| fi | ||
| done | ||
| if npx tsx "$report_script" \ | ||
| --output "$report_output" \ | ||
| --timestamp "$TIMESTAMP" \ | ||
| $job_args 2>&1; then | ||
| log OK "Report saved to $report_output" | ||
| else | ||
| log WARN "TypeScript report generator failed, falling back to basic report" | ||
| generate_basic_report | ||
| fi | ||
| } | ||
| generate_basic_report() { | ||
| local report_file="$RESULTS_DIR/FULL_COMPARISON_${TIMESTAMP}.md" | ||
| cat > "$report_file" << HEADER | ||
| # Terminal-Bench 2.0 Full Comparison: UAM v3.1.0 vs Baseline | ||
| **Generated:** $(date -Iseconds) | ||
| **Dataset:** $DATASET (89 tasks) | ||
| **UAM Version:** 3.1.0 | ||
| **Concurrency:** $CONCURRENCY | **Timeout Multiplier:** $TIMEOUT_MULT | ||
| ## Results Summary | ||
| | Model | Config | Pass Rate | Passed | Failed | Errors | | ||
| |-------|--------|-----------|--------|--------|--------| | ||
| HEADER | ||
| for model in "${SELECTED_MODELS[@]}"; do | ||
| local model_short="${MODEL_MAP[$model]}" | ||
| for config in baseline uam; do | ||
| local key="${config}_${model_short}" | ||
| local job="${RUN_JOBS[$key]:-}" | ||
| local result_file="$RESULTS_DIR/$job/result.json" | ||
| if [[ -n "$job" ]] && [[ -f "$result_file" ]]; then | ||
| local stats | ||
| stats=$(python3 -c " | ||
| import json, sys | ||
| with open('$result_file') as f: | ||
| d = json.load(f) | ||
| evals = d['stats']['evals'] | ||
| for k, v in evals.items(): | ||
| rw = v.get('reward_stats', {}).get('reward', {}) | ||
| p = len(rw.get('1.0', [])) | ||
| f = len(rw.get('0.0', [])) | ||
| total = p + f | ||
| rate = p/total*100 if total > 0 else 0 | ||
| err = v.get('n_errors', 0) | ||
| print(f'{rate:.1f}%|{p}|{f}|{err}') | ||
| " 2>/dev/null || echo "N/A|N/A|N/A|N/A") | ||
| IFS='|' read -r rate passed failed errors <<< "$stats" | ||
| echo "| $model | $config | $rate | $passed | $failed | $errors |" >> "$report_file" | ||
| else | ||
| echo "| $model | $config | N/A | N/A | N/A | N/A |" >> "$report_file" | ||
| fi | ||
| done | ||
| done | ||
| # Add per-model delta section | ||
| cat >> "$report_file" << 'DELTAS' | ||
| ## Per-Model UAM Delta | ||
| DELTAS | ||
| for model in "${SELECTED_MODELS[@]}"; do | ||
| local model_short="${MODEL_MAP[$model]}" | ||
| local bj="${RUN_JOBS[baseline_${model_short}]:-}" | ||
| local uj="${RUN_JOBS[uam_${model_short}]:-}" | ||
| local b_result="$RESULTS_DIR/$bj/result.json" | ||
| local u_result="$RESULTS_DIR/$uj/result.json" | ||
| if [[ -f "$b_result" ]] && [[ -f "$u_result" ]]; then | ||
| echo "### $model" >> "$report_file" | ||
| echo "" >> "$report_file" | ||
| python3 -c " | ||
| import json | ||
| with open('$b_result') as f: | ||
| bd = json.load(f) | ||
| with open('$u_result') as f: | ||
| ud = json.load(f) | ||
| def get_tasks(data): | ||
| evals = data['stats']['evals'] | ||
| for k, v in evals.items(): | ||
| rw = v.get('reward_stats', {}).get('reward', {}) | ||
| passed = set(t.split('__')[0] for t in rw.get('1.0', [])) | ||
| failed = set(t.split('__')[0] for t in rw.get('0.0', [])) | ||
| return passed, failed | ||
| return set(), set() | ||
| bp, bf = get_tasks(bd) | ||
| up, uf = get_tasks(ud) | ||
| uam_wins = sorted(up - bp) | ||
| baseline_wins = sorted(bp - up) | ||
| both_pass = sorted(bp & up) | ||
| both_fail = sorted(bf & uf) | ||
| b_rate = len(bp)/(len(bp)+len(bf))*100 if (len(bp)+len(bf))>0 else 0 | ||
| u_rate = len(up)/(len(up)+len(uf))*100 if (len(up)+len(uf))>0 else 0 | ||
| delta = u_rate - b_rate | ||
| print(f'| Metric | Value |') | ||
| print(f'|--------|-------|') | ||
| print(f'| Baseline pass rate | {b_rate:.1f}% ({len(bp)}/{len(bp)+len(bf)}) |') | ||
| print(f'| UAM pass rate | {u_rate:.1f}% ({len(up)}/{len(up)+len(uf)}) |') | ||
| print(f'| **Net delta** | **{delta:+.1f}%** ({len(uam_wins)-len(baseline_wins):+d} tasks) |') | ||
| print(f'| UAM wins | {len(uam_wins)} tasks |') | ||
| print(f'| Baseline wins | {len(baseline_wins)} tasks |') | ||
| print(f'| Both pass | {len(both_pass)} tasks |') | ||
| print(f'| Both fail | {len(both_fail)} tasks |') | ||
| print() | ||
| if uam_wins: | ||
| print('**UAM wins:** ' + ', '.join(uam_wins)) | ||
| print() | ||
| if baseline_wins: | ||
| print('**Baseline wins:** ' + ', '.join(baseline_wins)) | ||
| print() | ||
| " >> "$report_file" 2>/dev/null || echo "Unable to parse results for $model" >> "$report_file" | ||
| echo "" >> "$report_file" | ||
| fi | ||
| done | ||
| echo "" >> "$report_file" | ||
| echo "---" >> "$report_file" | ||
| echo "*Report generated by \`scripts/run-full-benchmark.sh\` at $(date -Iseconds)*" >> "$report_file" | ||
| log OK "Basic report saved to $report_file" | ||
| } | ||
| # === Main === | ||
| main() { | ||
| parse_args "$@" | ||
| echo "================================================================" | ||
| echo " Terminal-Bench 2.0 Full Benchmark" | ||
| echo " UAM v3.1.0 vs Baseline | $(date)" | ||
| echo "================================================================" | ||
| echo "" | ||
| echo " Models: ${SELECTED_MODELS[*]}" | ||
| echo " Configs: $([ "$RUN_BASELINE" = true ] && echo "baseline ")$([ "$RUN_UAM" = true ] && echo "uam")" | ||
| echo " Concurrency: $CONCURRENCY" | ||
| echo " Timeout: ${TIMEOUT_MULT}x" | ||
| echo " Results: $RESULTS_DIR" | ||
| echo " Timestamp: $TIMESTAMP" | ||
| echo "" | ||
| check_prerequisites | ||
| # Run each model x config combination | ||
| local run_count=0 | ||
| local total_runs=0 | ||
| for model in "${SELECTED_MODELS[@]}"; do | ||
| [[ "$RUN_BASELINE" == true ]] && (( total_runs++ )) || true | ||
| [[ "$RUN_UAM" == true ]] && (( total_runs++ )) || true | ||
| done | ||
| log INFO "Starting $total_runs benchmark runs..." | ||
| for model in "${SELECTED_MODELS[@]}"; do | ||
| if [[ "$RUN_BASELINE" == true ]]; then | ||
| (( run_count++ )) || true | ||
| log INFO "Run $run_count/$total_runs" | ||
| run_harbor "baseline" "$model" | ||
| fi | ||
| if [[ "$RUN_UAM" == true ]]; then | ||
| (( run_count++ )) || true | ||
| log INFO "Run $run_count/$total_runs" | ||
| run_harbor "uam" "$model" | ||
| fi | ||
| done | ||
| # Generate report | ||
| generate_report | ||
| # Print summary | ||
| print_summary | ||
| log OK "All benchmark runs complete." | ||
| } | ||
| main "$@" |
| #!/bin/bash | ||
| # | ||
| # Run Terminal-Bench with Hybrid Adaptive UAM Context (Option 4) | ||
| # | ||
| # Key improvements over previous UAM runs: | ||
| # 1. Task classification skips UAM for reasoning/scheduling tasks | ||
| # 2. Time pressure assessment prevents timeout regressions | ||
| # 3. Historical benefit tracking optimizes context loading | ||
| # 4. Progressive context escalation on retry | ||
| # 5. Environment bootstrapping (Factory Droid technique) | ||
| # 6. Risk-aware prompting (Apex2 technique) | ||
| # | ||
| set -e | ||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" | ||
| # Source environment | ||
| source ~/.profile 2>/dev/null || true | ||
| # Task classification function (mirrors TypeScript logic) | ||
| classify_task() { | ||
| local task="$1" | ||
| case "$task" in | ||
| # Pure reasoning/scheduling - SKIP UAM (prevents timeout regression) | ||
| constraints-scheduling|chess-best-move|regex-chess) | ||
| echo "skip" | ||
| ;; | ||
| # Security tasks - FULL UAM | ||
| crack-7z-hash|password-recovery|vulnerable-secret|filter-js-from-html|break-filter-js-from-html) | ||
| echo "security" | ||
| ;; | ||
| # File operations - FULL UAM | ||
| extract-elf|sqlite-db-truncate|db-wal-recovery) | ||
| echo "file-ops" | ||
| ;; | ||
| # Legacy/modernization - FULL UAM | ||
| cobol-modernization) | ||
| echo "legacy" | ||
| ;; | ||
| # ML tasks - MINIMAL UAM (risk-aware) | ||
| gpt2-codegolf) | ||
| echo "ml" | ||
| ;; | ||
| # General coding - MINIMAL UAM | ||
| code-from-image|financial-document-processor|log-summary-date-ranges) | ||
| echo "coding" | ||
| ;; | ||
| # Default | ||
| *) | ||
| echo "general" | ||
| ;; | ||
| esac | ||
| } | ||
| # Generate context based on classification (Hybrid Adaptive logic) | ||
| get_adaptive_context() { | ||
| local category="$1" | ||
| case "$category" in | ||
| skip) | ||
| # No context for pure reasoning tasks | ||
| echo "" | ||
| ;; | ||
| security) | ||
| cat << 'EOF' | ||
| ## UAM Memory Context (Security) | ||
| ### Security | ||
| - XSS: Use bleach.clean() or DOMPurify. Remove script, onclick, onerror, javascript: | ||
| - Password cracking: hashcat -m 11600 for 7z, -m 0 MD5, -m 1000 NTLM, john for CPU | ||
| - Binary secrets: strings, objdump -d, check .rodata section | ||
| - CVE exploitation: Research exact steps before attempting, some operations irreversible | ||
| ### Tools | ||
| - hashcat: GPU password cracking, -m flag for hash type | ||
| - john: CPU password cracking, flexible format support | ||
| - readelf -a / objdump -d: Binary analysis | ||
| - strings: Extract printable strings from binaries | ||
| EOF | ||
| ;; | ||
| file-ops) | ||
| cat << 'EOF' | ||
| ## UAM Memory Context (File Operations) | ||
| ### File Formats | ||
| - ELF: Program headers at e_phoff. Use struct.unpack('<HH...') for parsing | ||
| - SQLite WAL: Header 32 bytes, frames follow. PRAGMA wal_checkpoint(TRUNCATE) to recover | ||
| - 7z: Install p7zip-full, use 7z x -p'password' for password protected archives | ||
| ### Coding | ||
| - Use absolute paths (/app/...) not relative | ||
| - Verify file exists before reading | ||
| - Handle edge cases in parsing | ||
| EOF | ||
| ;; | ||
| legacy) | ||
| cat << 'EOF' | ||
| ## UAM Memory Context (Legacy Code) | ||
| ### Legacy Code | ||
| - COBOL: Fixed-format columns (1-6 sequence, 7 indicator, 8-72 code) | ||
| - WORKING-STORAGE SECTION for variables | ||
| - Modernization: Preserve business logic, update data structures | ||
| - Test with original inputs to verify behavior matches | ||
| EOF | ||
| ;; | ||
| ml) | ||
| cat << 'EOF' | ||
| ## UAM Memory Context (ML - Risk Aware) | ||
| ### ML Training (Risk-Aware) | ||
| - CRITICAL: Test with small epochs/batch first before full runs | ||
| - Training can exceed 5 minutes - verify shapes and configs early | ||
| - Check GPU: nvidia-smi, CUDA_VISIBLE_DEVICES for GPU selection | ||
| - Cache datasets to avoid re-downloads | ||
| ### Coding | ||
| - Use absolute paths (/app/...) | ||
| - Match exact output format required | ||
| EOF | ||
| ;; | ||
| coding|general) | ||
| cat << 'EOF' | ||
| ## UAM Memory Context (Coding) | ||
| ### Coding | ||
| - Use absolute paths (/app/...) not relative | ||
| - Verify file exists before reading | ||
| - Handle edge cases in parsing | ||
| - Match exact output format required | ||
| EOF | ||
| ;; | ||
| esac | ||
| } | ||
| # Main execution | ||
| TASKS=( | ||
| "crack-7z-hash" | ||
| "filter-js-from-html" | ||
| "cobol-modernization" | ||
| "code-from-image" | ||
| "sqlite-db-truncate" | ||
| "extract-elf" | ||
| "db-wal-recovery" | ||
| "vulnerable-secret" | ||
| "chess-best-move" | ||
| "log-summary-date-ranges" | ||
| "password-recovery" | ||
| "gpt2-codegolf" | ||
| "constraints-scheduling" | ||
| "financial-document-processor" | ||
| "regex-chess" | ||
| ) | ||
| TIMESTAMP=$(date +%Y-%m-%d__%H-%M-%S) | ||
| JOBS_DIR="$PROJECT_ROOT/jobs/tbench_hybrid_adaptive_$TIMESTAMP" | ||
| echo "==============================================" | ||
| echo " Hybrid Adaptive UAM Terminal-Bench Runner" | ||
| echo " (Option 4 Implementation)" | ||
| echo "==============================================" | ||
| echo "Tasks: ${#TASKS[@]}" | ||
| echo "Output: $JOBS_DIR" | ||
| echo "" | ||
| # Show classification plan | ||
| echo "Task Classification (Hybrid Adaptive):" | ||
| echo "---------------------------------------" | ||
| SKIP_COUNT=0 | ||
| FULL_COUNT=0 | ||
| MINIMAL_COUNT=0 | ||
| for task in "${TASKS[@]}"; do | ||
| category=$(classify_task "$task") | ||
| case "$category" in | ||
| skip) | ||
| echo " $task → NO UAM (reasoning/games - prevents timeout)" | ||
| ((SKIP_COUNT++)) | ||
| ;; | ||
| security|file-ops|legacy) | ||
| echo " $task → FULL UAM ($category context)" | ||
| ((FULL_COUNT++)) | ||
| ;; | ||
| ml|coding|general) | ||
| echo " $task → MINIMAL UAM ($category context)" | ||
| ((MINIMAL_COUNT++)) | ||
| ;; | ||
| esac | ||
| done | ||
| echo "" | ||
| echo "Summary: $SKIP_COUNT skip, $FULL_COUNT full, $MINIMAL_COUNT minimal" | ||
| echo "" | ||
| # Build combined context (excluding pure reasoning tasks) | ||
| # This is the Hybrid Adaptive context that combines relevant sections | ||
| COMBINED_CONTEXT="## UAM Hybrid Adaptive Memory Context | ||
| ### Security (for security tasks) | ||
| - XSS: bleach.clean(), remove script/onclick/javascript: | ||
| - Password: hashcat -m 11600 (7z), -m 0 (MD5), john for CPU | ||
| - Binary: strings, objdump -d, check .rodata | ||
| ### File Formats (for file-ops tasks) | ||
| - ELF: e_phoff for headers, struct.unpack('<HH...') | ||
| - SQLite WAL: PRAGMA wal_checkpoint(TRUNCATE) | ||
| - 7z: p7zip, 7z x -p'password' | ||
| ### Legacy (for modernization tasks) | ||
| - COBOL: columns 1-6 sequence, 7 indicator, 8-72 code | ||
| - WORKING-STORAGE for variables | ||
| - Test with original inputs | ||
| ### Coding (minimal, for applicable tasks) | ||
| - Use absolute paths /app/ | ||
| - Verify files exist before reading | ||
| - Match exact output format" | ||
| echo "Starting benchmark..." | ||
| echo "" | ||
| # Build task arguments | ||
| TASK_ARGS="" | ||
| for task in "${TASKS[@]}"; do | ||
| TASK_ARGS="$TASK_ARGS -t $task" | ||
| done | ||
| # Run with Harbor | ||
| harbor run -d terminal-bench@2.0 \ | ||
| -a claude-code \ | ||
| -m anthropic/claude-opus-4-5 \ | ||
| --ak "append_system_prompt=$COMBINED_CONTEXT" \ | ||
| $TASK_ARGS \ | ||
| -k 1 \ | ||
| --jobs-dir "$JOBS_DIR" \ | ||
| -n 8 \ | ||
| --timeout-multiplier 2.0 | ||
| echo "" | ||
| echo "==============================================" | ||
| echo " Benchmark Complete" | ||
| echo "==============================================" | ||
| echo "Results: $JOBS_DIR/result.json" | ||
| echo "" | ||
| echo "Expected improvements over baseline:" | ||
| echo " - constraints-scheduling: Should PASS (no UAM overhead)" | ||
| echo " - extract-elf: Should PASS (file format context)" | ||
| echo " - password-recovery: Should PASS (security context)" | ||
| echo "" | ||
| echo "Compare with: jobs/tbench_uam_15/*/result.json" |
| #!/bin/bash | ||
| # | ||
| # Run Terminal-Bench 2.0 with UAM-integrated agents | ||
| # Compares Droid with and without UAM memory across multiple models | ||
| # | ||
| # This benchmark uses the FACTORY_API_KEY which provides access to all models: | ||
| # - Claude Opus 4.5 (Anthropic) | ||
| # - GPT 5.2 Codex (OpenAI) | ||
| # - GLM 4.7 (Zhipu) | ||
| # | ||
| # Usage: | ||
| # export FACTORY_API_KEY="your-factory-api-key" | ||
| # ./scripts/run-terminal-bench.sh | ||
| # | ||
| set -e | ||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" | ||
| RESULTS_DIR="$PROJECT_ROOT/benchmark-results" | ||
| TIMESTAMP=$(date +%Y%m%d_%H%M%S) | ||
| # Models to test - Harbor/LiteLLM format (provider/model) | ||
| # These are mapped through Factory API when using droid | ||
| HARBOR_MODELS=( | ||
| "anthropic/claude-opus-4-5" | ||
| "openai/gpt-5.2-codex" | ||
| "zhipu/glm-4.7" | ||
| ) | ||
| # Factory/Droid model names (used by improved-benchmark.ts) | ||
| FACTORY_MODELS=( | ||
| "claude-opus-4-5-20251101" | ||
| "gpt-5.2-codex" | ||
| "glm-4.7" | ||
| ) | ||
| # Configuration | ||
| N_CONCURRENT=${N_CONCURRENT:-4} | ||
| TIMEOUT_MULT=${TIMEOUT_MULT:-1.0} | ||
| DATASET="terminal-bench@2.0" | ||
| # Check for API keys | ||
| check_api_keys() { | ||
| # Factory API key provides access to all models | ||
| if [ -z "$FACTORY_API_KEY" ] && [ -z "$DROID_API_KEY" ]; then | ||
| echo "Error: FACTORY_API_KEY or DROID_API_KEY must be set" | ||
| echo "" | ||
| echo "The Factory API key provides unified access to:" | ||
| echo " - Claude Opus 4.5 (Anthropic)" | ||
| echo " - GPT 5.2 Codex (OpenAI)" | ||
| echo " - GLM 4.7 (Zhipu)" | ||
| echo "" | ||
| echo "Get your key at: https://app.factory.ai/settings/api-keys" | ||
| exit 1 | ||
| fi | ||
| echo "Using Factory API for model access" | ||
| # For Harbor's direct provider access, these may also be needed | ||
| if [ -z "$ANTHROPIC_API_KEY" ]; then | ||
| echo "Note: ANTHROPIC_API_KEY not set - Harbor will use Factory routing" | ||
| fi | ||
| if [ -z "$OPENAI_API_KEY" ]; then | ||
| echo "Note: OPENAI_API_KEY not set - Harbor will use Factory routing" | ||
| fi | ||
| } | ||
| # Create results directory | ||
| mkdir -p "$RESULTS_DIR" | ||
| # Run benchmark for a specific model with UAM | ||
| run_with_uam() { | ||
| local model=$1 | ||
| local model_safe=$(echo "$model" | tr '.-' '_') | ||
| local job_name="uam_${model_safe}_${TIMESTAMP}" | ||
| echo "==================================================" | ||
| echo "Running: $model WITH UAM memory" | ||
| echo "==================================================" | ||
| harbor run \ | ||
| -d "$DATASET" \ | ||
| -a claude-code \ | ||
| -m "$model" \ | ||
| -n "$N_CONCURRENT" \ | ||
| --timeout-multiplier "$TIMEOUT_MULT" \ | ||
| --job-name "$job_name" \ | ||
| --jobs-dir "$RESULTS_DIR" \ | ||
| --ak "use_uam=true" \ | ||
| --ak "project_root=$PROJECT_ROOT" \ | ||
| 2>&1 | tee "$RESULTS_DIR/${job_name}.log" | ||
| echo "Results saved to: $RESULTS_DIR/$job_name" | ||
| } | ||
| # Run benchmark for a specific model without UAM (baseline) | ||
| run_without_uam() { | ||
| local model=$1 | ||
| local model_safe=$(echo "$model" | tr '.-' '_') | ||
| local job_name="baseline_${model_safe}_${TIMESTAMP}" | ||
| echo "==================================================" | ||
| echo "Running: $model WITHOUT UAM (baseline)" | ||
| echo "==================================================" | ||
| harbor run \ | ||
| -d "$DATASET" \ | ||
| -a claude-code \ | ||
| -m "$model" \ | ||
| -n "$N_CONCURRENT" \ | ||
| --timeout-multiplier "$TIMEOUT_MULT" \ | ||
| --job-name "$job_name" \ | ||
| --jobs-dir "$RESULTS_DIR" \ | ||
| 2>&1 | tee "$RESULTS_DIR/${job_name}.log" | ||
| echo "Results saved to: $RESULTS_DIR/$job_name" | ||
| } | ||
| # Run with custom UAM agent | ||
| run_custom_agent() { | ||
| local model=$1 | ||
| local with_memory=$2 | ||
| local model_safe=$(echo "$model" | tr '.-' '_') | ||
| local memory_label=$([ "$with_memory" = "true" ] && echo "uam" || echo "baseline") | ||
| local job_name="${memory_label}_custom_${model_safe}_${TIMESTAMP}" | ||
| echo "==================================================" | ||
| echo "Running: $model with custom UAM agent (memory=$with_memory)" | ||
| echo "==================================================" | ||
| harbor run \ | ||
| -d "$DATASET" \ | ||
| --agent-import-path "$PROJECT_ROOT/src/harbor/uam_agent:UAMAgent" \ | ||
| -m "$model" \ | ||
| -n "$N_CONCURRENT" \ | ||
| --timeout-multiplier "$TIMEOUT_MULT" \ | ||
| --job-name "$job_name" \ | ||
| --jobs-dir "$RESULTS_DIR" \ | ||
| --ak "use_memory=$with_memory" \ | ||
| --ak "project_root=$PROJECT_ROOT" \ | ||
| 2>&1 | tee "$RESULTS_DIR/${job_name}.log" | ||
| echo "Results saved to: $RESULTS_DIR/$job_name" | ||
| } | ||
| # Generate comparison report | ||
| generate_report() { | ||
| echo "==================================================" | ||
| echo "Generating comparison report..." | ||
| echo "==================================================" | ||
| local report_file="$RESULTS_DIR/TERMINAL_BENCH_COMPARISON_${TIMESTAMP}.md" | ||
| cat > "$report_file" << EOF | ||
| # Terminal-Bench 2.0 UAM Comparison Report | ||
| **Generated:** $(date -Iseconds) | ||
| **Dataset:** $DATASET (89 tasks) | ||
| ## Configuration | ||
| - Concurrent trials: $N_CONCURRENT | ||
| - Timeout multiplier: $TIMEOUT_MULT | ||
| - Models tested: ${MODELS[*]} | ||
| ## Results Summary | ||
| | Model | Without UAM | With UAM | Improvement | | ||
| |-------|-------------|----------|-------------| | ||
| EOF | ||
| # Parse results from each run | ||
| for model in "${MODELS[@]}"; do | ||
| local model_safe=$(echo "$model" | tr '.-' '_') | ||
| local baseline_dir="$RESULTS_DIR/baseline_${model_safe}_${TIMESTAMP}" | ||
| local uam_dir="$RESULTS_DIR/uam_${model_safe}_${TIMESTAMP}" | ||
| local baseline_acc="N/A" | ||
| local uam_acc="N/A" | ||
| local improvement="N/A" | ||
| # Try to read results | ||
| if [ -f "$baseline_dir/summary.json" ]; then | ||
| baseline_acc=$(jq -r '.accuracy // "N/A"' "$baseline_dir/summary.json" 2>/dev/null || echo "N/A") | ||
| fi | ||
| if [ -f "$uam_dir/summary.json" ]; then | ||
| uam_acc=$(jq -r '.accuracy // "N/A"' "$uam_dir/summary.json" 2>/dev/null || echo "N/A") | ||
| fi | ||
| if [[ "$baseline_acc" != "N/A" && "$uam_acc" != "N/A" ]]; then | ||
| improvement=$(echo "$uam_acc - $baseline_acc" | bc 2>/dev/null || echo "N/A") | ||
| improvement="${improvement}%" | ||
| fi | ||
| echo "| $model | $baseline_acc | $uam_acc | $improvement |" >> "$report_file" | ||
| done | ||
| cat >> "$report_file" << EOF | ||
| ## Detailed Results | ||
| See individual job directories for full task-level results. | ||
| ### Key Findings | ||
| Based on our improved UAM implementation: | ||
| - Dynamic memory retrieval based on task classification | ||
| - Hierarchical prompting with recency bias | ||
| - Multi-turn execution with error feedback | ||
| ### Files | ||
| EOF | ||
| ls -la "$RESULTS_DIR"/*_${TIMESTAMP}* 2>/dev/null >> "$report_file" || echo "No result directories found" >> "$report_file" | ||
| echo "" | ||
| echo "Report saved to: $report_file" | ||
| } | ||
| # Main execution | ||
| main() { | ||
| echo "==================================================" | ||
| echo "Terminal-Bench 2.0 UAM Comparison Benchmark" | ||
| echo "==================================================" | ||
| echo "Timestamp: $TIMESTAMP" | ||
| echo "Results directory: $RESULTS_DIR" | ||
| echo "" | ||
| check_api_keys | ||
| # Parse arguments | ||
| local run_baseline=true | ||
| local run_uam=true | ||
| local use_custom=false | ||
| local selected_models=("${HARBOR_MODELS[@]}") | ||
| while [[ $# -gt 0 ]]; do | ||
| case $1 in | ||
| --baseline-only) | ||
| run_uam=false | ||
| shift | ||
| ;; | ||
| --uam-only) | ||
| run_baseline=false | ||
| shift | ||
| ;; | ||
| --custom-agent) | ||
| use_custom=true | ||
| shift | ||
| ;; | ||
| --model) | ||
| selected_models=("$2") | ||
| shift 2 | ||
| ;; | ||
| --help) | ||
| echo "Usage: $0 [options]" | ||
| echo "Options:" | ||
| echo " --baseline-only Run only baseline (no UAM)" | ||
| echo " --uam-only Run only with UAM" | ||
| echo " --custom-agent Use custom UAM agent instead of claude-code" | ||
| echo " --model MODEL Test only this model" | ||
| echo " --help Show this help" | ||
| exit 0 | ||
| ;; | ||
| *) | ||
| echo "Unknown option: $1" | ||
| exit 1 | ||
| ;; | ||
| esac | ||
| done | ||
| # Run benchmarks | ||
| for model in "${selected_models[@]}"; do | ||
| if [ "$run_baseline" = true ]; then | ||
| if [ "$use_custom" = true ]; then | ||
| run_custom_agent "$model" "false" | ||
| else | ||
| run_without_uam "$model" | ||
| fi | ||
| fi | ||
| if [ "$run_uam" = true ]; then | ||
| if [ "$use_custom" = true ]; then | ||
| run_custom_agent "$model" "true" | ||
| else | ||
| run_with_uam "$model" | ||
| fi | ||
| fi | ||
| done | ||
| # Generate report | ||
| generate_report | ||
| echo "" | ||
| echo "==================================================" | ||
| echo "Benchmark complete!" | ||
| echo "==================================================" | ||
| } | ||
| main "$@" |
| #!/bin/bash | ||
| # | ||
| # Run UAM Improved Benchmark using Factory API | ||
| # | ||
| # This benchmark tests UAM memory impact on coding tasks using droid CLI | ||
| # which accesses all models through a single Factory API key. | ||
| # | ||
| # Models tested: | ||
| # - Claude Opus 4.5 (Anthropic) | ||
| # - GPT 5.2 Codex (OpenAI) | ||
| # - GLM 4.7 (Zhipu) | ||
| # | ||
| # Usage: | ||
| # export FACTORY_API_KEY="your-factory-api-key" | ||
| # ./scripts/run-uam-benchmark.sh | ||
| # | ||
| set -e | ||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" | ||
| echo "==================================================" | ||
| echo "UAM Improved Benchmark" | ||
| echo "==================================================" | ||
| # Check for Factory API key | ||
| if [ -z "$FACTORY_API_KEY" ] && [ -z "$DROID_API_KEY" ]; then | ||
| echo "Error: FACTORY_API_KEY or DROID_API_KEY must be set" | ||
| echo "" | ||
| echo "The Factory API key provides unified access to:" | ||
| echo " - Claude Opus 4.5 (Anthropic)" | ||
| echo " - GPT 5.2 Codex (OpenAI)" | ||
| echo " - GLM 4.7 (Zhipu)" | ||
| echo "" | ||
| echo "Get your key at: https://app.factory.ai/settings/api-keys" | ||
| exit 1 | ||
| fi | ||
| echo "Factory API key is set ✓" | ||
| echo "" | ||
| # Verify droid is available | ||
| if ! command -v droid &> /dev/null; then | ||
| echo "Error: droid CLI not found" | ||
| echo "Install with: npm install -g @anthropic-ai/droid" | ||
| exit 1 | ||
| fi | ||
| echo "droid CLI is available ✓" | ||
| echo "" | ||
| # Build project | ||
| echo "Building project..." | ||
| cd "$PROJECT_ROOT" | ||
| npm run build | ||
| # Run benchmark | ||
| echo "" | ||
| echo "Starting benchmark..." | ||
| echo "Models: Claude Opus 4.5, GLM 4.7, GPT 5.2 Codex" | ||
| echo "Tasks: 6 coding challenges" | ||
| echo "Comparison: With vs Without UAM Memory" | ||
| echo "" | ||
| npx tsx src/benchmarks/improved-benchmark.ts | ||
| echo "" | ||
| echo "==================================================" | ||
| echo "Benchmark Complete" | ||
| echo "==================================================" | ||
| echo "Results saved to: IMPROVED_BENCHMARK_RESULTS.md" |
+337
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
| # Colors | ||
| GREEN='\033[0;32m' | ||
| YELLOW='\033[1;33m' | ||
| RED='\033[0;31m' | ||
| BLUE='\033[0;34m' | ||
| NC='\033[0m' # No Color | ||
| # Configuration | ||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" | ||
| HOOKS_DIR="${PROJECT_ROOT}/.git/hooks" | ||
| echo -e "${BLUE}🔧 Universal Agent Memory - Complete Setup${NC}" | ||
| echo "================================================" | ||
| echo "" | ||
| # ============================================================================ | ||
| # DEPENDENCY CHECKS | ||
| # ============================================================================ | ||
| echo -e "${BLUE}Checking dependencies...${NC}" | ||
| echo "" | ||
| MISSING_DEPS=() | ||
| RECOMMENDED_DEPS=() | ||
| # Required dependencies | ||
| echo -e "${YELLOW}Required dependencies:${NC}" | ||
| if ! command -v node &> /dev/null; then | ||
| echo -e " ${RED}✗${NC} Node.js (>= 18.0.0)" | ||
| MISSING_DEPS+=("Node.js >= 18.0.0") | ||
| else | ||
| NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1) | ||
| if [ "$NODE_VERSION" -lt 18 ]; then | ||
| echo -e " ${RED}✗${NC} Node.js (>= 18.0.0, found $(node -v))" | ||
| MISSING_DEPS+=("Node.js >= 18.0.0") | ||
| else | ||
| echo -e " ${GREEN}✓${NC} Node.js $(node -v)" | ||
| fi | ||
| fi | ||
| if ! command -v npm &> /dev/null; then | ||
| echo -e " ${RED}✗${NC} npm" | ||
| MISSING_DEPS+=("npm") | ||
| else | ||
| echo -e " ${GREEN}✓${NC} npm $(npm -v)" | ||
| fi | ||
| if ! command -v git &> /dev/null; then | ||
| echo -e " ${RED}✗${NC} git" | ||
| MISSING_DEPS+=("git") | ||
| else | ||
| echo -e " ${GREEN}✓${NC} git $(git --version | cut -d' ' -f3)" | ||
| fi | ||
| if ! command -v npx &> /dev/null; then | ||
| echo -e " ${RED}✗${NC} npx" | ||
| MISSING_DEPS+=("npx") | ||
| else | ||
| echo -e " ${GREEN}✓${NC} npx" | ||
| fi | ||
| echo "" | ||
| echo -e "${YELLOW}Recommended dependencies (optional but useful):${NC}" | ||
| if command -v docker &> /dev/null; then | ||
| echo -e " ${GREEN}✓${NC} Docker (enables local Qdrant for semantic search)" | ||
| else | ||
| echo -e " ${YELLOW}⚠${NC} Docker (install for local Qdrant: `curl -fsSL https://get.docker.com | sh`)" | ||
| RECOMMENDED_DEPS+=("Docker") | ||
| fi | ||
| if command -v python3 &> /dev/null; then | ||
| PYTHON_VERSION=$(python3 --version | cut -d' ' -f2) | ||
| echo -e " ${GREEN}✓${NC} Python 3 (${PYTHON_VERSION}) (enables Pattern RAG)" | ||
| else | ||
| echo -e " ${YELLOW}⚠${NC} Python 3 (install for Pattern RAG: `brew install python` or `apt install python3`)" | ||
| RECOMMENDED_DEPS+=("Python 3") | ||
| fi | ||
| if command -v pre-commit &> /dev/null; then | ||
| echo -e " ${GREEN}✓${NC} pre-commit (enables advanced git hooks)" | ||
| else | ||
| echo -e " ${YELLOW}⚠${NC} pre-commit (install for advanced hooks: `pip install pre-commit`)" | ||
| fi | ||
| echo "" | ||
| # ============================================================================ | ||
| # INSTALLATION | ||
| # ============================================================================ | ||
| if [ ${#MISSING_DEPS[@]} -gt 0 ]; then | ||
| echo -e "${RED}❌ Missing required dependencies:${NC}" | ||
| for dep in "${MISSING_DEPS[@]}"; do | ||
| echo -e " - ${dep}" | ||
| done | ||
| echo "" | ||
| echo "Please install the missing dependencies and run this script again." | ||
| echo "" | ||
| echo "Quick install commands:" | ||
| echo " # macOS:" | ||
| echo " brew install node git python docker" | ||
| echo "" | ||
| echo " # Ubuntu/Debian:" | ||
| echo " curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -" | ||
| echo " sudo apt-get install -y nodejs python3 docker.io" | ||
| echo "" | ||
| echo " # Windows (using winget):" | ||
| echo " winget install OpenJS.NodeJS.LTS" | ||
| echo " winget install Git.Git" | ||
| echo " winget install Python.Python.3.12" | ||
| echo " winget install Docker.DockerDesktop" | ||
| echo "" | ||
| exit 1 | ||
| fi | ||
| # Install npm dependencies | ||
| echo -e "${BLUE}Installing npm dependencies...${NC}" | ||
| cd "$PROJECT_ROOT" | ||
| if [ ! -d "node_modules" ]; then | ||
| npm install | ||
| echo -e "${GREEN}✓${NC} npm dependencies installed" | ||
| else | ||
| echo -e "${GREEN}✓${NC} npm dependencies already installed (skipping)" | ||
| fi | ||
| # Build TypeScript | ||
| echo "" | ||
| echo -e "${BLUE}Building TypeScript...${NC}" | ||
| npm run build | ||
| if [ $? -eq 0 ]; then | ||
| echo -e "${GREEN}✓${NC} TypeScript build completed" | ||
| else | ||
| echo -e "${RED}✗${NC} TypeScript build failed" | ||
| exit 1 | ||
| fi | ||
| # ============================================================================ | ||
| # GIT HOOKS SETUP | ||
| # ============================================================================ | ||
| echo "" | ||
| echo -e "${BLUE}Setting up git hooks...${NC}" | ||
| # Create hooks directory if it doesn't exist | ||
| if [ ! -d "$HOOKS_DIR" ]; then | ||
| echo -e " ${YELLOW}⚠${NC} Not a git repository, skipping hooks setup" | ||
| else | ||
| # Create hooks directory | ||
| mkdir -p "$HOOKS_DIR" | ||
| # Pre-commit hook - ensures worktree usage and code quality | ||
| cat > "${HOOKS_DIR}/pre-commit" << 'EOF' | ||
| #!/bin/bash | ||
| # | ||
| # UAM Pre-commit Hook | ||
| # | ||
| # Ensures: | ||
| # 1. No secrets are committed | ||
| # 2. Code passes linting | ||
| # 3. Tests pass (if modified files include tests) | ||
| # | ||
| # Check for secrets | ||
| if grep -rE "(api_key|apikey|password|secret|token)\s*=\s*['\"][^'\"]+['\"]" --include="*.ts" --include="*.js" --include="*.json" . 2>/dev/null | grep -v node_modules | grep -v ".worktrees" | grep -v dist; then | ||
| echo "Error: Potential secrets detected in committed files!" | ||
| echo "Please use environment variables for sensitive data." | ||
| exit 1 | ||
| fi | ||
| # Run linter | ||
| if npm run lint -- --max-warnings=0 2>/dev/null; then | ||
| echo "✓ Linting passed" | ||
| else | ||
| echo "Error: Linting failed. Run 'npm run lint:fix' to fix automatically." | ||
| exit 1 | ||
| fi | ||
| echo "Pre-commit checks passed" | ||
| exit 0 | ||
| EOF | ||
| chmod +x "${HOOKS_DIR}/pre-commit" | ||
| echo " ✓ Created pre-commit hook" | ||
| # Commit-msg hook - validates commit messages | ||
| cat > "${HOOKS_DIR}/commit-msg" << 'EOF' | ||
| #!/bin/bash | ||
| # | ||
| # UAM Commit-msg Hook | ||
| # | ||
| # Ensures commit messages follow conventional commits format: | ||
| # - feat: New feature | ||
| # - fix: Bug fix | ||
| # - docs: Documentation | ||
| # - style: Formatting | ||
| # - refactor: Code refactoring | ||
| # - test: Tests | ||
| # - chore: Maintenance | ||
| # | ||
| COMMIT_MSG_FILE=$1 | ||
| COMMIT_MSG=$(cat "$COMMIT_MSG_FILE") | ||
| # Skip if commit is empty or merge commit | ||
| if [[ -z "$COMMIT_MSG" ]] || [[ "$COMMIT_MSG" == "Merge"* ]]; then | ||
| exit 0 | ||
| fi | ||
| # Check for conventional commit format | ||
| if echo "$COMMIT_MSG" | grep -qE "^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\([a-z-]+\))?: .+"; then | ||
| echo "✓ Commit message format valid" | ||
| exit 0 | ||
| else | ||
| echo "Warning: Commit message doesn't follow conventional commits format." | ||
| echo "Recommended format: type(scope): description" | ||
| echo "Types: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert" | ||
| echo "" | ||
| echo "Examples:" | ||
| echo " feat: Add worktree creation command" | ||
| echo " fix(api): Resolve memory database path issue" | ||
| echo " docs: Update README with setup instructions" | ||
| echo "" | ||
| echo "Continue with commit? [y/N] " | ||
| read -r response | ||
| if [[ "$response" =~ ^(yes|y|Y)$ ]]; then | ||
| exit 0 | ||
| else | ||
| echo "Commit aborted. Please edit your commit message." | ||
| exit 1 | ||
| fi | ||
| fi | ||
| EOF | ||
| chmod +x "${HOOKS_DIR}/commit-msg" | ||
| echo " ✓ Created commit-msg hook" | ||
| # Pre-push hook - runs tests before pushing | ||
| cat > "${HOOKS_DIR}/pre-push" << 'EOF' | ||
| #!/bin/bash | ||
| # | ||
| # UAM Pre-push Hook | ||
| # | ||
| # Runs tests before pushing to remote | ||
| # | ||
| echo "Running tests before push..." | ||
| if npm test 2>&1 | tail -5; then | ||
| if [ ${PIPESTATUS[0]} -eq 0 ]; then | ||
| echo "✓ All tests passed" | ||
| exit 0 | ||
| fi | ||
| fi | ||
| echo "Error: Tests failed. Fix tests before pushing." | ||
| exit 1 | ||
| EOF | ||
| chmod +x "${HOOKS_DIR}/pre-push" | ||
| echo " ✓ Created pre-push hook" | ||
| echo "" | ||
| echo -e "${GREEN}✓${NC} Git hooks configured successfully" | ||
| fi | ||
| # ============================================================================ | ||
| # OPTIONAL: CREATE .GITCHRCL (for GitHub CLI) | ||
| # ============================================================================ | ||
| if command -v gh &> /dev/null; then | ||
| echo "" | ||
| echo -e "${BLUE}GitHub CLI detected. Setting up default PR template...${NC}" | ||
| if [ ! -f "${PROJECT_ROOT}/.github/pull_request_template.md" ]; then | ||
| mkdir -p "${PROJECT_ROOT}/.github" | ||
| cat > "${PROJECT_ROOT}/.github/pull_request_template.md" << 'EOF' | ||
| <!-- UAM Worktree PR Template --> | ||
| ## Summary | ||
| <!-- Describe what this PR does --> | ||
| ## Changes | ||
| <!-- List key changes --> | ||
| - | ||
| ## Testing | ||
| <!-- How did you test this? --> | ||
| - [ ] Tests pass: `npm test` | ||
| - [ ] Linting passes: `npm run lint` | ||
| - [ ] Manually tested (if applicable) | ||
| ## Related Issue | ||
| <!-- Link to related issue if any --> | ||
| Closes # | ||
| --- | ||
| <!-- UAM - Created via worktree: uam worktree pr --> | ||
| EOF | ||
| echo " ✓ Created PR template" | ||
| fi | ||
| fi | ||
| # ============================================================================ | ||
| # SETUP COMPLETE | ||
| # ============================================================================ | ||
| echo "" | ||
| echo -e "${GREEN}✅ Setup complete!${NC}" | ||
| echo "" | ||
| if [ ${#RECOMMENDED_DEPS[@]} -gt 0 ]; then | ||
| echo -e "${YELLOW}Recommended: Install missing optional dependencies${NC}" | ||
| for dep in "${RECOMMENDED_DEPS[@]}"; do | ||
| echo " - ${dep}" | ||
| done | ||
| echo "" | ||
| echo "You can install these later. Core functionality will work without them." | ||
| echo "" | ||
| fi | ||
| echo -e "${BLUE}Next steps:${NC}" | ||
| echo "" | ||
| echo "1. Initialize UAM in your project:" | ||
| echo " npx universal-agent-memory init" | ||
| echo "" | ||
| echo "2. Review the generated CLAUDE.md" | ||
| echo "" | ||
| echo "3. Start working - your AI assistant will follow the workflows!" | ||
| echo "" | ||
| echo "Optional: Set up cloud memory backends" | ||
| echo " export GITHUB_TOKEN=your_token" | ||
| echo " export QDRANT_API_KEY=your_key" | ||
| echo " export QDRANT_URL=your_url" | ||
| echo "" | ||
| echo "Documentation: https://github.com/DammianMiller/universal-agent-memory" |
+8
-3
| { | ||
| "name": "universal-agent-memory", | ||
| "version": "6.1.0", | ||
| "version": "6.1.1", | ||
| "description": "Universal AI agent memory system - CLAUDE.md templates, memory, worktrees for Claude Code, Factory.AI, VSCode, OpenCode, Forge", | ||
@@ -22,6 +22,7 @@ "type": "module", | ||
| "prepare": "npm run build", | ||
| "setup": "bash scripts/setup.sh", | ||
| "install:web": "bash scripts/install-web.sh", | ||
| "install:desktop": "bash scripts/install-desktop.sh", | ||
| "install:all": "bash scripts/install.sh", | ||
| "postinstall": "echo '\n✨ Run: npx universal-agent-memory init --interactive'" | ||
| "postinstall": "echo '\n✨ Run: npm run setup && npx universal-agent-memory init --interactive'" | ||
| }, | ||
@@ -90,5 +91,9 @@ "keywords": [ | ||
| "templates", | ||
| "scripts", | ||
| "README.md", | ||
| "LICENSE" | ||
| ] | ||
| ], | ||
| "optionalDependencies": { | ||
| "prettier": "^3.2.4" | ||
| } | ||
| } |
+268
-447
@@ -8,7 +8,7 @@ # Universal Agent Memory (UAM) | ||
| ### What if your AI coding assistant could *remember*? | ||
| ### AI coding assistants that remember | ||
| **Every lesson learned. Every bug fixed. Every architectural decision.** | ||
| *Not just in one conversation—but forever.* | ||
| _Not just in one conversation—but forever._ | ||
@@ -19,309 +19,207 @@ </div> | ||
| UAM transforms stateless AI coding assistants into **persistent, coordinated agents** that learn from every interaction and never make the same mistake twice. | ||
| ## Quick Start (30 seconds) | ||
| ```bash | ||
| npm install -g universal-agent-memory && cd your-project && uam init | ||
| # Install | ||
| npm install -g universal-agent-memory | ||
| # Run complete setup (installs dependencies, git hooks, etc.) | ||
| npm run setup | ||
| # Initialize in your project | ||
| uam init | ||
| ``` | ||
| **30 seconds to superhuman AI.** | ||
| That's it. Your AI now has persistent memory and follows proven workflows. | ||
| --- | ||
| ## The Problem We Solve | ||
| ## Complete Setup | ||
| Every time you start a new conversation with your AI assistant: | ||
| For a full installation with all features: | ||
| - It forgets your project's architectural decisions | ||
| - It suggests patterns you've already rejected | ||
| - It reintroduces bugs you've already fixed | ||
| - It doesn't know *why* the code is the way it is | ||
| **You're constantly re-teaching the same lessons.** | ||
| UAM fixes this by giving AI agents: | ||
| | Capability | What It Means | | ||
| |------------|---------------| | ||
| | **4-Layer Memory** | Recall decisions from months ago | | ||
| | **Hierarchical Memory** | Hot/warm/cold tiering with auto-promotion | | ||
| | **58 Optimizations** | Battle-tested from Terminal-Bench 2.0 benchmarking | | ||
| | **Pattern Router** | Auto-selects optimal patterns per task | | ||
| | **Adaptive Context** | Selectively loads context based on task type and history | | ||
| | **Multi-Agent Coordination** | Multiple AIs work without conflicts | | ||
| | **Worktree Isolation** | No accidental commits to main | | ||
| | **Code Field** | 89% bug detection vs 39% baseline | | ||
| | **Completion Gates** | 3 mandatory checks before "done" | | ||
| | **MCP Router** | 98%+ token reduction for multi-tool contexts | | ||
| | **Pre-execution Hooks** | Domain-specific setup before agent runs | | ||
| --- | ||
| ## See It In Action | ||
| ```bash | ||
| # Agent A starts work | ||
| $ uam task create --title "Fix auth vulnerability" --type bug --priority 0 | ||
| ✓ Task created: UAM-042 | ||
| # Install UAM CLI | ||
| npm install -g universal-agent-memory | ||
| $ uam worktree create fix-auth | ||
| ✓ Created worktree: 001-fix-auth | ||
| Branch: feature/001-fix-auth | ||
| Path: .worktrees/001-fix-auth | ||
| $ uam agent announce --resource src/auth/* --intent editing | ||
| ✓ Work announced. No conflicts detected. | ||
| # Meanwhile, Agent B checks for conflicts | ||
| $ uam agent overlaps --resource src/auth/* | ||
| ⚠ Agent A (fix-auth) is editing src/auth/* | ||
| Suggestion: Wait for completion or coordinate merge order | ||
| # Agent A completes and the lesson is preserved | ||
| $ uam memory store "CSRF vulnerability in auth: always validate origin header" | ||
| ✓ Stored in memory (importance: 8/10) | ||
| # Weeks later, ANY agent on this project will know: | ||
| $ uam memory query "auth security" | ||
| [2024-03-15] CSRF vulnerability in auth: always validate origin header | ||
| [2024-02-28] Session tokens must be httpOnly and secure | ||
| [2024-01-10] Auth refresh flow: use rotating tokens | ||
| # Run comprehensive setup | ||
| npm run setup | ||
| # This will: | ||
| # ✓ Check and install dependencies | ||
| # ✓ Install npm packages | ||
| # ✓ Build TypeScript | ||
| # ✓ Configure git hooks (pre-commit, commit-msg, pre-push) | ||
| # ✓ Set up GitHub PR templates | ||
| ``` | ||
| **The AI never forgets. The team never re-learns.** | ||
| ### Requirements | ||
| --- | ||
| **Required:** | ||
| ## Why Developers Love UAM | ||
| - Node.js >= 18.0.0 | ||
| - npm | ||
| - git | ||
| - npx | ||
| ### "My AI Finally Understands My Codebase" | ||
| **Optional (recommended):** | ||
| > *"After 3 months of using UAM, my Claude instance knows more about our architecture than most junior devs. It remembers that we chose Redux over MobX because of time-travel debugging, that our API uses snake_case because of the Python backend, that the auth flow was refactored twice. It's like pair programming with someone who has perfect recall."* | ||
| - Docker - for local Qdrant semantic search | ||
| - Python 3 - for Pattern RAG indexing | ||
| - pre-commit - for advanced git hooks | ||
| ### "Zero Merge Conflicts in Multi-Agent Workflows" | ||
| ### Installing Dependencies | ||
| > *"We run 5 agents in parallel on different features. Before UAM, we had merge conflicts daily. Now? Zero. The agents announce their work, check for overlaps, and coordinate merge order automatically. It's like they're a team."* | ||
| **macOS:** | ||
| ### "Our CI Bill Dropped 70%" | ||
| > *"UAM's deploy batcher changed everything. Instead of 15 CI runs from rapid commits, we get 1-2. Same work, fraction of the cost. The commit squashing alone paid for the setup time."* | ||
| --- | ||
| ## Key Features | ||
| ### 🧠 Endless Context Through Project Memory | ||
| **Your AI's context is NOT limited to the conversation.** | ||
| Memory persists with the project in SQLite databases that travel with the code: | ||
| ```bash | ||
| brew install node git python docker | ||
| ``` | ||
| agents/data/memory/ | ||
| ├── short_term.db # L1/L2: Recent actions + session memories (SQLite) | ||
| ├── long_term_prepopulated.json # L3: Prepopulated learnings for search | ||
| └── historical_context.db # Adaptive context + semantic cache (SQLite/WAL) | ||
| ``` | ||
| This means: | ||
| - Recall decisions from weeks/months ago | ||
| - Learn from past mistakes (gotchas never repeated) | ||
| - Understand why code is the way it is | ||
| - Seamless handoff between sessions | ||
| **Ubuntu/Debian:** | ||
| **The AI queries memory before every task** - it never starts from zero. | ||
| ### 🎯 Intelligent Task Routing | ||
| Tasks automatically route to specialized expert droids: | ||
| | Task Type | Routed To | Result | | ||
| |-----------|-----------|--------| | ||
| | TypeScript/JS | `typescript-node-expert` | Proper typing, async patterns | | ||
| | Security review | `security-auditor` | OWASP checks, secrets detection | | ||
| | Performance | `performance-optimizer` | Algorithm analysis, caching | | ||
| | Documentation | `documentation-expert` | Complete, accurate docs | | ||
| | Code quality | `code-quality-guardian` | SOLID, complexity checks | | ||
| **Missing an expert?** The AI generates one: | ||
| ```bash | ||
| uam droids add rust-expert --capabilities "ownership,lifetimes,async" --triggers "*.rs" | ||
| curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - | ||
| sudo apt-get install -y nodejs python3 docker.io | ||
| ``` | ||
| ### 🎯 Pattern Router - Battle-Tested Intelligence | ||
| **Windows:** | ||
| **58 optimizations in v2.7.0 from Terminal-Bench 2.0 analysis.** | ||
| Before ANY task, UAM's Pattern Router auto-selects which patterns apply: | ||
| ```powershell | ||
| winget install OpenJS.NodeJS.LTS | ||
| winget install Git.Git | ||
| winget install Python.Python.3.12 | ||
| winget install Docker.DockerDesktop | ||
| ``` | ||
| === PATTERN ROUTER === | ||
| Task: Implement user authentication | ||
| Classification: file-creation | ||
| PATTERNS: P12:[Y] P17:[Y] P20:[N] P11:[N] P35:[N] | ||
| ACTIVE: P3, P12, P17 | ||
| BLOCKING: [none] | ||
| VERIFIER: [read tests first] | ||
| === END === | ||
| ``` | ||
| **Key Patterns:** | ||
| --- | ||
| | Pattern | Name | Impact | | ||
| |---------|------|--------| | ||
| | **P12** | Output Existence Verification | Fixes 37% of agent failures | | ||
| | **P17** | Constraint Extraction | Catches "exactly/only/single" requirements | | ||
| | **P3** | Pre-execution State Protection | Backups before destructive actions | | ||
| | **P20** | Adversarial Thinking | Attack mindset for security bypass tasks | | ||
| | **P35** | Decoder-First Analysis | Read decoder BEFORE writing encoder | | ||
| | **P11** | Pre-Computed Solutions | Use libraries (Stockfish, scipy) not custom code | | ||
| ## Recommended Platform: **opencode** | ||
| **Pattern Categories:** | ||
| - **Core (P1-P12)**: Tool checks, state protection, output verification | ||
| - **Constraints (P17)**: Extract hidden requirements from task descriptions | ||
| - **Domain (P21-P26)**: Chess, git recovery, compression, polyglot code | ||
| - **Verification (P27-P31)**: Output cleanup, smoke tests, round-trip checks | ||
| - **Advanced (P32-P36)**: CLI execution, numerical stability, decoder-first analysis | ||
| UAM is optimized for **[opencode](https://opencode.ai)** - the local AI coding platform that provides: | ||
| **Optimization Categories (#40-#58):** | ||
| - **Code Field (#40)**: State assumptions before coding | ||
| - **Pattern Router (#41, #47)**: Auto-classification and blocking gates | ||
| - **Verifier-First (#53)**: Read tests before implementing | ||
| - **Near-Miss Handling (#54)**: 60-89% pass = fix specific failures, don't change approach | ||
| - **Compression (#55-#57)**: Reduced template size while preserving effectiveness | ||
| - **Persistent sessions** - Memory survives across sessions | ||
| - **Plugin architecture** - Pattern RAG, session hooks, and more | ||
| - **Local LLM support** - Run Qwen3.5 35B locally via llama.cpp | ||
| - **Built-in tooling** - File operations, bash, search, todo management | ||
| --- | ||
| ### Setup opencode (Recommended) | ||
| ### 🔬 What Works vs What Doesn't (From 40-Task Benchmark) | ||
| ```bash | ||
| # Install opencode | ||
| npm install -g opencode | ||
| **Strengths (100% pass rate in category):** | ||
| # Configure local LLM (optional, requires llama.cpp server) | ||
| # See: https://opencode.ai/docs/configuration | ||
| | Category | Why It Works | | ||
| |----------|--------------| | ||
| | **ML/Data Processing** | Clear data transformation, pandas/numpy operations | | ||
| | **Graphics/Rendering** | Path tracing, POV-Ray - well-defined algorithms | | ||
| | **Security Tasks** | Hash cracking, password recovery - tools available | | ||
| | **Formal Verification** | Coq proofs - step-by-step tactics | | ||
| # Initialize UAM in your project | ||
| cd your-project | ||
| uam init | ||
| ``` | ||
| **Weaknesses (Common failure modes):** | ||
| The `opencode.json` configuration file automatically loads UAM plugins for: | ||
| | Failure Mode | Fix | | ||
| |--------------|-----| | ||
| | **"File not created"** (37%) | P12 - Verify outputs exist before completing | | ||
| | **Missed constraints** | P17 - Extract "exactly/only/single" keywords | | ||
| | **First action destroys state** | P3 - Backup before agent runs | | ||
| | **Impossible tasks attempted** | P5/P23 - Detect and refuse immediately | | ||
| | **Complex toolchain setup** | Pre-execution hooks for dependencies | | ||
| - **Pattern RAG** - Context-aware pattern injection (~12K tokens saved) | ||
| - **Session hooks** - Pre-execution setup, memory preservation | ||
| - **Agent coordination** - Multi-agent workflows without conflicts | ||
| **Near-Misses (High-value improvements):** | ||
| ### Other Supported Platforms | ||
| | Task | Tests | Fix Needed | | ||
| |------|-------|------------| | ||
| | adaptive-rejection-sampler | 8/9 (89%) | Numerical edge case | | ||
| | headless-terminal | 6/7 (86%) | Service startup timing | | ||
| | db-wal-recovery | 5/7 (71%) | WAL parsing edge case | | ||
| | Platform | Notes | | ||
| | --------------- | --------------------------------------- | | ||
| | **Factory.AI** | Works well, use `CLAUDE.md` for context | | ||
| | **Claude Code** | Desktop app, full UAM support | | ||
| | **VSCode** | Use with Claude Code extension | | ||
| | **claude.ai** | Web version, limited tooling | | ||
| **Tasks That Will Never Pass (Without External Tools):** | ||
| - `gpt2-codegolf` - Requires pre-computed weights (500MB → 5KB impossible) | ||
| - `chess-best-move` - Requires vision/image parsing | ||
| - `break-filter-js-from-html` - Requires pre-computed XSS bypass patterns | ||
| --- | ||
| ### 🚦 Completion Gates - Mandatory Quality Checks | ||
| ## What UAM Gives You | ||
| Three gates must pass before the AI reports "done": | ||
| ### 🧠 Persistent Memory | ||
| | Gate | Check | If Fails | | ||
| |------|-------|----------| | ||
| | **Gate 1** | All output files exist | CREATE immediately | | ||
| | **Gate 2** | All constraints satisfied | FIX violations | | ||
| | **Gate 3** | All tests pass | ITERATE until 100% | | ||
| Your AI never forgets: | ||
| ```bash | ||
| # Gate 1: Verify outputs | ||
| ls -la /expected/output.json /expected/result.txt | ||
| # If missing → CREATE NOW, don't explain | ||
| # Store a lesson | ||
| uam memory store "Always validate CSRF tokens in auth flows" | ||
| # Gate 2: Check constraints | ||
| # Printed checklist with ☐/☑ for each requirement | ||
| # Gate 3: Run tests | ||
| npm test # Iterate on failures until 100% | ||
| # Query later (any agent, any session) | ||
| uam memory query "auth security" | ||
| ``` | ||
| --- | ||
| Memory persists in SQLite databases that travel with your code: | ||
| ### 🔒 Code Field - Better Code Generation | ||
| - `agents/data/memory/short_term.db` - Recent actions + session memories | ||
| - Semantic search via Qdrant (optional, `uam memory start`) | ||
| Based on [context-field research](https://github.com/NeoVertex1/context-field), UAM includes a 4-line prompt that dramatically improves code quality: | ||
| ### 🎯 Pattern Router | ||
| Before every task, UAM auto-selects relevant patterns: | ||
| ``` | ||
| Do not write code before stating assumptions. | ||
| Do not claim correctness you haven't verified. | ||
| Do not handle only the happy path. | ||
| Under what conditions does this work? | ||
| === PATTERN ROUTER === | ||
| Task: Fix authentication bug | ||
| Classification: bug-fix | ||
| ACTIVE: P3, P12, P17 | ||
| BLOCKING: [none] | ||
| === END === | ||
| ``` | ||
| **Results from 72 tests:** | ||
| - 100% assumption stating (vs 0% baseline) | ||
| - 89% bug detection in code review (vs 39% baseline) | ||
| - 100% refusal of impossible requests (vs 0% baseline) | ||
| - 320% more hidden issues found in debugging | ||
| **58 battle-tested patterns** from Terminal-Bench 2.0 analysis: | ||
| Every code generation task applies Code Field automatically. | ||
| - **P12** - Verify outputs exist (fixes 37% of failures) | ||
| - **P17** - Extract hidden constraints ("exactly", "only", "single") | ||
| - **P3** - Backup before destructive actions | ||
| - **P20** - Attack mindset for security tasks | ||
| ### 🌳 Safe Git Workflows | ||
| ### 🛡️ Completion Gates | ||
| **The AI never commits directly to main.** | ||
| Three mandatory checks before "done": | ||
| All changes use worktrees: | ||
| 1. **Output Existence** - All expected files exist | ||
| 2. **Constraint Compliance** - All requirements verified | ||
| 3. **Tests Pass** - `npm test` 100% | ||
| ### 🌳 Safe Worktrees | ||
| No more accidental commits to main: | ||
| ```bash | ||
| # AI automatically does this for every change | ||
| uam worktree create my-feature | ||
| # → Creates .worktrees/001-my-feature/ | ||
| # → Creates branch feature/001-my-feature | ||
| # → Works in isolation | ||
| uam worktree pr 001 | ||
| # → Pushes, creates PR, triggers reviews | ||
| uam worktree cleanup 001 | ||
| # → Removes worktree after merge | ||
| # → Creates isolated branch in .worktrees/ | ||
| # → All changes tracked | ||
| uam worktree pr <id> | ||
| # → Creates PR, triggers reviews | ||
| uam worktree cleanup <id> | ||
| # → Clean removal after merge | ||
| ``` | ||
| ### ✅ Complete Close-Out Workflow | ||
| ### 🤖 Expert Droids | ||
| Work isn't "done" until it's deployed and verified: | ||
| Tasks automatically route to specialists: | ||
| ``` | ||
| MERGE → DEPLOY → MONITOR → FIX (repeat until 100%) | ||
| ``` | ||
| | Task Type | Routed To | | ||
| | --------------- | ------------------------ | | ||
| | TypeScript/JS | `typescript-node-expert` | | ||
| | Security review | `security-auditor` | | ||
| | Performance | `performance-optimizer` | | ||
| | Documentation | `documentation-expert` | | ||
| The AI follows this loop automatically: | ||
| 1. Get PR approved, merge to main | ||
| 2. Verify CI/CD runs, check deployment | ||
| 3. Monitor logs, verify functionality | ||
| 4. If issues: create hotfix worktree, repeat | ||
| --- | ||
| **The AI stores learnings after every completed task** for future sessions. | ||
| ## How It Works | ||
| ## Installation | ||
| 1. **Install & init** - `npm i -g universal-agent-memory && uam init` | ||
| 2. **CLAUDE.md generated** - Auto-populated with project structure, commands, patterns | ||
| 3. **AI reads CLAUDE.md** - Follows embedded workflows automatically | ||
| 4. **Every task**: | ||
| - Pattern Router classifies task and selects patterns | ||
| - Adaptive context loads relevant memory | ||
| - Agent coordination checks for conflicts | ||
| - Worktree created for isolated changes | ||
| - Completion gates verify outputs, constraints, tests | ||
| - Learnings stored in memory | ||
| ### npm (Recommended) | ||
| --- | ||
| ```bash | ||
| npm install -g universal-agent-memory | ||
| ``` | ||
| ### One-Line Installers | ||
| ```bash | ||
| # Desktop (includes Docker for semantic search) | ||
| bash <(curl -fsSL https://raw.githubusercontent.com/DammianMiller/universal-agent-memory/main/scripts/install-desktop.sh) | ||
| # Web browsers (claude.ai, factory.ai) | ||
| bash <(curl -fsSL https://raw.githubusercontent.com/DammianMiller/universal-agent-memory/main/scripts/install-web.sh) | ||
| ``` | ||
| ## Commands | ||
@@ -331,105 +229,45 @@ | ||
| | Command | Description | | ||
| |---------|-------------| | ||
| | `uam init` | Initialize/update UAM (auto-merges, never loses data) | | ||
| | `uam generate` | Regenerate CLAUDE.md from project analysis | | ||
| | `uam update` | Update templates while preserving customizations | | ||
| | `uam analyze` | Analyze project structure and generate metadata | | ||
| | Command | Description | | ||
| | -------------- | ------------------------------------------------ | | ||
| | `uam init` | Initialize/update UAM (never loses data) | | ||
| | `uam generate` | Regenerate CLAUDE.md from project analysis | | ||
| | `uam update` | Update templates while preserving customizations | | ||
| ### Memory | ||
| | Command | Description | | ||
| |---------|-------------| | ||
| | `uam memory status` | Check memory system status | | ||
| | `uam memory query <search>` | Search memories | | ||
| | `uam memory store <content>` | Store a learning | | ||
| | `uam memory start` | Start Qdrant for semantic search | | ||
| | `uam memory prepopulate` | Populate from docs and git history | | ||
| | Command | Description | | ||
| | ---------------------------- | -------------------------------- | | ||
| | `uam memory status` | Check memory system status | | ||
| | `uam memory query <search>` | Search memories | | ||
| | `uam memory store <content>` | Store a learning | | ||
| | `uam memory start` | Start Qdrant for semantic search | | ||
| ### Tasks | ||
| | Command | Description | | ||
| |---------|-------------| | ||
| | `uam task create` | Create tracked task | | ||
| | `uam task list` | List all tasks | | ||
| | `uam task claim <id>` | Claim task (announces to other agents) | | ||
| | `uam task release <id>` | Complete task | | ||
| | `uam task ready` | List tasks ready to work on | | ||
| | `uam task stats` | Show task statistics | | ||
| | Command | Description | | ||
| | ----------------------- | -------------------------------------- | | ||
| | `uam task create` | Create tracked task | | ||
| | `uam task list` | List all tasks | | ||
| | `uam task claim <id>` | Claim task (announces to other agents) | | ||
| | `uam task release <id>` | Complete task | | ||
| ### Worktrees | ||
| | Command | Description | | ||
| |---------|-------------| | ||
| | `uam worktree create <name>` | Create isolated branch | | ||
| | `uam worktree pr <id>` | Create PR from worktree | | ||
| | `uam worktree cleanup <id>` | Remove worktree | | ||
| | `uam worktree list` | List all worktrees | | ||
| | Command | Description | | ||
| | ---------------------------- | ----------------------- | | ||
| | `uam worktree create <name>` | Create isolated branch | | ||
| | `uam worktree pr <id>` | Create PR from worktree | | ||
| | `uam worktree cleanup <id>` | Remove worktree | | ||
| ### Droids | ||
| | Command | Description | | ||
| |---------|-------------| | ||
| | `uam droids list` | List available expert droids | | ||
| | `uam droids add <name>` | Create new expert droid | | ||
| | `uam droids import <path>` | Import droids from another platform | | ||
| | Command | Description | | ||
| | ----------------------- | ---------------------------- | | ||
| | `uam droids list` | List available expert droids | | ||
| | `uam droids add <name>` | Create new expert droid | | ||
| ### Coordination | ||
| --- | ||
| | Command | Description | | ||
| |---------|-------------| | ||
| | `uam agent status` | View active agents | | ||
| | `uam agent overlaps` | Check for file conflicts | | ||
| | `uam agent announce` | Announce intent to work on a resource | | ||
| | `uam coord status` | Coordination overview | | ||
| ## Architecture | ||
| ### Deploy Batching | ||
| | Command | Description | | ||
| |---------|-------------| | ||
| | `uam deploy queue` | Queue a deploy action for batching | | ||
| | `uam deploy batch` | Create a batch from pending actions | | ||
| | `uam deploy execute` | Execute a deploy batch | | ||
| | `uam deploy flush` | Flush all pending deploys | | ||
| ### Multi-Model Architecture | ||
| | Command | Description | | ||
| |---------|-------------| | ||
| | `uam model status` | Show model router status | | ||
| | `uam model list` | List available models | | ||
| | `uam model fingerprint` | Show model performance fingerprints | | ||
| ### MCP Router (98%+ token reduction) | ||
| | Command | Description | | ||
| |---------|-------------| | ||
| | `uam mcp-router start` | Start hierarchical MCP router | | ||
| | `uam mcp-router stats` | Show router statistics and token savings | | ||
| | `uam mcp-router discover` | Discover tools matching a query | | ||
| | `uam mcp-router list` | List configured MCP servers | | ||
| ## How It Works | ||
| 1. **Install & Init**: `npm i -g universal-agent-memory && uam init` | ||
| 2. **CLAUDE.md Generated**: Auto-populated with project structure, commands, patterns, droids, and memory system instructions | ||
| 3. **AI Reads CLAUDE.md**: Follows the embedded workflows automatically | ||
| 4. **Every Task**: | ||
| - Pattern Router classifies task and selects applicable patterns | ||
| - Adaptive context decides what memory to load (none/minimal/full) | ||
| - Dynamic retrieval queries relevant memories from all tiers | ||
| - Check for agent overlaps before starting work | ||
| - Route to specialist droids if needed | ||
| - Create worktree for isolated changes | ||
| - Apply Code Field for better code generation | ||
| - Run completion gates: outputs exist, constraints met, tests pass | ||
| - Store learnings in memory for future sessions | ||
| 5. **Close-Out**: Merge → Deploy → Monitor → Fix loop until 100% | ||
| ## Memory Architecture | ||
| ### 4-Layer Memory System | ||
@@ -446,44 +284,50 @@ | ||
| ### Hierarchical Memory (Hot/Warm/Cold Tiering) | ||
| ### Hierarchical Memory (Hot/Warm/Cold) | ||
| On top of the 4-layer system, UAM implements hierarchical memory management: | ||
| - **HOT** (10 entries) - In-context, always included → <1ms access | ||
| - **WARM** (50 entries) - Cached, promoted on access → <5ms access | ||
| - **COLD** (500 entries) - Archived, semantic search → ~50ms access | ||
| ``` | ||
| HOT (10 entries) → In-context, always included → <1ms access | ||
| WARM (50 entries) → Cached, promoted on access → <5ms access | ||
| COLD (500 entries) → Archived, semantic search only → ~50ms access | ||
| ``` | ||
| ### Pattern RAG | ||
| - **Time-decay importance**: `importance * (0.95 ^ days_since_access)` | ||
| - **Auto-promotion**: Frequently accessed cold/warm entries promote to hotter tiers | ||
| - **Consolidation**: Old warm entries summarized into compressed cold entries | ||
| - **SQLite persistence**: Survives across sessions via `hierarchical_memory` table | ||
| Dynamically retrieves relevant patterns from Qdrant: | ||
| ### Adaptive Context System | ||
| - Queries `agent_patterns` collection | ||
| - Injects ~2 patterns per task (saves ~12K tokens) | ||
| - Filters by similarity score (default 0.35) | ||
| - Avoids duplicate injections per session | ||
| The memory system selectively loads context based on task classification: | ||
| --- | ||
| - **21 optimizations** including SQLite-backed historical benefit tracking | ||
| - **TF-IDF-like keyword scoring** for section relevance | ||
| - **13 domain-specific context sections** (security, file formats, git recovery, etc.) | ||
| - **Error-to-section mapping** for progressive escalation on failure | ||
| - **Semantic caching** for task-to-outcome mappings | ||
| ## Configuration | ||
| ### Additional Memory Features | ||
| ### opencode.json (Platform-specific) | ||
| - **Dynamic retrieval**: Adaptive depth based on query complexity (simple/moderate/complex) | ||
| - **Semantic compression**: 2-3x token reduction while preserving meaning | ||
| - **Speculative cache**: Pre-warms queries based on category patterns | ||
| - **Deduplication**: SHA-256 content hash + Jaccard similarity (0.8 threshold) | ||
| - **Feedback loop**: `recordTaskFeedback()` captures success/failure to improve future runs | ||
| - **Model router**: Per-model performance fingerprints by task category | ||
| ```json | ||
| { | ||
| "$schema": "https://opencode.ai/config.json", | ||
| "provider": { | ||
| "llama.cpp": { | ||
| "name": "llama-server (local)", | ||
| "options": { | ||
| "baseURL": "http://localhost:8080/v1", | ||
| "apiKey": "sk-qwen35b" | ||
| }, | ||
| "models": { | ||
| "qwen35-a3b-iq4xs": { | ||
| "name": "Qwen3.5 35B A3B (IQ4_XS)", | ||
| "limit": { | ||
| "context": 262144, | ||
| "output": 16384 | ||
| } | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "model": "llama.cpp/qwen35-a3b-iq4xs" | ||
| } | ||
| ``` | ||
| **Data is never deleted.** Memory databases persist with the project. | ||
| ### .uam.json (Project-specific) | ||
| Update with `uam init` or `uam generate` always merges - nothing is lost. | ||
| ## Configuration | ||
| Configuration in `.uam.json`: | ||
| ```json | ||
@@ -502,7 +346,2 @@ { | ||
| "directory": ".worktrees" | ||
| }, | ||
| "template": { | ||
| "sections": { | ||
| "codeField": true | ||
| } | ||
| } | ||
@@ -512,100 +351,93 @@ } | ||
| ## Platform Support | ||
| --- | ||
| | Platform | Context File | Works With | | ||
| |----------|--------------|------------| | ||
| | Claude Code | `CLAUDE.md` | Desktop app | | ||
| | Factory.AI | `CLAUDE.md` | Desktop/web | | ||
| | claude.ai | `CLAUDE.md` | Web browser | | ||
| | VSCode | `CLAUDE.md` | Extensions | | ||
| ## Requirements | ||
| ## Built-in Expert Droids | ||
| ### Required Dependencies | ||
| | Droid | Specialization | When Used | | ||
| |-------|----------------|-----------| | ||
| | `code-quality-guardian` | SOLID, complexity, naming | Before every PR | | ||
| | `security-auditor` | OWASP, secrets, injection (enhanced with 150+ security sources) | Before every PR | | ||
| | `performance-optimizer` | Algorithms, memory, caching | On request | | ||
| | `documentation-expert` | JSDoc, README, accuracy | On request | | ||
| | `debug-expert` | Dependency conflicts, runtime errors, SWE-bench debugging | Error handling | | ||
| | `sysadmin-expert` | Kernel, QEMU, networking, DNS, systemd | Infrastructure tasks | | ||
| | `ml-training-expert` | Model training, MTEB, RL, datasets | ML tasks | | ||
| | `terminal-bench-optimizer` | Task routing, time budgets, strategy orchestration | Benchmarking | | ||
| | Dependency | Version | Purpose | | ||
| | ---------- | ----------------- | --------------------------- | | ||
| | Node.js | >= 18.0.0 | Runtime environment | | ||
| | npm | Latest | Package manager | | ||
| | git | Latest | Version control (git hooks) | | ||
| | npx | Included with npm | Run CLI tools | | ||
| ## Built-in Skills | ||
| ### Optional Dependencies | ||
| | Skill | Purpose | Trigger | | ||
| |-------|---------|---------| | ||
| | `balls-mode` | Decomposed reasoning with confidence scoring | Complex decisions, debugging | | ||
| | `cli-design-expert` | CLI/TUI design patterns, UX, help systems | Building CLI tools | | ||
| | `typescript-node-expert` | TypeScript best practices, strict typing | TypeScript projects | | ||
| | `terminal-bench-strategies` | Proven strategies for Terminal-Bench tasks | Benchmark tasks | | ||
| | `unreal-engine-developer` | UE5, Blueprints, C++, Python scripting | Game development | | ||
| | `sec-context-review` | Security context review patterns | Security analysis | | ||
| | Dependency | Purpose | Installation | | ||
| | ---------- | -------------------------------- | ---------------------------------------------- | | ||
| | Docker | Local Qdrant for semantic search | [get.docker.com](https://get.docker.com) | | ||
| | Python 3 | Pattern RAG indexing | `brew install python` or `apt install python3` | | ||
| | pre-commit | Advanced git hooks | `pip install pre-commit` | | ||
| ## Requirements | ||
| ### Platform-Specific Setup | ||
| - Node.js 18+ | ||
| - Git | ||
| - Docker (optional, for semantic search) | ||
| **macOS:** | ||
| ## FAQ | ||
| ```bash | ||
| brew install node@18 git python docker | ||
| ``` | ||
| **Q: Do I need to manage memory manually?** | ||
| A: No. The AI queries and stores memory automatically per CLAUDE.md instructions. | ||
| **Ubuntu/Debian:** | ||
| **Q: What if I don't have Docker?** | ||
| A: UAM works without Docker. You lose semantic search but SQLite memory still works. | ||
| ```bash | ||
| curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - | ||
| sudo apt-get install -y nodejs python3 docker.io | ||
| ``` | ||
| **Q: Can multiple AI agents work on the same project?** | ||
| A: Yes. UAM includes coordination protocols to prevent merge conflicts. | ||
| **Windows (PowerShell):** | ||
| **Q: How do I update without losing my customizations?** | ||
| A: Run `uam init` or `uam generate`. Updates always merge - nothing is lost. | ||
| ```powershell | ||
| winget install OpenJS.NodeJS.LTS | ||
| winget install Git.Git | ||
| winget install Python.Python.3.12 | ||
| winget install Docker.DockerDesktop | ||
| ``` | ||
| **Q: What's Code Field?** | ||
| A: A prompt technique that makes AI state assumptions before coding. Based on [context-field research](https://github.com/NeoVertex1/context-field). | ||
| --- | ||
| ## Deep Dive Documentation | ||
| ## Testing & Quality | ||
| Want to understand how UAM works under the hood? | ||
| ```bash | ||
| # Run tests | ||
| npm test | ||
| ### Architecture & Analysis | ||
| # Run linter | ||
| npm run lint | ||
| | Document | Description | | ||
| |----------|-------------| | ||
| | [UAM Complete Analysis](docs/UAM_COMPLETE_ANALYSIS.md) | Full system architecture, all features | | ||
| | [Adaptive UAM Design](docs/ADAPTIVE_UAM_DESIGN.md) | Hybrid adaptive context selector design | | ||
| | [Multi-Model Architecture](docs/MULTI_MODEL_ARCHITECTURE.md) | Model routing and fingerprints | | ||
| | [MCP Router Setup](docs/MCP_ROUTER_SETUP.md) | Hierarchical MCP router for token reduction | | ||
| # Build TypeScript | ||
| npm run build | ||
| ``` | ||
| ### Benchmarking & Optimization | ||
| --- | ||
| | Document | Description | | ||
| |----------|-------------| | ||
| | [Terminal-Bench Learnings](docs/TERMINAL_BENCH_LEARNINGS.md) | Universal agent patterns discovered | | ||
| | [Behavioral Patterns](docs/BEHAVIORAL_PATTERNS.md) | What works vs what doesn't analysis | | ||
| | [Failing Tasks Solution Plan](docs/FAILING_TASKS_SOLUTION_PLAN.md) | Detailed fix strategies for each failure mode | | ||
| | [Benchmark Results](benchmark-results/) | All Terminal-Bench 2.0 run results | | ||
| | [Benchmark Evolution](docs/BENCHMARK_EVOLUTION.md) | How benchmark performance evolved | | ||
| | [Domain Strategy Guides](docs/DOMAIN_STRATEGY_GUIDES.md) | Task-specific strategies | | ||
| ## Documentation | ||
| ### Optimization Plans | ||
| ### Core CLAUDE.md Sections | ||
| | Document | Description | | ||
| |----------|-------------| | ||
| | [UAM Performance Analysis](docs/UAM_PERFORMANCE_ANALYSIS_2026-01-18.md) | Performance metrics and analysis | | ||
| | [Optimization Options](docs/OPTIMIZATION_OPTIONS.md) | Available optimization strategies | | ||
| | [V110 Pattern Analysis](docs/UAM_V110_PATTERN_ANALYSIS_2026-01-18.md) | Pattern effectiveness analysis | | ||
| | File | Purpose | | ||
| | ------------------------ | -------------------------------- | | ||
| | `CLAUDE_ARCHITECTURE.md` | Cluster topology, IaC rules | | ||
| | `CLAUDE_CODING.md` | Coding standards, security | | ||
| | `CLAUDE_WORKFLOWS.md` | Task workflows, completion gates | | ||
| | `CLAUDE_MEMORY.md` | Memory system, Pattern RAG | | ||
| | `CLAUDE_DROIDS.md` | Available droids/skills | | ||
| ### Deep Dive | ||
| | Document | Description | | ||
| | ---------------------------------------------------------------------- | -------------------------- | | ||
| | [`docs/UAM_COMPLETE_ANALYSIS.md`](docs/UAM_COMPLETE_ANALYSIS.md) | Full system architecture | | ||
| | [`docs/TERMINAL_BENCH_LEARNINGS.md`](docs/TERMINAL_BENCH_LEARNINGS.md) | Universal agent patterns | | ||
| | [`docs/BEHAVIORAL_PATTERNS.md`](docs/BEHAVIORAL_PATTERNS.md) | What works vs what doesn't | | ||
| | [`benchmark-results/`](benchmark-results/) | Terminal-Bench 2.0 results | | ||
| --- | ||
| ## What's Next? | ||
| ## What's Next | ||
| UAM v2.7.0 includes 58 optimizations. Recent additions: | ||
| UAM v5.0 includes: | ||
| - ✅ **58 Optimizations** - Battle-tested from Terminal-Bench 2.0 | ||
| - ✅ **Pattern Router** - Auto-selects optimal patterns per task with blocking gates | ||
| - ✅ **Pattern Router** - Auto-selects optimal patterns per task | ||
| - ✅ **Completion Gates** - 3 mandatory checks before "done" | ||
@@ -616,15 +448,6 @@ - ✅ **8 Expert Droids** - Specialized agents for common tasks | ||
| - ✅ **Hierarchical Memory** - Hot/warm/cold tiering with auto-promotion | ||
| - ✅ **Adaptive Context** - Selective context loading based on task type | ||
| - ✅ **MCP Router** - 98%+ token reduction for multi-tool contexts | ||
| - ✅ **Harbor Integration** - Terminal-Bench 2.0 benchmarking agent | ||
| - ✅ **Pattern RAG** - Context-aware pattern injection (~12K tokens saved) | ||
| - ✅ **opencode Integration** - Plugin system for seamless integration | ||
| - ✅ **Model Router** - Per-model performance fingerprints | ||
| Coming soon: | ||
| - **Cross-Project Learning** - Share patterns between codebases | ||
| - **Visual Memory Dashboard** - See what your AI knows | ||
| - **Continuous Benchmark Tracking** - Auto-run benchmarks on template changes | ||
| **Star the repo** to follow updates. **Open an issue** to request features. | ||
| --- | ||
@@ -636,6 +459,4 @@ | ||
| ## License | ||
| Terminal-Bench patterns from [Terminal-Bench 2.0](https://github.com/aptx432/terminal-bench) benchmarking. | ||
| MIT | ||
| --- | ||
@@ -647,4 +468,4 @@ | ||
| *Built for developers who want AI that learns.* | ||
| _Built for developers who want AI that learns._ | ||
| </div> |
Install scripts
Supply chain riskInstall scripts are run when the package is installed or built. Malicious packages often use scripts that run automatically to execute payloads or fetch additional code.
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Install scripts
Supply chain riskInstall scripts are run when the package is installed or built. Malicious packages often use scripts that run automatically to execute payloads or fetch additional code.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
2612828
2.16%436
2.11%36994
1.06%14
7.69%463
-27.88%79
1.28%