@cpretzinger/boss-claude 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +304 -1
  2. package/bin/boss-claude.js +1138 -0
  3. package/bin/commands/mode.js +250 -0
  4. package/bin/onyx-guard.js +259 -0
  5. package/bin/onyx-guard.sh +251 -0
  6. package/bin/prompts.js +284 -0
  7. package/bin/rollback.js +85 -0
  8. package/bin/setup-wizard.js +492 -0
  9. package/config/.env.example +17 -0
  10. package/lib/README.md +83 -0
  11. package/lib/agent-logger.js +61 -0
  12. package/lib/agents/memory-engineers/github-memory-engineer.js +251 -0
  13. package/lib/agents/memory-engineers/postgres-memory-engineer.js +633 -0
  14. package/lib/agents/memory-engineers/qdrant-memory-engineer.js +358 -0
  15. package/lib/agents/memory-engineers/redis-memory-engineer.js +383 -0
  16. package/lib/agents/memory-supervisor.js +526 -0
  17. package/lib/agents/registry.js +135 -0
  18. package/lib/auto-monitor.js +131 -0
  19. package/lib/checkpoint-hook.js +112 -0
  20. package/lib/checkpoint.js +319 -0
  21. package/lib/commentator.js +213 -0
  22. package/lib/context-scribe.js +120 -0
  23. package/lib/delegation-strategies.js +326 -0
  24. package/lib/hierarchy-validator.js +643 -0
  25. package/lib/index.js +15 -0
  26. package/lib/init-with-mode.js +261 -0
  27. package/lib/init.js +44 -6
  28. package/lib/memory-result-aggregator.js +252 -0
  29. package/lib/memory.js +35 -7
  30. package/lib/mode-enforcer.js +473 -0
  31. package/lib/onyx-banner.js +169 -0
  32. package/lib/onyx-identity.js +214 -0
  33. package/lib/onyx-monitor.js +381 -0
  34. package/lib/onyx-reminder.js +188 -0
  35. package/lib/onyx-tool-interceptor.js +341 -0
  36. package/lib/onyx-wrapper.js +315 -0
  37. package/lib/orchestrator-gate.js +334 -0
  38. package/lib/output-formatter.js +296 -0
  39. package/lib/postgres.js +1 -1
  40. package/lib/prompt-injector.js +220 -0
  41. package/lib/prompts.js +532 -0
  42. package/lib/session.js +153 -6
  43. package/lib/setup/README.md +187 -0
  44. package/lib/setup/env-manager.js +785 -0
  45. package/lib/setup/error-recovery.js +630 -0
  46. package/lib/setup/explain-scopes.js +385 -0
  47. package/lib/setup/github-instructions.js +333 -0
  48. package/lib/setup/github-repo.js +254 -0
  49. package/lib/setup/import-credentials.js +498 -0
  50. package/lib/setup/index.js +62 -0
  51. package/lib/setup/init-postgres.js +785 -0
  52. package/lib/setup/init-redis.js +456 -0
  53. package/lib/setup/integration-test.js +652 -0
  54. package/lib/setup/progress.js +357 -0
  55. package/lib/setup/rollback.js +670 -0
  56. package/lib/setup/rollback.test.js +452 -0
  57. package/lib/setup/setup-with-rollback.example.js +351 -0
  58. package/lib/setup/summary.js +400 -0
  59. package/lib/setup/test-github-setup.js +10 -0
  60. package/lib/setup/test-postgres-init.js +98 -0
  61. package/lib/setup/verify-setup.js +102 -0
  62. package/lib/task-agent-worker.js +235 -0
  63. package/lib/token-monitor.js +466 -0
  64. package/lib/tool-wrapper-integration.js +369 -0
  65. package/lib/tool-wrapper.js +387 -0
  66. package/lib/validators/README.md +497 -0
  67. package/lib/validators/config.js +583 -0
  68. package/lib/validators/config.test.js +175 -0
  69. package/lib/validators/github.js +310 -0
  70. package/lib/validators/github.test.js +61 -0
  71. package/lib/validators/index.js +15 -0
  72. package/lib/validators/postgres.js +525 -0
  73. package/package.json +98 -13
  74. package/scripts/benchmark-memory.js +433 -0
  75. package/scripts/check-secrets.sh +12 -0
  76. package/scripts/fetch-todos.mjs +148 -0
  77. package/scripts/graceful-shutdown.sh +156 -0
  78. package/scripts/install-onyx-hooks.js +373 -0
  79. package/scripts/install.js +119 -18
  80. package/scripts/redis-monitor.js +284 -0
  81. package/scripts/redis-setup.js +412 -0
  82. package/scripts/test-memory-retrieval.js +201 -0
  83. package/scripts/validate-exports.js +68 -0
  84. package/scripts/validate-package.js +120 -0
  85. package/scripts/verify-onyx-deployment.js +309 -0
  86. package/scripts/verify-redis-deployment.js +354 -0
  87. package/scripts/verify-redis-init.js +219 -0
