@theihtisham/agent-shadow-brain 6.3.0 → 7.1.0

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 (66) hide show
  1. package/CHANGELOG.md +420 -391
  2. package/LICENSE +21 -21
  3. package/README.md +450 -438
  4. package/dist/adapters/aider.js +13 -13
  5. package/dist/adapters/base-adapter.js +14 -14
  6. package/dist/adapters/codex.js +8 -8
  7. package/dist/adapters/roo-code.js +18 -18
  8. package/dist/brain/adr-engine.js +11 -11
  9. package/dist/brain/analyzer.js +30 -30
  10. package/dist/brain/auto-update.js +1 -1
  11. package/dist/brain/brain-portability.js +1 -1
  12. package/dist/brain/global-brain.d.ts +52 -63
  13. package/dist/brain/global-brain.d.ts.map +1 -1
  14. package/dist/brain/global-brain.js +577 -339
  15. package/dist/brain/global-brain.js.map +1 -1
  16. package/dist/brain/health-score.js +19 -19
  17. package/dist/brain/learning-engine.js +59 -59
  18. package/dist/brain/mcp-server.d.ts +3 -0
  19. package/dist/brain/mcp-server.d.ts.map +1 -1
  20. package/dist/brain/mcp-server.js +50 -6
  21. package/dist/brain/mcp-server.js.map +1 -1
  22. package/dist/brain/orchestrator.js +1 -1
  23. package/dist/brain/plugin-system.js +23 -23
  24. package/dist/brain/pr-generator.js +19 -19
  25. package/dist/brain/project-context.js +1 -1
  26. package/dist/brain/project-context.js.map +1 -1
  27. package/dist/brain/report-generator.js +270 -270
  28. package/dist/brain/task-workflow.d.ts +22 -0
  29. package/dist/brain/task-workflow.d.ts.map +1 -0
  30. package/dist/brain/task-workflow.js +182 -0
  31. package/dist/brain/task-workflow.js.map +1 -0
  32. package/dist/brain/workflow-skills.d.ts +86 -0
  33. package/dist/brain/workflow-skills.d.ts.map +1 -0
  34. package/dist/brain/workflow-skills.js +514 -0
  35. package/dist/brain/workflow-skills.js.map +1 -0
  36. package/dist/cli.js +107 -34
  37. package/dist/cli.js.map +1 -1
  38. package/dist/dashboard/server.js +1 -1
  39. package/dist/dashboard/v6-dashboard-html.d.ts +1 -1
  40. package/dist/dashboard/v6-dashboard-html.d.ts.map +1 -1
  41. package/dist/dashboard/v6-dashboard-html.js +5 -5
  42. package/dist/index.d.ts +6 -0
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +4 -0
  45. package/dist/index.js.map +1 -1
  46. package/dist/types.d.ts +28 -10
  47. package/dist/types.d.ts.map +1 -1
  48. package/dist/watchers/git-watcher.d.ts.map +1 -1
  49. package/dist/watchers/git-watcher.js +1 -1
  50. package/dist/watchers/git-watcher.js.map +1 -1
  51. package/dist/workflow-cli.d.ts +3 -0
  52. package/dist/workflow-cli.d.ts.map +1 -0
  53. package/dist/workflow-cli.js +100 -0
  54. package/dist/workflow-cli.js.map +1 -0
  55. package/docs/WORKFLOW_INTEGRATION.md +105 -0
  56. package/docs/launch/RELEASE_CHECKLIST_v7.0.0.md +24 -0
  57. package/docs/launch/RELEASE_NOTES_v7.0.0.md +44 -0
  58. package/docs/launch/RELEASE_NOTES_v7.1.0.md +32 -0
  59. package/package.json +213 -204
  60. package/skills/shadow-debug/SKILL.md +16 -0
  61. package/skills/shadow-implement/SKILL.md +16 -0
  62. package/skills/shadow-release/SKILL.md +16 -0
  63. package/skills/shadow-research/SKILL.md +12 -0
  64. package/skills/shadow-review/SKILL.md +14 -0
  65. package/skills/shadow-workflow/SKILL.md +31 -0
  66. package/docs/launch/README.md +0 -61
package/dist/cli.js CHANGED
@@ -8,22 +8,29 @@ import * as path from 'path';
8
8
  import * as os from 'os';
9
9
  import { Orchestrator } from './brain/orchestrator.js';
10
10
  import { detectRunningAgents, createAdapter } from './adapters/index.js';
