@triedotdev/mcp 1.0.102 → 1.0.103

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 (36) hide show
  1. package/README.md +0 -1
  2. package/dist/{chunk-OVRG5RP3.js → chunk-33WL3D7A.js} +3 -5
  3. package/dist/{chunk-OVRG5RP3.js.map → chunk-33WL3D7A.js.map} +1 -1
  4. package/dist/{chunk-JDHR5BDR.js → chunk-6JPPYG7F.js} +928 -258
  5. package/dist/chunk-6JPPYG7F.js.map +1 -0
  6. package/dist/{chunk-M4JCQO5G.js → chunk-CKYU5JOD.js} +579 -114
  7. package/dist/chunk-CKYU5JOD.js.map +1 -0
  8. package/dist/{chunk-B3MNN3XB.js → chunk-HFKOGW7H.js} +6 -8
  9. package/dist/{chunk-B3MNN3XB.js.map → chunk-HFKOGW7H.js.map} +1 -1
  10. package/dist/chunk-HIKONDDO.js +26 -0
  11. package/dist/chunk-HIKONDDO.js.map +1 -0
  12. package/dist/chunk-M4YMTHGG.js +2822 -0
  13. package/dist/chunk-M4YMTHGG.js.map +1 -0
  14. package/dist/{chunk-NIASHOAB.js → chunk-SPQJC7RA.js} +5 -5
  15. package/dist/cli/main.js +16 -18
  16. package/dist/cli/main.js.map +1 -1
  17. package/dist/cli/yolo-daemon.js +17 -64
  18. package/dist/cli/yolo-daemon.js.map +1 -1
  19. package/dist/{goal-manager-LAOT4QQX.js → goal-manager-AP4LTE6U.js} +3 -4
  20. package/dist/{guardian-agent-M352CBE5.js → guardian-agent-WB6LWRLM.js} +7 -8
  21. package/dist/index.js +41 -119
  22. package/dist/index.js.map +1 -1
  23. package/package.json +4 -1
  24. package/dist/chunk-AE2XLMZC.js +0 -6152
  25. package/dist/chunk-AE2XLMZC.js.map +0 -1
  26. package/dist/chunk-CCI6LKXZ.js +0 -526
  27. package/dist/chunk-CCI6LKXZ.js.map +0 -1
  28. package/dist/chunk-JDHR5BDR.js.map +0 -1
  29. package/dist/chunk-M4JCQO5G.js.map +0 -1
  30. package/dist/chunk-R3I2GCZC.js +0 -682
  31. package/dist/chunk-R3I2GCZC.js.map +0 -1
  32. package/dist/issue-store-W2X33X2X.js +0 -28
  33. package/dist/issue-store-W2X33X2X.js.map +0 -1
  34. /package/dist/{chunk-NIASHOAB.js.map → chunk-SPQJC7RA.js.map} +0 -0
  35. /package/dist/{goal-manager-LAOT4QQX.js.map → goal-manager-AP4LTE6U.js.map} +0 -0
  36. /package/dist/{guardian-agent-M352CBE5.js.map → guardian-agent-WB6LWRLM.js.map} +0 -0