@@ -0,0 +1,354 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * REDIS IDENTITY LOCK SYSTEM - DEPLOYMENT VERIFICATION
5
+ *
6
+ * This script verifies that the Redis-based mode enforcement system
7
+ * is properly deployed and functional.
8
+ *
9
+ * Run: node scripts/verify-redis-deployment.js
10
+ */
11
+
12
+ import { getEnforcer, MODES } from '../lib/mode-enforcer.js';
13
+ import { getGate } from '../lib/orchestrator-gate.js';
14
+ import { loadIdentity } from '../lib/identity.js';
15
+ import chalk from 'chalk';
16
+
17
+ const CHECKS = {
18
+ passed: 0,
19
+ failed: 0,
20
+ warnings: 0
21
+ };
22
+
23
+ function logCheck(status, message) {
24
+ const icons = {
25
+ pass: chalk.green('✓'),
26
+ fail: chalk.red('✗'),
27
+ warn: chalk.yellow('⚠')
28
+ };
29
+
30
+ console.log(`${icons[status]} ${message}`);
31
+
32
+ if (status === 'pass') CHECKS.passed++;
33
+ if (status === 'fail') CHECKS.failed++;
34
+ if (status === 'warn') CHECKS.warnings++;
35
+ }
36
+
37
+ function logSection(title) {
38
+ console.log(`\n${chalk.cyan.bold('═'.repeat(60))}`);
39
+ console.log(chalk.cyan.bold(` ${title}`));
40
+ console.log(`${chalk.cyan.bold('═'.repeat(60))}\n`);
41
+ }
42
+
43
+ async function verify() {
44
+ console.log(chalk.bold.white('\n╔══════════════════════════════════════════════════════════╗'));
45
+ console.log(chalk.bold.white('║ REDIS IDENTITY LOCK SYSTEM - DEPLOYMENT VERIFICATION ║'));
46
+ console.log(chalk.bold.white('╚══════════════════════════════════════════════════════════╝\n'));
47
+
48
+ try {
49
+ // ==========================================
50
+ // CHECK 1: Redis Connection
51
+ // ==========================================
52
+ logSection('1. Redis Connection');
53
+
54
+ const enforcer = getEnforcer();
55
+ const gate = getGate();
56
+
57
+ try {
58
+ await enforcer.getCurrentMode();
59
+ logCheck('pass', 'Redis connection successful');
60
+ } catch (error) {
61
+ logCheck('fail', `Redis connection failed: ${error.message}`);
62
+ console.log(chalk.red('\nREDIS_URL must be set. Check ~/.boss-claude/.env or project .env'));
63
+ process.exit(1);
64
+ }
65
+
66
+ // ==========================================
67
+ // CHECK 2: Mode Enforcement System
68
+ // ==========================================
69
+ logSection('2. Mode Enforcement System');
70
+
71
+ // Test setting mode
72
+ try {
73
+ await enforcer.setMode(MODES.WORKER, {
74
+ agent: 'deployment-test',
75
+ reason: 'verification-script'
76
+ });
77
+ logCheck('pass', 'Mode setting works');
78
+ } catch (error) {
79
+ logCheck('fail', `Mode setting failed: ${error.message}`);
80
+ }
81
+
82
+ // Test getting mode
83
+ try {
84
+ const mode = await enforcer.getCurrentMode();
85
+ if (mode === MODES.WORKER) {
86
+ logCheck('pass', `Current mode retrieved: ${mode}`);
87
+ } else {
88
+ logCheck('warn', `Unexpected mode: ${mode}`);
89
+ }
90
+ } catch (error) {
91
+ logCheck('fail', `Mode retrieval failed: ${error.message}`);
92
+ }
93
+
94
+ // Test mode metadata
95
+ try {
96
+ const metadata = await enforcer.getModeMetadata();
97
+ if (metadata && metadata.setBy === 'deployment-test') {
98
+ logCheck('pass', 'Mode metadata stored correctly');
99
+ } else {
100
+ logCheck('warn', 'Mode metadata incomplete');
101
+ }
102
+ } catch (error) {
103
+ logCheck('fail', `Metadata retrieval failed: ${error.message}`);
104
+ }
105
+
106
+ // ==========================================
107
+ // CHECK 3: Capability Enforcement
108
+ // ==========================================
109
+ logSection('3. Capability Enforcement');
110
+
111
+ // Test that WORKER mode blocks delegation
112
+ try {
113
+ await enforcer.setMode(MODES.WORKER, {
114
+ agent: 'test-worker',
115
+ reason: 'capability-test'
116
+ });
117
+
118
+ try {
119
+ await enforcer.checkCapability('canDelegate', 'Test delegation');
120
+ logCheck('fail', 'Worker mode should block delegation');
121
+ } catch (error) {
122
+ if (error.message.includes('CAPABILITY ENFORCEMENT')) {
123
+ logCheck('pass', 'Worker mode correctly blocks delegation');
124
+ } else {
125
+ logCheck('warn', `Unexpected error: ${error.message}`);
126
+ }
127
+ }
128
+ } catch (error) {
129
+ logCheck('fail', `Capability test failed: ${error.message}`);
130
+ }
131
+
132
+ // Test that ORCHESTRATOR mode allows delegation
133
+ try {
134
+ await enforcer.setMode(MODES.ORCHESTRATOR, {
135
+ agent: 'test-orchestrator',
136
+ reason: 'capability-test'
137
+ });
138
+
139
+ await enforcer.checkCapability('canDelegate', 'Test delegation');
140
+ logCheck('pass', 'Orchestrator mode allows delegation');
141
+ } catch (error) {
142
+ logCheck('fail', `Orchestrator capability test failed: ${error.message}`);
143
+ }
144
+
145
+ // ==========================================
146
+ // CHECK 4: Token Budget Enforcement
147
+ // ==========================================
148
+ logSection('4. Token Budget Enforcement');
149
+
150
+ // Test token budget for WORKER mode (max 20k)
151
+ try {
152
+ await enforcer.setMode(MODES.WORKER, {
153
+ agent: 'test-worker',
154
+ reason: 'token-budget-test'
155
+ });
156
+
157
+ try {
158
+ await enforcer.enforceTokenBudget(50000, 'Large task');
159
+ logCheck('fail', 'Worker mode should block 50k token budget');
160
+ } catch (error) {
161
+ if (error.message.includes('TOKEN BUDGET ENFORCEMENT')) {
162
+ logCheck('pass', 'Token budget enforcement works (blocks 50k for worker)');
163
+ } else {
164
+ logCheck('warn', `Unexpected error: ${error.message}`);
165
+ }
166
+ }
167
+ } catch (error) {
168
+ logCheck('fail', `Token budget test failed: ${error.message}`);
169
+ }
170
+
171
+ // Test token budget within limits
172
+ try {
173
+ await enforcer.enforceTokenBudget(10000, 'Small task');
174
+ logCheck('pass', 'Token budget allows tasks within limits');
175
+ } catch (error) {
176
+ logCheck('fail', `Token budget within-limits test failed: ${error.message}`);
177
+ }
178
+
179
+ // ==========================================
180
+ // CHECK 5: Orchestrator Gate Integration
181
+ // ==========================================
182
+ logSection('5. Orchestrator Gate Integration');
183
+
184
+ // Test gate status retrieval
185
+ try {
186
+ const status = await gate.getStatus();
187
+ if (status.mode && status.capabilities && status.restrictions) {
188
+ logCheck('pass', 'Gate status retrieval works');
189
+ } else {
190
+ logCheck('warn', 'Gate status incomplete');
191
+ }
192
+ } catch (error) {
193
+ logCheck('fail', `Gate status failed: ${error.message}`);
194
+ }
195
+
196
+ // Test gate beforeExecute
197
+ try {
198
+ await enforcer.setMode(MODES.WORKER, {
199
+ agent: 'test-worker',
200
+ reason: 'gate-test'
201
+ });
202
+
203
+ await gate.beforeExecute(
204
+ { description: 'Test execution' },
205
+ 5000
206
+ );
207
+ logCheck('pass', 'Gate beforeExecute works');
208
+ } catch (error) {
209
+ logCheck('fail', `Gate beforeExecute failed: ${error.message}`);
210
+ }
211
+
212
+ // Test gate blocks delegation in worker mode
213
+ try {
214
+ try {
215
+ await gate.beforeDelegate(
216
+ 'postgres-specialist',
217
+ { description: 'Test delegation' },
218
+ 10000
219
+ );
220
+ logCheck('fail', 'Gate should block delegation in worker mode');
221
+ } catch (error) {
222
+ if (error.message.includes('GATE BLOCKED')) {
223
+ logCheck('pass', 'Gate correctly blocks delegation in worker mode');
224
+ } else {
225
+ logCheck('warn', `Unexpected error: ${error.message}`);
226
+ }
227
+ }
228
+ } catch (error) {
229
+ logCheck('fail', `Gate delegation test failed: ${error.message}`);
230
+ }
231
+
232
+ // ==========================================
233
+ // CHECK 6: Mode History & Audit Trail
234
+ // ==========================================
235
+ logSection('6. Mode History & Audit Trail');
236
+
237
+ try {
238
+ const history = await enforcer.getModeHistory(5);
239
+ if (history && history.length > 0) {
240
+ logCheck('pass', `Mode history tracked (${history.length} entries)`);
241
+ } else {
242
+ logCheck('warn', 'Mode history empty');
243
+ }
244
+ } catch (error) {
245
+ logCheck('fail', `Mode history retrieval failed: ${error.message}`);
246
+ }
247
+
248
+ try {
249
+ const blocked = await enforcer.getBlockedActions(5);
250
+ if (blocked !== undefined) {
251
+ logCheck('pass', `Blocked actions log available (${blocked.length} entries)`);
252
+ } else {
253
+ logCheck('warn', 'Blocked actions log unavailable');
254
+ }
255
+ } catch (error) {
256
+ logCheck('fail', `Blocked actions retrieval failed: ${error.message}`);
257
+ }
258
+
259
+ try {
260
+ const stats = await enforcer.getModeStats();
261
+ if (stats && Object.keys(stats).length > 0) {
262
+ logCheck('pass', 'Mode statistics tracked');
263
+ } else {
264
+ logCheck('warn', 'Mode statistics empty');
265
+ }
266
+ } catch (error) {
267
+ logCheck('fail', `Mode stats retrieval failed: ${error.message}`);
268
+ }
269
+
270
+ // ==========================================
271
+ // CHECK 7: Agent Identity Tracking
272
+ // ==========================================
273
+ logSection('7. Agent Identity Tracking');
274
+
275
+ try {
276
+ await enforcer.setAgentIdentity('test-agent', 'testing');
277
+ const identity = await enforcer.getAgentIdentity();
278
+
279
+ if (identity && identity.agent === 'test-agent' && identity.domain === 'testing') {
280
+ logCheck('pass', 'Agent identity tracking works');
281
+ } else {
282
+ logCheck('warn', 'Agent identity incomplete');
283
+ }
284
+ } catch (error) {
285
+ logCheck('fail', `Agent identity test failed: ${error.message}`);
286
+ }
287
+
288
+ // ==========================================
289
+ // CHECK 8: Boss Identity Integration
290
+ // ==========================================
291
+ logSection('8. Boss Identity Integration');
292
+
293
+ try {
294
+ const bossIdentity = await loadIdentity();
295
+ if (bossIdentity && bossIdentity.level !== undefined) {
296
+ logCheck('pass', `Boss identity loaded (Level ${bossIdentity.level})`);
297
+ } else {
298
+ logCheck('warn', 'Boss identity incomplete');
299
+ }
300
+ } catch (error) {
301
+ logCheck('fail', `Boss identity load failed: ${error.message}`);
302
+ }
303
+
304
+ // ==========================================
305
+ // CHECK 9: Emergency Reset
306
+ // ==========================================
307
+ logSection('9. Emergency Reset');
308
+
309
+ try {
310
+ await enforcer.resetMode();
311
+ const mode = await enforcer.getCurrentMode();
312
+
313
+ if (mode === MODES.WORKER) {
314
+ logCheck('pass', 'Emergency reset works (defaults to WORKER)');
315
+ } else {
316
+ logCheck('warn', `Emergency reset returned unexpected mode: ${mode}`);
317
+ }
318
+ } catch (error) {
319
+ logCheck('fail', `Emergency reset failed: ${error.message}`);
320
+ }
321
+
322
+ // ==========================================
323
+ // FINAL REPORT
324
+ // ==========================================
325
+ console.log(chalk.bold.white('\n╔══════════════════════════════════════════════════════════╗'));
326
+ console.log(chalk.bold.white('║ DEPLOYMENT VERIFICATION REPORT ║'));
327
+ console.log(chalk.bold.white('╚══════════════════════════════════════════════════════════╝\n'));
328
+
329
+ console.log(`${chalk.green('Passed:')} ${CHECKS.passed}`);
330
+ console.log(`${chalk.red('Failed:')} ${CHECKS.failed}`);
331
+ console.log(`${chalk.yellow('Warnings:')} ${CHECKS.warnings}`);
332
+
333
+ console.log('');
334
+
335
+ if (CHECKS.failed === 0 && CHECKS.warnings === 0) {
336
+ console.log(chalk.green.bold('✓ ALL CHECKS PASSED - System fully operational!\n'));
337
+ process.exit(0);
338
+ } else if (CHECKS.failed === 0) {
339
+ console.log(chalk.yellow.bold('⚠ System operational with warnings\n'));
340
+ process.exit(0);
341
+ } else {
342
+ console.log(chalk.red.bold('✗ System has failures - review errors above\n'));
343
+ process.exit(1);
344
+ }
345
+
346
+ } catch (error) {
347
+ console.error(chalk.red.bold(`\n✗ Verification failed: ${error.message}\n`));
348
+ console.error(error.stack);
349
+ process.exit(1);
350
+ }
351
+ }
352
+
353
+ // Run verification
354
+ verify();
@@ -0,0 +1,219 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Redis Initialization Verification Script
5
+ *
6
+ * Quick script to verify Redis initialization is working correctly.
7
+ * Run this after setup to confirm all structures are in place.
8
+ *
9
+ * Usage:
10
+ * node scripts/verify-redis-init.js
11
+ *
12
+ * Or from anywhere:
13
+ * boss-claude redis:verify
14
+ */
15
+
16
+ import chalk from 'chalk';
17
+ import { verifyRedis, getRedisStats } from '../lib/setup/init-redis.js';
18
+ import dotenv from 'dotenv';
19
+ import { join } from 'path';
20
+ import os from 'os';
21
+ import { existsSync } from 'fs';
22
+
23
+ // Load environment variables
24
+ const envPath = join(os.homedir(), '.boss-claude', '.env');
25
+ if (existsSync(envPath)) {
26
+ dotenv.config({ path: envPath });
27
+ }
28
+
29
+ async function main() {
30
+ console.log(chalk.blue('\n🔍 Boss Claude Redis Verification\n'));
31
+
32
+ // Check for Redis URL
33
+ if (!process.env.REDIS_URL) {
34
+ console.log(chalk.red('✗ REDIS_URL not configured'));
35
+ console.log(chalk.dim('\nPlease run: boss-claude setup\n'));
36
+ process.exit(1);
37
+ }
38
+
39
+ console.log(chalk.dim(`Redis URL: ${process.env.REDIS_URL.split('@')[1] || 'configured'}\n`));
40
+
41
+ // Step 1: Verify connection and structures
42
+ console.log(chalk.bold('Step 1: Verifying Connection & Structures'));
43
+ console.log(chalk.dim('─'.repeat(50)));
44
+
45
+ try {
46
+ const verification = await verifyRedis(process.env.REDIS_URL);
47
+
48
+ if (!verification.connected) {
49
+ console.log(chalk.red('✗ Connection Failed'));
50
+ console.log(chalk.dim(` Error: ${verification.error}\n`));
51
+ process.exit(1);
52
+ }
53
+
54
+ console.log(chalk.green('✓ Connection Successful'));
55
+ console.log(chalk.dim(` Redis Version: ${verification.version}`));
56
+
57
+ // Check structures
58
+ console.log();
59
+ if (verification.structures.identity) {
60
+ console.log(chalk.green('✓ boss:identity exists'));
61
+ } else {
62
+ console.log(chalk.red('✗ boss:identity missing'));
63
+ }
64
+
65
+ if (verification.structures.sessionHistory >= 0) {
66
+ console.log(chalk.green(`✓ boss:sessions:history exists (${verification.structures.sessionHistory} sessions)`));
67
+ } else {
68
+ console.log(chalk.red('✗ boss:sessions:history missing'));
69
+ }
70
+
71
+ if (verification.structures.leaderboard >= 0) {
72
+ console.log(chalk.green(`✓ boss:leaderboard:xp exists (${verification.structures.leaderboard} users)`));
73
+ } else {
74
+ console.log(chalk.red('✗ boss:leaderboard:xp missing'));
75
+ }
76
+
77
+ // Health check results
78
+ console.log();
79
+ if (verification.healthCheck.passed) {
80
+ console.log(chalk.green('✓ All health checks passed'));
81
+ } else {
82
+ console.log(chalk.red('✗ Health check failed'));
83
+ console.log();
84
+ Object.entries(verification.healthCheck.details).forEach(([key, value]) => {
85
+ const status = value === 'OK' ? chalk.green('✓') : chalk.red('✗');
86
+ console.log(` ${status} ${key}: ${chalk.dim(value)}`);
87
+ });
88
+ }
89
+
90
+ } catch (error) {
91
+ console.log(chalk.red(`✗ Verification failed: ${error.message}\n`));
92
+ process.exit(1);
93
+ }
94
+
95
+ // Step 2: Get statistics
96
+ console.log('\n' + chalk.bold('Step 2: Redis Statistics'));
97
+ console.log(chalk.dim('─'.repeat(50)));
98
+
99
+ try {
100
+ const stats = await getRedisStats(process.env.REDIS_URL);
101
+
102
+ if (stats.identity) {
103
+ console.log(chalk.cyan('\nBoss Identity:'));
104
+ console.log(` Level: ${chalk.yellow(stats.identity.level)}`);
105
+ console.log(` XP: ${chalk.cyan(stats.identity.xp)}`);
106
+ console.log(` Token Bank: ${chalk.magenta(stats.identity.token_bank.toLocaleString())}`);
107
+ console.log(` Total Sessions: ${chalk.blue(stats.identity.total_sessions)}`);
108
+ console.log(` Repos Managed: ${chalk.green(stats.identity.repos_managed)}`);
109
+ }
110
+
111
+ console.log(chalk.cyan('\nData Structures:'));
112
+ console.log(` Session History: ${chalk.cyan(stats.totalSessions)} sessions`);
113
+ console.log(` Tracked Repos: ${chalk.green(stats.totalRepos)} repositories`);
114
+ console.log(` Active Sessions: ${chalk.yellow(stats.activeSessions)}`);
115
+ console.log(` Leaderboard Size: ${chalk.blue(stats.leaderboardSize)} users`);
116
+ console.log(` Cache Keys: ${chalk.magenta(stats.cacheKeys)}`);
117
+
118
+ if (Object.keys(stats.achievements).length > 0) {
119
+ console.log(chalk.cyan('\nAchievements:'));
120
+ Object.entries(stats.achievements).forEach(([user, achievements]) => {
121
+ const achievementList = achievements.length > 0 ? achievements.join(', ') : chalk.dim('none');
122
+ console.log(` ${chalk.cyan(user)}: ${achievementList}`);
123
+ });
124
+ }
125
+
126
+ } catch (error) {
127
+ console.log(chalk.red(`✗ Failed to get stats: ${error.message}\n`));
128
+ process.exit(1);
129
+ }
130
+
131
+ // Step 3: Recommendations
132
+ console.log('\n' + chalk.bold('Step 3: Recommendations'));
133
+ console.log(chalk.dim('─'.repeat(50)));
134
+
135
+ const verification = await verifyRedis(process.env.REDIS_URL);
136
+ const stats = await getRedisStats(process.env.REDIS_URL);
137
+
138
+ const recommendations = [];
139
+
140
+ // Check if identity needs initialization
141
+ if (!verification.structures.identity) {
142
+ recommendations.push({
143
+ level: 'critical',
144
+ message: 'Boss identity not found',
145
+ action: 'Run: boss-claude redis:init'
146
+ });
147
+ }
148
+
149
+ // Check if health check failed
150
+ if (!verification.healthCheck.passed) {
151
+ recommendations.push({
152
+ level: 'warning',
153
+ message: 'Health checks failed',
154
+ action: 'Run: boss-claude redis:init --force'
155
+ });
156
+ }
157
+
158
+ // Check for stale cache keys
159
+ if (stats.cacheKeys > 100) {
160
+ recommendations.push({
161
+ level: 'info',
162
+ message: `${stats.cacheKeys} cache keys (may need cleanup)`,
163
+ action: 'Cache keys auto-expire after 1 hour'
164
+ });
165
+ }
166
+
167
+ // Check for active sessions without recent activity
168
+ if (stats.activeSessions > 5) {
169
+ recommendations.push({
170
+ level: 'info',
171
+ message: `${stats.activeSessions} active sessions`,
172
+ action: 'Consider completing or saving old sessions'
173
+ });
174
+ }
175
+
176
+ if (recommendations.length === 0) {
177
+ console.log(chalk.green('✓ Everything looks good!'));
178
+ console.log(chalk.dim('\nNo recommendations at this time.\n'));
179
+ } else {
180
+ console.log();
181
+ recommendations.forEach((rec) => {
182
+ let icon = '●';
183
+ let color = chalk.blue;
184
+
185
+ if (rec.level === 'critical') {
186
+ icon = '✗';
187
+ color = chalk.red;
188
+ } else if (rec.level === 'warning') {
189
+ icon = '⚠';
190
+ color = chalk.yellow;
191
+ }
192
+
193
+ console.log(color(`${icon} ${rec.message}`));
194
+ console.log(chalk.dim(` → ${rec.action}`));
195
+ console.log();
196
+ });
197
+ }
198
+
199
+ // Success summary
200
+ console.log(chalk.bold('Verification Complete'));
201
+ console.log(chalk.dim('─'.repeat(50)));
202
+
203
+ if (verification.healthCheck.passed) {
204
+ console.log(chalk.green('\n✓ Redis is properly initialized and healthy'));
205
+ console.log(chalk.dim('\nYou can now use Boss Claude with confidence!\n'));
206
+ process.exit(0);
207
+ } else {
208
+ console.log(chalk.yellow('\n⚠ Redis needs attention'));
209
+ console.log(chalk.dim('\nFollow the recommendations above to fix issues.\n'));
210
+ process.exit(1);
211
+ }
212
+ }
213
+
214
+ // Run verification
215
+ main().catch((error) => {
216
+ console.error(chalk.red('\n✗ Verification script failed:'), error.message);
217
+ console.error(chalk.dim(error.stack));
218
+ process.exit(1);
219
+ });