11
- const VERSION = '6.3.0';
12
- const config = new Conf({
13
- projectName: 'shadow-brain',
14
- defaults: {
15
- provider: 'ollama',
16
- model: undefined,
17
- agents: ['claude-code', 'kilo-code', 'cline', 'opencode', 'codex'],
18
- projectDir: process.cwd(),
19
- watchMode: true,
20
- autoInject: true,
21
- reviewDepth: 'standard',
22
- brainPersonality: 'balanced',
23
- },
24
- });
11
+ import { registerWorkflowCommands } from './workflow-cli.js';
12
+ const VERSION = '7.1.0';
13
+ // Defer config reads until a command actually needs provider settings.
14
+ let savedConfig;
15
+ function getConfig() {
16
+ savedConfig ?? (savedConfig = new Conf({
17
+ ...(process.env.SHADOW_BRAIN_CONFIG_DIR ? { cwd: process.env.SHADOW_BRAIN_CONFIG_DIR } : {}),
18
+ projectName: 'shadow-brain',
19
+ defaults: {
20
+ provider: 'ollama',
21
+ model: undefined,
22
+ agents: ['claude-code', 'kilo-code', 'cline', 'opencode', 'codex'],
23
+ projectDir: process.cwd(),
24
+ watchMode: true,
25
+ autoInject: true,
26
+ reviewDepth: 'standard',
27
+ brainPersonality: 'balanced',
28
+ },
29
+ }));
30
+ return savedConfig;
31
+ }
25
32
  function mergeConfig(cliOpts) {
26
- const saved = config.store;
33
+ const saved = getConfig().store;
27
34
  const watchMode = cliOpts.watchMode === false || cliOpts.watch === false
28
35
  ? false
29
36
  : saved.watchMode !== false;
@@ -393,7 +400,7 @@ const injectCmd = new Command('inject')
393
400
  const statusCmd = new Command('status')
394
401
  .description('Show current Shadow Brain configuration and status')
395
402
  .action(async () => {
396
- const saved = config.store;
403
+ const saved = getConfig().store;
397
404
  console.log(chalk.magenta.bold(`\n SHADOW BRAIN v${VERSION} Status\n`));
398
405
  console.log(chalk.dim(' Provider: ') + chalk.cyan(saved.provider || 'ollama'));
399
406
  console.log(chalk.dim(' Model: ') + chalk.cyan(saved.model || '(default)'));
@@ -431,7 +438,7 @@ const configCmd = new Command('config')
431
438
  .action(async (key, value, opts) => {
432
439
  if (opts?.list) {
433
440
  console.log(chalk.magenta.bold('\n SHADOW BRAIN Configuration\n'));
434
- const saved = config.store;
441
+ const saved = getConfig().store;
435
442
  for (const [k, v] of Object.entries(saved)) {
436
443
  const display = k === 'apiKey' && v ? '••••••••' : String(v);
437
444
  console.log(chalk.dim(` ${k}: `) + chalk.cyan(display));
@@ -440,7 +447,7 @@ const configCmd = new Command('config')
440
447
  return;
441
448
  }
442
449
  if (opts?.reset) {
443
- config.clear();
450
+ getConfig().clear();
444
451
  console.log(chalk.green(' Configuration reset to defaults.'));
445
452
  return;
446
453
  }
@@ -454,7 +461,7 @@ const configCmd = new Command('config')
454
461
  parsedValue = Number(value);
455
462
  else if (value.includes(','))
456
463
  parsedValue = value.split(',');
457
- config.set(key, parsedValue);
464
+ getConfig().set(key, parsedValue);
458
465
  console.log(chalk.green(` Set ${key} = ${parsedValue}`));
459
466
  return;
460
467
  }
@@ -479,12 +486,12 @@ const setupCmd = new Command('setup')
479
486
  const provider = await ask(chalk.yellow(' Choose provider [1-4] (default: 1): '));
480
487
  const providerMap = { '1': 'ollama', '2': 'anthropic', '3': 'openai', '4': 'openrouter' };
481
488
  const chosenProvider = providerMap[provider.trim() || '1'] || 'ollama';
482
- config.set('provider', chosenProvider);
489
+ getConfig().set('provider', chosenProvider);
483
490
  console.log(chalk.green(` ✓ Provider: ${chosenProvider}\n`));
484
491
  if (chosenProvider !== 'ollama') {
485
492
  const apiKey = await ask(chalk.yellow(` Enter ${chosenProvider} API key: `));
486
493
  if (apiKey.trim()) {
487
- config.set('apiKey', apiKey.trim());
494
+ getConfig().set('apiKey', apiKey.trim());
488
495
  console.log(chalk.green(' ✓ API key saved\n'));
489
496
  }
490
497
  else {
@@ -504,7 +511,7 @@ const setupCmd = new Command('setup')
504
511
  const personality = await ask(chalk.yellow(' Choose personality [1-6] (default: 1): '));
505
512
  const personalityMap = { '1': 'balanced', '2': 'mentor', '3': 'critic', '4': 'architect', '5': 'security', '6': 'performance' };
506
513
  const chosenPersonality = personalityMap[personality.trim() || '1'] || 'balanced';
507
- config.set('brainPersonality', chosenPersonality);
514
+ getConfig().set('brainPersonality', chosenPersonality);
508
515
  console.log(chalk.green(` ✓ Personality: ${chosenPersonality}\n`));
509
516
  console.log(chalk.cyan(' Review Depth:'));
510
517
  console.log(chalk.dim(' 1. standard (balanced — default)'));
@@ -512,14 +519,14 @@ const setupCmd = new Command('setup')
512
519
  console.log(chalk.dim(' 3. deep (thorough, full diffs)'));
513
520
  const depth = await ask(chalk.yellow(' Choose depth [1-3] (default: 1): '));
514
521
  const depthMap = { '1': 'standard', '2': 'quick', '3': 'deep' };
515
- config.set('reviewDepth', depthMap[depth.trim() || '1'] || 'standard');
522
+ getConfig().set('reviewDepth', depthMap[depth.trim() || '1'] || 'standard');
516
523
  console.log(chalk.green(' ✓ Review depth saved\n'));
517
524
  const inject = await ask(chalk.yellow(' Enable auto-injection? [Y/n] (default: Y): '));
518
- config.set('autoInject', inject.trim().toLowerCase() !== 'n');
525
+ getConfig().set('autoInject', inject.trim().toLowerCase() !== 'n');
519
526
  console.log(chalk.green(` ✓ Auto-injection: ${inject.trim().toLowerCase() !== 'n' ? 'enabled' : 'disabled'}\n`));
520
527
  rl.close();
521
528
  console.log(chalk.magenta.bold(' Setup complete!\n'));
522
- console.log(chalk.dim(' Configuration saved to: ') + chalk.cyan(config.path));
529
+ console.log(chalk.dim(' Configuration saved to: ') + chalk.cyan(getConfig().path));
523
530
  console.log();
524
531
  console.log(chalk.dim(' Next steps:'));
525
532
  console.log(chalk.cyan(' shadow-brain start .') + chalk.dim(' # Start watching a project'));
@@ -539,13 +546,13 @@ const doctorCmd = new Command('doctor')
539
546
  console.log(chalk.magenta.bold('\n SHADOW BRAIN Doctor\n'));
540
547
  const checks = [];
541
548
  try {
542
- const saved = config.store;
549
+ const saved = getConfig().store;
543
550
  checks.push({ name: 'Configuration', status: 'ok', detail: `provider=${saved.provider}, personality=${saved.brainPersonality}` });
544
551
  }
545
552
  catch {
546
553
  checks.push({ name: 'Configuration', status: 'fail', detail: 'Could not read config. Run `shadow-brain setup`.' });
547
554
  }
548
- const provider = config.get('provider') || 'ollama';
555
+ const provider = getConfig().get('provider') || 'ollama';
549
556
  if (provider === 'ollama') {
550
557
  try {
551
558
  const resp = await fetch('http://localhost:11434/api/tags', { signal: AbortSignal.timeout(3000) });
@@ -563,18 +570,19 @@ const doctorCmd = new Command('doctor')
563
570
  }
564
571
  }
565
572
  else {
566
- const apiKey = config.get('apiKey');
573
+ const apiKey = getConfig().get('apiKey');
567
574
  if (apiKey) {
568
- checks.push({ name: `${provider} API key`, status: 'ok', detail: 'Key is set (' + apiKey.slice(0, 4) + '...)' });
575
+ checks.push({ name: `${provider} API key`, status: 'ok', detail: 'Key is configured' });
569
576
  }
570
577
  else {
571
578
  checks.push({ name: `${provider} API key`, status: 'fail', detail: 'No API key configured. Run: shadow-brain config apiKey <key>' });
572
579
  }
573
580
  }
574
581
  const nodeVersion = process.version;
575
- const major = parseInt(nodeVersion.slice(1).split('.')[0]);
576
- checks.push({ name: 'Node.js', status: major >= 18 ? 'ok' : 'warn', detail: `${nodeVersion} ${major >= 18 ? '(supported)' : '(recommend v18+)'}` });
577
- const projectDir = config.get('projectDir') || process.cwd();
582
+ const [major, minor] = nodeVersion.slice(1).split('.').map(Number);
583
+ const nodeSupported = (major === 22 && minor >= 12) || major === 24 || major >= 26;
584
+ checks.push({ name: 'Node.js', status: nodeSupported ? 'ok' : 'warn', detail: `${nodeVersion} ${nodeSupported ? '(supported)' : '(requires Node 22.12+, 24.x, or 26+)'}` });
585
+ const projectDir = getConfig().get('projectDir') || process.cwd();
578
586
  try {
579
587
  const stat = fs.statSync(projectDir);
580
588
  checks.push({ name: 'Project directory', status: stat.isDirectory() ? 'ok' : 'fail', detail: projectDir });
@@ -2457,7 +2465,7 @@ const v5Cmd = new Command('v5')
2457
2465
  const program = new Command();
2458
2466
  program
2459
2467
  .name('shadow-brain')
2460
- .description('Shadow Brain v6.0.3 - local cross-agent memory, live brain health, resume context, and safety controls')
2468
+ .description('Shadow Brain - durable cross-agent memory, explained recall, and storage health')
2461
2469
  .version(VERSION);
2462
2470
  program.addCommand(startCmd);
2463
2471
  program.addCommand(reviewCmd);
@@ -5001,5 +5009,70 @@ program.addCommand(asciiCmd);
5001
5009
  program.addCommand(memesCmd);
5002
5010
  program.addCommand(brain3dCmd);
5003
5011
  program.addCommand(doppelgangerCmd);
5004
- program.parse();
5012
+ const storageHealthCmd = new Command('storage-health')
5013
+ .description('Check memory-store readability and report storage errors without loading provider settings')
5014
+ .option('--db <path>', 'Memory-store path (defaults to the global brain)')
5015
+ .option('--json', 'Print machine-readable JSON')
5016
+ .action(async (opts) => {
5017
+ const { getGlobalBrain } = await import('./brain/global-brain.js');
5018
+ const brain = getGlobalBrain(opts.db ? { dbPath: path.resolve(opts.db) } : undefined);
5019
+ try {
5020
+ await brain.init();
5021
+ }
5022
+ catch {
5023
+ process.exitCode = 1;
5024
+ }
5025
+ const health = brain.getStorageHealth();
5026
+ if (opts.json)
5027
+ console.log(JSON.stringify(health, null, 2));
5028
+ else {
5029
+ console.log(`Storage: ${health.status}\nDatabase: ${health.dbPath}\nPending operations: ${health.pendingOperations}`);
5030
+ if (health.lastError)
5031
+ console.log(`${health.lastError.code}: ${health.lastError.message}`);
5032
+ }
5033
+ if (health.initialized)
5034
+ await brain.shutdown();
5035
+ });
5036
+ const recallExplainCmd = new Command('recall-explain')
5037
+ .description('Recall memories with keyword matches, score components, and supporting agent identities')
5038
+ .argument('<query>', 'Keywords to search for')
5039
+ .option('--db <path>', 'Memory-store path (defaults to the global brain)')
5040
+ .option('--project <path>', 'Restrict recall to this project')
5041
+ .option('--limit <number>', 'Maximum results', '10')
5042
+ .option('--min-confidence <number>', 'Minimum heuristic score from 0 to 1', '0')
5043
+ .action(async (query, opts) => {
5044
+ const limit = Number(opts.limit);
5045
+ const minConfidence = Number(opts.minConfidence);
5046
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 1000 || !Number.isFinite(minConfidence) || minConfidence < 0 || minConfidence > 1) {
5047
+ console.error('Use --limit between 1 and 1000 and --min-confidence between 0 and 1.');
5048
+ process.exitCode = 1;
5049
+ return;
5050
+ }
5051
+ const { getGlobalBrain, GlobalBrain } = await import('./brain/global-brain.js');
5052
+ const brain = getGlobalBrain(opts.db ? { dbPath: path.resolve(opts.db) } : undefined);
5053
+ try {
5054
+ await brain.init();
5055
+ console.log(JSON.stringify(brain.recallScored({
5056
+ keywords: query.split(/\s+/),
5057
+ projectId: opts.project ? GlobalBrain.projectIdFor(opts.project) : undefined,
5058
+ limit,
5059
+ minConfidence,
5060
+ }), null, 2));
5061
+ }
5062
+ catch (error) {
5063
+ console.error(error instanceof Error ? error.message : 'Recall failed.');
5064
+ process.exitCode = 1;
5065
+ }
5066
+ finally {
5067
+ if (brain.getStorageHealth().initialized)
5068
+ await brain.shutdown();
5069
+ }
5070
+ });
5071
+ program.addCommand(storageHealthCmd);
5072
+ program.addCommand(recallExplainCmd);
5073
+ registerWorkflowCommands(program);
5074
+ program.parseAsync().catch((error) => {
5075
+ console.error(error instanceof Error ? error.message : 'Command failed.');
5076
+ process.exitCode = 1;
5077
+ });
5005
5078
  //# sourceMappingURL=cli.js.map