dual-brain 0.1.13 → 0.1.15

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 (2) hide show
  1. package/bin/dual-brain.mjs +65 -2
  2. package/package.json +1 -1
@@ -362,6 +362,18 @@ async function cmdGo(args) {
362
362
  provider: plan?._decision?.provider ?? 'claude',
363
363
  nextAction: null,
364
364
  }, cwd);
365
+ // ── Next steps suggestions (dual-brain consensus path) ──────────────────
366
+ try {
367
+ const { suggestNextSteps, formatNextSteps } = await import('../src/nextstep.mjs');
368
+ const steps = await suggestNextSteps(
369
+ { prompt, tier: plan?._decision?.tier ?? 'think', files, trigger: 'go' },
370
+ { success: true, filesChanged: files, error: null, duration: null },
371
+ cwd
372
+ );
373
+ if (steps?.steps?.length > 0) {
374
+ console.log('\n' + formatNextSteps(steps.steps, 3));
375
+ }
376
+ } catch { /* non-fatal */ }
365
377
  } else {
366
378
  const statusLine = result.status === 'completed' ? 'Done' : `Failed (exit ${result.exitCode})`;
367
379
  console.log(`\n${statusLine}${result.durationMs != null ? ` in ${(result.durationMs / 1000).toFixed(1)}s` : ''}`);
@@ -381,6 +393,28 @@ async function cmdGo(args) {
381
393
  }, cwd);
382
394
  if (result.status !== 'completed') process.exit(1);
383
395
  await offerAutoCommit(cwd);
396
+ // ── Next steps suggestions ──────────────────────────────────────────────
397
+ try {
398
+ const { suggestNextSteps, formatNextSteps } = await import('../src/nextstep.mjs');
399
+ const steps = await suggestNextSteps(
400
+ {
401
+ prompt,
402
+ tier: plan?._decision?.tier ?? 'execute',
403
+ files: result.filesChanged || files,
404
+ trigger: 'go',
405
+ },
406
+ {
407
+ success: result.status === 'completed',
408
+ filesChanged: result.filesChanged || files,
409
+ error: result.error,
410
+ duration: result.durationMs,
411
+ },
412
+ cwd
413
+ );
414
+ if (steps?.steps?.length > 0) {
415
+ console.log('\n' + formatNextSteps(steps.steps, 3));
416
+ }
417
+ } catch { /* non-fatal — module may not exist yet */ }
384
418
  }
385
419
  }
386
420
 
@@ -465,8 +499,9 @@ async function cmdStatus(args = []) {
465
499
  .filter(([k]) => k.startsWith(`${p.name}:`));
466
500
  const sess = sessionStats[p.name] ?? { calls: 0, tokens: 0 };
467
501
 
502
+ const planStr = p.plan ? ` plan=${p.plan}` : '';
468
503
  if (provStates.length === 0) {
469
- console.log(` ${label} plan=${p.plan} status=healthy calls=${sess.calls} tokens=${sess.tokens}`);
504
+ console.log(` ${label}${planStr} status=healthy calls=${sess.calls} tokens=${sess.tokens}`);
470
505
  } else {
471
506
  for (const [k, st] of provStates) {
472
507
  const modelClass = k.split(':').slice(1).join(':');
@@ -475,7 +510,7 @@ async function cmdStatus(args = []) {
475
510
  const remaining = remainingCooldownMinutes(p.name, modelClass, cwd);
476
511
  statusStr = remaining > 0 ? `hot (retry in ${remaining}m)` : 'hot (cooling)';
477
512
  }
478
- console.log(` ${label} plan=${p.plan} model=${modelClass} status=${statusStr} calls=${sess.calls} tokens=${sess.tokens}`);
513
+ console.log(` ${label}${planStr} model=${modelClass} status=${statusStr} calls=${sess.calls} tokens=${sess.tokens}`);
479
514
  }
480
515
  }
481
516
  }
@@ -1472,11 +1507,39 @@ async function mainScreen(rl, ask) {
1472
1507
  statusRows.push(row(`\x1b[2m📦 data-tools v${dtVersion}\x1b[0m`));
1473
1508
  }
1474
1509
 
1510
+ // ── Observer observations (top 2, high priority first) ───────────────────
1511
+ let quickObservations = [];
1512
+ try {
1513
+ const observerMod = await import('../src/observer.mjs');
1514
+ const quickState = await observerMod.getQuickState(cwd);
1515
+ if (quickState?.observations?.length > 0) {
1516
+ const PRIO = { high: 0, medium: 1, low: 2 };
1517
+ const sorted = [...quickState.observations].sort(
1518
+ (a, b) => (PRIO[a.priority] ?? 2) - (PRIO[b.priority] ?? 2)
1519
+ );
1520
+ quickObservations = sorted.slice(0, 2);
1521
+ for (const obs of quickObservations) {
1522
+ let prefix;
1523
+ if (obs.priority === 'high') prefix = '🔴';
1524
+ else if (obs.priority === 'medium') prefix = '🟡';
1525
+ else prefix = '\x1b[2m💡\x1b[0m';
1526
+ statusRows.push(row(`${prefix} ${obs.message}`));
1527
+ }
1528
+ }
1529
+ } catch { /* non-fatal — module may not exist yet */ }
1530
+
1475
1531
  // ── Action cards (git state + open PRs) ──────────────────────────────────
1476
1532
  const repoState = detectRepoState(cwd);
1477
1533
  const openPRs = await detectOpenPRs(cwd);
1478
1534
  const actionRows = buildActionRows(repoState, row, openPRs);
1479
1535
 
1536
+ // ── High-priority observer action cards ───────────────────────────────────
1537
+ if (quickObservations.some(o => o.priority === 'high')) {
1538
+ const DIM = '\x1b[2m';
1539
+ const RESET = '\x1b[0m';
1540
+ actionRows.push(row(`${DIM}[r] Security review [t] Run tests [c] Commit${RESET}`));
1541
+ }
1542
+
1480
1543
  // ── Related sessions hint (only when no continuation card is showing) ─────
1481
1544
  if (!interrupted && recentSessions.length > 0) {
1482
1545
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dual-brain",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "description": "AI orchestration across Claude + OpenAI subscriptions — smart routing, budget awareness, and dual-brain collaboration",
5
5
  "type": "module",
6
6
  "bin": {