@neurcode-ai/cli 0.4.0 → 0.4.1

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 (111) hide show
  1. package/dist/api-client.d.ts +105 -17
  2. package/dist/api-client.d.ts.map +1 -1
  3. package/dist/api-client.js +388 -85
  4. package/dist/api-client.js.map +1 -1
  5. package/dist/commands/allow.d.ts.map +1 -1
  6. package/dist/commands/allow.js +6 -33
  7. package/dist/commands/allow.js.map +1 -1
  8. package/dist/commands/check.d.ts.map +1 -1
  9. package/dist/commands/check.js +56 -13
  10. package/dist/commands/check.js.map +1 -1
  11. package/dist/commands/doctor.d.ts +7 -0
  12. package/dist/commands/doctor.d.ts.map +1 -0
  13. package/dist/commands/doctor.js +134 -0
  14. package/dist/commands/doctor.js.map +1 -0
  15. package/dist/commands/init.d.ts +13 -0
  16. package/dist/commands/init.d.ts.map +1 -0
  17. package/dist/commands/init.js +365 -0
  18. package/dist/commands/init.js.map +1 -0
  19. package/dist/commands/login.d.ts +8 -0
  20. package/dist/commands/login.d.ts.map +1 -0
  21. package/dist/commands/login.js +209 -0
  22. package/dist/commands/login.js.map +1 -0
  23. package/dist/commands/logout.d.ts +7 -0
  24. package/dist/commands/logout.d.ts.map +1 -0
  25. package/dist/commands/logout.js +70 -0
  26. package/dist/commands/logout.js.map +1 -0
  27. package/dist/commands/plan.d.ts +2 -0
  28. package/dist/commands/plan.d.ts.map +1 -1
  29. package/dist/commands/plan.js +210 -57
  30. package/dist/commands/plan.js.map +1 -1
  31. package/dist/commands/prompt.d.ts +6 -0
  32. package/dist/commands/prompt.d.ts.map +1 -0
  33. package/dist/commands/prompt.js +254 -0
  34. package/dist/commands/prompt.js.map +1 -0
  35. package/dist/commands/revert.d.ts.map +1 -1
  36. package/dist/commands/revert.js +10 -0
  37. package/dist/commands/revert.js.map +1 -1
  38. package/dist/commands/session.d.ts +29 -0
  39. package/dist/commands/session.d.ts.map +1 -0
  40. package/dist/commands/session.js +382 -0
  41. package/dist/commands/session.js.map +1 -0
  42. package/dist/commands/verify.d.ts.map +1 -1
  43. package/dist/commands/verify.js +127 -13
  44. package/dist/commands/verify.js.map +1 -1
  45. package/dist/commands/watch.d.ts +8 -0
  46. package/dist/commands/watch.d.ts.map +1 -0
  47. package/dist/commands/watch.js +78 -0
  48. package/dist/commands/watch.js.map +1 -0
  49. package/dist/config.d.ts +29 -4
  50. package/dist/config.d.ts.map +1 -1
  51. package/dist/config.js +186 -21
  52. package/dist/config.js.map +1 -1
  53. package/dist/index.js +120 -3
  54. package/dist/index.js.map +1 -1
  55. package/dist/services/integrations/TicketService.d.ts +68 -0
  56. package/dist/services/integrations/TicketService.d.ts.map +1 -0
  57. package/dist/services/integrations/TicketService.js +151 -0
  58. package/dist/services/integrations/TicketService.js.map +1 -0
  59. package/dist/services/security/SecurityGuard.d.ts +80 -0
  60. package/dist/services/security/SecurityGuard.d.ts.map +1 -0
  61. package/dist/services/security/SecurityGuard.js +410 -0
  62. package/dist/services/security/SecurityGuard.js.map +1 -0
  63. package/dist/services/watch/BlobStore.d.ts +33 -0
  64. package/dist/services/watch/BlobStore.d.ts.map +1 -0
  65. package/dist/services/watch/BlobStore.js +108 -0
  66. package/dist/services/watch/BlobStore.js.map +1 -0
  67. package/dist/services/watch/CommandPoller.d.ts +76 -0
  68. package/dist/services/watch/CommandPoller.d.ts.map +1 -0
  69. package/dist/services/watch/CommandPoller.js +298 -0
  70. package/dist/services/watch/CommandPoller.js.map +1 -0
  71. package/dist/services/watch/Journal.d.ts +58 -0
  72. package/dist/services/watch/Journal.d.ts.map +1 -0
  73. package/dist/services/watch/Journal.js +144 -0
  74. package/dist/services/watch/Journal.js.map +1 -0
  75. package/dist/services/watch/Sentinel.d.ts +49 -0
  76. package/dist/services/watch/Sentinel.d.ts.map +1 -0
  77. package/dist/services/watch/Sentinel.js +205 -0
  78. package/dist/services/watch/Sentinel.js.map +1 -0
  79. package/dist/services/watch/Syncer.d.ts +55 -0
  80. package/dist/services/watch/Syncer.d.ts.map +1 -0
  81. package/dist/services/watch/Syncer.js +231 -0
  82. package/dist/services/watch/Syncer.js.map +1 -0
  83. package/dist/utils/ROILogger.d.ts +16 -0
  84. package/dist/utils/ROILogger.d.ts.map +1 -0
  85. package/dist/utils/ROILogger.js +45 -0
  86. package/dist/utils/ROILogger.js.map +1 -0
  87. package/dist/utils/box.d.ts +16 -0
  88. package/dist/utils/box.d.ts.map +1 -0
  89. package/dist/utils/box.js +85 -0
  90. package/dist/utils/box.js.map +1 -0
  91. package/dist/utils/gitignore.d.ts +10 -0
  92. package/dist/utils/gitignore.d.ts.map +1 -0
  93. package/dist/utils/gitignore.js +34 -0
  94. package/dist/utils/gitignore.js.map +1 -0
  95. package/dist/utils/messages.d.ts +81 -0
  96. package/dist/utils/messages.d.ts.map +1 -0
  97. package/dist/utils/messages.js +306 -0
  98. package/dist/utils/messages.js.map +1 -0
  99. package/dist/utils/restore.d.ts +14 -0
  100. package/dist/utils/restore.d.ts.map +1 -0
  101. package/dist/utils/restore.js +89 -0
  102. package/dist/utils/restore.js.map +1 -0
  103. package/dist/utils/state.d.ts +69 -0
  104. package/dist/utils/state.d.ts.map +1 -0
  105. package/dist/utils/state.js +151 -0
  106. package/dist/utils/state.js.map +1 -0
  107. package/dist/utils/user-context.d.ts +28 -0
  108. package/dist/utils/user-context.d.ts.map +1 -0
  109. package/dist/utils/user-context.js +68 -0
  110. package/dist/utils/user-context.js.map +1 -0
  111. package/package.json +11 -4