@@ -0,0 +1,2822 @@
1
+ import {
2
+ getGuardian
3
+ } from "./chunk-HFKOGW7H.js";
4
+ import {
5
+ findCrossProjectPatterns,
6
+ isAIAvailable
7
+ } from "./chunk-SPQJC7RA.js";
8
+ import {
9
+ getGuardianState,
10
+ getMemoryStats,
11
+ getRecentIssues
12
+ } from "./chunk-6JPPYG7F.js";
13
+ import {
14
+ getTrieDirectory,
15
+ getWorkingDirectory
16
+ } from "./chunk-R4AAPFXC.js";
17
+ import {
18
+ isInteractiveMode
19
+ } from "./chunk-APMV77PU.js";
20
+
21
+ // src/tools/scan.ts
22
+ var TrieScanTool = class {
23
+ async execute(_input) {
24
+ console.error("\u2139\uFE0F Trie scan has been refocused on decision ledger");
25
+ console.error(" Use: trie tell - to report incidents");
26
+ console.error(" Use: trie gotcha - to predict risks");
27
+ console.error(" Use: trie learn - to learn from history");
28
+ return {
29
+ content: [{
30
+ type: "text",
31
+ text: "Scan functionality has been refocused on decision ledger.\n\nUse:\n- trie tell - to report incidents\n- trie gotcha - to predict risks\n- trie learn - to learn from history"
32
+ }]
33
+ };
34
+ }
35
+ };
36
+
37
+ // src/utils/streaming.ts
38
+ var shouldSuppressConsole = () => isInteractiveMode();
39
+ var StreamingManager = class {
40
+ listeners = /* @__PURE__ */ new Set();
41
+ progress = {
42
+ totalFiles: 0,
43
+ processedFiles: 0,
44
+ activeAgents: [],
45
+ completedAgents: [],
46
+ totalIssues: 0,
47
+ issuesBySeverity: { critical: 0, serious: 0, moderate: 0, low: 0 }
48
+ };
49
+ /**
50
+ * Subscribe to scan updates
51
+ */
52
+ subscribe(callback) {
53
+ this.listeners.add(callback);
54
+ return () => this.listeners.delete(callback);
55
+ }
56
+ /**
57
+ * Emit an update to all listeners
58
+ */
59
+ emit(type, data) {
60
+ const update = {
61
+ type,
62
+ timestamp: Date.now(),
63
+ data
64
+ };
65
+ this.listeners.forEach((listener) => {
66
+ try {
67
+ listener(update);
68
+ } catch (error) {
69
+ if (!shouldSuppressConsole()) {
70
+ console.warn("Stream listener error:", error);
71
+ }
72
+ }
73
+ });
74
+ }
75
+ /**
76
+ * Initialize scan with file count
77
+ */
78
+ startScan(totalFiles) {
79
+ this.progress = {
80
+ totalFiles,
81
+ processedFiles: 0,
82
+ activeAgents: [],
83
+ completedAgents: [],
84
+ totalIssues: 0,
85
+ issuesBySeverity: { critical: 0, serious: 0, moderate: 0, low: 0 }
86
+ };
87
+ this.emit("progress", { ...this.progress });
88
+ }
89
+ /**
90
+ * Update current file being processed
91
+ */
92
+ updateCurrentFile(file) {
93
+ this.progress.currentFile = file;
94
+ this.emit("progress", { ...this.progress });
95
+ }
96
+ /**
97
+ * Mark file as processed
98
+ */
99
+ completeFile() {
100
+ this.progress.processedFiles++;
101
+ this.emit("progress", { ...this.progress });
102
+ }
103
+ /**
104
+ * Start agent execution
105
+ */
106
+ startAgent(agentName) {
107
+ if (!this.progress.activeAgents.includes(agentName)) {
108
+ this.progress.activeAgents.push(agentName);
109
+ }
110
+ this.emit("agent_start", { agent: agentName });
111
+ this.emit("progress", { ...this.progress });
112
+ }
113
+ /**
114
+ * Complete agent execution
115
+ */
116
+ completeAgent(agentName, issues) {
117
+ this.progress.activeAgents = this.progress.activeAgents.filter((a) => a !== agentName);
118
+ if (!this.progress.completedAgents.includes(agentName)) {
119
+ this.progress.completedAgents.push(agentName);
120
+ }
121
+ for (const issue of issues) {
122
+ this.progress.issuesBySeverity[issue.severity]++;
123
+ this.progress.totalIssues++;
124
+ }
125
+ this.emit("agent_complete", {
126
+ agent: agentName,
127
+ issueCount: issues.length,
128
+ issues: issues.slice(0, 5)
129
+ // Only send first 5 for streaming
130
+ });
131
+ this.emit("progress", { ...this.progress });
132
+ }
133
+ /**
134
+ * Report new issue found
135
+ */
136
+ reportIssue(issue) {
137
+ this.progress.issuesBySeverity[issue.severity]++;
138
+ this.progress.totalIssues++;
139
+ this.emit("issue_found", issue);
140
+ this.emit("progress", { ...this.progress });
141
+ }
142
+ /**
143
+ * Complete the entire scan
144
+ */
145
+ completeScan(totalIssues) {
146
+ this.emit("scan_complete", {
147
+ totalFiles: this.progress.totalFiles,
148
+ totalIssues: totalIssues.length,
149
+ issues: totalIssues,
150
+ // Include all issues for the dashboard
151
+ issuesBySeverity: this.progress.issuesBySeverity,
152
+ completedAgents: this.progress.completedAgents
153
+ });
154
+ }
155
+ /**
156
+ * Report error
157
+ */
158
+ reportError(error, context) {
159
+ this.emit("error", {
160
+ message: error.message,
161
+ context,
162
+ stack: error.stack
163
+ });
164
+ }
165
+ /**
166
+ * Get current progress
167
+ */
168
+ getProgress() {
169
+ return { ...this.progress };
170
+ }
171
+ /**
172
+ * Reset state
173
+ */
174
+ reset() {
175
+ this.progress = {
176
+ totalFiles: 0,
177
+ processedFiles: 0,
178
+ activeAgents: [],
179
+ completedAgents: [],
180
+ totalIssues: 0,
181
+ issuesBySeverity: { critical: 0, serious: 0, moderate: 0, low: 0 }
182
+ };
183
+ }
184
+ /**
185
+ * Report watch status (directories, debounce, last change)
186
+ */
187
+ reportWatchStatus(status) {
188
+ this.emit("watch_status", status);
189
+ }
190
+ /**
191
+ * Report a specific file change when watching
192
+ */
193
+ reportWatchChange(file) {
194
+ this.emit("watch_change", { file });
195
+ }
196
+ /**
197
+ * Report memory operations (saving context, learning patterns)
198
+ */
199
+ reportMemory(action, details) {
200
+ this.emit("memory", { action, details });
201
+ }
202
+ /**
203
+ * Report signal extraction from watch mode
204
+ */
205
+ reportSignalExtraction(signals) {
206
+ this.emit("signal_extracted", signals);
207
+ }
208
+ // ============================================
209
+ // Rich Content Events (for TUI panes)
210
+ // ============================================
211
+ /**
212
+ * Report a code snippet for display
213
+ */
214
+ reportSnippet(snippet) {
215
+ this.emit("snippet", snippet);
216
+ }
217
+ /**
218
+ * Report cost estimate from Moneybags
219
+ */
220
+ reportCost(cost) {
221
+ this.emit("cost_report", cost);
222
+ }
223
+ /**
224
+ * Report production readiness score
225
+ */
226
+ reportReadiness(readiness) {
227
+ this.emit("readiness_report", readiness);
228
+ }
229
+ /**
230
+ * Report semantic analysis results
231
+ */
232
+ reportSemantic(semantic) {
233
+ this.emit("semantic_report", semantic);
234
+ }
235
+ /**
236
+ * Report attack surface analysis
237
+ */
238
+ reportAttackSurface(attack) {
239
+ this.emit("attack_surface", attack);
240
+ }
241
+ /**
242
+ * Report skill banner (ASCII art + quote)
243
+ */
244
+ reportBanner(banner) {
245
+ this.emit("skill_banner", banner);
246
+ }
247
+ /**
248
+ * Report raw log entry
249
+ */
250
+ reportRawLog(level, message) {
251
+ this.emit("raw_log", { level, message, time: (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false }) });
252
+ }
253
+ };
254
+
255
+ // src/cli/dashboard/index.ts
256
+ import { render } from "ink";
257
+ import React7 from "react";
258
+
259
+ // src/cli/dashboard/App.tsx
260
+ import { useState as useState2, useEffect as useEffect2, useCallback as useCallback4, useRef } from "react";
261
+ import { Box as Box11, useInput as useInput7, useApp } from "ink";
262
+
263
+ // src/cli/dashboard/state.tsx
264
+ import React, { createContext, useContext, useReducer } from "react";
265
+ import { jsx } from "react/jsx-runtime";
266
+ function addActivity(state, message) {
267
+ const time = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit" });
268
+ const activityLog = [{ time, message }, ...state.activityLog].slice(0, 50);
269
+ return { ...state, activityLog };
270
+ }
271
+ function getVisibleInsights(state) {
272
+ return state.agentInsights.filter((i) => !i.dismissed);
273
+ }
274
+ function getMemoryTreeNodes(state) {
275
+ const nodes = [];
276
+ const { expandedNodes, issues, globalPatterns } = state.memoryTree;
277
+ nodes.push({ id: "severity", level: 0 });
278
+ if (expandedNodes.has("severity")) {
279
+ nodes.push({ id: "severity-critical", level: 1 });
280
+ if (expandedNodes.has("severity-critical")) {
281
+ issues.filter((i) => i.severity === "critical").slice(0, 5).forEach((issue) => {
282
+ nodes.push({ id: `severity-critical-${issue.id}`, level: 2 });
283
+ });
284
+ }
285
+ nodes.push({ id: "severity-serious", level: 1 });
286
+ nodes.push({ id: "severity-moderate", level: 1 });
287
+ nodes.push({ id: "severity-low", level: 1 });
288
+ }
289
+ nodes.push({ id: "files", level: 0 });
290
+ if (expandedNodes.has("files")) {
291
+ const byFile = /* @__PURE__ */ new Map();
292
+ for (const issue of issues) {
293
+ byFile.set(issue.file, (byFile.get(issue.file) || 0) + 1);
294
+ }
295
+ Array.from(byFile.entries()).sort((a, b) => b[1] - a[1]).slice(0, 10).forEach(([file]) => nodes.push({ id: `file-${file}`, level: 1 }));
296
+ }
297
+ nodes.push({ id: "agents", level: 0 });
298
+ if (expandedNodes.has("agents")) {
299
+ const byAgent = /* @__PURE__ */ new Map();
300
+ for (const issue of issues) {
301
+ byAgent.set(issue.agent, (byAgent.get(issue.agent) || 0) + 1);
302
+ }
303
+ Array.from(byAgent.entries()).sort((a, b) => b[1] - a[1]).forEach(([agent]) => nodes.push({ id: `agent-${agent}`, level: 1 }));
304
+ }
305
+ nodes.push({ id: "patterns", level: 0 });
306
+ if (expandedNodes.has("patterns")) {
307
+ globalPatterns.slice(0, 5).forEach((p) => nodes.push({ id: `pattern-${p.id}`, level: 1 }));
308
+ }
309
+ return nodes;
310
+ }
311
+ function handleStreamUpdate(state, update) {
312
+ let s = { ...state, lastUpdate: Date.now() };
313
+ switch (update.type) {
314
+ case "progress": {
315
+ const oldProgress = s.progress;
316
+ if (oldProgress.totalFiles === 0 && update.data.totalFiles > 0 || oldProgress.processedFiles > 0 && update.data.processedFiles === 0) {
317
+ s.scanStartTime = Date.now();
318
+ s.scanComplete = false;
319
+ s = { ...s };
320
+ delete s.scanEndTime;
321
+ }
322
+ s.progress = update.data;
323
+ if (update.data.issuesBySeverity?.critical > 0) {
324
+ s.alerts = { hasCritical: true, lastCriticalAt: update.timestamp };
325
+ }
326
+ if (update.data.currentFile && update.data.processedFiles % 10 === 0 && update.data.processedFiles !== oldProgress.processedFiles) {
327
+ s = addActivity(s, `Scanned ${update.data.processedFiles}/${update.data.totalFiles} files`);
328
+ }
329
+ break;
330
+ }
331
+ case "agent_start":
332
+ s = addActivity(s, `[*] Scout started: ${update.data.agent}`);
333
+ break;
334
+ case "agent_complete":
335
+ s = addActivity(s, `[+] Scout complete: ${update.data.agent} (${update.data.issueCount} issues)`);
336
+ break;
337
+ case "issue_found":
338
+ s.issues = [...s.issues, update.data];
339
+ if (update.data.severity === "critical" || update.data.severity === "serious") {
340
+ const icon = update.data.severity === "critical" ? "[!]" : "[x]";
341
+ const fileName = update.data.file?.split("/").pop() || "unknown";
342
+ s = addActivity(s, `${icon} ${update.data.severity.toUpperCase()}: ${update.data.message?.slice(0, 40) || fileName}`);
343
+ if (update.data.severity === "critical") {
344
+ s.alerts = { hasCritical: true, lastCriticalAt: update.timestamp };
345
+ }
346
+ }
347
+ break;
348
+ case "scan_complete":
349
+ s.scanComplete = true;
350
+ s.scanEndTime = update.timestamp;
351
+ s.progress = { ...s.progress, processedFiles: s.progress.totalFiles };
352
+ if (update.data.issues && Array.isArray(update.data.issues)) {
353
+ s.issues = update.data.issues;
354
+ }
355
+ s = addActivity(s, `=== Scan complete - ${s.progress.totalIssues} issues ===`);
356
+ break;
357
+ case "watch_status":
358
+ s.watch = {
359
+ watching: update.data.watching ?? s.watch.watching,
360
+ directories: update.data.directories ?? s.watch.directories,
361
+ debounceMs: update.data.debounceMs ?? s.watch.debounceMs,
362
+ lastChange: update.data.lastChange ?? s.watch.lastChange,
363
+ recentChanges: update.data.recentChanges ?? s.watch.recentChanges
364
+ };
365
+ if (update.data.watching !== void 0) {
366
+ s = addActivity(s, update.data.watching ? `[*] Watch mode: ACTIVE (${update.data.directories ?? 0} dirs)` : "[*] Watch mode: OFF");
367
+ }
368
+ break;
369
+ case "watch_change": {
370
+ const entry = { file: update.data.file, time: new Date(update.timestamp).toLocaleTimeString("en-US", { hour12: false }) };
371
+ s.watch = {
372
+ ...s.watch,
373
+ recentChanges: [entry, ...s.watch.recentChanges].slice(0, 5),
374
+ lastChange: entry.time
375
+ };
376
+ s = addActivity(s, `Change detected: ${update.data.file}`);
377
+ break;
378
+ }
379
+ case "signal_extracted": {
380
+ const se = { ...s.signalExtraction };
381
+ if (update.data.decisions) se.decisionsExtracted += update.data.decisions;
382
+ if (update.data.facts) se.factsExtracted += update.data.facts;
383
+ if (update.data.blockers) se.blockersExtracted += update.data.blockers;
384
+ if (update.data.questions) se.questionsExtracted += update.data.questions;
385
+ s.signalExtraction = se;
386
+ const total = (update.data.decisions || 0) + (update.data.facts || 0) + (update.data.blockers || 0) + (update.data.questions || 0);
387
+ if (total > 0) {
388
+ s = addActivity(s, `[+] Extracted ${total} signals (${update.data.decisions}d, ${update.data.facts}f, ${update.data.blockers}b)`);
389
+ }
390
+ break;
391
+ }
392
+ case "memory":
393
+ if (update.data.action === "saving") s = addActivity(s, "[~] Saving to memory...");
394
+ else if (update.data.action === "saved") s = addActivity(s, `[+] Memory updated: ${update.data.details || "context saved"}`);
395
+ else if (update.data.action === "learning") s = addActivity(s, `[~] Learning: ${update.data.details || "analyzing patterns"}`);
396
+ break;
397
+ case "raw_log":
398
+ s.rawLog = [{
399
+ time: update.data.time || new Date(update.timestamp).toLocaleTimeString("en-US", { hour12: false }),
400
+ level: update.data.level,
401
+ message: update.data.message
402
+ }, ...s.rawLog].slice(0, 500);
403
+ break;
404
+ }
405
+ return s;
406
+ }
407
+ function applyAgentConfigPatch(current, patch) {
408
+ const config = { ...current };
409
+ if (patch.agentSmith) {
410
+ config.agentSmith = {
411
+ ...config.agentSmith,
412
+ ...patch.agentSmith,
413
+ enabledCategories: {
414
+ ...config.agentSmith.enabledCategories,
415
+ ...patch.agentSmith.enabledCategories || {}
416
+ }
417
+ };
418
+ }
419
+ if (patch.performance) config.performance = { ...config.performance, ...patch.performance };
420
+ if (patch.riskThresholds) config.riskThresholds = { ...config.riskThresholds, ...patch.riskThresholds };
421
+ return config;
422
+ }
423
+ function dashboardReducer(state, action) {
424
+ switch (action.type) {
425
+ case "STREAM_UPDATE":
426
+ return handleStreamUpdate(state, action.update);
427
+ case "SET_VIEW":
428
+ return { ...state, previousView: state.view, view: action.view };
429
+ case "GO_BACK":
430
+ return { ...state, view: state.previousView || "overview", previousView: null };
431
+ case "ADD_ACTIVITY":
432
+ return addActivity(state, action.message);
433
+ case "SHOW_NOTIFICATION": {
434
+ const now = Date.now();
435
+ const historyEntry = {
436
+ message: action.message,
437
+ severity: action.severity,
438
+ timestamp: now,
439
+ dismissed: false
440
+ };
441
+ if (action.file !== void 0) historyEntry.file = action.file;
442
+ const notification = {
443
+ active: true,
444
+ message: action.message,
445
+ severity: action.severity,
446
+ timestamp: now
447
+ };
448
+ if (action.file !== void 0) notification.file = action.file;
449
+ if (action.autoHideMs !== void 0) notification.autoHideAt = now + action.autoHideMs;
450
+ let s = {
451
+ ...state,
452
+ notification,
453
+ notificationHistory: [historyEntry, ...state.notificationHistory].slice(0, 50)
454
+ };
455
+ const prefix = action.severity === "critical" ? "[!]" : action.severity === "warning" ? "[!]" : "[>]";
456
+ s = addActivity(s, `${prefix} ${action.message}`);
457
+ return s;
458
+ }
459
+ case "DISMISS_NOTIFICATION": {
460
+ if (!state.notification) return state;
461
+ const history = state.notificationHistory.map(
462
+ (h) => h.timestamp === state.notification?.timestamp ? { ...h, dismissed: true } : h
463
+ );
464
+ return { ...state, notification: null, notificationHistory: history };
465
+ }
466
+ case "SET_INSIGHTS":
467
+ return { ...state, agentInsights: action.insights };
468
+ case "ADD_INSIGHTS": {
469
+ const existing = state.agentInsights;
470
+ const newOnes = action.insights.filter(
471
+ (ni) => !existing.some((ei) => ei.message === ni.message && !ei.dismissed)
472
+ );
473
+ const merged = [...newOnes, ...existing].slice(0, 50);
474
+ let s = { ...state, agentInsights: merged };
475
+ if (newOnes.length > 0) {
476
+ s = addActivity(s, `Trie Agent: ${newOnes.length} new insight${newOnes.length > 1 ? "s" : ""}`);
477
+ }
478
+ return s;
479
+ }
480
+ case "SET_AGENT_INITIALIZED":
481
+ return { ...state, agentInitialized: action.initialized };
482
+ case "SET_AGENCY_STATUS":
483
+ return { ...state, agencyStatus: action.status };
484
+ case "SELECT_INSIGHT":
485
+ return { ...state, selectedInsight: action.index };
486
+ case "TOGGLE_INSIGHT":
487
+ return {
488
+ ...state,
489
+ expandedInsight: state.expandedInsight === action.index ? null : action.index
490
+ };
491
+ case "DISMISS_INSIGHT": {
492
+ const visible = getVisibleInsights(state);
493
+ const insight = visible[action.index];
494
+ if (!insight) return state;
495
+ const insights = state.agentInsights.map(
496
+ (i) => i.id === insight.id ? { ...i, dismissed: true } : i
497
+ );
498
+ const remaining = insights.filter((i) => !i.dismissed);
499
+ return {
500
+ ...state,
501
+ agentInsights: insights,
502
+ selectedInsight: Math.min(state.selectedInsight, Math.max(0, remaining.length - 1)),
503
+ expandedInsight: state.expandedInsight === action.index ? null : state.expandedInsight
504
+ };
505
+ }
506
+ case "IGNORE_INSIGHT": {
507
+ const visible = getVisibleInsights(state);
508
+ const insight = visible[action.index];
509
+ if (!insight) return state;
510
+ const insights = state.agentInsights.map(
511
+ (i) => i.id === insight.id ? { ...i, dismissed: true } : i
512
+ );
513
+ const remaining = insights.filter((i) => !i.dismissed);
514
+ let s = { ...state, agentInsights: insights };
515
+ s.selectedInsight = Math.min(s.selectedInsight, Math.max(0, remaining.length - 1));
516
+ s.expandedInsight = s.expandedInsight === action.index ? null : s.expandedInsight;
517
+ s = addActivity(s, `Ignored: ${insight.message.slice(0, 40)}...`);
518
+ return s;
519
+ }
520
+ case "CLEAR_DISMISSED_INSIGHTS": {
521
+ const dismissedCount = state.agentInsights.filter((i) => i.dismissed).length;
522
+ if (dismissedCount === 0) return addActivity(state, "No dismissed insights to clear");
523
+ const filtered = state.agentInsights.filter((i) => !i.dismissed);
524
+ let s = {
525
+ ...state,
526
+ agentInsights: filtered,
527
+ notificationHistory: [],
528
+ expandedInsight: null,
529
+ scrollPositions: { ...state.scrollPositions, agent: 0 }
530
+ };
531
+ s.selectedInsight = Math.min(s.selectedInsight, Math.max(0, filtered.length - 1));
532
+ s = addActivity(s, `Cleared ${dismissedCount} dismissed insight${dismissedCount !== 1 ? "s" : ""}`);
533
+ return s;
534
+ }
535
+ case "SET_GOALS":
536
+ return { ...state, goalsPanel: { ...state.goalsPanel, goals: action.goals } };
537
+ case "SET_GOALS_INPUT_MODE":
538
+ return { ...state, goalsPanel: { ...state.goalsPanel, inputMode: action.mode, inputBuffer: action.mode === "add" ? "" : state.goalsPanel.inputBuffer } };
539
+ case "SET_GOALS_INPUT_BUFFER":
540
+ return { ...state, goalsPanel: { ...state.goalsPanel, inputBuffer: action.buffer } };
541
+ case "SELECT_GOAL":
542
+ return { ...state, goalsPanel: { ...state.goalsPanel, selectedIndex: action.index } };
543
+ case "SET_HYPOTHESES":
544
+ return { ...state, hypothesesPanel: { ...state.hypothesesPanel, hypotheses: action.hypotheses } };
545
+ case "SET_HYPOTHESES_INPUT_MODE":
546
+ return { ...state, hypothesesPanel: { ...state.hypothesesPanel, inputMode: action.mode, inputBuffer: action.mode === "add" ? "" : state.hypothesesPanel.inputBuffer } };
547
+ case "SET_HYPOTHESES_INPUT_BUFFER":
548
+ return { ...state, hypothesesPanel: { ...state.hypothesesPanel, inputBuffer: action.buffer } };
549
+ case "SELECT_HYPOTHESIS":
550
+ return { ...state, hypothesesPanel: { ...state.hypothesesPanel, selectedIndex: action.index } };
551
+ case "SET_MEMORY_TREE":
552
+ return {
553
+ ...state,
554
+ memoryTree: { ...state.memoryTree, loaded: true, issues: action.issues, stats: action.stats, globalPatterns: action.patterns }
555
+ };
556
+ case "SELECT_MEMORY_NODE":
557
+ return { ...state, memoryTree: { ...state.memoryTree, selectedNode: action.nodeId } };
558
+ case "TOGGLE_MEMORY_NODE": {
559
+ const expandable = ["severity", "files", "agents", "patterns", "severity-critical", "severity-serious", "severity-moderate", "severity-low"];
560
+ if (!expandable.includes(action.nodeId)) return state;
561
+ const expanded = new Set(state.memoryTree.expandedNodes);
562
+ if (expanded.has(action.nodeId)) expanded.delete(action.nodeId);
563
+ else expanded.add(action.nodeId);
564
+ return { ...state, memoryTree: { ...state.memoryTree, expandedNodes: expanded } };
565
+ }
566
+ case "SET_AGENT_CONFIG":
567
+ return { ...state, agentConfig: applyAgentConfigPatch(state.agentConfig, action.config) };
568
+ case "NAVIGATE_UP": {
569
+ if (state.view === "agent") {
570
+ const visible = getVisibleInsights(state);
571
+ if (visible.length === 0) return state;
572
+ const idx = Math.max(0, state.selectedInsight - 1);
573
+ const scroll = Math.min(state.scrollPositions.agent, idx);
574
+ return { ...state, selectedInsight: idx, scrollPositions: { ...state.scrollPositions, agent: scroll } };
575
+ }
576
+ if (state.view === "memory") {
577
+ const nodes = getMemoryTreeNodes(state);
578
+ const cur = nodes.findIndex((n) => n.id === state.memoryTree.selectedNode);
579
+ if (cur > 0) {
580
+ return { ...state, memoryTree: { ...state.memoryTree, selectedNode: nodes[cur - 1]?.id || "severity" } };
581
+ }
582
+ return state;
583
+ }
584
+ return state;
585
+ }
586
+ case "NAVIGATE_DOWN": {
587
+ if (state.view === "agent") {
588
+ const visible = getVisibleInsights(state);
589
+ if (visible.length === 0) return state;
590
+ const maxIdx = Math.max(0, visible.length - 1);
591
+ const idx = Math.min(maxIdx, state.selectedInsight + 1);
592
+ const visibleItems = Math.floor(20 / 4);
593
+ let scroll = state.scrollPositions.agent;
594
+ if (idx >= scroll + visibleItems) scroll = idx - visibleItems + 1;
595
+ return { ...state, selectedInsight: idx, scrollPositions: { ...state.scrollPositions, agent: scroll } };
596
+ }
597
+ if (state.view === "memory") {
598
+ const nodes = getMemoryTreeNodes(state);
599
+ const cur = nodes.findIndex((n) => n.id === state.memoryTree.selectedNode);
600
+ if (cur < nodes.length - 1) {
601
+ return { ...state, memoryTree: { ...state.memoryTree, selectedNode: nodes[cur + 1]?.id || "severity" } };
602
+ }
603
+ return state;
604
+ }
605
+ return state;
606
+ }
607
+ case "NEXT_PAGE":
608
+ return { ...state, activityPage: Math.min(Math.max(1, Math.ceil(state.activityLog.length / 6)) - 1, state.activityPage + 1) };
609
+ case "PREV_PAGE":
610
+ return { ...state, activityPage: Math.max(0, state.activityPage - 1) };
611
+ case "SET_RAW_LOG_PAGE":
612
+ return { ...state, rawLogPage: action.page };
613
+ case "AUTO_DISMISS_NOTIFICATIONS": {
614
+ const now = Date.now();
615
+ let changed = false;
616
+ const history = state.notificationHistory.map((n) => {
617
+ if (!n.dismissed && n.severity !== "critical") {
618
+ const age = now - n.timestamp;
619
+ const autoHideMs = n.severity === "info" ? 3e4 : 6e4;
620
+ if (age > autoHideMs) {
621
+ changed = true;
622
+ return { ...n, dismissed: true };
623
+ }
624
+ }
625
+ return n;
626
+ });
627
+ if (!changed) return state;
628
+ return { ...state, notificationHistory: history };
629
+ }
630
+ default:
631
+ return state;
632
+ }
633
+ }
634
+ function createInitialState() {
635
+ return {
636
+ issues: [],
637
+ progress: {
638
+ totalFiles: 0,
639
+ processedFiles: 0,
640
+ activeAgents: [],
641
+ completedAgents: [],
642
+ totalIssues: 0,
643
+ issuesBySeverity: { critical: 0, serious: 0, moderate: 0, low: 0 }
644
+ },
645
+ filter: { severity: "all", agent: "all", search: "" },
646
+ view: "overview",
647
+ previousView: null,
648
+ lastUpdate: Date.now(),
649
+ scanComplete: true,
650
+ startTime: Date.now(),
651
+ scanStartTime: Date.now(),
652
+ activityLog: [],
653
+ activityPage: 0,
654
+ quietMode: false,
655
+ signalExtraction: {
656
+ enabled: !!process.env["ANTHROPIC_API_KEY"],
657
+ decisionsExtracted: 0,
658
+ factsExtracted: 0,
659
+ blockersExtracted: 0,
660
+ questionsExtracted: 0
661
+ },
662
+ alerts: { hasCritical: false },
663
+ watch: { watching: false, directories: 0, recentChanges: [] },
664
+ rawLog: [],
665
+ rawLogPage: 0,
666
+ scrollPositions: { overview: 0, rawlog: 0, agent: 0, goals: 0, hypotheses: 0, memory: 0 },
667
+ notification: null,
668
+ notificationHistory: [],
669
+ agentInsights: [],
670
+ agentInitialized: false,
671
+ agencyStatus: null,
672
+ selectedInsight: 0,
673
+ expandedInsight: null,
674
+ agentConfig: {
675
+ agentSmith: {
676
+ aiEnhancement: true,
677
+ minSeverity: "low",
678
+ enabledCategories: { security: true, codeSmells: true, asyncBugs: true, reactPatterns: true, uxPatterns: true, backendPatterns: true },
679
+ memoryRetentionDays: 30
680
+ },
681
+ performance: { parallel: true, cache: true, maxConcurrency: 4, timeoutMs: 12e4, workers: true, streaming: true },
682
+ riskThresholds: { critical: 70, high: 40, medium: 20 }
683
+ },
684
+ goalsPanel: { goals: [], selectedIndex: 0, selectedAchievedIndex: 0, inputMode: "browse", inputBuffer: "", lastRefresh: 0 },
685
+ hypothesesPanel: { hypotheses: [], selectedIndex: 0, selectedCompletedIndex: 0, inputMode: "browse", inputBuffer: "", lastRefresh: 0 },
686
+ memoryTree: { loaded: false, issues: [], stats: null, globalPatterns: [], expandedNodes: /* @__PURE__ */ new Set(["severity", "files"]), selectedNode: "severity", scrollPosition: 0, lastRefresh: 0 }
687
+ };
688
+ }
689
+ var DashboardContext = createContext(null);
690
+ function DashboardProvider({ children, initialState }) {
691
+ const [state, dispatch] = useReducer(dashboardReducer, initialState || createInitialState());
692
+ const value = React.useMemo(() => ({ state, dispatch }), [state, dispatch]);
693
+ return /* @__PURE__ */ jsx(DashboardContext.Provider, { value, children });
694
+ }
695
+ function useDashboard() {
696
+ const ctx = useContext(DashboardContext);
697
+ if (!ctx) throw new Error("useDashboard must be used within DashboardProvider");
698
+ return ctx;
699
+ }
700
+
701
+ // src/utils/output-manager.ts
702
+ import pc from "picocolors";
703
+ var OutputManagerImpl = class {
704
+ mode = "console";
705
+ streamingManager;
706
+ markdownBuffer = [];
707
+ jsonBuffer = [];
708
+ rawLogBuffer = [];
709
+ // Callbacks for TUI integration (explicitly allow undefined for exactOptionalPropertyTypes)
710
+ onBanner = void 0;
711
+ onSnippet = void 0;
712
+ onCost = void 0;
713
+ onReadiness = void 0;
714
+ onSemantic = void 0;
715
+ onAttack = void 0;
716
+ onActivity = void 0;
717
+ onLog = void 0;
718
+ onNudge = void 0;
719
+ /**
720
+ * Set the output mode
721
+ */
722
+ setMode(mode) {
723
+ this.mode = mode;
724
+ }
725
+ /**
726
+ * Get current output mode
727
+ */
728
+ getMode() {
729
+ return this.mode;
730
+ }
731
+ /**
732
+ * Set streaming manager for TUI updates
733
+ */
734
+ setStreamingManager(manager) {
735
+ this.streamingManager = manager;
736
+ }
737
+ /**
738
+ * Register TUI callbacks for rich content
739
+ */
740
+ registerTUICallbacks(callbacks) {
741
+ this.onBanner = callbacks.onBanner;
742
+ this.onSnippet = callbacks.onSnippet;
743
+ this.onCost = callbacks.onCost;
744
+ this.onReadiness = callbacks.onReadiness;
745
+ this.onSemantic = callbacks.onSemantic;
746
+ this.onAttack = callbacks.onAttack;
747
+ this.onActivity = callbacks.onActivity;
748
+ this.onLog = callbacks.onLog;
749
+ this.onNudge = callbacks.onNudge;
750
+ }
751
+ /**
752
+ * Clear TUI callbacks (when dashboard stops)
753
+ */
754
+ clearTUICallbacks() {
755
+ this.onBanner = void 0;
756
+ this.onSnippet = void 0;
757
+ this.onCost = void 0;
758
+ this.onReadiness = void 0;
759
+ this.onSemantic = void 0;
760
+ this.onAttack = void 0;
761
+ this.onActivity = void 0;
762
+ this.onLog = void 0;
763
+ this.onNudge = void 0;
764
+ }
765
+ /**
766
+ * Emit content - routes to appropriate handler based on mode
767
+ */
768
+ emit(content) {
769
+ content.timestamp = content.timestamp ?? Date.now();
770
+ switch (this.mode) {
771
+ case "tui":
772
+ this.routeToTUI(content);
773
+ break;
774
+ case "console":
775
+ this.routeToConsole(content);
776
+ break;
777
+ case "mcp":
778
+ this.routeToMarkdown(content);
779
+ break;
780
+ case "json":
781
+ this.routeToJson(content);
782
+ break;
783
+ case "silent":
784
+ break;
785
+ }
786
+ this.captureRawLog(content);
787
+ }
788
+ /**
789
+ * Route content to TUI (dashboard callbacks)
790
+ */
791
+ routeToTUI(content) {
792
+ switch (content.type) {
793
+ case "banner":
794
+ this.onBanner?.(content.content);
795
+ break;
796
+ case "snippet":
797
+ this.onSnippet?.(content.content);
798
+ break;
799
+ case "cost":
800
+ this.onCost?.(content.content);
801
+ break;
802
+ case "readiness":
803
+ this.onReadiness?.(content.content);
804
+ break;
805
+ case "semantic":
806
+ this.onSemantic?.(content.content);
807
+ break;
808
+ case "attack":
809
+ this.onAttack?.(content.content);
810
+ break;
811
+ case "activity":
812
+ this.onActivity?.(content.content);
813
+ break;
814
+ case "log":
815
+ const level = content.metadata?.severity ?? "info";
816
+ this.onLog?.(level, content.content);
817
+ break;
818
+ case "issue":
819
+ this.streamingManager?.reportIssue(content.content);
820
+ break;
821
+ case "progress":
822
+ break;
823
+ case "report":
824
+ break;
825
+ case "nudge":
826
+ this.onNudge?.(content.content);
827
+ break;
828
+ }
829
+ }
830
+ /**
831
+ * Route content to console (ANSI formatted)
832
+ */
833
+ routeToConsole(content) {
834
+ switch (content.type) {
835
+ case "banner":
836
+ const banner = content.content;
837
+ console.error("\n" + "=".repeat(60));
838
+ console.error(banner.art);
839
+ if (banner.version) {
840
+ console.error(` ${banner.skill} v${banner.version}`);
841
+ }
842
+ console.error("");
843
+ if (banner.quote) {
844
+ console.error(` "${banner.quote}"`);
845
+ }
846
+ console.error("=".repeat(60) + "\n");
847
+ break;
848
+ case "snippet":
849
+ const snippet = content.content;
850
+ console.error(`
851
+ ${pc.dim("File:")} ${snippet.file}`);
852
+ for (let i = 0; i < snippet.lines.length; i++) {
853
+ const lineNum = snippet.startLine + i;
854
+ const isHighlight = lineNum === snippet.highlightLine;
855
+ const prefix = isHighlight ? pc.red("\u2192") : " ";
856
+ const lineNumStr = pc.dim(lineNum.toString().padStart(4));
857
+ const line = isHighlight ? pc.yellow(snippet.lines[i]) : snippet.lines[i];
858
+ console.error(`${prefix} ${lineNumStr} | ${line}`);
859
+ }
860
+ console.error("");
861
+ break;
862
+ case "cost":
863
+ const cost = content.content;
864
+ console.error("\n" + pc.cyan("[$] Cost Estimate:"));
865
+ console.error(` Fix now: ${pc.green(this.formatCurrency(cost.fixNowCost))}`);
866
+ console.error(` If production: ${pc.red(this.formatCurrency(cost.productionCost))}`);
867
+ console.error(` Savings: ${pc.yellow(this.formatCurrency(cost.savings))}`);
868
+ console.error("");
869
+ break;
870
+ case "readiness":
871
+ const readiness = content.content;
872
+ const statusColor = readiness.status === "ready" ? pc.green : readiness.status === "caution" ? pc.yellow : pc.red;
873
+ console.error("\n" + pc.cyan("[%] Production Readiness:"));
874
+ console.error(` Score: ${statusColor(readiness.score + "/100")}`);
875
+ console.error(` Requirements: ${readiness.requirementsMet}/${readiness.total}`);
876
+ console.error(` Status: ${statusColor(readiness.status.toUpperCase())}`);
877
+ console.error("");
878
+ break;
879
+ case "semantic":
880
+ const semantic = content.content;
881
+ console.error("\n" + pc.cyan("[?] Semantic Analysis:"));
882
+ if (semantic.dataFlowIssues > 0) {
883
+ console.error(` ${pc.red("[!]")} ${semantic.dataFlowIssues} data flow vulnerabilities`);
884
+ }
885
+ if (semantic.raceConditions > 0) {
886
+ console.error(` ${pc.yellow("[~]")} ${semantic.raceConditions} race conditions`);
887
+ }
888
+ if (semantic.authIssues > 0) {
889
+ console.error(` ${pc.red("[!]")} ${semantic.authIssues} authentication issues`);
890
+ }
891
+ console.error("");
892
+ break;
893
+ case "attack":
894
+ const attack = content.content;
895
+ console.error("\n" + pc.cyan("[>] Attack Surface:"));
896
+ console.error(` Endpoints: ${attack.totalEndpoints}`);
897
+ if (attack.unprotected > 0) {
898
+ console.error(` ${pc.red("Unprotected:")} ${attack.unprotected}`);
899
+ }
900
+ console.error(` Risk Score: ${attack.riskScore}/100`);
901
+ console.error("");
902
+ break;
903
+ case "activity":
904
+ console.error(pc.dim(`[${this.formatTime()}]`) + ` ${content.content}`);
905
+ break;
906
+ case "log":
907
+ const logLevel = String(content.metadata?.severity ?? "info");
908
+ const levelColor = logLevel === "error" || logLevel === "critical" ? pc.red : logLevel === "warn" || logLevel === "serious" ? pc.yellow : logLevel === "info" || logLevel === "moderate" ? pc.blue : pc.dim;
909
+ console.error(levelColor(`[${logLevel.toUpperCase()}]`) + ` ${content.content}`);
910
+ break;
911
+ case "issue":
912
+ const issue = content.content;
913
+ const sevColor = issue.severity === "critical" ? pc.red : issue.severity === "serious" ? pc.yellow : issue.severity === "moderate" ? pc.blue : pc.dim;
914
+ console.error(`${sevColor(`[${issue.severity.toUpperCase()}]`)} ${issue.issue}`);
915
+ console.error(` ${pc.dim("File:")} ${issue.file}:${issue.line ?? "?"}`);
916
+ break;
917
+ case "report":
918
+ console.error(content.content);
919
+ break;
920
+ case "nudge":
921
+ const nudge = content.content;
922
+ const nudgeColor = nudge.severity === "critical" ? pc.red : nudge.severity === "warning" ? pc.yellow : pc.cyan;
923
+ const nudgeIcon = nudge.severity === "critical" ? "[!!!]" : nudge.severity === "warning" ? "[!]" : "[>]";
924
+ console.error("");
925
+ console.error(nudgeColor("\u2501".repeat(60)));
926
+ console.error(nudgeColor(`${nudgeIcon} TRIE AGENT SAYS:`));
927
+ console.error(nudgeColor("\u2501".repeat(60)));
928
+ console.error("");
929
+ console.error(` ${pc.bold(nudge.message)}`);
930
+ if (nudge.file) {
931
+ console.error(` ${pc.dim("File:")} ${nudge.file}`);
932
+ }
933
+ console.error("");
934
+ console.error(nudgeColor("\u2501".repeat(60)));
935
+ console.error("");
936
+ break;
937
+ }
938
+ }
939
+ /**
940
+ * Route content to markdown buffer
941
+ */
942
+ routeToMarkdown(content) {
943
+ switch (content.type) {
944
+ case "banner":
945
+ const banner = content.content;
946
+ this.markdownBuffer.push(`## ${banner.skill}
947
+ `);
948
+ if (banner.quote) {
949
+ this.markdownBuffer.push(`> ${banner.quote}
950
+ `);
951
+ }
952
+ break;
953
+ case "snippet":
954
+ const snippet = content.content;
955
+ this.markdownBuffer.push(`
956
+ **File:** \`${snippet.file}\`
957
+ `);
958
+ this.markdownBuffer.push("```\n");
959
+ for (let i = 0; i < snippet.lines.length; i++) {
960
+ const lineNum = snippet.startLine + i;
961
+ const prefix = lineNum === snippet.highlightLine ? "\u2192" : " ";
962
+ this.markdownBuffer.push(`${prefix} ${lineNum.toString().padStart(4)} | ${snippet.lines[i]}
963
+ `);
964
+ }
965
+ this.markdownBuffer.push("```\n");
966
+ break;
967
+ case "cost":
968
+ const cost = content.content;
969
+ this.markdownBuffer.push(`
970
+ ### Cost Estimate
971
+ `);
972
+ this.markdownBuffer.push(`- Fix now: ${this.formatCurrency(cost.fixNowCost)}
973
+ `);
974
+ this.markdownBuffer.push(`- If production: ${this.formatCurrency(cost.productionCost)}
975
+ `);
976
+ this.markdownBuffer.push(`- Savings: ${this.formatCurrency(cost.savings)}
977
+ `);
978
+ break;
979
+ case "readiness":
980
+ const readiness = content.content;
981
+ this.markdownBuffer.push(`
982
+ ### Production Readiness
983
+ `);
984
+ this.markdownBuffer.push(`- Score: ${readiness.score}/100
985
+ `);
986
+ this.markdownBuffer.push(`- Requirements: ${readiness.requirementsMet}/${readiness.total}
987
+ `);
988
+ this.markdownBuffer.push(`- Status: **${readiness.status.toUpperCase()}**
989
+ `);
990
+ break;
991
+ case "semantic":
992
+ const semantic = content.content;
993
+ this.markdownBuffer.push(`
994
+ ### Semantic Analysis
995
+ `);
996
+ if (semantic.dataFlowIssues > 0) {
997
+ this.markdownBuffer.push(`- [CRITICAL] ${semantic.dataFlowIssues} data flow vulnerabilities
998
+ `);
999
+ }
1000
+ if (semantic.raceConditions > 0) {
1001
+ this.markdownBuffer.push(`- [WARN] ${semantic.raceConditions} race conditions
1002
+ `);
1003
+ }
1004
+ if (semantic.authIssues > 0) {
1005
+ this.markdownBuffer.push(`- [CRITICAL] ${semantic.authIssues} authentication issues
1006
+ `);
1007
+ }
1008
+ break;
1009
+ case "attack":
1010
+ const attack = content.content;
1011
+ this.markdownBuffer.push(`
1012
+ ### Attack Surface
1013
+ `);
1014
+ this.markdownBuffer.push(`- Endpoints: ${attack.totalEndpoints}
1015
+ `);
1016
+ this.markdownBuffer.push(`- Unprotected: ${attack.unprotected}
1017
+ `);
1018
+ this.markdownBuffer.push(`- Risk Score: ${attack.riskScore}/100
1019
+ `);
1020
+ break;
1021
+ case "report":
1022
+ this.markdownBuffer.push(content.content);
1023
+ break;
1024
+ default:
1025
+ this.jsonBuffer.push(content);
1026
+ }
1027
+ }
1028
+ /**
1029
+ * Route content to JSON buffer
1030
+ */
1031
+ routeToJson(content) {
1032
+ this.jsonBuffer.push(content);
1033
+ }
1034
+ /**
1035
+ * Capture content in raw log buffer
1036
+ */
1037
+ captureRawLog(content) {
1038
+ const time = this.formatTime(content.timestamp);
1039
+ const level = content.metadata?.severity ?? content.type;
1040
+ let message = "";
1041
+ switch (content.type) {
1042
+ case "banner":
1043
+ message = `[BANNER] ${content.content.skill}`;
1044
+ break;
1045
+ case "activity":
1046
+ case "log":
1047
+ message = content.content;
1048
+ break;
1049
+ case "issue":
1050
+ const issue = content.content;
1051
+ message = `[${issue.severity.toUpperCase()}] ${issue.issue}`;
1052
+ break;
1053
+ default:
1054
+ message = `[${content.type.toUpperCase()}] Content received`;
1055
+ }
1056
+ this.rawLogBuffer.push({ time, level, message });
1057
+ if (this.rawLogBuffer.length > 500) {
1058
+ this.rawLogBuffer = this.rawLogBuffer.slice(-500);
1059
+ }
1060
+ }
1061
+ /**
1062
+ * Get raw log buffer for display
1063
+ */
1064
+ getRawLog() {
1065
+ return [...this.rawLogBuffer];
1066
+ }
1067
+ /**
1068
+ * Get accumulated markdown output
1069
+ */
1070
+ getMarkdown() {
1071
+ return this.markdownBuffer.join("\n");
1072
+ }
1073
+ /**
1074
+ * Get accumulated JSON output
1075
+ */
1076
+ getJson() {
1077
+ return [...this.jsonBuffer];
1078
+ }
1079
+ /**
1080
+ * Clear buffers
1081
+ */
1082
+ clearBuffers() {
1083
+ this.markdownBuffer = [];
1084
+ this.jsonBuffer = [];
1085
+ }
1086
+ // ============================================
1087
+ // Convenience methods for common output types
1088
+ // ============================================
1089
+ /**
1090
+ * Display a skill banner
1091
+ */
1092
+ banner(skill, art, options) {
1093
+ this.emit({
1094
+ type: "banner",
1095
+ content: { skill, art, quote: options?.quote, version: options?.version },
1096
+ metadata: { agent: skill }
1097
+ });
1098
+ }
1099
+ /**
1100
+ * Display a code snippet
1101
+ */
1102
+ snippet(file, lines, startLine, highlightLine) {
1103
+ this.emit({
1104
+ type: "snippet",
1105
+ content: { file, lines, startLine, highlightLine },
1106
+ metadata: { file }
1107
+ });
1108
+ }
1109
+ /**
1110
+ * Display cost estimate
1111
+ */
1112
+ cost(fixNowCost, productionCost, savings, perIssue) {
1113
+ this.emit({
1114
+ type: "cost",
1115
+ content: { fixNowCost, productionCost, savings, perIssue }
1116
+ });
1117
+ }
1118
+ /**
1119
+ * Display production readiness
1120
+ */
1121
+ readiness(score, requirementsMet, total, status, requirements) {
1122
+ const content = { score, requirementsMet, total, status };
1123
+ if (requirements) {
1124
+ content.requirements = requirements;
1125
+ }
1126
+ this.emit({
1127
+ type: "readiness",
1128
+ content
1129
+ });
1130
+ }
1131
+ /**
1132
+ * Display semantic analysis results
1133
+ */
1134
+ semantic(dataFlowIssues, raceConditions, authIssues) {
1135
+ this.emit({
1136
+ type: "semantic",
1137
+ content: { dataFlowIssues, raceConditions, authIssues }
1138
+ });
1139
+ }
1140
+ /**
1141
+ * Display attack surface analysis
1142
+ */
1143
+ attack(totalEndpoints, unprotected, riskScore) {
1144
+ this.emit({
1145
+ type: "attack",
1146
+ content: { totalEndpoints, unprotected, riskScore }
1147
+ });
1148
+ }
1149
+ /**
1150
+ * Log an activity message
1151
+ */
1152
+ activity(message) {
1153
+ this.emit({
1154
+ type: "activity",
1155
+ content: message
1156
+ });
1157
+ }
1158
+ /**
1159
+ * Log a message at specified level
1160
+ */
1161
+ log(level, message) {
1162
+ this.emit({
1163
+ type: "log",
1164
+ content: message,
1165
+ metadata: { severity: level }
1166
+ });
1167
+ }
1168
+ /**
1169
+ * Log info message
1170
+ */
1171
+ info(message) {
1172
+ this.log("info", message);
1173
+ }
1174
+ /**
1175
+ * Log warning message
1176
+ */
1177
+ warn(message) {
1178
+ this.log("warn", message);
1179
+ }
1180
+ /**
1181
+ * Log error message
1182
+ */
1183
+ error(message) {
1184
+ this.log("error", message);
1185
+ }
1186
+ /**
1187
+ * Log debug message
1188
+ */
1189
+ debug(message) {
1190
+ this.log("debug", message);
1191
+ }
1192
+ /**
1193
+ * Report an issue
1194
+ */
1195
+ issue(issue) {
1196
+ this.emit({
1197
+ type: "issue",
1198
+ content: issue,
1199
+ metadata: { severity: issue.severity, agent: issue.agent, file: issue.file }
1200
+ });
1201
+ }
1202
+ /**
1203
+ * Add a report section
1204
+ */
1205
+ report(content) {
1206
+ this.emit({
1207
+ type: "report",
1208
+ content
1209
+ });
1210
+ }
1211
+ /**
1212
+ * Send a proactive notification/nudge to the user
1213
+ * This creates a prominent popup in TUI mode or a boxed message in console mode
1214
+ */
1215
+ nudge(message, severity = "warning", file, autoHideMs) {
1216
+ const metadata = {};
1217
+ if (severity === "critical") metadata.severity = "critical";
1218
+ else if (severity === "warning") metadata.severity = "moderate";
1219
+ else metadata.severity = "low";
1220
+ if (file !== void 0) metadata.file = file;
1221
+ this.emit({
1222
+ type: "nudge",
1223
+ content: { message, severity, file, autoHideMs },
1224
+ metadata
1225
+ });
1226
+ }
1227
+ // ============================================
1228
+ // Helpers
1229
+ // ============================================
1230
+ formatCurrency(amount) {
1231
+ if (amount >= 1e6) return `$${(amount / 1e6).toFixed(2)}M`;
1232
+ if (amount >= 1e3) return `$${(amount / 1e3).toFixed(1)}k`;
1233
+ return `$${amount}`;
1234
+ }
1235
+ formatTime(timestamp) {
1236
+ const date = timestamp ? new Date(timestamp) : /* @__PURE__ */ new Date();
1237
+ return date.toLocaleTimeString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit" });
1238
+ }
1239
+ };
1240
+ var instance = null;
1241
+ function getOutputManager() {
1242
+ if (!instance) {
1243
+ instance = new OutputManagerImpl();
1244
+ if (isInteractiveMode()) {
1245
+ instance.setMode("tui");
1246
+ }
1247
+ }
1248
+ return instance;
1249
+ }
1250
+
1251
+ // src/cli/dashboard/App.tsx
1252
+ import { existsSync } from "fs";
1253
+ import { readFile, writeFile, mkdir } from "fs/promises";
1254
+ import { join } from "path";
1255
+
1256
+ // src/cli/dashboard/components/Header.tsx
1257
+ import { Box, Text } from "ink";
1258
+
1259
+ // src/cli/dashboard/theme.ts
1260
+ import pc2 from "picocolors";
1261
+ var colors = {
1262
+ border: (s) => pc2.cyan(s),
1263
+ header: (s) => pc2.bold(pc2.cyan(s)),
1264
+ brand: (s) => pc2.bold(pc2.cyan(s)),
1265
+ dim: (s) => pc2.dim(s),
1266
+ critical: (s) => pc2.bold(pc2.red(s)),
1267
+ serious: (s) => pc2.yellow(s),
1268
+ moderate: (s) => pc2.blue(s),
1269
+ low: (s) => pc2.dim(s),
1270
+ success: (s) => pc2.green(s),
1271
+ running: (s) => pc2.yellow(s),
1272
+ waiting: (s) => pc2.dim(s),
1273
+ alert: (s) => pc2.bold(pc2.red(s)),
1274
+ selected: (s) => pc2.bold(pc2.magenta(s)),
1275
+ highlight: (s) => pc2.bold(pc2.white(s)),
1276
+ yellow: (s) => pc2.yellow(s)
1277
+ };
1278
+ var WATCH_FRAMES = ["\u25D0", "\u25D3", "\u25D1", "\u25D2"];
1279
+ function formatTimeAgo(timestamp) {
1280
+ const seconds = Math.floor((Date.now() - timestamp) / 1e3);
1281
+ if (seconds < 10) return "just now";
1282
+ if (seconds < 60) return `${seconds}s ago`;
1283
+ const minutes = Math.floor(seconds / 60);
1284
+ if (minutes < 60) return `${minutes}m ago`;
1285
+ const hours = Math.floor(minutes / 60);
1286
+ return `${hours}h ago`;
1287
+ }
1288
+ function insightIcon(type) {
1289
+ switch (type) {
1290
+ case "warning":
1291
+ return { icon: "[!]", color: colors.critical };
1292
+ case "observation":
1293
+ return { icon: "[>]", color: colors.serious };
1294
+ case "suggestion":
1295
+ return { icon: "[?]", color: colors.highlight };
1296
+ case "celebration":
1297
+ return { icon: "[+]", color: colors.success };
1298
+ case "question":
1299
+ return { icon: "[?]", color: colors.moderate };
1300
+ default:
1301
+ return { icon: "[>]", color: colors.dim };
1302
+ }
1303
+ }
1304
+ function progressBar(current, total, width = 10) {
1305
+ if (total <= 0) return colors.dim("[" + "\u2591".repeat(width) + "]");
1306
+ const progress = Math.min(1, current / total);
1307
+ const filled = Math.round(width * progress);
1308
+ const empty = width - filled;
1309
+ return colors.border("[") + colors.success("\u2588".repeat(filled)) + colors.dim("\u2591".repeat(empty)) + colors.border("]");
1310
+ }
1311
+ function stripEmojis(s) {
1312
+ return s.replace(/[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{FE00}-\u{FE0F}\u{200D}\u{20E3}\u{FE0F}\u{E0020}-\u{E007F}]/gu, "").trim();
1313
+ }
1314
+
1315
+ // src/cli/dashboard/components/Header.tsx
1316
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
1317
+ function Header() {
1318
+ const { state } = useDashboard();
1319
+ const time = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit" });
1320
+ const frameIdx = Math.floor(Date.now() / 200) % WATCH_FRAMES.length;
1321
+ const spinner = WATCH_FRAMES[frameIdx] || "\u25D0";
1322
+ const { signalExtraction, watch, alerts } = state;
1323
+ const totalExtracted = signalExtraction.decisionsExtracted + signalExtraction.factsExtracted + signalExtraction.blockersExtracted + signalExtraction.questionsExtracted;
1324
+ let statusLabel;
1325
+ if (watch.watching) {
1326
+ statusLabel = totalExtracted > 0 ? /* @__PURE__ */ jsxs(Text, { children: [
1327
+ /* @__PURE__ */ jsxs(Text, { color: "green", bold: true, children: [
1328
+ spinner,
1329
+ " LEARNING"
1330
+ ] }),
1331
+ " ",
1332
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1333
+ totalExtracted,
1334
+ " signals"
1335
+ ] })
1336
+ ] }) : /* @__PURE__ */ jsxs(Text, { children: [
1337
+ /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
1338
+ spinner,
1339
+ " WATCHING"
1340
+ ] }),
1341
+ " ",
1342
+ /* @__PURE__ */ jsx2(Text, { dimColor: true, children: "ready" })
1343
+ ] });
1344
+ } else {
1345
+ statusLabel = /* @__PURE__ */ jsx2(Text, { dimColor: true, children: "IDLE" });
1346
+ }
1347
+ const watchBadge = watch.watching ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
1348
+ "[",
1349
+ spinner,
1350
+ " WATCHING]"
1351
+ ] }) : /* @__PURE__ */ jsx2(Text, { dimColor: true, children: "[WATCH OFF]" });
1352
+ return /* @__PURE__ */ jsxs(Box, { borderStyle: "single", borderColor: "cyan", paddingX: 1, justifyContent: "space-between", children: [
1353
+ /* @__PURE__ */ jsxs(Box, { children: [
1354
+ /* @__PURE__ */ jsx2(Text, { color: "cyan", bold: true, children: "TRIE" }),
1355
+ watch.watching && /* @__PURE__ */ jsx2(Text, { dimColor: true, children: " [autonomous]" })
1356
+ ] }),
1357
+ /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
1358
+ statusLabel,
1359
+ watchBadge,
1360
+ alerts.hasCritical && /* @__PURE__ */ jsx2(Text, { color: "red", bold: true, children: "\u2502 ALERT: CRITICAL" }),
1361
+ /* @__PURE__ */ jsx2(Text, { dimColor: true, children: time })
1362
+ ] })
1363
+ ] });
1364
+ }
1365
+
1366
+ // src/cli/dashboard/components/Footer.tsx
1367
+ import { Box as Box2, Text as Text2 } from "ink";
1368
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1369
+ var VIEW_LABELS = {
1370
+ overview: "Overview",
1371
+ rawlog: "Log",
1372
+ agent: "Agent",
1373
+ goals: "Goals",
1374
+ hypotheses: "Hypotheses",
1375
+ memory: "Memory"
1376
+ };
1377
+ function Hint({ k, label }) {
1378
+ return /* @__PURE__ */ jsxs2(Text2, { children: [
1379
+ /* @__PURE__ */ jsx3(Text2, { color: "cyan", children: "[" }),
1380
+ /* @__PURE__ */ jsx3(Text2, { bold: true, children: k }),
1381
+ /* @__PURE__ */ jsx3(Text2, { color: "cyan", children: "]" }),
1382
+ /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
1383
+ " ",
1384
+ label
1385
+ ] })
1386
+ ] });
1387
+ }
1388
+ function Footer() {
1389
+ const { state } = useDashboard();
1390
+ const { view } = state;
1391
+ const viewTabs = ["overview", "memory", "goals", "hypotheses", "agent"].map((v) => {
1392
+ const isActive = v === view;
1393
+ const label = VIEW_LABELS[v];
1394
+ return isActive ? /* @__PURE__ */ jsx3(Text2, { color: "cyan", bold: true, inverse: true, children: ` ${label} ` }, v) : /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: ` ${label} ` }, v);
1395
+ });
1396
+ let hints;
1397
+ if (view === "goals" && state.goalsPanel.inputMode === "add") {
1398
+ hints = /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
1399
+ /* @__PURE__ */ jsx3(Hint, { k: "Enter", label: "Save" }),
1400
+ /* @__PURE__ */ jsx3(Hint, { k: "Esc", label: "Cancel" })
1401
+ ] });
1402
+ } else if (view === "hypotheses" && state.hypothesesPanel.inputMode === "add") {
1403
+ hints = /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
1404
+ /* @__PURE__ */ jsx3(Hint, { k: "Enter", label: "Save" }),
1405
+ /* @__PURE__ */ jsx3(Hint, { k: "Esc", label: "Cancel" })
1406
+ ] });
1407
+ } else if (view === "goals") {
1408
+ hints = /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
1409
+ /* @__PURE__ */ jsx3(Hint, { k: "j/k", label: "Nav" }),
1410
+ /* @__PURE__ */ jsx3(Hint, { k: "a", label: "Add" }),
1411
+ /* @__PURE__ */ jsx3(Hint, { k: "Enter", label: "Complete" }),
1412
+ /* @__PURE__ */ jsx3(Hint, { k: "d", label: "Delete" })
1413
+ ] });
1414
+ } else if (view === "hypotheses") {
1415
+ hints = /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
1416
+ /* @__PURE__ */ jsx3(Hint, { k: "j/k", label: "Nav" }),
1417
+ /* @__PURE__ */ jsx3(Hint, { k: "a", label: "Add" }),
1418
+ /* @__PURE__ */ jsx3(Hint, { k: "v", label: "Validate" }),
1419
+ /* @__PURE__ */ jsx3(Hint, { k: "x", label: "Invalidate" })
1420
+ ] });
1421
+ } else if (view === "agent") {
1422
+ hints = /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
1423
+ /* @__PURE__ */ jsx3(Hint, { k: "j/k", label: "Nav" }),
1424
+ /* @__PURE__ */ jsx3(Hint, { k: "Enter", label: "Expand" }),
1425
+ /* @__PURE__ */ jsx3(Hint, { k: "d", label: "Dismiss" }),
1426
+ /* @__PURE__ */ jsx3(Hint, { k: "i", label: "Ignore" }),
1427
+ /* @__PURE__ */ jsx3(Hint, { k: "x", label: "Clear" })
1428
+ ] });
1429
+ } else if (view === "memory") {
1430
+ hints = /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
1431
+ /* @__PURE__ */ jsx3(Hint, { k: "j/k", label: "Nav" }),
1432
+ /* @__PURE__ */ jsx3(Hint, { k: "Enter", label: "Expand" }),
1433
+ /* @__PURE__ */ jsx3(Hint, { k: "b", label: "Back" })
1434
+ ] });
1435
+ } else if (view === "rawlog") {
1436
+ hints = /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
1437
+ /* @__PURE__ */ jsx3(Hint, { k: "n/p", label: "Pages" }),
1438
+ /* @__PURE__ */ jsx3(Hint, { k: "b", label: "Back" })
1439
+ ] });
1440
+ } else {
1441
+ hints = /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
1442
+ /* @__PURE__ */ jsx3(Hint, { k: "Tab", label: "Views" }),
1443
+ /* @__PURE__ */ jsx3(Hint, { k: "n/p", label: "Pages" }),
1444
+ /* @__PURE__ */ jsx3(Hint, { k: "h", label: "Help" })
1445
+ ] });
1446
+ }
1447
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
1448
+ /* @__PURE__ */ jsx3(Box2, { borderStyle: "single", borderColor: "cyan", borderTop: false, borderLeft: false, borderRight: false, children: /* @__PURE__ */ jsx3(Box2, { gap: 0, children: viewTabs }) }),
1449
+ /* @__PURE__ */ jsxs2(Box2, { paddingX: 1, justifyContent: "space-between", children: [
1450
+ hints,
1451
+ /* @__PURE__ */ jsx3(Hint, { k: "q", label: "Quit" })
1452
+ ] })
1453
+ ] });
1454
+ }
1455
+
1456
+ // src/cli/dashboard/components/Notification.tsx
1457
+ import { Box as Box3, Text as Text3 } from "ink";
1458
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1459
+ function Notification() {
1460
+ const { state } = useDashboard();
1461
+ const { notification } = state;
1462
+ if (!notification || !notification.active) return null;
1463
+ if (notification.autoHideAt && Date.now() > notification.autoHideAt) return null;
1464
+ const bgColor = notification.severity === "critical" ? "red" : notification.severity === "warning" ? "yellow" : "blue";
1465
+ const icon = notification.severity === "critical" ? "[!]" : notification.severity === "warning" ? "[!]" : "[>]";
1466
+ return /* @__PURE__ */ jsxs3(Box3, { paddingX: 1, children: [
1467
+ /* @__PURE__ */ jsx4(Text3, { backgroundColor: bgColor, color: "white", bold: true, children: ` ${icon} ${notification.message} ` }),
1468
+ notification.file && /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
1469
+ " (",
1470
+ notification.file,
1471
+ ")"
1472
+ ] })
1473
+ ] });
1474
+ }
1475
+
1476
+ // src/cli/dashboard/components/ConfigDialog.tsx
1477
+ import { useState } from "react";
1478
+ import { Box as Box4, Text as Text4, useInput } from "ink";
1479
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1480
+ function ConfigDialog({ onClose }) {
1481
+ const { state, dispatch } = useDashboard();
1482
+ const [section, setSection] = useState("main");
1483
+ const [selectedIndex, setSelectedIndex] = useState(0);
1484
+ const [editing, setEditing] = useState(false);
1485
+ const [editBuffer, setEditBuffer] = useState("");
1486
+ const config = state.agentConfig;
1487
+ const mainMenu = [
1488
+ { label: "Agent Smith Settings", key: "agentSmith", value: config.agentSmith.aiEnhancement ? "AI Enhanced" : "Basic", section: "main" },
1489
+ { label: "Performance Settings", key: "performance", value: `${config.performance.maxConcurrency} concurrent`, section: "main" },
1490
+ { label: "Risk Thresholds", key: "riskThresholds", value: `critical: ${config.riskThresholds.critical}%`, section: "main" }
1491
+ ];
1492
+ const performanceItems = [
1493
+ { label: "Max Concurrency", key: "maxConcurrency", value: String(config.performance.maxConcurrency), section: "performance" },
1494
+ { label: "Timeout (ms)", key: "timeoutMs", value: String(config.performance.timeoutMs), section: "performance" },
1495
+ { label: "Parallel", key: "parallel", value: config.performance.parallel ? "on" : "off", section: "performance" },
1496
+ { label: "Cache", key: "cache", value: config.performance.cache ? "on" : "off", section: "performance" },
1497
+ { label: "Workers", key: "workers", value: config.performance.workers ? "on" : "off", section: "performance" }
1498
+ ];
1499
+ const riskItems = [
1500
+ { label: "Critical Threshold", key: "critical", value: String(config.riskThresholds.critical), section: "riskThresholds" },
1501
+ { label: "High Threshold", key: "high", value: String(config.riskThresholds.high), section: "riskThresholds" },
1502
+ { label: "Medium Threshold", key: "medium", value: String(config.riskThresholds.medium), section: "riskThresholds" }
1503
+ ];
1504
+ const items = section === "main" ? mainMenu : section === "performance" ? performanceItems : section === "riskThresholds" ? riskItems : mainMenu;
1505
+ useInput((_input, key) => {
1506
+ if (editing) {
1507
+ if (key.escape) {
1508
+ setEditing(false);
1509
+ setEditBuffer("");
1510
+ } else if (key.return) {
1511
+ const item = items[selectedIndex];
1512
+ if (item) {
1513
+ const val = parseInt(editBuffer, 10);
1514
+ if (!isNaN(val)) {
1515
+ const patch = {};
1516
+ if (section === "performance") {
1517
+ if (item.key === "maxConcurrency" || item.key === "timeoutMs") {
1518
+ patch.performance = { ...config.performance, [item.key]: val };
1519
+ }
1520
+ } else if (section === "riskThresholds") {
1521
+ patch.riskThresholds = { ...config.riskThresholds, [item.key]: val };
1522
+ }
1523
+ if (Object.keys(patch).length > 0) {
1524
+ dispatch({ type: "SET_AGENT_CONFIG", config: patch });
1525
+ dispatch({ type: "ADD_ACTIVITY", message: `Config: ${item.label} set to ${val}` });
1526
+ }
1527
+ }
1528
+ }
1529
+ setEditing(false);
1530
+ setEditBuffer("");
1531
+ } else if (key.backspace || key.delete) {
1532
+ setEditBuffer(editBuffer.slice(0, -1));
1533
+ } else if (_input && /\d/.test(_input)) {
1534
+ setEditBuffer(editBuffer + _input);
1535
+ }
1536
+ return;
1537
+ }
1538
+ if (key.escape || _input === "b") {
1539
+ if (section === "main") onClose();
1540
+ else {
1541
+ setSection("main");
1542
+ setSelectedIndex(0);
1543
+ }
1544
+ } else if (key.upArrow || _input === "k") {
1545
+ setSelectedIndex(Math.max(0, selectedIndex - 1));
1546
+ } else if (key.downArrow || _input === "j") {
1547
+ setSelectedIndex(Math.min(items.length - 1, selectedIndex + 1));
1548
+ } else if (key.return) {
1549
+ if (section === "main") {
1550
+ const item = items[selectedIndex];
1551
+ if (item) {
1552
+ setSection(item.key);
1553
+ setSelectedIndex(0);
1554
+ }
1555
+ } else {
1556
+ const item = items[selectedIndex];
1557
+ if (item) {
1558
+ if (["parallel", "cache", "workers"].includes(item.key)) {
1559
+ const patch = {
1560
+ performance: { ...config.performance, [item.key]: !config.performance[item.key] }
1561
+ };
1562
+ dispatch({ type: "SET_AGENT_CONFIG", config: patch });
1563
+ } else {
1564
+ setEditing(true);
1565
+ setEditBuffer(item.value);
1566
+ }
1567
+ }
1568
+ }
1569
+ }
1570
+ });
1571
+ const sectionTitle = section === "main" ? "TRIE AGENT CONFIGURATION" : section === "performance" ? "PERFORMANCE SETTINGS" : section === "riskThresholds" ? "RISK THRESHOLDS" : section === "agentSmith" ? "AGENT SMITH SETTINGS" : "CONFIGURATION";
1572
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, paddingY: 0, children: [
1573
+ /* @__PURE__ */ jsx5(Text4, { color: "cyan", bold: true, children: sectionTitle }),
1574
+ /* @__PURE__ */ jsx5(Text4, { children: " " }),
1575
+ items.map((item, idx) => {
1576
+ const isSelected = selectedIndex === idx;
1577
+ return /* @__PURE__ */ jsxs4(Text4, { children: [
1578
+ isSelected ? /* @__PURE__ */ jsx5(Text4, { bold: true, color: "magenta", children: "\u25B6 " }) : /* @__PURE__ */ jsx5(Text4, { children: " " }),
1579
+ /* @__PURE__ */ jsxs4(Text4, { bold: isSelected, children: [
1580
+ item.label,
1581
+ ": "
1582
+ ] }),
1583
+ editing && isSelected ? /* @__PURE__ */ jsxs4(Text4, { children: [
1584
+ editBuffer,
1585
+ /* @__PURE__ */ jsx5(Text4, { bold: true, color: "cyan", children: "\u258C" })
1586
+ ] }) : /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: item.value })
1587
+ ] }, item.key);
1588
+ }),
1589
+ /* @__PURE__ */ jsx5(Text4, { children: " " }),
1590
+ /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: section === "main" ? "Enter to select \u2022 Esc to close" : "Enter to edit \u2022 Esc/b to go back" })
1591
+ ] });
1592
+ }
1593
+
1594
+ // src/cli/dashboard/views/OverviewView.tsx
1595
+ import { Box as Box5, Text as Text5 } from "ink";
1596
+ import { Fragment, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1597
+ function OverviewView() {
1598
+ const { state } = useDashboard();
1599
+ const { progress, signalExtraction, watch, issues, activityLog, activityPage } = state;
1600
+ const { issuesBySeverity, totalIssues, processedFiles } = progress;
1601
+ const endTime = state.scanComplete && state.scanEndTime ? state.scanEndTime : Date.now();
1602
+ const elapsed = ((endTime - state.scanStartTime) / 1e3).toFixed(1);
1603
+ const totalExtracted = signalExtraction.decisionsExtracted + signalExtraction.factsExtracted + signalExtraction.blockersExtracted + signalExtraction.questionsExtracted;
1604
+ const criticalIssues = issues.filter((i) => i.severity === "critical").slice(0, 3);
1605
+ const activityRows = 8;
1606
+ const startIdx = activityPage * activityRows;
1607
+ const pageActivities = activityLog.slice(startIdx, startIdx + activityRows);
1608
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", paddingX: 1, children: [
1609
+ /* @__PURE__ */ jsxs5(Text5, { children: [
1610
+ /* @__PURE__ */ jsx6(Text5, { bold: true, children: processedFiles }),
1611
+ /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
1612
+ " files scanned in ",
1613
+ elapsed,
1614
+ "s"
1615
+ ] })
1616
+ ] }),
1617
+ watch.watching && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1618
+ /* @__PURE__ */ jsxs5(Text5, { children: [
1619
+ signalExtraction.enabled ? "[+]" : "[!]",
1620
+ " Signal extraction:",
1621
+ " ",
1622
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: signalExtraction.enabled ? "enabled" : "limited (set ANTHROPIC_API_KEY)" })
1623
+ ] }),
1624
+ totalExtracted > 0 && /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
1625
+ " \u2514 ",
1626
+ signalExtraction.decisionsExtracted,
1627
+ " decisions, ",
1628
+ signalExtraction.factsExtracted,
1629
+ " facts, ",
1630
+ signalExtraction.blockersExtracted,
1631
+ " blockers extracted"
1632
+ ] })
1633
+ ] }),
1634
+ /* @__PURE__ */ jsx6(Text5, { children: " " }),
1635
+ /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1636
+ /* @__PURE__ */ jsx6(Text5, { color: "cyan", bold: true, children: "SUMMARY" }),
1637
+ /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1638
+ /* @__PURE__ */ jsxs5(Text5, { children: [
1639
+ /* @__PURE__ */ jsxs5(Text5, { color: "red", bold: true, children: [
1640
+ "[!] ",
1641
+ String(issuesBySeverity.critical).padStart(4),
1642
+ " Critical issues"
1643
+ ] }),
1644
+ issuesBySeverity.critical > 0 && /* @__PURE__ */ jsxs5(Text5, { color: "red", bold: true, children: [
1645
+ " ",
1646
+ "<-",
1647
+ " FIX NOW"
1648
+ ] })
1649
+ ] }),
1650
+ /* @__PURE__ */ jsxs5(Text5, { color: "yellow", children: [
1651
+ "[x] ",
1652
+ String(issuesBySeverity.serious).padStart(4),
1653
+ " Serious issues"
1654
+ ] }),
1655
+ /* @__PURE__ */ jsxs5(Text5, { color: "blue", children: [
1656
+ "[~] ",
1657
+ String(issuesBySeverity.moderate).padStart(4),
1658
+ " Moderate issues"
1659
+ ] }),
1660
+ /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
1661
+ "[-] ",
1662
+ String(issuesBySeverity.low).padStart(4),
1663
+ " Low issues"
1664
+ ] })
1665
+ ] })
1666
+ ] }),
1667
+ watch.watching && signalExtraction.enabled && /* @__PURE__ */ jsxs5(Fragment, { children: [
1668
+ /* @__PURE__ */ jsx6(Text5, { children: " " }),
1669
+ /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1670
+ /* @__PURE__ */ jsx6(Text5, { color: "cyan", bold: true, children: "DECISION LEDGER" }),
1671
+ /* @__PURE__ */ jsxs5(Text5, { children: [
1672
+ /* @__PURE__ */ jsx6(Text5, { bold: true, children: "Agent Learning" }),
1673
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " - Building institutional knowledge" })
1674
+ ] }),
1675
+ /* @__PURE__ */ jsx6(Text5, { children: " " }),
1676
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: "Signals Extracted:" }),
1677
+ /* @__PURE__ */ jsxs5(Text5, { children: [
1678
+ " ",
1679
+ /* @__PURE__ */ jsx6(Text5, { bold: true, children: signalExtraction.decisionsExtracted }),
1680
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " decisions" })
1681
+ ] }),
1682
+ /* @__PURE__ */ jsxs5(Text5, { children: [
1683
+ " ",
1684
+ /* @__PURE__ */ jsx6(Text5, { bold: true, children: signalExtraction.factsExtracted }),
1685
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " facts" })
1686
+ ] }),
1687
+ /* @__PURE__ */ jsxs5(Text5, { children: [
1688
+ " ",
1689
+ /* @__PURE__ */ jsx6(Text5, { bold: true, children: signalExtraction.blockersExtracted }),
1690
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " blockers" })
1691
+ ] }),
1692
+ /* @__PURE__ */ jsxs5(Text5, { children: [
1693
+ " ",
1694
+ /* @__PURE__ */ jsx6(Text5, { bold: true, children: signalExtraction.questionsExtracted }),
1695
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " questions" })
1696
+ ] }),
1697
+ /* @__PURE__ */ jsx6(Text5, { children: " " }),
1698
+ /* @__PURE__ */ jsxs5(Text5, { children: [
1699
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: "Use " }),
1700
+ /* @__PURE__ */ jsx6(Text5, { bold: true, children: "trie gotcha" }),
1701
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " to query the ledger" })
1702
+ ] })
1703
+ ] })
1704
+ ] }),
1705
+ criticalIssues.length > 0 && /* @__PURE__ */ jsxs5(Fragment, { children: [
1706
+ /* @__PURE__ */ jsx6(Text5, { children: " " }),
1707
+ /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1708
+ /* @__PURE__ */ jsx6(Text5, { color: "red", bold: true, children: "TOP CRITICAL ISSUES" }),
1709
+ criticalIssues.map((issue, i) => {
1710
+ const filename = issue.file.split("/").pop() || issue.file;
1711
+ const lineNum = issue.line ? `:${issue.line}` : "";
1712
+ const desc = issue.issue.slice(0, 50) + (issue.issue.length > 50 ? "..." : "");
1713
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1714
+ /* @__PURE__ */ jsxs5(Text5, { children: [
1715
+ /* @__PURE__ */ jsx6(Text5, { color: "red", children: "\u25B8" }),
1716
+ " ",
1717
+ /* @__PURE__ */ jsx6(Text5, { color: "red", children: desc })
1718
+ ] }),
1719
+ /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
1720
+ " ",
1721
+ filename,
1722
+ lineNum
1723
+ ] })
1724
+ ] }, i);
1725
+ })
1726
+ ] })
1727
+ ] }),
1728
+ totalIssues === 0 && criticalIssues.length === 0 && /* @__PURE__ */ jsxs5(Fragment, { children: [
1729
+ /* @__PURE__ */ jsx6(Text5, { children: " " }),
1730
+ /* @__PURE__ */ jsx6(Text5, { color: "green", children: "[ok] No issues found" })
1731
+ ] }),
1732
+ /* @__PURE__ */ jsx6(Text5, { children: " " }),
1733
+ /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1734
+ /* @__PURE__ */ jsx6(Text5, { color: "cyan", bold: true, children: "ACTIVITY LOG" }),
1735
+ pageActivities.map((entry, i) => /* @__PURE__ */ jsxs5(Text5, { children: [
1736
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: entry.time }),
1737
+ " ",
1738
+ entry.message
1739
+ ] }, i)),
1740
+ pageActivities.length === 0 && /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: "No activity yet." })
1741
+ ] })
1742
+ ] });
1743
+ }
1744
+
1745
+ // src/cli/dashboard/views/AgentView.tsx
1746
+ import { Box as Box6, Text as Text6, useInput as useInput2 } from "ink";
1747
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1748
+ function AgentView() {
1749
+ const { state, dispatch } = useDashboard();
1750
+ const { agentInsights, agencyStatus, selectedInsight, expandedInsight } = state;
1751
+ const totalInsights = agentInsights.length;
1752
+ const visibleInsights = getVisibleInsights(state);
1753
+ const activeCount = visibleInsights.length;
1754
+ useInput2((input, key) => {
1755
+ if (key.upArrow || input === "k") {
1756
+ dispatch({ type: "NAVIGATE_UP" });
1757
+ } else if (key.downArrow || input === "j") {
1758
+ dispatch({ type: "NAVIGATE_DOWN" });
1759
+ } else if (key.return) {
1760
+ dispatch({ type: "TOGGLE_INSIGHT", index: selectedInsight });
1761
+ } else if (input === "d") {
1762
+ dispatch({ type: "DISMISS_INSIGHT", index: selectedInsight });
1763
+ } else if (input === "i") {
1764
+ dispatch({ type: "IGNORE_INSIGHT", index: selectedInsight });
1765
+ } else if (input === "x") {
1766
+ dispatch({ type: "CLEAR_DISMISSED_INSIGHTS" });
1767
+ }
1768
+ });
1769
+ const agency = agencyStatus;
1770
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 1, children: [
1771
+ /* @__PURE__ */ jsxs6(Text6, { children: [
1772
+ /* @__PURE__ */ jsx7(Text6, { color: "cyan", bold: true, children: "TRIE AGENT INSIGHTS" }),
1773
+ activeCount > 0 ? /* @__PURE__ */ jsxs6(Text6, { color: "red", bold: true, children: [
1774
+ " (",
1775
+ activeCount,
1776
+ " active)"
1777
+ ] }) : /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1778
+ " (",
1779
+ totalInsights,
1780
+ " total)"
1781
+ ] }),
1782
+ " ",
1783
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Your autonomous code companion" })
1784
+ ] }),
1785
+ agency && /* @__PURE__ */ jsxs6(Box6, { gap: 2, children: [
1786
+ /* @__PURE__ */ jsxs6(Text6, { children: [
1787
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Goals:" }),
1788
+ " ",
1789
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: agency.goals.active }),
1790
+ "/",
1791
+ agency.goals.completed + agency.goals.active
1792
+ ] }),
1793
+ /* @__PURE__ */ jsxs6(Text6, { children: [
1794
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Hypo:" }),
1795
+ " ",
1796
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: agency.hypotheses.testing }),
1797
+ " testing"
1798
+ ] }),
1799
+ /* @__PURE__ */ jsxs6(Text6, { children: [
1800
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Risk:" }),
1801
+ " ",
1802
+ /* @__PURE__ */ jsx7(Text6, { color: agency.riskLevel === "critical" ? "red" : agency.riskLevel === "high" ? "yellow" : agency.riskLevel === "medium" ? "yellow" : "green", children: agency.riskLevel.toUpperCase() })
1803
+ ] }),
1804
+ /* @__PURE__ */ jsxs6(Text6, { children: [
1805
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Effect:" }),
1806
+ " ",
1807
+ /* @__PURE__ */ jsxs6(Text6, { color: agency.effectiveness >= 80 ? "green" : agency.effectiveness >= 50 ? "yellow" : "yellow", children: [
1808
+ agency.effectiveness,
1809
+ "%"
1810
+ ] })
1811
+ ] }),
1812
+ agency.isQuietHours && /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "[quiet]" })
1813
+ ] }),
1814
+ /* @__PURE__ */ jsx7(Text6, { children: " " }),
1815
+ visibleInsights.length === 0 && state.notificationHistory.length === 0 ? /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
1816
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: "The Trie Agent is watching over your code." }),
1817
+ /* @__PURE__ */ jsx7(Text6, { children: " " }),
1818
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Unlike a log viewer, the Trie Agent:" }),
1819
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " \u2022 Synthesizes insights from all skills" }),
1820
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " \u2022 Speaks conversationally about what matters" }),
1821
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " \u2022 Suggests specific actions to take" }),
1822
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " \u2022 Celebrates when you fix issues" }),
1823
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " \u2022 Tracks patterns over time" }),
1824
+ /* @__PURE__ */ jsx7(Text6, { children: " " }),
1825
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "When the Trie Agent has something to say, it'll appear here." }),
1826
+ /* @__PURE__ */ jsx7(Text6, { children: " " }),
1827
+ isAIAvailable() ? /* @__PURE__ */ jsxs6(Text6, { children: [
1828
+ /* @__PURE__ */ jsx7(Text6, { color: "green", children: "[+]" }),
1829
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " AI-enhanced insights enabled" })
1830
+ ] }) : /* @__PURE__ */ jsxs6(Text6, { children: [
1831
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Want smarter insights? Set " }),
1832
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: "ANTHROPIC_API_KEY" }),
1833
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " for AI enhancement" })
1834
+ ] })
1835
+ ] }) : /* @__PURE__ */ jsx7(Box6, { flexDirection: "column", children: visibleInsights.map((insight, idx) => {
1836
+ const isSelected = idx === selectedInsight;
1837
+ const isExpanded = idx === expandedInsight;
1838
+ const ago = formatTimeAgo(insight.timestamp);
1839
+ const { icon, color } = insightIcon(insight.type);
1840
+ const cleanMessage = stripEmojis(insight.message);
1841
+ const msgMaxLen = 70;
1842
+ const msg = cleanMessage.length > msgMaxLen ? cleanMessage.slice(0, msgMaxLen - 3) + "..." : cleanMessage;
1843
+ const status = isExpanded ? "v" : ">";
1844
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginBottom: 1, children: [
1845
+ /* @__PURE__ */ jsxs6(Text6, { children: [
1846
+ isSelected ? /* @__PURE__ */ jsx7(Text6, { bold: true, color: "magenta", children: "\u25B6 " }) : /* @__PURE__ */ jsx7(Text6, { children: " " }),
1847
+ /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1848
+ status,
1849
+ " "
1850
+ ] }),
1851
+ isSelected ? /* @__PURE__ */ jsx7(Text6, { inverse: true, children: ` ${icon} ${msg} ` }) : /* @__PURE__ */ jsxs6(Text6, { children: [
1852
+ icon,
1853
+ " ",
1854
+ color(msg)
1855
+ ] })
1856
+ ] }),
1857
+ /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1858
+ " ",
1859
+ ago,
1860
+ " \u2022 ",
1861
+ insight.category,
1862
+ isSelected && !isExpanded ? " \u2022 Press Enter to expand" : ""
1863
+ ] }),
1864
+ isExpanded && insight.details && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginLeft: 7, children: [
1865
+ insight.details.issueBreakdown && Object.keys(insight.details.issueBreakdown).length > 0 && /* @__PURE__ */ jsxs6(Text6, { children: [
1866
+ insight.details.issueBreakdown["critical"] ? /* @__PURE__ */ jsxs6(Text6, { color: "red", children: [
1867
+ insight.details.issueBreakdown["critical"],
1868
+ " critical"
1869
+ ] }) : null,
1870
+ insight.details.issueBreakdown["serious"] ? /* @__PURE__ */ jsxs6(Text6, { color: "yellow", children: [
1871
+ " \u2022 ",
1872
+ insight.details.issueBreakdown["serious"],
1873
+ " serious"
1874
+ ] }) : null,
1875
+ insight.details.issueBreakdown["moderate"] ? /* @__PURE__ */ jsxs6(Text6, { color: "blue", children: [
1876
+ " \u2022 ",
1877
+ insight.details.issueBreakdown["moderate"],
1878
+ " moderate"
1879
+ ] }) : null
1880
+ ] }),
1881
+ insight.details.affectedFiles && insight.details.affectedFiles.length > 0 && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
1882
+ /* @__PURE__ */ jsx7(Text6, { color: "cyan", bold: true, children: "Files:" }),
1883
+ insight.details.affectedFiles.slice(0, 8).map((f, fi) => /* @__PURE__ */ jsxs6(Text6, { color: "cyan", children: [
1884
+ " \u2022 ",
1885
+ f
1886
+ ] }, fi)),
1887
+ insight.details.affectedFiles.length > 8 && /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1888
+ " ... +",
1889
+ insight.details.affectedFiles.length - 8,
1890
+ " more"
1891
+ ] })
1892
+ ] }),
1893
+ insight.details.examples && insight.details.examples.length > 0 && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
1894
+ /* @__PURE__ */ jsx7(Text6, { color: "cyan", bold: true, children: "Examples:" }),
1895
+ insight.details.examples.slice(0, 5).map((ex, ei) => /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1896
+ " \u2022 ",
1897
+ ex.slice(0, 60),
1898
+ ex.length > 60 ? "..." : ""
1899
+ ] }, ei))
1900
+ ] }),
1901
+ insight.details.comparison && /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1902
+ insight.details.trend === "improving" ? "\u2193" : insight.details.trend === "worsening" ? "\u2191" : "\u2192",
1903
+ " ",
1904
+ insight.details.comparison
1905
+ ] })
1906
+ ] }),
1907
+ insight.suggestedAction && (isExpanded || isSelected) && /* @__PURE__ */ jsxs6(Text6, { children: [
1908
+ " ",
1909
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u2192 " }),
1910
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: insight.suggestedAction })
1911
+ ] }),
1912
+ insight.actionCommand && isExpanded && /* @__PURE__ */ jsxs6(Text6, { children: [
1913
+ " ",
1914
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "$ " }),
1915
+ /* @__PURE__ */ jsx7(Text6, { color: "green", children: insight.actionCommand }),
1916
+ isSelected && /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " " }),
1917
+ isSelected && /* @__PURE__ */ jsx7(Text6, { bold: true, children: "[Enter to run]" })
1918
+ ] })
1919
+ ] }, insight.id);
1920
+ }) }),
1921
+ /* @__PURE__ */ jsx7(Text6, { children: " " }),
1922
+ /* @__PURE__ */ jsxs6(Box6, { gap: 2, children: [
1923
+ agentInsights.filter((i) => i.type === "warning").length > 0 && /* @__PURE__ */ jsxs6(Text6, { color: "red", children: [
1924
+ agentInsights.filter((i) => i.type === "warning").length,
1925
+ " warnings"
1926
+ ] }),
1927
+ agentInsights.filter((i) => i.type === "suggestion").length > 0 && /* @__PURE__ */ jsxs6(Text6, { bold: true, children: [
1928
+ agentInsights.filter((i) => i.type === "suggestion").length,
1929
+ " suggestions"
1930
+ ] }),
1931
+ agentInsights.filter((i) => i.type === "celebration").length > 0 && /* @__PURE__ */ jsxs6(Text6, { color: "green", children: [
1932
+ agentInsights.filter((i) => i.type === "celebration").length,
1933
+ " wins"
1934
+ ] }),
1935
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u2502" }),
1936
+ isAIAvailable() ? /* @__PURE__ */ jsx7(Text6, { color: "green", children: "AI \u2713" }) : /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "AI off" })
1937
+ ] })
1938
+ ] });
1939
+ }
1940
+
1941
+ // src/cli/dashboard/views/GoalsView.tsx
1942
+ import { useCallback } from "react";
1943
+ import { Box as Box7, Text as Text7, useInput as useInput3 } from "ink";
1944
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1945
+ function calculateGoalProgress(goal) {
1946
+ if (goal.target <= 0) return 0;
1947
+ const startValue = goal.startValue ?? goal.currentValue;
1948
+ if (startValue > goal.target) {
1949
+ const totalReduction = startValue - goal.target;
1950
+ const actualReduction = startValue - goal.currentValue;
1951
+ return Math.round(actualReduction / totalReduction * 100);
1952
+ }
1953
+ return Math.round(goal.currentValue / goal.target * 100);
1954
+ }
1955
+ function GoalsView() {
1956
+ const { state, dispatch } = useDashboard();
1957
+ const { goalsPanel } = state;
1958
+ const activeGoals = goalsPanel.goals.filter((g) => g.status === "active");
1959
+ const achievedGoals = goalsPanel.goals.filter((g) => g.status === "achieved");
1960
+ const otherGoals = goalsPanel.goals.filter((g) => g.status !== "active" && g.status !== "achieved");
1961
+ const refreshGoals = useCallback(async () => {
1962
+ try {
1963
+ const workDir = getWorkingDirectory(void 0, true);
1964
+ const agentState = getGuardianState(workDir);
1965
+ await agentState.load();
1966
+ const goals = agentState.getAllGoals();
1967
+ dispatch({
1968
+ type: "SET_GOALS",
1969
+ goals: goals.map((g) => {
1970
+ const base = { id: g.id, description: g.description, type: g.type, target: g.target, currentValue: g.currentValue, status: g.status, autoGenerated: g.autoGenerated, updatedAt: g.updatedAt };
1971
+ return g.category ? { ...base, category: g.category } : base;
1972
+ })
1973
+ });
1974
+ } catch {
1975
+ }
1976
+ }, [dispatch]);
1977
+ const addGoal = useCallback(async (description) => {
1978
+ if (!description.trim()) return;
1979
+ try {
1980
+ const workDir = getWorkingDirectory(void 0, true);
1981
+ const agentState = getGuardianState(workDir);
1982
+ await agentState.load();
1983
+ const goal = {
1984
+ id: `goal-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
1985
+ description: description.trim(),
1986
+ type: "reduction",
1987
+ metric: "semantic",
1988
+ target: 0,
1989
+ currentValue: 0,
1990
+ startValue: 0,
1991
+ status: "active",
1992
+ autoGenerated: false,
1993
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1994
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1995
+ deadline: new Date(Date.now() + 14 * 864e5).toISOString()
1996
+ };
1997
+ await agentState.addGoal(goal);
1998
+ dispatch({ type: "ADD_ACTIVITY", message: `Goal added: ${description.slice(0, 40)}` });
1999
+ await refreshGoals();
2000
+ } catch {
2001
+ }
2002
+ }, [dispatch, refreshGoals]);
2003
+ const completeGoal = useCallback(async (goalId) => {
2004
+ try {
2005
+ const workDir = getWorkingDirectory(void 0, true);
2006
+ const agentState = getGuardianState(workDir);
2007
+ await agentState.load();
2008
+ const goals = agentState.getAllGoals();
2009
+ const goal = goals.find((g) => g.id === goalId);
2010
+ if (goal) {
2011
+ await agentState.updateGoal(goalId, { status: "achieved", currentValue: goal.target, achievedAt: (/* @__PURE__ */ new Date()).toISOString() });
2012
+ dispatch({ type: "ADD_ACTIVITY", message: `Goal achieved: ${goal.description.slice(0, 30)}` });
2013
+ await refreshGoals();
2014
+ }
2015
+ } catch {
2016
+ }
2017
+ }, [dispatch, refreshGoals]);
2018
+ const deleteGoal = useCallback(async (goalId) => {
2019
+ try {
2020
+ const workDir = getWorkingDirectory(void 0, true);
2021
+ const agentState = getGuardianState(workDir);
2022
+ await agentState.load();
2023
+ await agentState.updateGoal(goalId, { status: "rejected" });
2024
+ dispatch({ type: "ADD_ACTIVITY", message: "Goal removed" });
2025
+ await refreshGoals();
2026
+ } catch {
2027
+ }
2028
+ }, [dispatch, refreshGoals]);
2029
+ const reactivateGoal = useCallback(async (goalId) => {
2030
+ try {
2031
+ const workDir = getWorkingDirectory(void 0, true);
2032
+ const agentState = getGuardianState(workDir);
2033
+ await agentState.load();
2034
+ await agentState.updateGoal(goalId, { status: "active", achievedAt: void 0 });
2035
+ dispatch({ type: "ADD_ACTIVITY", message: "Goal reactivated" });
2036
+ await refreshGoals();
2037
+ } catch {
2038
+ }
2039
+ }, [dispatch, refreshGoals]);
2040
+ useInput3((_input, key) => {
2041
+ if (goalsPanel.inputMode === "add") {
2042
+ if (key.escape) {
2043
+ dispatch({ type: "SET_GOALS_INPUT_MODE", mode: "browse" });
2044
+ } else if (key.return) {
2045
+ void addGoal(goalsPanel.inputBuffer);
2046
+ dispatch({ type: "SET_GOALS_INPUT_MODE", mode: "browse" });
2047
+ } else if (key.backspace || key.delete) {
2048
+ dispatch({ type: "SET_GOALS_INPUT_BUFFER", buffer: goalsPanel.inputBuffer.slice(0, -1) });
2049
+ } else if (_input && _input.length === 1 && !key.ctrl && !key.meta) {
2050
+ dispatch({ type: "SET_GOALS_INPUT_BUFFER", buffer: goalsPanel.inputBuffer + _input });
2051
+ }
2052
+ return;
2053
+ }
2054
+ if (_input === "a") dispatch({ type: "SET_GOALS_INPUT_MODE", mode: "add" });
2055
+ else if (key.upArrow || _input === "k") dispatch({ type: "SELECT_GOAL", index: Math.max(0, goalsPanel.selectedIndex - 1) });
2056
+ else if (key.downArrow || _input === "j") dispatch({ type: "SELECT_GOAL", index: Math.min(activeGoals.length - 1, goalsPanel.selectedIndex + 1) });
2057
+ else if (key.return) {
2058
+ const selected = activeGoals[goalsPanel.selectedIndex];
2059
+ if (selected) void completeGoal(selected.id);
2060
+ } else if (_input === "d") {
2061
+ const selected = activeGoals[goalsPanel.selectedIndex];
2062
+ if (selected) void deleteGoal(selected.id);
2063
+ } else if (_input === "x") {
2064
+ const completed = goalsPanel.goals.filter((g) => g.status === "achieved" || g.status === "failed");
2065
+ if (completed[0]) void deleteGoal(completed[0].id);
2066
+ } else if (_input === "u") {
2067
+ const recent = goalsPanel.goals.filter((g) => g.status === "achieved").sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
2068
+ if (recent[0]) void reactivateGoal(recent[0].id);
2069
+ }
2070
+ });
2071
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", paddingX: 1, children: [
2072
+ /* @__PURE__ */ jsxs7(Text7, { children: [
2073
+ /* @__PURE__ */ jsx8(Text7, { color: "cyan", bold: true, children: "GOALS" }),
2074
+ " ",
2075
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "Track progress, achieve targets" })
2076
+ ] }),
2077
+ /* @__PURE__ */ jsx8(Text7, { children: " " }),
2078
+ goalsPanel.inputMode === "add" ? /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2079
+ /* @__PURE__ */ jsxs7(Text7, { children: [
2080
+ /* @__PURE__ */ jsx8(Text7, { bold: true, children: "New goal:" }),
2081
+ " ",
2082
+ goalsPanel.inputBuffer,
2083
+ /* @__PURE__ */ jsx8(Text7, { bold: true, color: "cyan", children: "\u258C" })
2084
+ ] }),
2085
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: 'Examples: "Reduce auth bugs by 50%", "Eliminate critical issues"' }),
2086
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "Press Enter to add, Escape to cancel" })
2087
+ ] }) : /* @__PURE__ */ jsx8(Fragment2, { children: goalsPanel.goals.length === 0 ? /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2088
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "No goals yet." }),
2089
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "Press [a] to add your first goal, or wait for auto-generated goals." })
2090
+ ] }) : /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2091
+ activeGoals.length > 0 && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2092
+ /* @__PURE__ */ jsx8(Text7, { bold: true, children: "Active:" }),
2093
+ activeGoals.map((goal, idx) => {
2094
+ const isSelected = goalsPanel.selectedIndex === idx;
2095
+ const progress = calculateGoalProgress(goal);
2096
+ const bar = progressBar(progress, 100, 10);
2097
+ const source = goal.autoGenerated ? /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "[auto]" }) : /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "[manual]" });
2098
+ return /* @__PURE__ */ jsxs7(Text7, { children: [
2099
+ isSelected ? /* @__PURE__ */ jsx8(Text7, { bold: true, color: "magenta", children: "\u25B6 " }) : /* @__PURE__ */ jsx8(Text7, { children: " " }),
2100
+ bar,
2101
+ " ",
2102
+ goal.description.slice(0, 50),
2103
+ " ",
2104
+ source
2105
+ ] }, goal.id);
2106
+ }),
2107
+ /* @__PURE__ */ jsx8(Text7, { children: " " })
2108
+ ] }),
2109
+ achievedGoals.length > 0 && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2110
+ /* @__PURE__ */ jsxs7(Text7, { children: [
2111
+ /* @__PURE__ */ jsx8(Text7, { color: "green", children: "Achieved:" }),
2112
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: " [x to remove]" })
2113
+ ] }),
2114
+ achievedGoals.slice(0, 5).map((g) => /* @__PURE__ */ jsxs7(Text7, { color: "green", children: [
2115
+ " [+] ",
2116
+ g.description.slice(0, 50)
2117
+ ] }, g.id)),
2118
+ achievedGoals.length > 5 && /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
2119
+ " +",
2120
+ achievedGoals.length - 5,
2121
+ " more"
2122
+ ] }),
2123
+ /* @__PURE__ */ jsx8(Text7, { children: " " })
2124
+ ] }),
2125
+ otherGoals.length > 0 && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2126
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "Other:" }),
2127
+ otherGoals.slice(0, 2).map((g) => {
2128
+ const icon = g.status === "failed" ? "[X]" : g.status === "paused" ? "[P]" : "\u2022";
2129
+ return /* @__PURE__ */ jsxs7(Text7, { children: [
2130
+ " ",
2131
+ icon,
2132
+ " ",
2133
+ g.description.slice(0, 50),
2134
+ /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
2135
+ " (",
2136
+ g.status,
2137
+ ")"
2138
+ ] })
2139
+ ] }, g.id);
2140
+ })
2141
+ ] })
2142
+ ] }) })
2143
+ ] });
2144
+ }
2145
+
2146
+ // src/cli/dashboard/views/HypothesesView.tsx
2147
+ import { useCallback as useCallback2 } from "react";
2148
+ import { Box as Box8, Text as Text8, useInput as useInput4 } from "ink";
2149
+ import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2150
+ function HypothesesView() {
2151
+ const { state, dispatch } = useDashboard();
2152
+ const { hypothesesPanel } = state;
2153
+ const testing = hypothesesPanel.hypotheses.filter((h) => h.status === "testing");
2154
+ const validated = hypothesesPanel.hypotheses.filter((h) => h.status === "validated");
2155
+ const invalidated = hypothesesPanel.hypotheses.filter((h) => h.status === "invalidated");
2156
+ const refreshHypotheses = useCallback2(async () => {
2157
+ try {
2158
+ const workDir = getWorkingDirectory(void 0, true);
2159
+ const agentState = getGuardianState(workDir);
2160
+ await agentState.load();
2161
+ const hypotheses = agentState.getAllHypotheses();
2162
+ dispatch({
2163
+ type: "SET_HYPOTHESES",
2164
+ hypotheses: hypotheses.map((h) => {
2165
+ const base = { id: h.id, statement: h.statement, confidence: h.confidence, status: h.status, evidenceCount: h.evidence.length, updatedAt: h.updatedAt };
2166
+ return h.category ? { ...base, category: h.category } : base;
2167
+ })
2168
+ });
2169
+ } catch {
2170
+ }
2171
+ }, [dispatch]);
2172
+ const addHypothesis = useCallback2(async (statement) => {
2173
+ if (!statement.trim()) return;
2174
+ try {
2175
+ const workDir = getWorkingDirectory(void 0, true);
2176
+ const agentState = getGuardianState(workDir);
2177
+ await agentState.load();
2178
+ const hypothesis = {
2179
+ id: `hypo-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
2180
+ statement: statement.trim(),
2181
+ confidence: 0.5,
2182
+ status: "testing",
2183
+ evidence: [],
2184
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
2185
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
2186
+ testCriteria: "Collect evidence from scans"
2187
+ };
2188
+ await agentState.addHypothesis(hypothesis);
2189
+ dispatch({ type: "ADD_ACTIVITY", message: `Hypothesis added: ${statement.slice(0, 40)}` });
2190
+ await refreshHypotheses();
2191
+ } catch {
2192
+ }
2193
+ }, [dispatch, refreshHypotheses]);
2194
+ const updateHypothesis = useCallback2(async (hypoId, action) => {
2195
+ try {
2196
+ const workDir = getWorkingDirectory(void 0, true);
2197
+ const agentState = getGuardianState(workDir);
2198
+ await agentState.load();
2199
+ if (action === "validate") await agentState.updateHypothesis(hypoId, { status: "validated", confidence: 0.9 });
2200
+ else if (action === "invalidate") await agentState.updateHypothesis(hypoId, { status: "invalidated", confidence: 0.1 });
2201
+ else await agentState.updateHypothesis(hypoId, { status: "retired" });
2202
+ dispatch({ type: "ADD_ACTIVITY", message: `Hypothesis ${action === "validate" ? "validated" : action === "invalidate" ? "invalidated" : "removed"}` });
2203
+ await refreshHypotheses();
2204
+ } catch {
2205
+ }
2206
+ }, [dispatch, refreshHypotheses]);
2207
+ const reactivateHypothesis = useCallback2(async (hypoId) => {
2208
+ try {
2209
+ const workDir = getWorkingDirectory(void 0, true);
2210
+ const agentState = getGuardianState(workDir);
2211
+ await agentState.load();
2212
+ await agentState.updateHypothesis(hypoId, { status: "testing", confidence: 0.5, validatedAt: void 0 });
2213
+ dispatch({ type: "ADD_ACTIVITY", message: "Hypothesis reactivated" });
2214
+ await refreshHypotheses();
2215
+ } catch {
2216
+ }
2217
+ }, [dispatch, refreshHypotheses]);
2218
+ useInput4((_input, key) => {
2219
+ if (hypothesesPanel.inputMode === "add") {
2220
+ if (key.escape) {
2221
+ dispatch({ type: "SET_HYPOTHESES_INPUT_MODE", mode: "browse" });
2222
+ } else if (key.return) {
2223
+ void addHypothesis(hypothesesPanel.inputBuffer);
2224
+ dispatch({ type: "SET_HYPOTHESES_INPUT_MODE", mode: "browse" });
2225
+ } else if (key.backspace || key.delete) {
2226
+ dispatch({ type: "SET_HYPOTHESES_INPUT_BUFFER", buffer: hypothesesPanel.inputBuffer.slice(0, -1) });
2227
+ } else if (_input && _input.length === 1 && !key.ctrl && !key.meta) {
2228
+ dispatch({ type: "SET_HYPOTHESES_INPUT_BUFFER", buffer: hypothesesPanel.inputBuffer + _input });
2229
+ }
2230
+ return;
2231
+ }
2232
+ if (_input === "a") dispatch({ type: "SET_HYPOTHESES_INPUT_MODE", mode: "add" });
2233
+ else if (key.upArrow || _input === "k") dispatch({ type: "SELECT_HYPOTHESIS", index: Math.max(0, hypothesesPanel.selectedIndex - 1) });
2234
+ else if (key.downArrow || _input === "j") dispatch({ type: "SELECT_HYPOTHESIS", index: Math.min(testing.length - 1, hypothesesPanel.selectedIndex + 1) });
2235
+ else if (_input === "v") {
2236
+ const selected = testing[hypothesesPanel.selectedIndex];
2237
+ if (selected) void updateHypothesis(selected.id, "validate");
2238
+ } else if (_input === "x") {
2239
+ const selected = testing[hypothesesPanel.selectedIndex];
2240
+ if (selected) void updateHypothesis(selected.id, "invalidate");
2241
+ } else if (_input === "d") {
2242
+ const selected = testing[hypothesesPanel.selectedIndex];
2243
+ if (selected) void updateHypothesis(selected.id, "delete");
2244
+ } else if (_input === "r") {
2245
+ const completed = hypothesesPanel.hypotheses.filter((h) => h.status === "validated" || h.status === "invalidated");
2246
+ if (completed[0]) void updateHypothesis(completed[0].id, "delete");
2247
+ } else if (_input === "u") {
2248
+ const recent = hypothesesPanel.hypotheses.filter((h) => h.status === "validated" || h.status === "invalidated").sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
2249
+ if (recent[0]) void reactivateHypothesis(recent[0].id);
2250
+ }
2251
+ });
2252
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: 1, children: [
2253
+ /* @__PURE__ */ jsxs8(Text8, { children: [
2254
+ /* @__PURE__ */ jsx9(Text8, { color: "cyan", bold: true, children: "HYPOTHESES" }),
2255
+ " ",
2256
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Test theories about your codebase" })
2257
+ ] }),
2258
+ /* @__PURE__ */ jsx9(Text8, { children: " " }),
2259
+ hypothesesPanel.inputMode === "add" ? /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2260
+ /* @__PURE__ */ jsxs8(Text8, { children: [
2261
+ /* @__PURE__ */ jsx9(Text8, { bold: true, children: "New hypothesis:" }),
2262
+ " ",
2263
+ hypothesesPanel.inputBuffer,
2264
+ /* @__PURE__ */ jsx9(Text8, { bold: true, color: "cyan", children: "\u258C" })
2265
+ ] }),
2266
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: 'Examples: "Mondays have more bugs", "Code reviews reduce issues"' }),
2267
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Press Enter to add, Escape to cancel" })
2268
+ ] }) : /* @__PURE__ */ jsx9(Fragment3, { children: hypothesesPanel.hypotheses.length === 0 ? /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2269
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "No hypotheses yet." }),
2270
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Press [a] to add your first hypothesis." }),
2271
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "The agent will collect evidence and update confidence over time." })
2272
+ ] }) : /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2273
+ testing.length > 0 && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2274
+ /* @__PURE__ */ jsx9(Text8, { bold: true, children: "Testing:" }),
2275
+ testing.map((hypo, idx) => {
2276
+ const isSelected = hypothesesPanel.selectedIndex === idx;
2277
+ const conf = Math.round(hypo.confidence * 100);
2278
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2279
+ /* @__PURE__ */ jsxs8(Text8, { children: [
2280
+ isSelected ? /* @__PURE__ */ jsx9(Text8, { bold: true, color: "magenta", children: "\u25B6 " }) : /* @__PURE__ */ jsx9(Text8, { children: " " }),
2281
+ '[?] "',
2282
+ hypo.statement.slice(0, 50),
2283
+ '" ',
2284
+ /* @__PURE__ */ jsxs8(Text8, { color: conf >= 70 ? "green" : conf >= 40 ? "yellow" : "yellow", children: [
2285
+ "(",
2286
+ conf,
2287
+ "%)"
2288
+ ] })
2289
+ ] }),
2290
+ /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
2291
+ " Evidence: ",
2292
+ hypo.evidenceCount,
2293
+ " points"
2294
+ ] })
2295
+ ] }, hypo.id);
2296
+ }),
2297
+ /* @__PURE__ */ jsx9(Text8, { children: " " })
2298
+ ] }),
2299
+ validated.length > 0 && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2300
+ /* @__PURE__ */ jsxs8(Text8, { children: [
2301
+ /* @__PURE__ */ jsx9(Text8, { color: "green", children: "Validated:" }),
2302
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " [r to remove]" })
2303
+ ] }),
2304
+ validated.slice(0, 3).map((h) => /* @__PURE__ */ jsxs8(Text8, { color: "green", children: [
2305
+ ' [+] "',
2306
+ h.statement.slice(0, 50),
2307
+ '"'
2308
+ ] }, h.id)),
2309
+ validated.length > 3 && /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
2310
+ " +",
2311
+ validated.length - 3,
2312
+ " more"
2313
+ ] }),
2314
+ /* @__PURE__ */ jsx9(Text8, { children: " " })
2315
+ ] }),
2316
+ invalidated.length > 0 && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2317
+ /* @__PURE__ */ jsxs8(Text8, { children: [
2318
+ /* @__PURE__ */ jsx9(Text8, { color: "yellow", children: "Invalidated:" }),
2319
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " [r to remove]" })
2320
+ ] }),
2321
+ invalidated.slice(0, 2).map((h) => /* @__PURE__ */ jsx9(Text8, { children: /* @__PURE__ */ jsxs8(Text8, { color: "yellow", children: [
2322
+ ' [X] "',
2323
+ h.statement.slice(0, 50),
2324
+ '"'
2325
+ ] }) }, h.id)),
2326
+ invalidated.length > 2 && /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
2327
+ " +",
2328
+ invalidated.length - 2,
2329
+ " more"
2330
+ ] })
2331
+ ] })
2332
+ ] }) })
2333
+ ] });
2334
+ }
2335
+
2336
+ // src/cli/dashboard/views/MemoryTreeView.tsx
2337
+ import { useEffect, useCallback as useCallback3 } from "react";
2338
+ import { Box as Box9, Text as Text9, useInput as useInput5 } from "ink";
2339
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2340
+ function severityBar(count, max, width = 16) {
2341
+ const filled = max > 0 ? Math.round(count / max * width) : 0;
2342
+ return "\u2588".repeat(filled) + "\u2591".repeat(width - filled);
2343
+ }
2344
+ function MemoryTreeView() {
2345
+ const { state, dispatch } = useDashboard();
2346
+ const { memoryTree } = state;
2347
+ const { issues, stats, globalPatterns, expandedNodes, selectedNode, loaded } = memoryTree;
2348
+ const loadData = useCallback3(async () => {
2349
+ try {
2350
+ const workDir = getWorkingDirectory(void 0, true);
2351
+ const [issueList, memStats, patterns] = await Promise.all([
2352
+ getRecentIssues({ workDir, limit: 200, daysBack: 30 }),
2353
+ getMemoryStats(workDir),
2354
+ findCrossProjectPatterns(2)
2355
+ ]);
2356
+ dispatch({ type: "SET_MEMORY_TREE", issues: issueList, stats: memStats, patterns });
2357
+ } catch {
2358
+ dispatch({ type: "ADD_ACTIVITY", message: "Memory load error" });
2359
+ }
2360
+ }, [dispatch]);
2361
+ useEffect(() => {
2362
+ if (!loaded) {
2363
+ void loadData();
2364
+ }
2365
+ }, [loaded, loadData]);
2366
+ useInput5((_input, key) => {
2367
+ if (key.upArrow || _input === "k") dispatch({ type: "NAVIGATE_UP" });
2368
+ else if (key.downArrow || _input === "j") dispatch({ type: "NAVIGATE_DOWN" });
2369
+ else if (key.return) dispatch({ type: "TOGGLE_MEMORY_NODE", nodeId: selectedNode });
2370
+ });
2371
+ const bySeverity = { critical: [], serious: [], moderate: [], low: [] };
2372
+ for (const issue of issues) {
2373
+ const arr = bySeverity[issue.severity];
2374
+ if (arr) arr.push(issue);
2375
+ }
2376
+ const byFile = /* @__PURE__ */ new Map();
2377
+ for (const issue of issues) {
2378
+ if (!byFile.has(issue.file)) byFile.set(issue.file, []);
2379
+ byFile.get(issue.file).push(issue);
2380
+ }
2381
+ const sortedFiles = Array.from(byFile.entries()).sort((a, b) => b[1].length - a[1].length).slice(0, 10);
2382
+ const byAgent = /* @__PURE__ */ new Map();
2383
+ for (const issue of issues) {
2384
+ if (!byAgent.has(issue.agent)) byAgent.set(issue.agent, []);
2385
+ byAgent.get(issue.agent).push(issue);
2386
+ }
2387
+ const sortedAgents = Array.from(byAgent.entries()).sort((a, b) => b[1].length - a[1].length);
2388
+ const maxCount = Math.max(bySeverity["critical"]?.length || 0, bySeverity["serious"]?.length || 0, bySeverity["moderate"]?.length || 0, bySeverity["low"]?.length || 0, 1);
2389
+ const totalIssues = stats?.totalIssues || issues.length;
2390
+ const sel = (nodeId) => selectedNode === nodeId;
2391
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingX: 1, children: [
2392
+ /* @__PURE__ */ jsxs9(Text9, { children: [
2393
+ /* @__PURE__ */ jsx10(Text9, { color: "cyan", bold: true, children: "MEMORY TREE" }),
2394
+ " ",
2395
+ /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2396
+ "[",
2397
+ totalIssues,
2398
+ " issues]"
2399
+ ] })
2400
+ ] }),
2401
+ /* @__PURE__ */ jsx10(Text9, { children: " " }),
2402
+ !loaded ? /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "Loading memory data..." }) : issues.length === 0 && globalPatterns.length === 0 ? /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2403
+ /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "No issues in memory yet." }),
2404
+ /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "Run a scan to populate the memory tree." })
2405
+ ] }) : /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2406
+ /* @__PURE__ */ jsxs9(Text9, { children: [
2407
+ sel("severity") ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "magenta", children: "\u2192 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2408
+ expandedNodes.has("severity") ? "\u25BC" : "\u25B6",
2409
+ " ",
2410
+ sel("severity") ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "magenta", children: "By Severity" }) : /* @__PURE__ */ jsx10(Text9, { color: "cyan", bold: true, children: "By Severity" })
2411
+ ] }),
2412
+ expandedNodes.has("severity") && ["critical", "serious", "moderate", "low"].map((sev) => {
2413
+ const count = bySeverity[sev]?.length || 0;
2414
+ const nodeId = `severity-${sev}`;
2415
+ const barStr = severityBar(count, maxCount);
2416
+ const isLow = sev === "low";
2417
+ const sevColorMap = { critical: "red", serious: "yellow", moderate: "blue" };
2418
+ const sevColor = isLow ? void 0 : sevColorMap[sev];
2419
+ const SevText = ({ children }) => isLow ? /* @__PURE__ */ jsx10(Text9, { dimColor: true, children }) : sevColor ? /* @__PURE__ */ jsx10(Text9, { color: sevColor, children }) : /* @__PURE__ */ jsx10(Text9, { children });
2420
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2421
+ /* @__PURE__ */ jsxs9(Text9, { children: [
2422
+ sel(nodeId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "magenta", children: "\u2192 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2423
+ " \u2502 ",
2424
+ sel(nodeId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "magenta", children: sev }) : /* @__PURE__ */ jsx10(SevText, { children: sev }),
2425
+ ` (${count}) `,
2426
+ /* @__PURE__ */ jsx10(SevText, { children: barStr })
2427
+ ] }),
2428
+ expandedNodes.has(nodeId) && (bySeverity[sev] || []).slice(0, 5).map((issue, i) => {
2429
+ const issueId = `severity-${sev}-${issue.id}`;
2430
+ const filename = issue.file.split("/").pop() || issue.file;
2431
+ const line = issue.line ? `:${issue.line}` : "";
2432
+ const desc = issue.issue.slice(0, 35) + (issue.issue.length > 35 ? "..." : "");
2433
+ return /* @__PURE__ */ jsxs9(Text9, { children: [
2434
+ sel(issueId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "magenta", children: "\u2192 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2435
+ " \u2502 ",
2436
+ i === Math.min(5, bySeverity[sev]?.length || 0) - 1 ? "\u2514\u2500 " : "\u251C\u2500 ",
2437
+ /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2438
+ filename,
2439
+ line
2440
+ ] }),
2441
+ " - ",
2442
+ /* @__PURE__ */ jsx10(SevText, { children: desc })
2443
+ ] }, i);
2444
+ })
2445
+ ] }, sev);
2446
+ }),
2447
+ /* @__PURE__ */ jsxs9(Text9, { children: [
2448
+ sel("files") ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "magenta", children: "\u2192 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2449
+ expandedNodes.has("files") ? "\u25BC" : "\u25B6",
2450
+ " ",
2451
+ sel("files") ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "magenta", children: "By File (Hot Spots)" }) : /* @__PURE__ */ jsx10(Text9, { color: "cyan", bold: true, children: "By File (Hot Spots)" })
2452
+ ] }),
2453
+ expandedNodes.has("files") && sortedFiles.map(([file, fileIssues], idx) => {
2454
+ const fileId = `file-${file}`;
2455
+ const filename = file.split("/").pop() || file;
2456
+ const count = fileIssues.length;
2457
+ const isLast = idx === sortedFiles.length - 1;
2458
+ return /* @__PURE__ */ jsxs9(Text9, { children: [
2459
+ sel(fileId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "magenta", children: "\u2192 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2460
+ " ",
2461
+ isLast ? "\u2514\u2500 " : "\u251C\u2500 ",
2462
+ sel(fileId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "magenta", children: filename }) : /* @__PURE__ */ jsx10(Text9, { children: filename }),
2463
+ ` (${count})`
2464
+ ] }, file);
2465
+ }),
2466
+ /* @__PURE__ */ jsxs9(Text9, { children: [
2467
+ sel("agents") ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "magenta", children: "\u2192 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2468
+ expandedNodes.has("agents") ? "\u25BC" : "\u25B6",
2469
+ " ",
2470
+ sel("agents") ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "magenta", children: "By Agent" }) : /* @__PURE__ */ jsx10(Text9, { color: "cyan", bold: true, children: "By Agent" })
2471
+ ] }),
2472
+ expandedNodes.has("agents") && sortedAgents.map(([agent, agentIssues], idx) => {
2473
+ const agentId = `agent-${agent}`;
2474
+ const isLast = idx === sortedAgents.length - 1;
2475
+ return /* @__PURE__ */ jsxs9(Text9, { children: [
2476
+ sel(agentId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "magenta", children: "\u2192 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2477
+ " ",
2478
+ isLast ? "\u2514\u2500 " : "\u251C\u2500 ",
2479
+ sel(agentId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "magenta", children: agent }) : /* @__PURE__ */ jsx10(Text9, { children: agent }),
2480
+ ` (${agentIssues.length})`
2481
+ ] }, agent);
2482
+ }),
2483
+ /* @__PURE__ */ jsxs9(Text9, { children: [
2484
+ sel("patterns") ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "magenta", children: "\u2192 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2485
+ expandedNodes.has("patterns") ? "\u25BC" : "\u25B6",
2486
+ " ",
2487
+ sel("patterns") ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "magenta", children: [
2488
+ "Cross-Project Patterns (",
2489
+ globalPatterns.length,
2490
+ " recurring)"
2491
+ ] }) : /* @__PURE__ */ jsxs9(Text9, { color: "cyan", bold: true, children: [
2492
+ "Cross-Project Patterns (",
2493
+ globalPatterns.length,
2494
+ " recurring)"
2495
+ ] })
2496
+ ] }),
2497
+ expandedNodes.has("patterns") && globalPatterns.slice(0, 5).map((pattern, idx) => {
2498
+ const patternId = `pattern-${pattern.id}`;
2499
+ const isLast = idx === Math.min(4, globalPatterns.length - 1);
2500
+ const desc = pattern.pattern.slice(0, 40) + (pattern.pattern.length > 40 ? "..." : "");
2501
+ return /* @__PURE__ */ jsxs9(Text9, { children: [
2502
+ sel(patternId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "magenta", children: "\u2192 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2503
+ " ",
2504
+ isLast ? "\u2514\u2500 " : "\u251C\u2500 ",
2505
+ /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2506
+ '"',
2507
+ desc,
2508
+ '" - seen in ',
2509
+ pattern.projects.length,
2510
+ " projects"
2511
+ ] })
2512
+ ] }, pattern.id);
2513
+ }),
2514
+ /* @__PURE__ */ jsx10(Text9, { children: " " }),
2515
+ /* @__PURE__ */ jsxs9(Box9, { gap: 2, children: [
2516
+ /* @__PURE__ */ jsxs9(Text9, { children: [
2517
+ /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "Trend: " }),
2518
+ stats?.improvementTrend === "improving" ? /* @__PURE__ */ jsx10(Text9, { color: "green", children: "\u2191 Improving" }) : stats?.improvementTrend === "declining" ? /* @__PURE__ */ jsx10(Text9, { color: "red", children: "\u2193 Declining" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u2192 Stable" })
2519
+ ] }),
2520
+ /* @__PURE__ */ jsxs9(Text9, { children: [
2521
+ /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "Resolved:" }),
2522
+ " ",
2523
+ /* @__PURE__ */ jsx10(Text9, { color: "green", children: stats?.resolvedCount || 0 })
2524
+ ] }),
2525
+ /* @__PURE__ */ jsxs9(Text9, { children: [
2526
+ /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "Historical:" }),
2527
+ " ",
2528
+ /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: stats?.historicalIssues || 0 })
2529
+ ] })
2530
+ ] })
2531
+ ] })
2532
+ ] });
2533
+ }
2534
+
2535
+ // src/cli/dashboard/views/RawLogView.tsx
2536
+ import { Box as Box10, Text as Text10, useInput as useInput6 } from "ink";
2537
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2538
+ function RawLogView() {
2539
+ const { state, dispatch } = useDashboard();
2540
+ const { rawLog, rawLogPage } = state;
2541
+ const pageSize = Math.max(10, (process.stdout.rows || 40) - 15);
2542
+ const totalPages = Math.max(1, Math.ceil(rawLog.length / pageSize));
2543
+ useInput6((input, _key) => {
2544
+ if (input === "n") {
2545
+ dispatch({ type: "SET_RAW_LOG_PAGE", page: Math.min(totalPages - 1, rawLogPage + 1) });
2546
+ } else if (input === "p") {
2547
+ dispatch({ type: "SET_RAW_LOG_PAGE", page: Math.max(0, rawLogPage - 1) });
2548
+ }
2549
+ });
2550
+ const startIdx = rawLogPage * pageSize;
2551
+ const logs = rawLog.slice(startIdx, startIdx + pageSize);
2552
+ return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", paddingX: 1, children: [
2553
+ /* @__PURE__ */ jsxs10(Text10, { children: [
2554
+ /* @__PURE__ */ jsx11(Text10, { color: "cyan", bold: true, children: "RAW LOG" }),
2555
+ " ",
2556
+ /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
2557
+ "Page ",
2558
+ rawLogPage + 1,
2559
+ "/",
2560
+ totalPages
2561
+ ] }),
2562
+ " ",
2563
+ /* @__PURE__ */ jsx11(Text10, { bold: true, children: rawLog.length }),
2564
+ /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: " entries" })
2565
+ ] }),
2566
+ /* @__PURE__ */ jsx11(Text10, { children: " " }),
2567
+ rawLog.length === 0 ? /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: "No log entries yet." }) : /* @__PURE__ */ jsx11(Box10, { flexDirection: "column", children: logs.map((entry, i) => {
2568
+ const levelTag = `[${entry.level.toUpperCase().padEnd(5)}]`;
2569
+ const levelEl = entry.level === "error" ? /* @__PURE__ */ jsx11(Text10, { color: "red", children: levelTag }) : entry.level === "warn" ? /* @__PURE__ */ jsx11(Text10, { color: "yellow", children: levelTag }) : entry.level === "info" ? /* @__PURE__ */ jsx11(Text10, { color: "green", children: levelTag }) : /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: levelTag });
2570
+ return /* @__PURE__ */ jsxs10(Text10, { children: [
2571
+ /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: entry.time }),
2572
+ " ",
2573
+ levelEl,
2574
+ " ",
2575
+ entry.message.slice(0, 80)
2576
+ ] }, i);
2577
+ }) })
2578
+ ] });
2579
+ }
2580
+
2581
+ // src/cli/dashboard/App.tsx
2582
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
2583
+ var MAIN_VIEWS = ["overview", "memory", "goals", "hypotheses", "agent"];
2584
+ function DashboardApp({ onReady }) {
2585
+ const { state, dispatch } = useDashboard();
2586
+ const { exit } = useApp();
2587
+ const [showConfig, setShowConfig] = useState2(false);
2588
+ const dispatchRef = useRef(dispatch);
2589
+ dispatchRef.current = dispatch;
2590
+ const stateRef = useRef(state);
2591
+ stateRef.current = state;
2592
+ const configPath = join(getTrieDirectory(getWorkingDirectory(void 0, true)), "agent.json");
2593
+ const loadConfig = useCallback4(async () => {
2594
+ if (!existsSync(configPath)) return;
2595
+ try {
2596
+ const raw = await readFile(configPath, "utf-8");
2597
+ const parsed = JSON.parse(raw);
2598
+ dispatchRef.current({ type: "SET_AGENT_CONFIG", config: parsed });
2599
+ } catch {
2600
+ }
2601
+ }, [configPath]);
2602
+ const persistConfig = useCallback4(async () => {
2603
+ try {
2604
+ await mkdir(getTrieDirectory(getWorkingDirectory(void 0, true)), { recursive: true });
2605
+ await writeFile(configPath, JSON.stringify(stateRef.current.agentConfig, null, 2), "utf-8");
2606
+ } catch {
2607
+ }
2608
+ }, [configPath]);
2609
+ const processInsights = useCallback4(async (issues) => {
2610
+ try {
2611
+ const workDir = getWorkingDirectory(void 0, true);
2612
+ const trieAgent = getGuardian(workDir);
2613
+ if (!stateRef.current.agentInitialized) {
2614
+ await trieAgent.initialize();
2615
+ dispatchRef.current({ type: "SET_AGENT_INITIALIZED", initialized: true });
2616
+ const persisted = trieAgent.getActiveInsights();
2617
+ if (persisted.length > 0) {
2618
+ dispatchRef.current({ type: "ADD_INSIGHTS", insights: persisted });
2619
+ }
2620
+ }
2621
+ const filesChanged = stateRef.current.watch.recentChanges.map((c) => c.file);
2622
+ const newInsights = await trieAgent.processIssues(issues, { filesChanged, isWatchMode: stateRef.current.watch.watching });
2623
+ if (newInsights.length > 0) {
2624
+ dispatchRef.current({ type: "ADD_INSIGHTS", insights: newInsights });
2625
+ }
2626
+ try {
2627
+ const agencyStatus = await trieAgent.getAgencyStatus();
2628
+ dispatchRef.current({ type: "SET_AGENCY_STATUS", status: agencyStatus });
2629
+ } catch {
2630
+ }
2631
+ } catch (error) {
2632
+ dispatchRef.current({ type: "ADD_ACTIVITY", message: `Trie Agent error: ${error instanceof Error ? error.message : "unknown"}` });
2633
+ }
2634
+ }, []);
2635
+ const refreshGoals = useCallback4(async () => {
2636
+ try {
2637
+ const workDir = getWorkingDirectory(void 0, true);
2638
+ const agentState = getGuardianState(workDir);
2639
+ await agentState.load();
2640
+ const goals = agentState.getAllGoals();
2641
+ dispatchRef.current({
2642
+ type: "SET_GOALS",
2643
+ goals: goals.map((g) => {
2644
+ const base = { id: g.id, description: g.description, type: g.type, target: g.target, currentValue: g.currentValue, status: g.status, autoGenerated: g.autoGenerated, updatedAt: g.updatedAt };
2645
+ return g.category ? { ...base, category: g.category } : base;
2646
+ })
2647
+ });
2648
+ } catch {
2649
+ }
2650
+ }, []);
2651
+ const refreshHypotheses = useCallback4(async () => {
2652
+ try {
2653
+ const workDir = getWorkingDirectory(void 0, true);
2654
+ const agentState = getGuardianState(workDir);
2655
+ await agentState.load();
2656
+ const hypotheses = agentState.getAllHypotheses();
2657
+ dispatchRef.current({
2658
+ type: "SET_HYPOTHESES",
2659
+ hypotheses: hypotheses.map((h) => {
2660
+ const base = { id: h.id, statement: h.statement, confidence: h.confidence, status: h.status, evidenceCount: h.evidence.length, updatedAt: h.updatedAt };
2661
+ return h.category ? { ...base, category: h.category } : base;
2662
+ })
2663
+ });
2664
+ } catch {
2665
+ }
2666
+ }, []);
2667
+ useEffect2(() => {
2668
+ void loadConfig();
2669
+ void refreshGoals();
2670
+ void refreshHypotheses();
2671
+ const outputManager = getOutputManager();
2672
+ outputManager.setMode("tui");
2673
+ outputManager.registerTUICallbacks({
2674
+ onActivity: (message) => {
2675
+ dispatchRef.current({ type: "ADD_ACTIVITY", message });
2676
+ },
2677
+ onLog: (level, message) => {
2678
+ const time = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit" });
2679
+ dispatchRef.current({ type: "STREAM_UPDATE", update: { type: "raw_log", data: { time, level, message }, timestamp: Date.now() } });
2680
+ },
2681
+ onNudge: (nudge) => {
2682
+ const action = { type: "SHOW_NOTIFICATION", message: nudge.message, severity: nudge.severity };
2683
+ if (nudge.file !== void 0) action.file = nudge.file;
2684
+ if (nudge.autoHideMs !== void 0) action.autoHideMs = nudge.autoHideMs;
2685
+ dispatchRef.current(action);
2686
+ }
2687
+ });
2688
+ const handleUpdate = (update) => {
2689
+ dispatchRef.current({ type: "STREAM_UPDATE", update });
2690
+ if (update.type === "scan_complete" && update.data.issues) {
2691
+ void processInsights(update.data.issues);
2692
+ }
2693
+ };
2694
+ const getConfig = () => {
2695
+ const c = stateRef.current.agentConfig;
2696
+ return {
2697
+ agentSmith: { ...c.agentSmith, enabledCategories: { ...c.agentSmith.enabledCategories } },
2698
+ performance: { ...c.performance },
2699
+ riskThresholds: { ...c.riskThresholds }
2700
+ };
2701
+ };
2702
+ onReady(handleUpdate, getConfig);
2703
+ return () => {
2704
+ outputManager.clearTUICallbacks();
2705
+ outputManager.setMode("console");
2706
+ };
2707
+ }, [loadConfig, onReady, processInsights, refreshGoals, refreshHypotheses]);
2708
+ useEffect2(() => {
2709
+ const interval = setInterval(() => {
2710
+ dispatchRef.current({ type: "AUTO_DISMISS_NOTIFICATIONS" });
2711
+ }, 5e3);
2712
+ return () => clearInterval(interval);
2713
+ }, []);
2714
+ useInput7((input, key) => {
2715
+ if (showConfig) return;
2716
+ if (state.view === "goals" && state.goalsPanel.inputMode === "add") return;
2717
+ if (state.view === "hypotheses" && state.hypothesesPanel.inputMode === "add") return;
2718
+ if (state.view === "agent" || state.view === "memory") return;
2719
+ if (input === "q" || key.escape) {
2720
+ exit();
2721
+ process.exit(0);
2722
+ }
2723
+ if (key.tab) {
2724
+ const currentIndex = MAIN_VIEWS.indexOf(state.view);
2725
+ const nextIndex = currentIndex >= 0 ? (currentIndex + 1) % MAIN_VIEWS.length : 0;
2726
+ dispatch({ type: "SET_VIEW", view: MAIN_VIEWS[nextIndex] || "overview" });
2727
+ }
2728
+ if (input === "b") dispatch({ type: "GO_BACK" });
2729
+ if (input === "c") setShowConfig(true);
2730
+ if (input === "n") dispatch({ type: "NEXT_PAGE" });
2731
+ if (input === "p") dispatch({ type: "PREV_PAGE" });
2732
+ if (input === "l") dispatch({ type: "SET_VIEW", view: "rawlog" });
2733
+ if (input === "g") dispatch({ type: "SET_VIEW", view: "agent" });
2734
+ if (input === "o") {
2735
+ dispatch({ type: "SET_VIEW", view: "goals" });
2736
+ void refreshGoals();
2737
+ }
2738
+ if (input === "y") {
2739
+ dispatch({ type: "SET_VIEW", view: "hypotheses" });
2740
+ void refreshHypotheses();
2741
+ }
2742
+ if (input === "t") dispatch({ type: "SET_VIEW", view: "memory" });
2743
+ });
2744
+ let viewComponent;
2745
+ switch (state.view) {
2746
+ case "overview":
2747
+ viewComponent = /* @__PURE__ */ jsx12(OverviewView, {});
2748
+ break;
2749
+ case "agent":
2750
+ viewComponent = /* @__PURE__ */ jsx12(AgentView, {});
2751
+ break;
2752
+ case "goals":
2753
+ viewComponent = /* @__PURE__ */ jsx12(GoalsView, {});
2754
+ break;
2755
+ case "hypotheses":
2756
+ viewComponent = /* @__PURE__ */ jsx12(HypothesesView, {});
2757
+ break;
2758
+ case "memory":
2759
+ viewComponent = /* @__PURE__ */ jsx12(MemoryTreeView, {});
2760
+ break;
2761
+ case "rawlog":
2762
+ viewComponent = /* @__PURE__ */ jsx12(RawLogView, {});
2763
+ break;
2764
+ default:
2765
+ viewComponent = /* @__PURE__ */ jsx12(OverviewView, {});
2766
+ }
2767
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", height: process.stdout.rows || 40, children: [
2768
+ /* @__PURE__ */ jsx12(Header, {}),
2769
+ /* @__PURE__ */ jsx12(Notification, {}),
2770
+ /* @__PURE__ */ jsx12(Box11, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: showConfig ? /* @__PURE__ */ jsx12(ConfigDialog, { onClose: () => {
2771
+ setShowConfig(false);
2772
+ void persistConfig();
2773
+ } }) : viewComponent }),
2774
+ /* @__PURE__ */ jsx12(Footer, {})
2775
+ ] });
2776
+ }
2777
+ function App({ onReady }) {
2778
+ return /* @__PURE__ */ jsx12(DashboardProvider, { children: /* @__PURE__ */ jsx12(DashboardApp, { onReady }) });
2779
+ }
2780
+
2781
+ // src/cli/dashboard/index.ts
2782
+ var InteractiveDashboard = class {
2783
+ app = null;
2784
+ updateHandler = null;
2785
+ getConfigFn = null;
2786
+ async start() {
2787
+ this.app = render(
2788
+ React7.createElement(App, {
2789
+ onReady: (handler, getConfig) => {
2790
+ this.updateHandler = handler;
2791
+ this.getConfigFn = getConfig;
2792
+ }
2793
+ }),
2794
+ { exitOnCtrlC: false }
2795
+ );
2796
+ }
2797
+ stop() {
2798
+ if (this.app) {
2799
+ this.app.unmount();
2800
+ this.app = null;
2801
+ }
2802
+ }
2803
+ handleStreamUpdate(update) {
2804
+ this.updateHandler?.(update);
2805
+ }
2806
+ getAgentConfig() {
2807
+ if (this.getConfigFn) return this.getConfigFn();
2808
+ return {
2809
+ agentSmith: { aiEnhancement: true, minSeverity: "low", enabledCategories: { security: true, codeSmells: true, asyncBugs: true, reactPatterns: true, uxPatterns: true, backendPatterns: true }, memoryRetentionDays: 30 },
2810
+ performance: { parallel: true, cache: true, maxConcurrency: 4, timeoutMs: 12e4, workers: true, streaming: true },
2811
+ riskThresholds: { critical: 70, high: 40, medium: 20 }
2812
+ };
2813
+ }
2814
+ };
2815
+
2816
+ export {
2817
+ TrieScanTool,
2818
+ StreamingManager,
2819
+ getOutputManager,
2820
+ InteractiveDashboard
2821
+ };
2822
+ //# sourceMappingURL=chunk-M4YMTHGG.js.map