erosolar-cli 1.7.394 โ†’ 1.7.395

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.
@@ -35,7 +35,6 @@ import { generateTestFlows, detectBugs, detectUIUpdates, saveTestFlows, saveBugR
35
35
  import { TerminalInputAdapter } from './terminalInputAdapter.js';
36
36
  import { renderSessionFrame } from '../ui/unified/layout.js';
37
37
  import { isUpdateInProgress, maybeOfferCliUpdate } from './updateManager.js';
38
- import { writeLock } from '../ui/writeLock.js';
39
38
  import { enterStreamingMode, exitStreamingMode } from '../ui/globalWriteLock.js';
40
39
  import { setGlobalAIEnhancer } from '../tools/localExplore.js';
41
40
  import { createProvider } from '../providers/providerFactory.js';
@@ -119,6 +118,7 @@ export class InteractiveShell {
119
118
  statusSubscription = null;
120
119
  followUpQueue = [];
121
120
  isDrainingQueue = false;
121
+ apiKeyGateActive = false;
122
122
  activeContextWindowTokens = null;
123
123
  latestTokenUsage = { used: null, limit: null };
124
124
  planApprovalBridgeRegistered = false;
@@ -128,6 +128,8 @@ export class InteractiveShell {
128
128
  autosaveEnabled;
129
129
  autoContinueEnabled;
130
130
  verificationEnabled = true;
131
+ alphaZeroModeEnabled;
132
+ alphaZeroVerificationSnapshot = null;
131
133
  editGuardMode = 'display-edits';
132
134
  pendingPermissionInput = null;
133
135
  pendingHistoryLoad = null;
@@ -161,6 +163,7 @@ export class InteractiveShell {
161
163
  lastStreamingElapsedSeconds = null; // Preserve final elapsed time
162
164
  statusLineState = null;
163
165
  statusMessageOverride = null;
166
+ hasShownThoughtProcess = false;
164
167
  promptRefreshTimer = null;
165
168
  launchPaletteShown = false;
166
169
  version;
@@ -176,6 +179,7 @@ export class InteractiveShell {
176
179
  this.thinkingMode = this.sessionPreferences.thinkingMode;
177
180
  this.autosaveEnabled = this.sessionPreferences.autosave;
178
181
  this.autoContinueEnabled = this.sessionPreferences.autoContinue;
182
+ this.alphaZeroModeEnabled = this.sessionPreferences.alphaZeroMode;
179
183
  this.sessionRestoreConfig = config.sessionRestore ?? { mode: 'none' };
180
184
  this._enabledPlugins = config.enabledPlugins ?? [];
181
185
  this.version = config.version ?? '0.0.0';
@@ -231,6 +235,11 @@ export class InteractiveShell {
231
235
  description: 'AlphaZero offensive security run (start/status/next)',
232
236
  category: 'automation',
233
237
  });
238
+ this.slashCommands.push({
239
+ command: '/alphazero',
240
+ description: 'Toggle AlphaZero RL mode with full-cycle verification',
241
+ category: 'mode',
242
+ });
234
243
  this.statusTracker = config.statusTracker;
235
244
  this.ui = config.ui;
236
245
  this.uiAdapter = config.ui.adapter;
@@ -242,7 +251,11 @@ export class InteractiveShell {
242
251
  });
243
252
  // Set up tool status callback to update status during tool execution
244
253
  this.uiAdapter.setToolStatusCallback((status) => {
245
- this.updateStatusMessage(status ?? null);
254
+ const statusText = status?.text ?? null;
255
+ if (statusText) {
256
+ this.terminalInput.recordRecentAction(`[tool] ${statusText}`);
257
+ }
258
+ this.updateStatusMessage(statusText, { logRecent: false });
246
259
  });
247
260
  this.skillRepository = new SkillRepository({
248
261
  workingDir: this.workingDir,
@@ -262,6 +275,7 @@ export class InteractiveShell {
262
275
  onToggleVerify: () => this.toggleVerificationMode(),
263
276
  onToggleAutoContinue: () => this.toggleAutoContinueMode(),
264
277
  onToggleThinking: () => this.cycleThinkingMode(),
278
+ onToggleAlphaZero: () => this.toggleAlphaZeroMode('shortcut'),
265
279
  onClearContext: () => this.handleClearContext(),
266
280
  });
267
281
  // Initialize Alpha Zero 2 metrics tracking
@@ -289,7 +303,7 @@ export class InteractiveShell {
289
303
  this.terminalInput.streamContent(banner + '\n\n');
290
304
  // Render chat box after banner is streamed
291
305
  this.refreshControlBar();
292
- this.terminalInput.forceRender();
306
+ this.renderPromptArea(true);
293
307
  this.rebuildAgent();
294
308
  this.setupHandlers();
295
309
  this.refreshBannerSessionInfo();
@@ -304,7 +318,13 @@ export class InteractiveShell {
304
318
  this.parallelAgentDisplayLines = manager.formatDisplay();
305
319
  // Trigger UI refresh if streaming
306
320
  if (this.streamingHeartbeatStart) {
307
- this.displayParallelAgents();
321
+ this.uiUpdates.enqueue({
322
+ lane: 'stream',
323
+ mode: ['streaming', 'processing'],
324
+ coalesceKey: 'parallel-agents',
325
+ description: 'parallel agent status',
326
+ run: () => this.displayParallelAgents(),
327
+ });
308
328
  }
309
329
  };
310
330
  manager.on('agent:started', updateDisplay);
@@ -385,7 +405,7 @@ export class InteractiveShell {
385
405
  }
386
406
  this.showLaunchCommandPalette();
387
407
  // Ensure the terminal input is visible
388
- this.terminalInput.render();
408
+ this.renderPromptArea();
389
409
  }
390
410
  showLaunchCommandPalette() {
391
411
  // Disabled: Quick commands palette takes up too much space
@@ -482,6 +502,7 @@ export class InteractiveShell {
482
502
  // Mode toggles
483
503
  '/thinking',
484
504
  '/autocontinue',
505
+ '/alphazero',
485
506
  // Discovery and plugins
486
507
  '/local', '/discover',
487
508
  '/plugins',
@@ -533,7 +554,7 @@ export class InteractiveShell {
533
554
  display.showSystemMessage('โœ๏ธ Display edits mode enabled.');
534
555
  }
535
556
  }
536
- this.terminalInput.render();
557
+ this.renderPromptArea();
537
558
  }
538
559
  toggleVerificationMode() {
539
560
  this.setVerificationMode(!this.verificationEnabled, 'shortcut');
@@ -570,6 +591,37 @@ export class InteractiveShell {
570
591
  : 'The model will not be auto-prompted to continue.') +
571
592
  ' Toggle with Ctrl+Shift+C.');
572
593
  }
594
+ toggleAlphaZeroMode(source = 'shortcut') {
595
+ this.setAlphaZeroMode(!this.alphaZeroModeEnabled, source);
596
+ }
597
+ setAlphaZeroMode(enabled, source) {
598
+ const changed = this.alphaZeroModeEnabled !== enabled;
599
+ this.alphaZeroModeEnabled = enabled;
600
+ saveSessionPreferences({ alphaZeroMode: this.alphaZeroModeEnabled });
601
+ // Force verification on while AlphaZero mode is active to guarantee deep checks
602
+ if (enabled) {
603
+ if (this.alphaZeroVerificationSnapshot === null) {
604
+ this.alphaZeroVerificationSnapshot = this.verificationEnabled;
605
+ }
606
+ if (!this.verificationEnabled) {
607
+ this.setVerificationMode(true, 'command');
608
+ }
609
+ }
610
+ else if (this.alphaZeroVerificationSnapshot !== null) {
611
+ this.setVerificationMode(this.alphaZeroVerificationSnapshot, 'command');
612
+ this.alphaZeroVerificationSnapshot = null;
613
+ }
614
+ this.refreshControlBar();
615
+ if (!changed && source === 'shortcut') {
616
+ return;
617
+ }
618
+ if (enabled) {
619
+ display.showSystemMessage('โ™ž AlphaZero RL mode enabled. Difficult prompts will use the duel/self-critique playbook with full lifecycle verification.');
620
+ }
621
+ else {
622
+ display.showInfo('AlphaZero RL mode disabled. Returning to standard flow.');
623
+ }
624
+ }
573
625
  /**
574
626
  * Cycle through thinking modes (Ctrl+Shift+T keyboard shortcut).
575
627
  */
@@ -647,7 +699,7 @@ export class InteractiveShell {
647
699
  if (['n', 'no', 'cancel', '/cancel'].includes(lower)) {
648
700
  this.pendingPermissionInput = null;
649
701
  display.showInfo('Request cancelled.');
650
- this.terminalInput.render();
702
+ this.renderPromptArea();
651
703
  return null;
652
704
  }
653
705
  // Treat any other input as a replacement request that also needs confirmation
@@ -665,7 +717,7 @@ export class InteractiveShell {
665
717
  ]
666
718
  .filter(Boolean)
667
719
  .join('\n'));
668
- this.terminalInput.render();
720
+ this.renderPromptArea();
669
721
  }
670
722
  /**
671
723
  * Handle Ctrl+C presses in three stages:
@@ -680,7 +732,7 @@ export class InteractiveShell {
680
732
  this.clearChatInput();
681
733
  const prefix = hadBuffer ? 'Input cleared.' : 'Nothing to clear.';
682
734
  display.showSystemMessage(`${prefix} Press Ctrl+C again to pause the AI; a third time quits.`);
683
- this.terminalInput.render();
735
+ this.renderPromptArea();
684
736
  return;
685
737
  }
686
738
  if (this.ctrlCPressCount === 2) {
@@ -781,8 +833,11 @@ export class InteractiveShell {
781
833
  /**
782
834
  * Update status bar message
783
835
  */
784
- updateStatusMessage(message) {
836
+ updateStatusMessage(message, options = {}) {
785
837
  this.statusMessageOverride = message;
838
+ if (message && options.logRecent !== false) {
839
+ this.terminalInput.recordRecentAction(`[status] ${message}`);
840
+ }
786
841
  // During streaming we still want the spinner prefix; when idle force a fast refresh.
787
842
  this.refreshStatusLine(!this.isProcessing);
788
843
  }
@@ -794,26 +849,26 @@ export class InteractiveShell {
794
849
  const trimmed = input.trim();
795
850
  if (!trimmed) {
796
851
  display.showWarning('Enter a number, "save", "defaults", or "cancel".');
797
- this.terminalInput.render();
852
+ this.renderPromptArea();
798
853
  return;
799
854
  }
800
855
  const normalized = trimmed.toLowerCase();
801
856
  if (normalized === 'cancel') {
802
857
  this.pendingInteraction = null;
803
858
  display.showInfo('Tool selection cancelled.');
804
- this.terminalInput.render();
859
+ this.renderPromptArea();
805
860
  return;
806
861
  }
807
862
  if (normalized === 'defaults') {
808
863
  pending.selection = buildEnabledToolSet(null);
809
864
  this.renderToolMenu(pending);
810
- this.terminalInput.render();
865
+ this.renderPromptArea();
811
866
  return;
812
867
  }
813
868
  if (normalized === 'save') {
814
869
  await this.persistToolSelection(pending);
815
870
  this.pendingInteraction = null;
816
- this.terminalInput.render();
871
+ this.renderPromptArea();
817
872
  return;
818
873
  }
819
874
  const choice = Number.parseInt(trimmed, 10);
@@ -831,11 +886,11 @@ export class InteractiveShell {
831
886
  }
832
887
  this.renderToolMenu(pending);
833
888
  }
834
- this.terminalInput.render();
889
+ this.renderPromptArea();
835
890
  return;
836
891
  }
837
892
  display.showWarning('Enter a number, "save", "defaults", or "cancel".');
838
- this.terminalInput.render();
893
+ this.renderPromptArea();
839
894
  }
840
895
  async persistToolSelection(interaction) {
841
896
  if (setsEqual(interaction.selection, interaction.initialSelection)) {
@@ -862,36 +917,36 @@ export class InteractiveShell {
862
917
  if (!this.agentMenu) {
863
918
  this.pendingInteraction = null;
864
919
  display.showWarning('Agent selection is unavailable in this CLI.');
865
- this.terminalInput.render();
920
+ this.renderPromptArea();
866
921
  return;
867
922
  }
868
923
  const trimmed = input.trim();
869
924
  if (!trimmed) {
870
925
  display.showWarning('Enter a number or type "cancel".');
871
- this.terminalInput.render();
926
+ this.renderPromptArea();
872
927
  return;
873
928
  }
874
929
  if (trimmed.toLowerCase() === 'cancel') {
875
930
  this.pendingInteraction = null;
876
931
  display.showInfo('Agent selection cancelled.');
877
- this.terminalInput.render();
932
+ this.renderPromptArea();
878
933
  return;
879
934
  }
880
935
  const choice = Number.parseInt(trimmed, 10);
881
936
  if (!Number.isFinite(choice)) {
882
937
  display.showWarning('Please enter a valid number.');
883
- this.terminalInput.render();
938
+ this.renderPromptArea();
884
939
  return;
885
940
  }
886
941
  const option = pending.options[choice - 1];
887
942
  if (!option) {
888
943
  display.showWarning('That option is not available.');
889
- this.terminalInput.render();
944
+ this.renderPromptArea();
890
945
  return;
891
946
  }
892
947
  await this.persistAgentSelection(option.name);
893
948
  this.pendingInteraction = null;
894
- this.terminalInput.render();
949
+ this.renderPromptArea();
895
950
  }
896
951
  async persistAgentSelection(profileName) {
897
952
  if (!this.agentMenu) {
@@ -964,7 +1019,7 @@ export class InteractiveShell {
964
1019
  lines.push(` ${theme.primary('[text]')} Submit your own solution instead`);
965
1020
  lines.push('');
966
1021
  display.showSystemMessage(lines.join('\n'));
967
- this.terminalInput.render();
1022
+ this.renderPromptArea();
968
1023
  }
969
1024
  async handlePlanApprovalInput(input) {
970
1025
  const pending = this.pendingInteraction;
@@ -973,7 +1028,7 @@ export class InteractiveShell {
973
1028
  const trimmed = input.trim();
974
1029
  if (!trimmed) {
975
1030
  display.showWarning('Enter a command or your own solution.');
976
- this.terminalInput.render();
1031
+ this.renderPromptArea();
977
1032
  return;
978
1033
  }
979
1034
  const lower = trimmed.toLowerCase();
@@ -981,7 +1036,7 @@ export class InteractiveShell {
981
1036
  if (lower === 'cancel' || lower === 'c') {
982
1037
  this.pendingInteraction = null;
983
1038
  display.showInfo('Plan cancelled. You can continue with a different approach.');
984
- this.terminalInput.render();
1039
+ this.renderPromptArea();
985
1040
  return;
986
1041
  }
987
1042
  // Select all
@@ -1001,7 +1056,7 @@ export class InteractiveShell {
1001
1056
  const selectedSteps = pending.steps.filter(s => pending.selectedSteps.has(s.id));
1002
1057
  if (selectedSteps.length === 0) {
1003
1058
  display.showWarning('No steps selected. Select steps or enter your own solution.');
1004
- this.terminalInput.render();
1059
+ this.renderPromptArea();
1005
1060
  return;
1006
1061
  }
1007
1062
  this.pendingInteraction = null;
@@ -1034,15 +1089,17 @@ export class InteractiveShell {
1034
1089
  return;
1035
1090
  }
1036
1091
  display.showWarning('Invalid input. Enter a step number, command (go/cancel/all/none), or your own solution.');
1037
- this.terminalInput.render();
1092
+ this.renderPromptArea();
1038
1093
  }
1039
1094
  setupHandlers() {
1040
1095
  // Handle terminal resize
1041
1096
  output.on('resize', () => {
1097
+ this.terminalInput.resetContentPosition();
1042
1098
  this.terminalInput.handleResize();
1099
+ this.terminalInput.forceRender();
1043
1100
  });
1044
1101
  // Show initial input UI
1045
- this.terminalInput.render();
1102
+ this.renderPromptArea();
1046
1103
  }
1047
1104
  /**
1048
1105
  * Set up command autocomplete with all available slash commands.
@@ -1073,6 +1130,14 @@ export class InteractiveShell {
1073
1130
  catch {
1074
1131
  // Custom commands are optional
1075
1132
  }
1133
+ // Add manual commands that are not yet in the schema
1134
+ if (!commands.some((cmd) => cmd.command === '/alphazero')) {
1135
+ commands.push({
1136
+ command: '/alphazero',
1137
+ description: 'Toggle AlphaZero RL mode',
1138
+ category: 'mode',
1139
+ });
1140
+ }
1076
1141
  // Sort commands alphabetically
1077
1142
  commands.sort((a, b) => a.command.localeCompare(b.command));
1078
1143
  this.terminalInput.setAvailableCommands(commands);
@@ -1153,23 +1218,51 @@ export class InteractiveShell {
1153
1218
  autoContinueHotkey: 'ctrl+shift+c',
1154
1219
  thinkingModeLabel: this.thinkingMode,
1155
1220
  thinkingHotkey: 'ctrl+shift+t',
1221
+ alphaZeroEnabled: this.alphaZeroModeEnabled,
1222
+ alphaZeroHotkey: 'ctrl+shift+a',
1223
+ alphaZeroLabel: 'AlphaZero RL',
1156
1224
  });
1157
1225
  this.refreshStatusLine();
1158
- this.terminalInput.render();
1226
+ this.renderPromptArea();
1159
1227
  }
1160
1228
  writeLocked(content) {
1161
1229
  if (!content) {
1162
1230
  return;
1163
1231
  }
1164
- // If lock is already held, write directly - we're in a protected context
1165
- // This prevents queuing issues where content gets delayed
1166
- if (writeLock.isLocked()) {
1167
- process.stdout.write(content);
1232
+ // Route through display stream so scroll regions and streaming locks stay in sync
1233
+ display.stream(content);
1234
+ }
1235
+ isStreamingUiActive() {
1236
+ return this.streamingHeartbeatStart !== null;
1237
+ }
1238
+ /**
1239
+ * Render the prompt/control bar. During streaming, rely on the streaming frame
1240
+ * renderer and enqueue through the UIUpdateCoordinator to avoid fighting the
1241
+ * scroll region or duplicating the prompt.
1242
+ */
1243
+ renderPromptArea(force = false) {
1244
+ if (this.isStreamingUiActive()) {
1245
+ this.uiUpdates.enqueue({
1246
+ lane: 'prompt',
1247
+ mode: ['streaming', 'processing'],
1248
+ coalesceKey: 'prompt:streaming-frame',
1249
+ description: 'render streaming prompt frame',
1250
+ run: () => {
1251
+ if (force) {
1252
+ this.terminalInput.renderStreamingFrame(true);
1253
+ return;
1254
+ }
1255
+ this.terminalInput.renderStreamingFrame();
1256
+ },
1257
+ });
1168
1258
  return;
1169
1259
  }
1170
- writeLock.withLock(() => {
1171
- process.stdout.write(content);
1172
- }, 'interactiveShell.stdout');
1260
+ if (force) {
1261
+ this.terminalInput.forceRender();
1262
+ }
1263
+ else {
1264
+ this.terminalInput.render();
1265
+ }
1173
1266
  }
1174
1267
  /**
1175
1268
  * Refresh the status line in the persistent input area.
@@ -1215,7 +1308,7 @@ export class InteractiveShell {
1215
1308
  provider: this.providerLabel(this.sessionState.provider),
1216
1309
  });
1217
1310
  if (forceRender) {
1218
- this.terminalInput.render();
1311
+ this.renderPromptArea(true);
1219
1312
  }
1220
1313
  }
1221
1314
  /**
@@ -1252,7 +1345,7 @@ export class InteractiveShell {
1252
1345
  * Ensure the terminal input is ready for interactive input.
1253
1346
  */
1254
1347
  ensureReadlineReady() {
1255
- this.terminalInput.render();
1348
+ this.renderPromptArea();
1256
1349
  }
1257
1350
  /**
1258
1351
  * Log user prompt to the scroll region so it's part of the conversation flow.
@@ -1274,7 +1367,7 @@ export class InteractiveShell {
1274
1367
  }
1275
1368
  requestPromptRefresh(force = false) {
1276
1369
  if (force) {
1277
- this.terminalInput.forceRender();
1370
+ this.renderPromptArea(true);
1278
1371
  return;
1279
1372
  }
1280
1373
  if (this.promptRefreshTimer) {
@@ -1282,7 +1375,7 @@ export class InteractiveShell {
1282
1375
  }
1283
1376
  this.promptRefreshTimer = setTimeout(() => {
1284
1377
  this.promptRefreshTimer = null;
1285
- this.terminalInput.render();
1378
+ this.renderPromptArea();
1286
1379
  }, 48);
1287
1380
  }
1288
1381
  clearPromptRefreshTimer() {
@@ -1291,6 +1384,25 @@ export class InteractiveShell {
1291
1384
  this.promptRefreshTimer = null;
1292
1385
  }
1293
1386
  }
1387
+ async withStreamingUi(label, run) {
1388
+ if (this.isStreamingUiActive()) {
1389
+ return run();
1390
+ }
1391
+ this.terminalInput.setStreaming(true);
1392
+ this.startStreamingHeartbeat(label);
1393
+ try {
1394
+ return await run();
1395
+ }
1396
+ finally {
1397
+ this.stopStreamingHeartbeat();
1398
+ this.terminalInput.setStreaming(false);
1399
+ const nextMode = this.isProcessing ? 'processing' : 'idle';
1400
+ this.uiUpdates.setMode(nextMode);
1401
+ if (nextMode === 'processing') {
1402
+ queueMicrotask(() => this.uiUpdates.setMode('idle'));
1403
+ }
1404
+ }
1405
+ }
1294
1406
  startStreamingHeartbeat(label = 'Streaming') {
1295
1407
  this.stopStreamingHeartbeat();
1296
1408
  // Enter global streaming mode - blocks all non-streaming UI output
@@ -1371,7 +1483,7 @@ export class InteractiveShell {
1371
1483
  else {
1372
1484
  this.setIdleStatus();
1373
1485
  }
1374
- this.terminalInput.render();
1486
+ this.renderPromptArea();
1375
1487
  }
1376
1488
  enqueueFollowUpAction(action) {
1377
1489
  this.followUpQueue.push(action);
@@ -1390,7 +1502,7 @@ export class InteractiveShell {
1390
1502
  this.refreshQueueIndicators();
1391
1503
  this.scheduleQueueProcessing();
1392
1504
  // Re-show the prompt so user can continue typing more follow-ups
1393
- this.terminalInput.render();
1505
+ this.renderPromptArea();
1394
1506
  }
1395
1507
  scheduleQueueProcessing() {
1396
1508
  if (!this.followUpQueue.length) {
@@ -1445,12 +1557,12 @@ export class InteractiveShell {
1445
1557
  }
1446
1558
  if (lower === 'clear') {
1447
1559
  display.clear();
1448
- this.terminalInput.render();
1560
+ this.renderPromptArea();
1449
1561
  return;
1450
1562
  }
1451
1563
  if (lower === 'help') {
1452
1564
  this.showHelp();
1453
- this.terminalInput.render();
1565
+ this.renderPromptArea();
1454
1566
  return;
1455
1567
  }
1456
1568
  if (trimmed.startsWith('/')) {
@@ -1460,12 +1572,12 @@ export class InteractiveShell {
1460
1572
  // Check for continuous/infinite loop commands
1461
1573
  if (this.isContinuousCommand(trimmed)) {
1462
1574
  await this.processContinuousRequest(trimmed);
1463
- this.terminalInput.render();
1575
+ this.renderPromptArea();
1464
1576
  return;
1465
1577
  }
1466
1578
  // Direct execution for all inputs, including multi-line pastes
1467
1579
  await this.processRequest(trimmed);
1468
- this.terminalInput.render();
1580
+ this.renderPromptArea();
1469
1581
  }
1470
1582
  /**
1471
1583
  * Check if the command is a continuous/infinite loop command
@@ -1503,6 +1615,60 @@ export class InteractiveShell {
1503
1615
  ];
1504
1616
  return patterns.some(pattern => pattern.test(lower));
1505
1617
  }
1618
+ isDifficultProblem(input) {
1619
+ const normalized = input.toLowerCase();
1620
+ const wordCount = normalized.split(/\s+/).filter(Boolean).length;
1621
+ if (normalized.length > 600 || wordCount > 80) {
1622
+ return true;
1623
+ }
1624
+ const signals = [
1625
+ 'root cause',
1626
+ 'postmortem',
1627
+ 'crash',
1628
+ 'incident',
1629
+ 'outage',
1630
+ 'optimiz',
1631
+ 'performance',
1632
+ 'throughput',
1633
+ 'latency',
1634
+ 'scalab',
1635
+ 'architecture',
1636
+ 'rewrite',
1637
+ 'migration',
1638
+ 'refactor',
1639
+ 'reverse engineer',
1640
+ 'security',
1641
+ 'exploit',
1642
+ 'injection',
1643
+ 'vulnerability',
1644
+ 'compliance',
1645
+ 'multi-step',
1646
+ 'complex',
1647
+ 'difficult',
1648
+ 'hard problem',
1649
+ 'debug',
1650
+ 'trace',
1651
+ 'profil',
1652
+ 'bottleneck',
1653
+ ];
1654
+ return signals.some((signal) => normalized.includes(signal));
1655
+ }
1656
+ buildAlphaZeroPrompt(request, flaggedDifficult) {
1657
+ const playbook = [
1658
+ 'AlphaZero RL MODE is ACTIVE. Operate as a self-play reinforcement loop.',
1659
+ flaggedDifficult
1660
+ ? 'Treat this as a difficult, high-risk task and over-verify the result.'
1661
+ : 'Apply the reinforcement loop even if the task looks small.',
1662
+ 'Follow this closed-loop playbook:',
1663
+ '- Draft two competing solution strategies and merge the strongest ideas before executing.',
1664
+ '- Execute with tools while logging decisions and evidence.',
1665
+ '- Self-critique and repair until the quality is excellent (aim โ‰ฅ90/100).',
1666
+ '- Run full-lifecycle verification like a human reviewer: build/tests, manual sanity checks, edge cases, performance/safety/security probes, docs/UX/readiness notes.',
1667
+ '- Keep a verification ledger: each check with PASS/FAIL, evidence, and remaining risks. If anything fails, fix and re-verify before claiming completion.',
1668
+ 'Finish with a concise sign-off that lists what was achieved and the proof of completion.',
1669
+ ];
1670
+ return `${playbook.join('\n')}\n\nPrimary user request:\n${request.trim()}`;
1671
+ }
1506
1672
  async handlePendingInteraction(input) {
1507
1673
  if (!this.pendingInteraction) {
1508
1674
  return false;
@@ -1510,7 +1676,7 @@ export class InteractiveShell {
1510
1676
  switch (this.pendingInteraction.type) {
1511
1677
  case 'model-loading':
1512
1678
  display.showInfo('Still fetching model options. Please wait a moment.');
1513
- this.terminalInput.render();
1679
+ this.renderPromptArea();
1514
1680
  return true;
1515
1681
  case 'model-provider':
1516
1682
  await this.handleModelProviderSelection(input);
@@ -1541,7 +1707,7 @@ export class InteractiveShell {
1541
1707
  const [command] = input.split(/\s+/);
1542
1708
  if (!command) {
1543
1709
  display.showWarning('Enter a slash command.');
1544
- this.terminalInput.render();
1710
+ this.renderPromptArea();
1545
1711
  return;
1546
1712
  }
1547
1713
  switch (command) {
@@ -1599,6 +1765,9 @@ export class InteractiveShell {
1599
1765
  case '/autocontinue':
1600
1766
  this.handleAutoContinueCommand(input);
1601
1767
  break;
1768
+ case '/alphazero':
1769
+ this.handleAlphaZeroCommand(input);
1770
+ break;
1602
1771
  case '/shortcuts':
1603
1772
  case '/keys':
1604
1773
  this.handleShortcutsCommand();
@@ -1703,7 +1872,7 @@ export class InteractiveShell {
1703
1872
  }
1704
1873
  break;
1705
1874
  }
1706
- this.terminalInput.render();
1875
+ this.renderPromptArea();
1707
1876
  }
1708
1877
  async tryCustomSlashCommand(command, fullInput) {
1709
1878
  const custom = this.customCommandMap.get(command);
@@ -1740,6 +1909,7 @@ export class InteractiveShell {
1740
1909
  ` ${theme.info('Option+V')} ${theme.ui.muted('Toggle verification')}`,
1741
1910
  ` ${theme.info('Option+C')} ${theme.ui.muted('Toggle auto-continue')}`,
1742
1911
  ` ${theme.info('Option+T')} ${theme.ui.muted('Cycle thinking mode')}`,
1912
+ ` ${theme.info('Option+A')} ${theme.ui.muted('Toggle AlphaZero RL mode')}`,
1743
1913
  ` ${theme.info('Option+E')} ${theme.ui.muted('Toggle edit permission mode')}`,
1744
1914
  ` ${theme.info('Option+X')} ${theme.ui.muted('Clear/compact context')}`,
1745
1915
  '',
@@ -2025,6 +2195,24 @@ export class InteractiveShell {
2025
2195
  };
2026
2196
  display.showInfo(`Thinking mode set to ${theme.info(value)} โ€“ ${descriptions[this.thinkingMode]}`);
2027
2197
  }
2198
+ handleAlphaZeroCommand(input) {
2199
+ const value = input.slice('/alphazero'.length).trim().toLowerCase();
2200
+ if (!value || value === 'status') {
2201
+ const status = this.alphaZeroModeEnabled ? theme.success('on') : theme.ui.muted('off');
2202
+ const verification = this.verificationEnabled ? 'verification locked on' : 'verification optional';
2203
+ display.showInfo(`AlphaZero RL mode is ${status}. When enabled, difficult prompts use duel/self-critique and human-style verification (${verification}).`);
2204
+ return;
2205
+ }
2206
+ if (['on', 'enable', 'enabled'].includes(value)) {
2207
+ this.setAlphaZeroMode(true, 'command');
2208
+ return;
2209
+ }
2210
+ if (['off', 'disable', 'disabled'].includes(value)) {
2211
+ this.setAlphaZeroMode(false, 'command');
2212
+ return;
2213
+ }
2214
+ display.showWarning('Usage: /alphazero [on|off|status]');
2215
+ }
2028
2216
  handleShortcutsCommand() {
2029
2217
  // Display keyboard shortcuts help (Claude Code style)
2030
2218
  display.showSystemMessage(formatShortcutsHelp());
@@ -3494,7 +3682,7 @@ export class InteractiveShell {
3494
3682
  display.clear();
3495
3683
  clearAutosaveSnapshot(this.profile);
3496
3684
  display.showInfo('Conversation cleared. Starting fresh.');
3497
- this.terminalInput.render();
3685
+ this.renderPromptArea();
3498
3686
  }
3499
3687
  async handleResumeCommand(input) {
3500
3688
  const tokens = input.split(/\s+/).slice(1);
@@ -3803,7 +3991,7 @@ export class InteractiveShell {
3803
3991
  if (!providerOptions.length) {
3804
3992
  display.showWarning('No providers are available.');
3805
3993
  this.pendingInteraction = null;
3806
- this.terminalInput.render();
3994
+ this.renderPromptArea();
3807
3995
  return;
3808
3996
  }
3809
3997
  const lines = [
@@ -3824,7 +4012,7 @@ export class InteractiveShell {
3824
4012
  catch (error) {
3825
4013
  display.showError('Failed to load model list. Try again in a moment.', error);
3826
4014
  this.pendingInteraction = null;
3827
- this.terminalInput.render();
4015
+ this.renderPromptArea();
3828
4016
  }
3829
4017
  }
3830
4018
  buildProviderOptions() {
@@ -4369,29 +4557,29 @@ export class InteractiveShell {
4369
4557
  const trimmed = input.trim();
4370
4558
  if (!trimmed) {
4371
4559
  display.showWarning('Enter a number or type cancel.');
4372
- this.terminalInput.render();
4560
+ this.renderPromptArea();
4373
4561
  return;
4374
4562
  }
4375
4563
  if (trimmed.toLowerCase() === 'cancel') {
4376
4564
  this.pendingInteraction = null;
4377
4565
  display.showInfo('Model selection cancelled.');
4378
- this.terminalInput.render();
4566
+ this.renderPromptArea();
4379
4567
  return;
4380
4568
  }
4381
4569
  const choice = Number.parseInt(trimmed, 10);
4382
4570
  if (!Number.isFinite(choice)) {
4383
4571
  display.showWarning('Please enter a valid number.');
4384
- this.terminalInput.render();
4572
+ this.renderPromptArea();
4385
4573
  return;
4386
4574
  }
4387
4575
  const option = pending.options[choice - 1];
4388
4576
  if (!option) {
4389
4577
  display.showWarning('That option is not available.');
4390
- this.terminalInput.render();
4578
+ this.renderPromptArea();
4391
4579
  return;
4392
4580
  }
4393
4581
  this.showProviderModels(option);
4394
- this.terminalInput.render();
4582
+ this.renderPromptArea();
4395
4583
  }
4396
4584
  async handleModelSelection(input) {
4397
4585
  const pending = this.pendingInteraction;
@@ -4401,35 +4589,35 @@ export class InteractiveShell {
4401
4589
  const trimmed = input.trim();
4402
4590
  if (!trimmed) {
4403
4591
  display.showWarning('Enter a number, type "back", or type "cancel".');
4404
- this.terminalInput.render();
4592
+ this.renderPromptArea();
4405
4593
  return;
4406
4594
  }
4407
4595
  if (trimmed.toLowerCase() === 'back') {
4408
4596
  this.showModelMenu();
4409
- this.terminalInput.render();
4597
+ this.renderPromptArea();
4410
4598
  return;
4411
4599
  }
4412
4600
  if (trimmed.toLowerCase() === 'cancel') {
4413
4601
  this.pendingInteraction = null;
4414
4602
  display.showInfo('Model selection cancelled.');
4415
- this.terminalInput.render();
4603
+ this.renderPromptArea();
4416
4604
  return;
4417
4605
  }
4418
4606
  const choice = Number.parseInt(trimmed, 10);
4419
4607
  if (!Number.isFinite(choice)) {
4420
4608
  display.showWarning('Please enter a valid number.');
4421
- this.terminalInput.render();
4609
+ this.renderPromptArea();
4422
4610
  return;
4423
4611
  }
4424
4612
  const preset = pending.options[choice - 1];
4425
4613
  if (!preset) {
4426
4614
  display.showWarning('That option is not available.');
4427
- this.terminalInput.render();
4615
+ this.renderPromptArea();
4428
4616
  return;
4429
4617
  }
4430
4618
  this.pendingInteraction = null;
4431
4619
  await this.applyModelPreset(preset);
4432
- this.terminalInput.render();
4620
+ this.renderPromptArea();
4433
4621
  }
4434
4622
  async applyModelPreset(preset) {
4435
4623
  try {
@@ -4462,30 +4650,30 @@ export class InteractiveShell {
4462
4650
  const trimmed = input.trim();
4463
4651
  if (!trimmed) {
4464
4652
  display.showWarning('Enter a number or type cancel.');
4465
- this.terminalInput.render();
4653
+ this.renderPromptArea();
4466
4654
  return;
4467
4655
  }
4468
4656
  if (trimmed.toLowerCase() === 'cancel') {
4469
4657
  this.pendingInteraction = null;
4470
4658
  display.showInfo('Secret management cancelled.');
4471
- this.terminalInput.render();
4659
+ this.renderPromptArea();
4472
4660
  return;
4473
4661
  }
4474
4662
  const choice = Number.parseInt(trimmed, 10);
4475
4663
  if (!Number.isFinite(choice)) {
4476
4664
  display.showWarning('Please enter a valid number.');
4477
- this.terminalInput.render();
4665
+ this.renderPromptArea();
4478
4666
  return;
4479
4667
  }
4480
4668
  const secret = pending.options[choice - 1];
4481
4669
  if (!secret) {
4482
4670
  display.showWarning('That option is not available.');
4483
- this.terminalInput.render();
4671
+ this.renderPromptArea();
4484
4672
  return;
4485
4673
  }
4486
4674
  display.showSystemMessage(`Enter a new value for ${secret.label} or type "cancel".`);
4487
4675
  this.pendingInteraction = { type: 'secret-input', secret };
4488
- this.terminalInput.render();
4676
+ this.renderPromptArea();
4489
4677
  }
4490
4678
  async handleSecretInput(input) {
4491
4679
  const pending = this.pendingInteraction;
@@ -4495,14 +4683,14 @@ export class InteractiveShell {
4495
4683
  const trimmed = input.trim();
4496
4684
  if (!trimmed) {
4497
4685
  display.showWarning('Enter a value or type cancel.');
4498
- this.terminalInput.render();
4686
+ this.renderPromptArea();
4499
4687
  return;
4500
4688
  }
4501
4689
  if (trimmed.toLowerCase() === 'cancel') {
4502
4690
  this.pendingInteraction = null;
4503
4691
  this.pendingSecretRetry = null;
4504
4692
  display.showInfo('Secret unchanged.');
4505
- this.terminalInput.render();
4693
+ this.renderPromptArea();
4506
4694
  return;
4507
4695
  }
4508
4696
  try {
@@ -4526,11 +4714,11 @@ export class InteractiveShell {
4526
4714
  this.pendingInteraction = null;
4527
4715
  this.pendingSecretRetry = null;
4528
4716
  }
4529
- this.terminalInput.render();
4717
+ this.renderPromptArea();
4530
4718
  }
4531
- async processRequest(request) {
4719
+ async processRequest(userRequest) {
4532
4720
  if (this.isProcessing) {
4533
- this.enqueueFollowUpAction({ type: 'request', text: request });
4721
+ this.enqueueFollowUpAction({ type: 'request', text: userRequest });
4534
4722
  return;
4535
4723
  }
4536
4724
  if (!this.agent && !this.rebuildAgent()) {
@@ -4541,28 +4729,48 @@ export class InteractiveShell {
4541
4729
  if (!agent) {
4542
4730
  return;
4543
4731
  }
4544
- this.logUserPrompt(request);
4732
+ const alphaZeroEngaged = this.alphaZeroModeEnabled;
4733
+ const alphaZeroDifficult = alphaZeroEngaged ? this.isDifficultProblem(userRequest) : false;
4734
+ const requestForAgent = alphaZeroEngaged
4735
+ ? this.buildAlphaZeroPrompt(userRequest, alphaZeroDifficult)
4736
+ : userRequest;
4737
+ const alphaZeroStatusId = 'alpha-zero';
4738
+ let alphaZeroStatusApplied = false;
4739
+ let alphaZeroTaskStarted = false;
4740
+ let alphaZeroTaskCompleted = false;
4741
+ if (alphaZeroEngaged) {
4742
+ const detail = alphaZeroDifficult ? 'Difficult request detected' : 'Reinforcement loop enabled';
4743
+ this.statusTracker.pushOverride(alphaZeroStatusId, 'AlphaZero RL active', {
4744
+ detail: `${detail} ยท full verification`,
4745
+ tone: 'info',
4746
+ });
4747
+ alphaZeroStatusApplied = true;
4748
+ display.showInfo(`AlphaZero RL mode engaged${alphaZeroDifficult ? ' for a difficult request' : ''}. Duel + self-critique with verification enabled.`);
4749
+ this.alphaZeroMetrics.startAlphaZeroTask(userRequest);
4750
+ alphaZeroTaskStarted = true;
4751
+ }
4752
+ this.logUserPrompt(userRequest);
4545
4753
  this.isProcessing = true;
4546
4754
  this.uiUpdates.setMode('processing');
4547
4755
  this.terminalInput.setStreaming(true);
4548
4756
  // Keep the persistent input/control bar active as we transition into streaming.
4549
- this.terminalInput.forceRender();
4757
+ this.renderPromptArea(true);
4550
4758
  const requestStartTime = Date.now(); // Alpha Zero 2 timing
4551
4759
  // Clear previous parallel agents and start fresh for new request
4552
4760
  const parallelManager = getParallelAgentManager();
4553
4761
  parallelManager.clear();
4554
4762
  parallelManager.startBatch();
4555
4763
  // AlphaZero: Track task for learning
4556
- this.lastUserQuery = request;
4557
- this.currentTaskType = classifyTaskType(request);
4764
+ this.lastUserQuery = userRequest;
4765
+ this.currentTaskType = classifyTaskType(userRequest);
4558
4766
  this.currentToolCalls = [];
4559
4767
  this.uiAdapter.startProcessing('Working on your request');
4560
4768
  this.setProcessingStatus();
4561
4769
  let responseText = '';
4562
4770
  try {
4563
4771
  // Start streaming - no header needed, the input area already provides context
4564
- this.startStreamingHeartbeat('Streaming response');
4565
- responseText = await agent.send(request, true);
4772
+ this.startStreamingHeartbeat(alphaZeroEngaged ? 'AlphaZero RL' : 'Streaming response');
4773
+ responseText = await agent.send(requestForAgent, true);
4566
4774
  await this.awaitPendingCleanup();
4567
4775
  this.captureHistorySnapshot();
4568
4776
  this.autosaveIfEnabled();
@@ -4583,8 +4791,12 @@ export class InteractiveShell {
4583
4791
  // AlphaZero: Check for failure in response
4584
4792
  const failure = detectFailure(responseText, {
4585
4793
  toolCalls: this.currentToolCalls,
4586
- userMessage: request,
4794
+ userMessage: userRequest,
4587
4795
  });
4796
+ if (alphaZeroEngaged && alphaZeroTaskStarted && !alphaZeroTaskCompleted) {
4797
+ this.alphaZeroMetrics.completeAlphaZeroTask(!failure);
4798
+ alphaZeroTaskCompleted = true;
4799
+ }
4588
4800
  if (failure) {
4589
4801
  this.lastFailure = failure;
4590
4802
  // Check if we have a recovery strategy
@@ -4611,13 +4823,23 @@ export class InteractiveShell {
4611
4823
  }
4612
4824
  }
4613
4825
  catch (error) {
4614
- const handled = this.handleProviderError(error, () => this.processRequest(request));
4826
+ const handled = this.handleProviderError(error, () => this.processRequest(userRequest));
4827
+ if (alphaZeroEngaged && alphaZeroTaskStarted && !alphaZeroTaskCompleted) {
4828
+ this.alphaZeroMetrics.completeAlphaZeroTask(false);
4829
+ alphaZeroTaskCompleted = true;
4830
+ }
4615
4831
  if (!handled) {
4616
4832
  // Pass full error object for enhanced formatting with stack trace
4617
4833
  display.showError(error instanceof Error ? error.message : String(error), error);
4618
4834
  }
4619
4835
  }
4620
4836
  finally {
4837
+ if (alphaZeroEngaged && alphaZeroStatusApplied) {
4838
+ this.statusTracker.clearOverride(alphaZeroStatusId);
4839
+ }
4840
+ if (alphaZeroEngaged && alphaZeroTaskStarted && !alphaZeroTaskCompleted) {
4841
+ this.alphaZeroMetrics.completeAlphaZeroTask(false);
4842
+ }
4621
4843
  display.stopThinking(false);
4622
4844
  this.uiUpdates.setMode('processing');
4623
4845
  this.stopStreamingHeartbeat();
@@ -4631,7 +4853,7 @@ export class InteractiveShell {
4631
4853
  // CRITICAL: Ensure readline prompt is active for user input
4632
4854
  // Claude Code style: New prompt naturally appears at bottom
4633
4855
  this.ensureReadlineReady();
4634
- this.terminalInput.render();
4856
+ this.renderPromptArea();
4635
4857
  this.scheduleQueueProcessing();
4636
4858
  this.refreshQueueIndicators();
4637
4859
  }
@@ -5102,6 +5324,8 @@ What's the next action?`;
5102
5324
  finally {
5103
5325
  this.updateStatusMessage(null);
5104
5326
  this.autoTestInFlight = false;
5327
+ this.terminalInput.resetContentPosition();
5328
+ this.terminalInput.forceRender();
5105
5329
  }
5106
5330
  }
5107
5331
  isBuildToolCall(entry) {
@@ -5208,7 +5432,7 @@ What's the next action?`;
5208
5432
  // Send the error to the agent for fixing
5209
5433
  display.showThinking('Analyzing build errors');
5210
5434
  this.refreshStatusLine(true);
5211
- const response = await this.agent.send(prompt, true);
5435
+ const response = await this.withStreamingUi('Fixing build errors', () => this.agent.send(prompt, true));
5212
5436
  display.stopThinking();
5213
5437
  this.refreshStatusLine(true);
5214
5438
  if (response) {
@@ -5318,19 +5542,19 @@ What's the next action?`;
5318
5542
  this.updateContextUsage(percentage);
5319
5543
  }
5320
5544
  // Ensure prompt remains visible at bottom after context messages
5321
- this.terminalInput.render();
5545
+ this.renderPromptArea();
5322
5546
  },
5323
5547
  onContinueAfterRecovery: () => {
5324
5548
  // Update UI to show we're continuing after context recovery
5325
5549
  display.showSystemMessage(`๐Ÿ”„ Continuing after context recovery...`);
5326
5550
  this.updateStatusMessage('Retrying with reduced context...');
5327
- this.terminalInput.render();
5551
+ this.renderPromptArea();
5328
5552
  },
5329
5553
  onAutoContinue: (attempt, maxAttempts, _message) => {
5330
5554
  // Show auto-continue progress in UI
5331
5555
  display.showSystemMessage(`๐Ÿ”„ Auto-continue (${attempt}/${maxAttempts}): Model expressed intent, prompting to act...`);
5332
5556
  this.updateStatusMessage('Auto-continuing...');
5333
- this.terminalInput.render();
5557
+ this.renderPromptArea();
5334
5558
  },
5335
5559
  onCancelled: () => {
5336
5560
  // Update UI to show operation was cancelled
@@ -5339,7 +5563,7 @@ What's the next action?`;
5339
5563
  this.stopStreamingHeartbeat();
5340
5564
  this.updateStatusMessage(null);
5341
5565
  this.terminalInput.setStreaming(false);
5342
- this.terminalInput.render();
5566
+ this.renderPromptArea();
5343
5567
  },
5344
5568
  onVerificationNeeded: () => {
5345
5569
  void this.enforceAutoBuild('verification');
@@ -5377,7 +5601,7 @@ What's the next action?`;
5377
5601
  resetChatBoxAfterModelSwap() {
5378
5602
  this.updateStatusMessage(null);
5379
5603
  this.terminalInput.setStreaming(false);
5380
- this.terminalInput.render();
5604
+ this.renderPromptArea();
5381
5605
  this.ensureReadlineReady();
5382
5606
  }
5383
5607
  /**