@@ -0,0 +1,382 @@
1
+ "use strict";
2
+ /**
3
+ * Session Management Command
4
+ *
5
+ * Manages AI coding sessions - list, end, and view session status.
6
+ *
7
+ * Commands:
8
+ * - neurcode session list - List all sessions
9
+ * - neurcode session end - End the current or specified session
10
+ * - neurcode session status - Show status of current session
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.listSessionsCommand = listSessionsCommand;
47
+ exports.endSessionCommand = endSessionCommand;
48
+ exports.sessionStatusCommand = sessionStatusCommand;
49
+ const config_1 = require("../config");
50
+ const api_client_1 = require("../api-client");
51
+ const state_1 = require("../utils/state");
52
+ const messages_1 = require("../utils/messages");
53
+ const readline = __importStar(require("readline"));
54
+ // Import chalk with fallback
55
+ let chalk;
56
+ try {
57
+ chalk = require('chalk');
58
+ }
59
+ catch {
60
+ chalk = {
61
+ green: (str) => str,
62
+ yellow: (str) => str,
63
+ red: (str) => str,
64
+ bold: (str) => str,
65
+ dim: (str) => str,
66
+ cyan: (str) => str,
67
+ white: (str) => str,
68
+ blue: (str) => str,
69
+ };
70
+ }
71
+ /**
72
+ * Prompt user for input
73
+ */
74
+ function promptUser(question) {
75
+ const rl = readline.createInterface({
76
+ input: process.stdin,
77
+ output: process.stdout,
78
+ });
79
+ return new Promise((resolve) => {
80
+ rl.question(question, (answer) => {
81
+ rl.close();
82
+ resolve(answer.trim());
83
+ });
84
+ });
85
+ }
86
+ /**
87
+ * List all sessions
88
+ */
89
+ async function listSessionsCommand(options) {
90
+ try {
91
+ const config = (0, config_1.loadConfig)();
92
+ if (!config.apiKey) {
93
+ config.apiKey = (0, config_1.requireApiKey)();
94
+ }
95
+ const client = new api_client_1.ApiClient(config);
96
+ const projectId = options.projectId || config.projectId;
97
+ (0, messages_1.printSection)('Session History');
98
+ (0, messages_1.printInfo)('Fetching sessions', projectId ? `Project: ${projectId}` : 'All projects');
99
+ const sessions = await client.getSessions(projectId, options.all ? 100 : 20);
100
+ if (sessions.length === 0) {
101
+ (0, messages_1.printInfo)('No Sessions Found', 'You haven\'t created any sessions yet.\n Start one with: neurcode plan "<your intent>"');
102
+ return;
103
+ }
104
+ // Group sessions by status
105
+ const activeSessions = sessions.filter(s => s.status === 'active');
106
+ const completedSessions = sessions.filter(s => s.status === 'completed');
107
+ const cancelledSessions = sessions.filter(s => s.status === 'cancelled');
108
+ if (activeSessions.length > 0) {
109
+ (0, messages_1.printSection)('Active Sessions');
110
+ const tableRows = [
111
+ ['Session ID', 'Title/Intent', 'Created', 'Files Changed']
112
+ ];
113
+ for (const session of activeSessions) {
114
+ const title = session.title || session.intentDescription || 'Untitled';
115
+ const shortId = session.sessionId.substring(0, 16) + '...';
116
+ const created = new Date(session.createdAt).toLocaleDateString();
117
+ tableRows.push([
118
+ shortId,
119
+ title.length > 40 ? title.substring(0, 40) + '...' : title,
120
+ created,
121
+ '—' // Files changed would need additional API call
122
+ ]);
123
+ }
124
+ (0, messages_1.printTable)(tableRows);
125
+ }
126
+ if (completedSessions.length > 0) {
127
+ (0, messages_1.printSection)('Completed Sessions');
128
+ console.log(chalk.dim(` ${completedSessions.length} completed session(s)`));
129
+ if (!options.all && completedSessions.length > 5) {
130
+ console.log(chalk.dim(' (Showing most recent. Use --all to see all)'));
131
+ }
132
+ console.log('');
133
+ }
134
+ if (cancelledSessions.length > 0) {
135
+ (0, messages_1.printSection)('Cancelled Sessions');
136
+ console.log(chalk.dim(` ${cancelledSessions.length} cancelled session(s)`));
137
+ console.log('');
138
+ }
139
+ (0, messages_1.printInfo)('Session Management', [
140
+ `Active: ${activeSessions.length} | Completed: ${completedSessions.length} | Cancelled: ${cancelledSessions.length}`,
141
+ 'End a session: neurcode session end [session-id]',
142
+ 'View session details: neurcode session status [session-id]'
143
+ ].join('\n • '));
144
+ }
145
+ catch (error) {
146
+ if (error instanceof Error) {
147
+ if (error.message.includes('401') || error.message.includes('403')) {
148
+ await (0, messages_1.printAuthError)(error);
149
+ }
150
+ else if (error.message.includes('project') || error.message.includes('404')) {
151
+ (0, messages_1.printProjectError)(error, options.projectId);
152
+ }
153
+ else {
154
+ (0, messages_1.printError)('Failed to List Sessions', error);
155
+ }
156
+ }
157
+ else {
158
+ (0, messages_1.printError)('Failed to List Sessions', String(error));
159
+ }
160
+ process.exit(1);
161
+ }
162
+ }
163
+ /**
164
+ * End a session
165
+ */
166
+ async function endSessionCommand(options) {
167
+ try {
168
+ const config = (0, config_1.loadConfig)();
169
+ if (!config.apiKey) {
170
+ config.apiKey = (0, config_1.requireApiKey)();
171
+ }
172
+ const client = new api_client_1.ApiClient(config);
173
+ let sessionId = options.sessionId;
174
+ // If no session ID provided, try to get from state
175
+ if (!sessionId) {
176
+ const stateSessionId = (0, state_1.getSessionId)();
177
+ sessionId = stateSessionId || undefined;
178
+ if (!sessionId) {
179
+ // List active sessions and let user choose
180
+ (0, messages_1.printInfo)('No Active Session', 'Looking for active sessions...');
181
+ const sessions = await client.getSessions(config.projectId, 10);
182
+ const activeSessions = sessions.filter(s => s.status === 'active');
183
+ if (activeSessions.length === 0) {
184
+ (0, messages_1.printInfo)('No Active Sessions', 'There are no active sessions to end.');
185
+ return;
186
+ }
187
+ if (activeSessions.length === 1) {
188
+ sessionId = activeSessions[0].sessionId;
189
+ const title = activeSessions[0].title || activeSessions[0].intentDescription || 'Untitled';
190
+ (0, messages_1.printInfo)('Found Active Session', `Ending: ${title}`);
191
+ }
192
+ else {
193
+ // Multiple active sessions - let user choose
194
+ (0, messages_1.printSection)('Multiple Active Sessions');
195
+ activeSessions.forEach((session, index) => {
196
+ const title = session.title || session.intentDescription || 'Untitled';
197
+ console.log(chalk.cyan(` ${index + 1}.`), chalk.white(title));
198
+ console.log(chalk.dim(` ${session.sessionId.substring(0, 20)}...`));
199
+ });
200
+ console.log('');
201
+ const answer = await promptUser(chalk.bold('Select session to end (1-' + activeSessions.length + '): '));
202
+ const choice = parseInt(answer, 10);
203
+ if (choice >= 1 && choice <= activeSessions.length) {
204
+ sessionId = activeSessions[choice - 1].sessionId;
205
+ }
206
+ else {
207
+ (0, messages_1.printError)('Invalid Selection', undefined, ['Please run the command again and select a valid number']);
208
+ process.exit(1);
209
+ }
210
+ }
211
+ }
212
+ }
213
+ if (!sessionId) {
214
+ (0, messages_1.printError)('No Session Specified', undefined, [
215
+ 'No session ID provided and no active session found',
216
+ 'Usage: neurcode session end [session-id]',
217
+ 'Or set a session: neurcode init'
218
+ ]);
219
+ process.exit(1);
220
+ }
221
+ // Get session details first
222
+ try {
223
+ const sessionData = await client.getSession(sessionId);
224
+ const session = sessionData.session;
225
+ if (session.status === 'completed') {
226
+ (0, messages_1.printWarning)('Session Already Completed', `Session "${session.title || session.intentDescription || sessionId}" is already ended.`);
227
+ return;
228
+ }
229
+ if (session.status === 'cancelled') {
230
+ (0, messages_1.printWarning)('Session Already Cancelled', `Session "${session.title || session.intentDescription || sessionId}" was already cancelled.`);
231
+ return;
232
+ }
233
+ // Show session summary
234
+ const title = session.title || session.intentDescription || 'Untitled Session';
235
+ const filesCount = sessionData.files?.length || 0;
236
+ (0, messages_1.printSection)('Session Summary');
237
+ console.log(chalk.white(` Title: ${title}`));
238
+ console.log(chalk.white(` Files Changed: ${filesCount}`));
239
+ console.log(chalk.dim(` Session ID: ${sessionId}`));
240
+ console.log('');
241
+ // Confirm before ending
242
+ const confirm = await promptUser(chalk.bold('End this session? (y/n): '));
243
+ if (confirm.toLowerCase() !== 'y' && confirm.toLowerCase() !== 'yes') {
244
+ (0, messages_1.printInfo)('Cancelled', 'Session was not ended.');
245
+ return;
246
+ }
247
+ await client.endSession(sessionId);
248
+ // Clear session ID from local state if it matches the ended session
249
+ try {
250
+ const currentSessionId = (0, state_1.getSessionId)();
251
+ if (currentSessionId === sessionId) {
252
+ const { clearSessionId } = await Promise.resolve().then(() => __importStar(require('../utils/state')));
253
+ clearSessionId();
254
+ }
255
+ }
256
+ catch {
257
+ // Non-critical - continue if state clearing fails
258
+ }
259
+ const firstName = await (0, messages_1.getUserFirstName)();
260
+ await (0, messages_1.printSuccessBanner)('Session Completed', `Great work, ${firstName}! Your session has been marked as complete.`);
261
+ (0, messages_1.printSuccess)('Session Ended Successfully', `"${title}" is now marked as completed.\n View in dashboard: dashboard.neurcode.com`);
262
+ // Display Session ROI Summary
263
+ try {
264
+ // Fetch ROI summary from API
265
+ const apiUrl = config.apiUrl || process.env.NEURCODE_API_URL || 'https://api.neurcode.ai';
266
+ const roiUrl = `${apiUrl}/api/v1/roi/summary?timeRange=7d`;
267
+ const roiResponse = await fetch(roiUrl, {
268
+ headers: {
269
+ 'Authorization': `Bearer ${config.apiKey}`,
270
+ 'Content-Type': 'application/json',
271
+ },
272
+ }).catch(() => null);
273
+ if (roiResponse && roiResponse.ok) {
274
+ const roiData = await roiResponse.json().catch(() => null);
275
+ if (roiData && roiData.totalCapitalSaved) {
276
+ const capitalSaved = typeof roiData.totalCapitalSaved === 'string'
277
+ ? parseFloat(roiData.totalCapitalSaved)
278
+ : roiData.totalCapitalSaved;
279
+ const formattedAmount = capitalSaved.toFixed(2);
280
+ const dashboardUrl = 'https://dashboard.neurcode.ai/roi';
281
+ console.log('');
282
+ console.log(chalk.cyan('📊'), chalk.bold.white('Current Session ROI:'), chalk.green.bold(`+$${formattedAmount}`));
283
+ console.log(chalk.dim(` View full report: ${dashboardUrl}`));
284
+ console.log('');
285
+ }
286
+ }
287
+ }
288
+ catch {
289
+ // Silently fail - ROI summary is a nice-to-have
290
+ }
291
+ }
292
+ catch (error) {
293
+ if (error.message?.includes('not found') || error.message?.includes('404')) {
294
+ (0, messages_1.printError)('Session Not Found', error, [
295
+ `Session "${sessionId}" could not be found`,
296
+ 'List your sessions: neurcode session list',
297
+ 'Verify the session ID is correct'
298
+ ]);
299
+ }
300
+ else {
301
+ throw error;
302
+ }
303
+ }
304
+ }
305
+ catch (error) {
306
+ if (error instanceof Error) {
307
+ if (error.message.includes('401') || error.message.includes('403')) {
308
+ await (0, messages_1.printAuthError)(error);
309
+ }
310
+ else {
311
+ (0, messages_1.printError)('Failed to End Session', error);
312
+ }
313
+ }
314
+ else {
315
+ (0, messages_1.printError)('Failed to End Session', String(error));
316
+ }
317
+ process.exit(1);
318
+ }
319
+ }
320
+ /**
321
+ * Show session status
322
+ */
323
+ async function sessionStatusCommand(options) {
324
+ try {
325
+ const config = (0, config_1.loadConfig)();
326
+ if (!config.apiKey) {
327
+ config.apiKey = (0, config_1.requireApiKey)();
328
+ }
329
+ const client = new api_client_1.ApiClient(config);
330
+ let sessionId = options.sessionId || (0, state_1.getSessionId)();
331
+ if (!sessionId) {
332
+ (0, messages_1.printError)('No Session Found', undefined, [
333
+ 'No active session in this directory',
334
+ 'Start a session: neurcode plan "<your intent>"',
335
+ 'Or specify a session: neurcode session status <session-id>'
336
+ ]);
337
+ process.exit(1);
338
+ }
339
+ const sessionData = await client.getSession(sessionId);
340
+ const session = sessionData.session;
341
+ await (0, messages_1.printSuccessBanner)('Session Status');
342
+ (0, messages_1.printSection)('Session Details');
343
+ console.log(chalk.white(` Title: ${session.title || session.intentDescription || 'Untitled'}`));
344
+ console.log(chalk.white(` Status: ${session.status === 'active' ? chalk.green('Active') : session.status === 'completed' ? chalk.dim('Completed') : chalk.yellow('Cancelled')}`));
345
+ console.log(chalk.white(` Created: ${new Date(session.createdAt).toLocaleString()}`));
346
+ if (session.endedAt) {
347
+ console.log(chalk.white(` Ended: ${new Date(session.endedAt).toLocaleString()}`));
348
+ }
349
+ console.log(chalk.white(` Files Changed: ${sessionData.files?.length || 0}`));
350
+ console.log(chalk.dim(` Session ID: ${sessionId}`));
351
+ console.log('');
352
+ if (session.status === 'active') {
353
+ (0, messages_1.printInfo)('Active Session', [
354
+ 'This session is currently active',
355
+ 'End it with: neurcode session end',
356
+ 'Or continue working and end it when done'
357
+ ].join('\n • '));
358
+ }
359
+ }
360
+ catch (error) {
361
+ if (error instanceof Error) {
362
+ if (error.message.includes('401') || error.message.includes('403')) {
363
+ await (0, messages_1.printAuthError)(error);
364
+ }
365
+ else if (error.message.includes('not found') || error.message.includes('404')) {
366
+ (0, messages_1.printError)('Session Not Found', error, [
367
+ `Session "${options.sessionId || 'unknown'}" could not be found`,
368
+ 'List your sessions: neurcode session list',
369
+ 'Start a new session: neurcode plan "<your intent>"'
370
+ ]);
371
+ }
372
+ else {
373
+ (0, messages_1.printError)('Failed to Get Session Status', error);
374
+ }
375
+ }
376
+ else {
377
+ (0, messages_1.printError)('Failed to Get Session Status', String(error));
378
+ }
379
+ process.exit(1);
380
+ }
381
+ }
382
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/commands/session.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/commands/verify.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA0BH,UAAU,aAAa;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AASD,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,iBAwezD"}
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/commands/verify.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkCH,UAAU,aAAa;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA4DD,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,iBAohBzD"}
@@ -12,10 +12,17 @@ const config_1 = require("../config");
12
12
  const api_client_1 = require("../api-client");
