#!/usr/bin/env node /** * Tractatus Session Closedown (v2.0) * * Comprehensive session shutdown procedure: * - Cleanup (ALL processes, files, sync) * - Framework performance analysis (TERMINAL + HANDOFF) * - Git change categorization (deployment readiness) * - Interactive deployment prompt * - Handoff document creation (AT END with deployment results) * - Compaction marker placement * * Copyright 2025 Tractatus Project * Licensed under Apache License 2.0 */ const fs = require('fs'); const path = require('path'); const { execSync } = require('child_process'); const readline = require('readline'); const SESSION_STATE_PATH = path.join(__dirname, '../.claude/session-state.json'); const SESSION_MARKER_PATH = path.join(__dirname, '../.claude/session-complete.marker'); const INSTRUCTION_HISTORY_PATH = path.join(__dirname, '../.claude/instruction-history.json'); /** * Color output helpers */ const colors = { reset: '\x1b[0m', bright: '\x1b[1m', green: '\x1b[32m', yellow: '\x1b[33m', blue: '\x1b[34m', red: '\x1b[31m', cyan: '\x1b[36m', magenta: '\x1b[35m' }; function log(message, color = 'reset') { console.log(`${colors[color]}${message}${colors.reset}`); } function header(message) { console.log(''); log('═'.repeat(70), 'cyan'); log(` ${message}`, 'bright'); log('═'.repeat(70), 'cyan'); console.log(''); } function section(message) { console.log(''); log(`▶ ${message}`, 'blue'); } function success(message) { log(` ✓ ${message}`, 'green'); } function warning(message) { log(` ⚠ ${message}`, 'yellow'); } function error(message) { log(` ✗ ${message}`, 'red'); } function info(message) { log(` ${message}`, 'cyan'); } /** * Prompt user for input */ function prompt(question) { const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); return new Promise(resolve => { rl.question(colors.yellow + question + colors.reset + ' ', answer => { rl.close(); resolve(answer.trim().toLowerCase()); }); }); } /** * Create visual pressure gauge */ function createPressureGauge(pressure, level) { // Normalize pressure to 0-1 range const normalizedPressure = Math.max(0, Math.min(1, pressure)); // Gauge parameters const gaugeWidth = 50; const filledLength = Math.round(normalizedPressure * gaugeWidth); const emptyLength = gaugeWidth - filledLength; // Choose color based on pressure level let gaugeColor = 'green'; let levelIndicator = '✓'; if (level === 'ELEVATED' || level === 'HIGH') { gaugeColor = 'yellow'; levelIndicator = '⚠'; } else if (level === 'CRITICAL' || level === 'SEVERE') { gaugeColor = 'red'; levelIndicator = '✗'; } // Build gauge const filled = '█'.repeat(filledLength); const empty = '░'.repeat(emptyLength); const percentage = (normalizedPressure * 100).toFixed(1); const gaugeLine = ` [${colors[gaugeColor]}${filled}${colors.reset}${empty}] ${percentage}%`; const statusLine = ` ${colors[gaugeColor]}${levelIndicator} Status: ${level}${colors.reset}`; return gaugeLine + '\n' + statusLine; } /** * Phase 1: Comprehensive Cleanup */ async function cleanup() { section('Phase 1: Comprehensive Cleanup'); const cleanupResults = { processes_killed: 0, files_cleaned: 0, instructions_synced: false, sync_verified: false }; // 1. Kill tracked background processes (inst_023) try { info('Cleaning up tracked background processes (inst_023)...'); // Use the new tracking script try { const cleanupOutput = execSync('node scripts/track-background-process.js cleanup', { encoding: 'utf8', stdio: 'pipe' }); const killedMatch = cleanupOutput.match(/(\d+) killed/); if (killedMatch) { cleanupResults.processes_killed = parseInt(killedMatch[1]); success(`Killed ${cleanupResults.processes_killed} tracked background process(es)`); } } catch (trackErr) { warning(` Tracked process cleanup failed: ${trackErr.message}`); } // Also check for untracked node/npm processes info('Checking for untracked background processes...'); let processes = []; try { const psOutput = execSync('ps aux | grep -E "npm|jest|node" | grep -v grep', { encoding: 'utf8' }); processes = psOutput.trim().split('\n').filter(line => line.length > 0); } catch (err) { // No processes found (grep returns non-zero) processes = []; } if (processes.length === 0) { success('No untracked background processes found'); } else { info(`Found ${processes.length} background process(es)`); processes.forEach((proc, index) => { const parts = proc.trim().split(/\s+/); const pid = parts[1]; const command = parts.slice(10).join(' '); // Don't kill system processes, systemd, or this script if (command.includes('session-closedown') || command.includes('systemd') || command.includes('/usr/lib/') || pid === process.pid.toString()) { info(` Skipping: ${command.substring(0, 60)}...`); return; } // Don't kill the dev server on port 9000 (inst_002: app runs on port 9000) // Killing dev server during session closedown breaks active development try { const portCheck = execSync(`lsof -i :9000 -t 2>/dev/null || true`, { encoding: 'utf8' }); if (portCheck.trim() === pid) { info(` Skipping dev server: ${command.substring(0, 60)}... (port 9000)`); return; } } catch (portErr) { // lsof failed, continue with kill attempt } info(` Killing PID ${pid}: ${command.substring(0, 60)}...`); try { execSync(`kill ${pid}`, { stdio: 'pipe' }); cleanupResults.processes_killed++; } catch (killErr) { // Process may already be dead, that's ok if (!killErr.message.includes('No such process')) { warning(` Could not kill PID ${pid}: ${killErr.message}`); } } }); success(`Killed ${cleanupResults.processes_killed} background process(es)`); // Verify cleanup try { const remainingOutput = execSync('ps aux | grep -E "npm start|node src/server" | grep -v grep', { encoding: 'utf8' }); if (remainingOutput.trim().length > 0) { warning('Some processes may still be running. Run `ps aux | grep node` to check.'); } else { success('Process cleanup verified - all target processes terminated'); } } catch (err) { // No processes found - cleanup successful success('Process cleanup verified - all target processes terminated'); } } } catch (err) { warning(`Process cleanup error: ${err.message}`); } // 2. Clean temporary artifacts try { info('Cleaning temporary artifacts...'); const artifactsToCheck = [ { path: '.memory-test', type: 'directory' }, { path: 'test-audit-logging.js', type: 'file' }, { path: 'test-audit-error.js', type: 'file' }, { path: 'trigger-all-services.js', type: 'file' }, { path: 'trigger-remaining-services.js', type: 'file' }, { path: 'test-audit-direct.js', type: 'file' }, { path: 'trigger-audit-test.js', type: 'file' } ]; artifactsToCheck.forEach(artifact => { const fullPath = path.join(__dirname, '..', artifact.path); if (fs.existsSync(fullPath)) { if (artifact.type === 'directory') { fs.rmSync(fullPath, { recursive: true, force: true }); } else { fs.unlinkSync(fullPath); } cleanupResults.files_cleaned++; info(` Removed: ${artifact.path}`); } }); if (cleanupResults.files_cleaned === 0) { success('No temporary artifacts to clean'); } else { success(`Cleaned ${cleanupResults.files_cleaned} temporary artifact(s)`); } } catch (err) { warning(`Artifact cleanup error: ${err.message}`); } // 3. Sync instruction history to database try { info('Syncing instruction history to database...'); const syncScript = path.join(__dirname, 'sync-instructions-to-db.js'); const output = execSync(`node ${syncScript} --force`, { encoding: 'utf8' }); // Parse output for counts const addedMatch = output.match(/Added: (\d+)/); const updatedMatch = output.match(/Updated: (\d+)/); cleanupResults.instructions_synced = true; cleanupResults.sync_verified = true; success('Instructions synced to database'); if (addedMatch) info(` Added: ${addedMatch[1]}`); if (updatedMatch) info(` Updated: ${updatedMatch[1]}`); } catch (err) { warning(`Instruction sync failed: ${err.message}`); } return cleanupResults; } /** * Phase 2: Framework Performance Analysis (WITH TERMINAL OUTPUT) */ async function analyzeFrameworkPerformance() { section('Phase 2: Framework Performance Analysis'); try { // Import services const BoundaryEnforcer = require('../src/services/BoundaryEnforcer.service'); const ContextPressureMonitor = require('../src/services/ContextPressureMonitor.service'); const CrossReferenceValidator = require('../src/services/CrossReferenceValidator.service'); const InstructionPersistenceClassifier = require('../src/services/InstructionPersistenceClassifier.service'); const MetacognitiveVerifier = require('../src/services/MetacognitiveVerifier.service'); const PluralisticDeliberationOrchestrator = require('../src/services/PluralisticDeliberationOrchestrator.service'); const stats = { boundary: BoundaryEnforcer.getStats(), pressure: ContextPressureMonitor.getStats(), validator: CrossReferenceValidator.getStats(), classifier: InstructionPersistenceClassifier.getStats(), verifier: MetacognitiveVerifier.getStats(), deliberation: PluralisticDeliberationOrchestrator.getStats() }; const totalActivity = stats.boundary.total_enforcements + stats.pressure.total_analyses + stats.validator.total_validations + stats.classifier.total_classifications + stats.verifier.total_verifications + stats.deliberation.total_deliberations; // *** OUTPUT TO TERMINAL *** // Display pressure gauge first const pressureValue = stats.pressure.current_pressure || 0; const pressureLevel = stats.pressure.pressure_level || 'NORMAL'; const pressureGauge = createPressureGauge(pressureValue, pressureLevel); console.log(''); log(' Context Pressure Gauge:', 'bright'); console.log(pressureGauge); console.log(''); if (totalActivity === 0) { warning('No framework activity recorded this session'); info('Framework services may not have been triggered'); info('This is expected if PreToolUse hook is not yet active'); } else { success(`Framework activity: ${totalActivity} total operations`); console.log(''); // Display per-service stats if (stats.boundary.total_enforcements > 0) { info(`BoundaryEnforcer: ${stats.boundary.total_enforcements} enforcements`); info(` Violations: ${stats.boundary.boundaries_violated}`); info(` Allowed: ${stats.boundary.allowed_count}`); } if (stats.pressure.total_analyses > 0) { info(`ContextPressureMonitor: ${stats.pressure.total_analyses} analyses`); info(` Current pressure: ${pressureValue.toFixed(2)} (${pressureLevel})`); } if (stats.validator.total_validations > 0) { info(`CrossReferenceValidator: ${stats.validator.total_validations} validations`); info(` Conflicts: ${stats.validator.conflicts_detected}`); } if (stats.classifier.total_classifications > 0) { info(`InstructionPersistenceClassifier: ${stats.classifier.total_classifications} classifications`); } if (stats.verifier.total_verifications > 0) { info(`MetacognitiveVerifier: ${stats.verifier.total_verifications} verifications`); } if (stats.deliberation.total_deliberations > 0) { info(`PluralisticDeliberationOrchestrator: ${stats.deliberation.total_deliberations} deliberations`); } // Calculate health score (0-100) const violations = stats.boundary.boundaries_violated || 0; const conflicts = stats.validator.conflicts_detected || 0; const totalChecks = totalActivity || 1; const healthScore = Math.max(0, 100 - ((violations + conflicts) / totalChecks * 100)); console.log(''); success(`Health Score: ${healthScore.toFixed(0)}/100`); } // Connect to MongoDB for audit log analysis const mongoose = require('mongoose'); await mongoose.connect('mongodb://localhost:27017/tractatus_dev', { serverSelectionTimeoutMS: 2000 }); const AuditLog = mongoose.model('AuditLog'); const auditLogs = await AuditLog.find({}).sort({ timestamp: -1 }).lean(); // Count by service const byService = {}; auditLogs.forEach(log => { byService[log.service] = (byService[log.service] || 0) + 1; }); const servicesActive = Object.keys(byService).length; console.log(''); info(`Audit Logs: ${auditLogs.length} total`); info(`Services Logging: ${servicesActive}/6`); if (servicesActive < 6) { warning('Not all framework services are logging to database'); const missing = ['BoundaryEnforcer', 'ContextPressureMonitor', 'CrossReferenceValidator', 'InstructionPersistenceClassifier', 'MetacognitiveVerifier', 'PluralisticDeliberationOrchestrator'] .filter(s => !byService[s]); info(` Missing: ${missing.join(', ')}`); } else { success('All 6 framework services are logging ✓'); } // Calculate health score const violations = stats.boundary?.boundaries_violated || 0; const conflicts = stats.validator?.conflicts_detected || 0; const totalChecks = totalActivity || 1; const healthScore = Math.max(0, 100 - ((violations + conflicts) / totalChecks * 100)); return { stats, totalActivity, healthScore, auditLogsCount: auditLogs.length, servicesActive, pressure: { value: pressureValue, level: pressureLevel, gauge: pressureGauge } }; } catch (err) { error(`Framework analysis failed: ${err.message}`); return { stats: null, totalActivity: 0, healthScore: 0, auditLogsCount: 0, servicesActive: 0, pressure: { value: 0, level: 'UNKNOWN', gauge: '' } }; } } /** * Phase 3: Git Change Categorization & Deployment Readiness */ function analyzeGitChanges() { section('Phase 3: Git Change Categorization'); const gitAnalysis = { branch: 'unknown', working_tree: 'unknown', modified_files: [], recent_commits: [], categories: { framework_services: [], documentation: [], configuration: [], features: [], temp_files: [], scripts: [], hooks: [] }, deployment_ready: [], excluded: [] }; try { // Get current branch gitAnalysis.branch = execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8' }).trim(); info(`Branch: ${gitAnalysis.branch}`); // Get status const status = execSync('git status --porcelain', { encoding: 'utf8' }); if (status.trim().length === 0) { gitAnalysis.working_tree = 'clean'; success('Working tree: clean - no changes to deploy'); return gitAnalysis; } gitAnalysis.working_tree = 'modified'; gitAnalysis.modified_files = status.trim().split('\n').map(line => line.substring(3)); info(`Working tree: ${gitAnalysis.modified_files.length} file(s) modified`); // Categorize changes gitAnalysis.modified_files.forEach(file => { // Framework services if (file.includes('src/services/') && file.endsWith('.service.js')) { gitAnalysis.categories.framework_services.push(file); } // Documentation else if (file.match(/\.(md|txt)$/i) && !file.includes('SESSION_')) { gitAnalysis.categories.documentation.push(file); } // Configuration else if (file.match(/\.(json|yaml|yml|env)$/) && !file.includes('session-state') && !file.includes('token-checkpoints')) { gitAnalysis.categories.configuration.push(file); } // Hooks else if (file.includes('.claude/hooks/')) { gitAnalysis.categories.hooks.push(file); } // Scripts else if (file.includes('scripts/')) { gitAnalysis.categories.scripts.push(file); } // Temp/test files else if (file.match(/test-|SESSION_|session-state|token-checkpoints/)) { gitAnalysis.categories.temp_files.push(file); } // Features (controllers, middleware, public files) else if (file.match(/src\/(controllers|middleware|models)|public\//)) { gitAnalysis.categories.features.push(file); } }); // Determine deployment-ready vs excluded gitAnalysis.deployment_ready = [ ...gitAnalysis.categories.framework_services, ...gitAnalysis.categories.features, ...gitAnalysis.categories.configuration, ...gitAnalysis.categories.hooks, ...gitAnalysis.categories.scripts ].filter(f => !f.includes('test-') && !f.includes('.test.') && !f.includes('session-state') && !f.includes('token-checkpoints') ); gitAnalysis.excluded = [ ...gitAnalysis.categories.temp_files, ...gitAnalysis.categories.documentation ]; // *** OUTPUT TO TERMINAL *** console.log(''); success('Git Change Analysis:'); console.log(''); if (gitAnalysis.categories.framework_services.length > 0) { log(' Framework Services:', 'bright'); gitAnalysis.categories.framework_services.forEach(f => info(` • ${f}`)); } if (gitAnalysis.categories.features.length > 0) { log(' Features:', 'bright'); gitAnalysis.categories.features.forEach(f => info(` • ${f}`)); } if (gitAnalysis.categories.configuration.length > 0) { log(' Configuration:', 'bright'); gitAnalysis.categories.configuration.forEach(f => info(` • ${f}`)); } if (gitAnalysis.categories.hooks.length > 0) { log(' Hooks:', 'bright'); gitAnalysis.categories.hooks.forEach(f => info(` • ${f}`)); } if (gitAnalysis.categories.scripts.length > 0) { log(' Scripts:', 'bright'); gitAnalysis.categories.scripts.forEach(f => info(` • ${f}`)); } if (gitAnalysis.categories.documentation.length > 0) { log(' Documentation (not deployed):', 'bright'); gitAnalysis.categories.documentation.forEach(f => info(` • ${f}`)); } if (gitAnalysis.categories.temp_files.length > 0) { log(' Temporary Files (excluded from deployment):', 'bright'); gitAnalysis.categories.temp_files.forEach(f => warning(` • ${f}`)); } console.log(''); success(`Deployment-ready changes: ${gitAnalysis.deployment_ready.length}`); warning(`Excluded from deployment: ${gitAnalysis.excluded.length}`); // Get recent commits const commits = execSync('git log --oneline -5', { encoding: 'utf8' }).trim(); gitAnalysis.recent_commits = commits.split('\n'); } catch (err) { error(`Git analysis error: ${err.message}`); } return gitAnalysis; } /** * Phase 4: Interactive Deployment */ async function interactiveDeployment(gitAnalysis, autoAnswer = null) { section('Phase 4: Deployment Decision'); const deploymentResult = { deployed: false, skipped: false, failed: false, output: '', error: null }; if (gitAnalysis.working_tree === 'clean') { info('No changes to deploy - working tree is clean'); deploymentResult.skipped = true; return deploymentResult; } if (gitAnalysis.deployment_ready.length === 0) { warning('No deployment-ready changes found'); info('All changes are documentation or temp files'); deploymentResult.skipped = true; return deploymentResult; } // Show summary console.log(''); log('═══════════════════════════════════════════════════════════', 'cyan'); log(' DEPLOYMENT SUMMARY', 'bright'); log('═══════════════════════════════════════════════════════════', 'cyan'); console.log(''); info(`Files ready for deployment: ${gitAnalysis.deployment_ready.length}`); console.log(''); gitAnalysis.deployment_ready.forEach(f => { info(` • ${f}`); }); console.log(''); log('═══════════════════════════════════════════════════════════', 'cyan'); console.log(''); // Use auto-answer if provided (non-interactive mode), otherwise prompt let answer; if (autoAnswer !== null) { answer = autoAnswer; info(`Auto-deploying: ${answer ? 'yes' : 'no'} (non-interactive mode)`); } else { answer = await prompt('Deploy these changes to production? (yes/no):'); } if (answer === 'yes' || answer === 'y' || answer === true) { info('Starting deployment...'); try { const deployScript = path.join(__dirname, 'deploy-full-project-SAFE.sh'); if (!fs.existsSync(deployScript)) { error('Deployment script not found: deploy-full-project-SAFE.sh'); deploymentResult.failed = true; deploymentResult.error = 'Deployment script not found'; return deploymentResult; } const output = execSync(`bash ${deployScript}`, { encoding: 'utf8', cwd: __dirname }); deploymentResult.deployed = true; deploymentResult.output = output; success('Deployment completed successfully!'); console.log(''); info('Deployment output:'); console.log(output); } catch (err) { error('Deployment failed!'); error(err.message); deploymentResult.failed = true; deploymentResult.error = err.message; deploymentResult.output = err.stdout || err.stderr || ''; } } else { info('Deployment skipped by user'); deploymentResult.skipped = true; } return deploymentResult; } /** * Helper: Get scope adjustment summary (inst_052) */ function getScopeAdjustmentSummary() { const scopeLogPath = path.join(__dirname, '../.claude/scope-adjustments.json'); if (!fs.existsSync(scopeLogPath)) { return '✅ No scope adjustments made this session'; } const log = JSON.parse(fs.readFileSync(scopeLogPath, 'utf8')); const sessionState = JSON.parse(fs.readFileSync(SESSION_STATE_PATH, 'utf8')); const sessionAdjustments = log.adjustments.filter(a => a.sessionId === sessionState.sessionId); if (sessionAdjustments.length === 0) { return '✅ No scope adjustments made this session'; } let summary = `⚠️ **${sessionAdjustments.length} scope adjustment(s) made:**\n\n`; sessionAdjustments.forEach((adj, idx) => { summary += `${idx + 1}. **${adj.type.toUpperCase()}** (message #${adj.messageNumber})\n`; summary += ` - Rationale: ${adj.rationale}\n`; if (adj.details) { summary += ` - Details: ${adj.details}\n`; } summary += ` - User discretion: ${adj.userGrantedDiscretion ? 'Yes' : 'No'}\n\n`; }); return summary; } /** * Helper: Get hook approval summary (inst_061) */ function getHookApprovalSummary() { const approvalCachePath = path.join(__dirname, '../.claude/approval-cache.json'); if (!fs.existsSync(approvalCachePath)) { return '✅ No hook approvals cached'; } const cache = JSON.parse(fs.readFileSync(approvalCachePath, 'utf8')); const sessionState = JSON.parse(fs.readFileSync(SESSION_STATE_PATH, 'utf8')); if (cache.sessionId !== sessionState.sessionId || cache.approvals.length === 0) { return '✅ No hook approvals cached for this session'; } let summary = `📋 **${cache.approvals.length} approval(s) cached:**\n\n`; summary += '_These "don\'t ask again" approvals will be reset at next session start._\n\n'; cache.approvals.forEach((approval, idx) => { summary += `${idx + 1}. \`${approval.commandType}\` in \`${approval.directory}\`\n`; }); return summary + '\n'; } /** * Phase 5: Create Handoff Document (AT END with all results) */ function createHandoffDocument(cleanupResults, frameworkAnalysis, gitAnalysis, deploymentResult) { section('Phase 5: Creating Session Handoff Document'); const today = new Date().toISOString().split('T')[0]; const handoffPath = path.join(__dirname, `../SESSION_CLOSEDOWN_${today}.md`); const content = `# Session Closedown - ${today} ## 🚀 NEXT SESSION STARTUP (Step-by-Step) ### 1. Initialize Session (MANDATORY - BLOCKS WITHOUT LOCAL SERVER) \`\`\`bash node scripts/session-init.js \`\`\` **⚠️ CRITICAL**: Run IMMEDIATELY at session start AND after context compaction! **Blocks if**: Local server not running on port 9000 **Fix**: 1. Open new terminal window 2. \`cd /home/theflow/projects/tractatus\` 3. \`npm start\` 4. Wait for "Server running on port 9000" 5. Re-run: \`node scripts/session-init.js\` **What session-init validates** (must all pass): - ✅ Local development server on port 9000 - ✅ All 6 framework components operational - ✅ Framework unit tests passing - ✅ Token checkpoints reset (50k, 100k, 150k) - ✅ Instruction history loaded from database - ✅ MongoDB connection (tractatus_dev) - ✅ CSP compliance scan - ✅ Defense-in-depth audit - ✅ Dependency license check --- ### 2. Review This Handoff Document **Read fully, especially**: - 🎯 **SESSION ACCOMPLISHMENTS** (what was done) - 🚨 **CRITICAL ISSUES IDENTIFIED** (what needs fixing) - 📋 **NEXT SESSION PRIORITIES** (what to do next) - 📊 **Framework Performance** (health metrics) - 🔧 **Git Changes & Deployment** (deployment status) --- ### 3. Verify System Ready **Quick health checks**: - [ ] Local server: http://localhost:9000 (must be accessible) - [ ] MongoDB: tractatus_dev accessible (checked by session-init) - [ ] Framework: All 6 services operational (reported by session-init) - [ ] Git: Review recent commits below \`\`\`bash git status # Check current branch and changes git log --oneline -5 # Review recent commits \`\`\` --- ### 4. Review Framework Context (If Needed) **Framework triggers** (use during session): - \`ff\` = Full framework audit for values/boundary questions - \`ffs\` = Framework statistics (use: \`node scripts/framework-stats.js --tokens=X/200000\`) **Token budget**: 200k (checkpoints at 50k, 100k, 150k) **Current pressure** (from previous session): - Level: ${frameworkAnalysis.pressure.level} - Score: ${(frameworkAnalysis.pressure.value * 100).toFixed(1)}% --- ### 5. Quick Reference **Database**: tractatus_dev (MongoDB port 27017) **Local Dev**: Port 9000 (MUST be running) **Production**: vps-93a693da.vps.ovh.net **Deployment**: \`./scripts/deploy.sh\` **Common Commands**: \`\`\`bash npm start # Start local server node scripts/framework-stats.js --tokens=X/200000 # Framework status ./scripts/deploy.sh --dry-run # Preview deployment \`\`\` **Documentation**: - **Quick Ref**: CLAUDE.md (project root) - **Session Guide**: docs/SESSION_MANAGEMENT_REFERENCE.md - **Full Framework**: CLAUDE_Tractatus_Maintenance_Guide.md --- ### 6. Common Issues & Troubleshooting **Issue**: "Local server not running" block **Fix**: \`npm start\` in separate terminal, then re-run session-init.js **Issue**: Framework tests failing **Fix**: \`npm test -- --testPathPattern="tests/unit"\` for details, fix failures, re-run **Issue**: MongoDB connection failed **Fix**: \`sudo systemctl start mongod\`, then re-run session-init.js **Issue**: Handoff not auto-loading after compaction **Fix**: Manually read latest SESSION_CLOSEDOWN_*.md in project root --- ## Session Summary **Date**: ${today} **Session ID**: ${gitAnalysis.branch} --- ## 🎯 SESSION ACCOMPLISHMENTS ⚠️ **IMPORTANT**: This section must be manually filled by Claude before closedown completes. The automated script cannot capture session-specific work. Claude must document: ### Major Deliverables Created **List all significant files/features/documents created:** - Example: "Publication timing research document (docs/outreach/PUBLICATION-TIMING-RESEARCH-NZ.md)" - Example: "Compressed 2-week launch plan (docs/outreach/COMPRESSED-LAUNCH-PLAN-2WEEKS.md)" - Example: "Config file updates (src/config/publication-targets.config.js)" ### Strategic Decisions Made **Document key decisions and rationale:** - Example: "Decided to start with Caixin Global (lower stakes, Asia-Pacific market)" - Example: "Article variation strategy (5 versions, >60% different for exclusivity)" ### Research & Analysis Completed **What was investigated/analyzed:** - Example: "All 20 publications researched with NZ timezone conversions" - Example: "Optimal submission windows calculated for each outlet" **⚠️ If this section is still templated/generic, the handoff document is INCOMPLETE.** --- ## 🚨 CRITICAL ISSUES IDENTIFIED ⚠️ **IMPORTANT**: Document bugs, blockers, or issues discovered during session. ### P0: Blockers (Must Fix Before Major Work) **List critical issues that block progress:** - Example: "docs.html language persistence broken (localStorage not working)" - Example: "API endpoint returning 500 errors" ### P1: High Value (Should Fix Soon) **List important but non-blocking issues:** - Example: "blog-curation.html Generate Draft has 404/400/500 errors" - Example: "Performance issue on large data sets" ### P2: Nice-to-Have (Can Defer) **List improvements or minor issues:** - Example: "UI could be more intuitive" - Example: "Code refactoring needed" **⚠️ If this section is empty but issues exist, document is INCOMPLETE.** --- ## 📋 NEXT SESSION PRIORITIES ⚠️ **IMPORTANT**: Specify exact tasks for next session with time estimates. ### Critical Path (Must Do First) **Ordered list of highest priority tasks:** 1. **[P0] Fix docs.html language issues** (2-3 hours) - Debug localStorage/cookie handling - Test all 8 language switches - Verify professional appearance 2. **[P1] Fix blog-curation Generate Draft** (2-3 hours) - Debug 404/400/500 API errors - Test end-to-end workflow ### Secondary Tasks (If Time Permits) **Additional work if critical path completed:** - Example: "Prepare content variations" - Example: "Review documentation" ### Decision Points **When to proceed vs. pivot:** - Example: "If docs.html not fixed, delay launch" - Example: "If blog tool not fixed, use manual workaround" **⚠️ If this section is generic ("Review work", "Continue development"), document is INCOMPLETE.** --- ## Framework Performance ### Context Pressure Gauge \`\`\` Pressure: ${(frameworkAnalysis.pressure.value * 100).toFixed(1)}% Status: ${frameworkAnalysis.pressure.level} ${'█'.repeat(Math.round(frameworkAnalysis.pressure.value * 50))}${'░'.repeat(50 - Math.round(frameworkAnalysis.pressure.value * 50))} \`\`\` ${frameworkAnalysis.pressure.level === 'CRITICAL' || frameworkAnalysis.pressure.level === 'SEVERE' ? '⚠️ **WARNING**: Context pressure is high. Consider session closedown.\n' : frameworkAnalysis.pressure.level === 'ELEVATED' || frameworkAnalysis.pressure.level === 'HIGH' ? '⚠️ **CAUTION**: Context pressure is elevated. Monitor closely.\n' : '✅ Context pressure is normal.\n'} ### Statistics ${frameworkAnalysis.totalActivity === 0 ? '⚠️ **No framework activity recorded**\n\nFramework services were not triggered during this session. This is expected if the PreToolUse hook is not yet active (requires session restart).' : `✅ **Framework Active** **Total Operations**: ${frameworkAnalysis.totalActivity} **Health Score**: ${frameworkAnalysis.healthScore.toFixed(0)}/100 **By Service**: ${frameworkAnalysis.stats.boundary.total_enforcements > 0 ? `- BoundaryEnforcer: ${frameworkAnalysis.stats.boundary.total_enforcements} enforcements\n` : ''}${frameworkAnalysis.stats.pressure.total_analyses > 0 ? `- ContextPressureMonitor: ${frameworkAnalysis.stats.pressure.total_analyses} analyses\n` : ''}${frameworkAnalysis.stats.validator.total_validations > 0 ? `- CrossReferenceValidator: ${frameworkAnalysis.stats.validator.total_validations} validations\n` : ''}${frameworkAnalysis.stats.classifier.total_classifications > 0 ? `- InstructionPersistenceClassifier: ${frameworkAnalysis.stats.classifier.total_classifications} classifications\n` : ''}${frameworkAnalysis.stats.verifier.total_verifications > 0 ? `- MetacognitiveVerifier: ${frameworkAnalysis.stats.verifier.total_verifications} verifications\n` : ''}${frameworkAnalysis.stats.deliberation.total_deliberations > 0 ? `- PluralisticDeliberationOrchestrator: ${frameworkAnalysis.stats.deliberation.total_deliberations} deliberations\n` : ''}`} ### Audit Logs **Total Logs**: ${frameworkAnalysis.auditLogsCount} **Services Logging**: ${frameworkAnalysis.servicesActive}/6 ${frameworkAnalysis.servicesActive < 6 ? `⚠️ **Warning**: Not all framework services are logging audit data.` : `✅ All framework services are operational.`} --- ## Git Changes & Deployment **Branch**: \`${gitAnalysis.branch}\` **Working Tree**: ${gitAnalysis.working_tree} ${gitAnalysis.deployment_ready.length > 0 ? `### Deployment-Ready Changes (${gitAnalysis.deployment_ready.length}) ${gitAnalysis.deployment_ready.map(f => `- ${f}`).join('\n')} ### Deployment Status ${deploymentResult.deployed ? `✅ **DEPLOYED TO PRODUCTION** Deployment completed successfully. \`\`\` ${deploymentResult.output} \`\`\`` : deploymentResult.skipped ? '⏭️ **SKIPPED** - Deployment was not performed' : deploymentResult.failed ? `❌ **FAILED** Error: ${deploymentResult.error} \`\`\` ${deploymentResult.output} \`\`\`` : '❓ **UNKNOWN** - Deployment status unclear'} ` : 'No deployment-ready changes.'} ${gitAnalysis.excluded.length > 0 ? `### Excluded from Deployment (${gitAnalysis.excluded.length}) ${gitAnalysis.excluded.map(f => `- ${f}`).join('\n')}` : ''} **Recent Commits**: \`\`\` ${gitAnalysis.recent_commits.join('\n')} \`\`\` --- ## Cleanup Summary - ✅ Background processes killed: ${cleanupResults.processes_killed} - ✅ Temporary files cleaned: ${cleanupResults.files_cleaned} - ${cleanupResults.instructions_synced ? '✅' : '❌'} Instructions synced to database - ${cleanupResults.sync_verified ? '✅' : '❌'} Sync verification complete --- ## Session Activity Tracking ### Scope Adjustments (inst_052) ${getScopeAdjustmentSummary()} ### Hook Approvals (inst_061) ${getHookApprovalSummary()} --- ## Next Session **Startup Sequence**: 1. Run \`node scripts/session-init.js\` (MANDATORY) 2. Review this closedown document 3. ${deploymentResult.deployed ? 'Verify production deployment' : 'Consider deploying changes if ready'} **⚠️ REMINDER**: If "SESSION ACCOMPLISHMENTS", "CRITICAL ISSUES", or "NEXT SESSION PRIORITIES" sections above are still showing example/template text, this handoff document is INCOMPLETE. Claude must fill those sections with actual session-specific content before closedown completes. --- ## 📊 Dashboard View framework analytics: - **Audit Dashboard**: http://localhost:9000/admin/audit-analytics.html - **Calendar**: http://localhost:9000/admin/calendar.html --- **Session closed**: ${new Date().toISOString()} **Next action**: Run session-init.js at start of new session --- ## ⚠️ DOCUMENT COMPLETENESS CHECK Before using this handoff document, verify: - [ ] "🎯 SESSION ACCOMPLISHMENTS" has real content (not examples) - [ ] "🚨 CRITICAL ISSUES IDENTIFIED" lists actual bugs/issues (or explicitly says "None") - [ ] "📋 NEXT SESSION PRIORITIES" has specific tasks with time estimates (not generic "continue work") **If any section is still templated, search for corrected version or regenerate handoff manually.** `; fs.writeFileSync(handoffPath, content, 'utf8'); success(`Handoff document created: SESSION_CLOSEDOWN_${today}.md`); warning('⚠️ IMPORTANT: Handoff document contains template sections that MUST be filled:'); warning(' • SESSION ACCOMPLISHMENTS - Document actual work completed'); warning(' • CRITICAL ISSUES IDENTIFIED - List bugs/blockers discovered'); warning(' • NEXT SESSION PRIORITIES - Specify exact tasks with time estimates'); warning(' If these sections remain templated, the handoff is INCOMPLETE!'); return handoffPath; } /** * Phase 6: Create Compaction Marker */ function createCompactionMarker(handoffPath) { section('Phase 6: Setting Compaction Marker'); const marker = { session_completed: true, closedown_timestamp: new Date().toISOString(), next_action: 'compaction_expected', recovery_doc: path.basename(handoffPath) }; fs.writeFileSync(SESSION_MARKER_PATH, JSON.stringify(marker, null, 2), 'utf8'); success('Compaction marker created'); info('Next session-init will detect post-compaction restart'); } /** * Main execution */ async function main() { // Parse command-line arguments const args = process.argv.slice(2); let autoAnswer = null; if (args.includes('--deploy') || args.includes('-y')) { autoAnswer = true; } else if (args.includes('--no-deploy') || args.includes('-n')) { autoAnswer = false; } header('Tractatus Session Closedown (v2.0)'); log(' Comprehensive session shutdown with deployment support', 'cyan'); log(' This will cleanup, analyze, optionally deploy, and create handoff', 'cyan'); if (autoAnswer !== null) { log(` Non-interactive mode: ${autoAnswer ? 'will deploy' : 'will skip deployment'}`, 'cyan'); } console.log(''); // Phase 1: Comprehensive Cleanup const cleanupResults = await cleanup(); // Phase 2: Framework Analysis (with terminal output) const frameworkAnalysis = await analyzeFrameworkPerformance(); // Phase 3: Git Change Categorization const gitAnalysis = analyzeGitChanges(); // Phase 4: Interactive Deployment const deploymentResult = await interactiveDeployment(gitAnalysis, autoAnswer); // Phase 5: Create Handoff (AT END with all results) const handoffPath = createHandoffDocument(cleanupResults, frameworkAnalysis, gitAnalysis, deploymentResult); // Phase 6: Compaction Marker createCompactionMarker(handoffPath); // Summary header('Session Closedown Complete'); console.log(''); success('All phases completed successfully'); console.log(''); if (deploymentResult.deployed) { success('✓ Changes deployed to production'); } else if (deploymentResult.skipped) { info('⏭ Deployment skipped'); } else if (deploymentResult.failed) { error('✗ Deployment failed - see handoff document'); } console.log(''); info('Handoff document created:'); log(` ${handoffPath}`, 'bright'); console.log(''); info('Next session startup:'); log(' node scripts/session-init.js', 'bright'); console.log(''); warning('⚠️ STOP ALL WORK NOW - Session is complete'); console.log(''); log(' Handoff signals intent to start NEW session with fresh context.', 'yellow'); log(' Do NOT continue working after closedown.', 'yellow'); console.log(''); process.exit(0); } // Run main().catch(err => { console.error(''); error(`Closedown failed: ${err.message}`); console.error(''); process.exit(1); });