13
13
  const path_1 = require("path");
14
14
  const fs_1 = require("fs");
15
+ const state_1 = require("../utils/state");
16
+ const ROILogger_1 = require("../utils/ROILogger");
17
+ const box_1 = require("../utils/box");
15
18
  // Import chalk with fallback
16
19
  let chalk;
17
20
  try {
18
21
  chalk = require('chalk');
22
+ // Disable colors in CI environments for cleaner logs
23
+ if (process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true') {
24
+ chalk.level = 0;
25
+ }
19
26
  }
20
27
  catch {
21
28
  chalk = {
@@ -28,6 +35,50 @@ catch {
28
35
  white: (str) => str,
29
36
  };
30
37
  }
38
+ /**
39
+ * Check if a file path should be excluded from verification analysis
40
+ * Excludes internal/system files that should not count towards plan adherence
41
+ */
42
+ function isExcludedFile(filePath) {
43
+ // Normalize path separators (handle both / and \)
44
+ const normalizedPath = filePath.replace(/\\/g, '/');
45
+ // Check if path starts with any excluded prefix
46
+ const excludedPrefixes = [
47
+ '.neurcode/',
48
+ '.git/',
49
+ 'node_modules/',
50
+ ];
51
+ // Check prefixes
52
+ for (const prefix of excludedPrefixes) {
53
+ if (normalizedPath.startsWith(prefix)) {
54
+ return true;
55
+ }
56
+ }
57
+ // Check for .DS_Store file (macOS system file) - can appear at any directory level
58
+ if (normalizedPath === '.DS_Store' || normalizedPath.endsWith('/.DS_Store')) {
59
+ return true;
60
+ }
61
+ // Exclude common meta-configuration files (gitignore, npmignore, dockerignore, etc.)
62
+ // These are project configuration files and shouldn't be part of scope checking
63
+ const configFilePatterns = [
64
+ /^\.gitignore$/,
65
+ /\.gitignore$/,
66
+ /^\.npmignore$/,
67
+ /\.npmignore$/,
68
+ /^\.dockerignore$/,
69
+ /\.dockerignore$/,
70
+ /^\.prettierignore$/,
71
+ /\.prettierignore$/,
72
+ /^\.eslintignore$/,
73
+ /\.eslintignore$/,
74
+ ];
75
+ for (const pattern of configFilePatterns) {
76
+ if (pattern.test(normalizedPath)) {
77
+ return true;
78
+ }
79
+ }
80
+ return false;
81
+ }
31
82
  async function verifyCommand(options) {
32
83
  try {
33
84
  // Load configuration
@@ -116,7 +167,15 @@ async function verifyCommand(options) {
116
167
  process.exit(0);
117
168
  }
118
169
  // Parse the diff
119
- const diffFiles = (0, diff_parser_1.parseDiff)(diffText);
170
+ const allDiffFiles = (0, diff_parser_1.parseDiff)(diffText);
171
+ // Filter out internal/system files before analysis
172
+ // This prevents self-interference where the tool flags its own files as bloat
173
+ const diffFiles = allDiffFiles.filter(file => {
174
+ // Check both path and oldPath (for renames) against exclusion list
175
+ const excludePath = isExcludedFile(file.path);
176
+ const excludeOldPath = file.oldPath ? isExcludedFile(file.oldPath) : false;
177
+ return !excludePath && !excludeOldPath;
178
+ });
120
179
  const summary = (0, diff_parser_1.getDiffSummary)(diffFiles);
121
180
  if (diffFiles.length === 0) {
122
181
  if (!options.json) {
@@ -142,15 +201,35 @@ async function verifyCommand(options) {
142
201
  console.log(chalk.dim(` Found ${summary.totalFiles} file(s) changed`));
143
202
  console.log(chalk.dim(` ${summary.totalAdded} lines added, ${summary.totalRemoved} lines removed\n`));
144
203
  }
145
- // Get planId (from options, config, or fetch latest)
204
+ // Get planId: Priority 1: options flag, Priority 2: state file (.neurcode/config.json), Priority 3: legacy config
146
205
  let planId = options.planId;
147
206
  if (!planId) {
148
- // Try to get planId from config (neurcode.config.json may have lastPlanId)
149
- // Use the configData we already loaded above
150
- if (configData.lastPlanId && typeof configData.lastPlanId === 'string') {
151
- planId = configData.lastPlanId;
207
+ // Try to get planId from state file (.neurcode/config.json) - this is the canonical source
208
+ const activePlanId = (0, state_1.getActivePlanId)();
209
+ if (activePlanId) {
210
+ planId = activePlanId;
152
211
  if (!options.json) {
153
- console.log(chalk.dim(` Using plan from config: ${configData.lastPlanId.substring(0, 8)}...`));
212
+ console.log(chalk.dim(` Using active plan from state: ${activePlanId.substring(0, 8)}...`));
213
+ // Optional check: Warn if plan is older than 24 hours
214
+ const lastPlanGeneratedAt = (0, state_1.getLastPlanGeneratedAt)();
215
+ if (lastPlanGeneratedAt) {
216
+ const planAge = Date.now() - new Date(lastPlanGeneratedAt).getTime();
217
+ const hoursSinceGeneration = planAge / (1000 * 60 * 60);
218
+ if (hoursSinceGeneration > 24) {
219
+ console.log(chalk.yellow(` ⚠️ Warning: This plan was generated ${Math.round(hoursSinceGeneration)} hours ago`));
220
+ console.log(chalk.yellow(` You may be verifying against an old plan. Consider running 'neurcode plan' to generate a new one.`));
221
+ }
222
+ }
223
+ }
224
+ }
225
+ else {
226
+ // Fallback: Try legacy config file (neurcode.config.json) for backward compatibility
227
+ if (configData.lastPlanId && typeof configData.lastPlanId === 'string') {
228
+ planId = configData.lastPlanId;
229
+ if (!options.json) {
230
+ console.log(chalk.dim(` Using plan from legacy config: ${configData.lastPlanId.substring(0, 8)}...`));
231
+ console.log(chalk.yellow(` ⚠️ Consider running 'neurcode plan' to update state file`));
232
+ }
154
233
  }
155
234
  }
156
235
  }
@@ -197,10 +276,10 @@ async function verifyCommand(options) {
197
276
  const planFiles = planData.content.files
198
277
  .filter(f => f.action === 'CREATE' || f.action === 'MODIFY')
199
278
  .map(f => f.path);
200
- // Get sessionId from config (check both sessionId and lastSessionId)
201
- // Fallback to sessionId from plan if not in config
279
+ // Get sessionId from state file (.neurcode/state.json) first, then fallback to config
280
+ // Fallback to sessionId from plan if not in state/config
202
281
  // This is the session_id string needed to fetch the session
203
- let sessionIdString = configData.sessionId || configData.lastSessionId || null;
282
+ let sessionIdString = (0, state_1.getSessionId)() || configData.sessionId || configData.lastSessionId || null;
204
283
  // Fallback: Use sessionId from plan if not in config
205
284
  if (!sessionIdString && planData.sessionId) {
206
285
  sessionIdString = planData.sessionId;
@@ -327,6 +406,20 @@ async function verifyCommand(options) {
327
406
  let grade;
328
407
  if (verifyResult.verdict === 'PASS') {
329
408
  grade = 'A';
409
+ // Log ROI event for PASS verification (non-blocking)
410
+ try {
411
+ (0, ROILogger_1.logROIEvent)('VERIFY_PASS', {
412
+ planId: finalPlanId,
413
+ adherenceScore: verifyResult.adherenceScore,
414
+ plannedFilesModified: verifyResult.plannedFilesModified,
415
+ totalPlannedFiles: verifyResult.totalPlannedFiles,
416
+ }, projectId || null).catch(() => {
417
+ // Silently ignore - ROI logging should never block user workflows
418
+ });
419
+ }
420
+ catch {
421
+ // Silently ignore - ROI logging should never block user workflows
422
+ }
330
423
  }
331
424
  else if (verifyResult.verdict === 'WARN') {
332
425
  grade = verifyResult.adherenceScore >= 70 ? 'B' : verifyResult.adherenceScore >= 50 ? 'C' : 'D';
@@ -627,9 +720,7 @@ async function reportVerification(grade, violations, verifyResult, apiKey, apiUr
627
720
  * Display verification results in a formatted report card
628
721
  */
629
722
  function displayVerifyResults(result) {
630
- console.log(chalk.bold.cyan('📋 Plan Adherence Report\n'));
631
- console.log('━'.repeat(50));
632
- // Display grade/score
723
+ // Calculate grade/score
633
724
  let grade;
634
725
  let gradeColor;
635
726
  if (result.verdict === 'PASS') {
@@ -644,6 +735,29 @@ function displayVerifyResults(result) {
644
735
  grade = 'F';
645
736
  gradeColor = chalk.red;
646
737
  }
738
+ // Calculate estimated time saved (5 minutes per VERIFY_PASS)
739
+ const estimatedMinutesSaved = result.verdict === 'PASS' ? 5 : 0;
740
+ // Calculate policy compliance percentage
741
+ const policyCompliance = result.bloatCount === 0 ? 100 : Math.max(0, 100 - (result.bloatCount * 10));
742
+ // Display Governance Badge for PASS verdicts
743
+ if (result.verdict === 'PASS') {
744
+ console.log('\n');
745
+ const badgeContent = [
746
+ `${chalk.bold.white('Governance Badge')}`,
747
+ '',
748
+ `${chalk.cyan('Grade:')} ${chalk.green.bold(grade)} ${chalk.dim(`(${result.adherenceScore}%)`)}`,
749
+ `${chalk.cyan('Estimated Time Saved:')} ${chalk.green.bold(`${estimatedMinutesSaved}m`)}`,
750
+ `${chalk.cyan('Policy Compliance:')} ${chalk.green.bold(`${policyCompliance}%`)}`,
751
+ ].join('\n');
752
+ console.log((0, box_1.createBox)(badgeContent, {
753
+ borderColor: 'green',
754
+ titleColor: 'white',
755
+ padding: 2,
756
+ }));
757
+ console.log('');
758
+ }
759
+ console.log(chalk.bold.cyan('📋 Plan Adherence Report\n'));
760
+ console.log('━'.repeat(50));
647
761
  const scoreDisplay = gradeColor(`Grade: ${grade} (${result.adherenceScore}%)`);
648
762
  if (result.verdict === 'PASS') {
649
763
  console.log(chalk.green('✅'), scoreDisplay);