@neurcode-ai/cli 0.7.12 → 0.8.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 (70) hide show
  1. package/dist/api-client.d.ts +38 -18
  2. package/dist/api-client.d.ts.map +1 -1
  3. package/dist/api-client.js +226 -121
  4. package/dist/api-client.js.map +1 -1
  5. package/dist/commands/apply.d.ts.map +1 -1
  6. package/dist/commands/apply.js +127 -1
  7. package/dist/commands/apply.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.map +1 -1
  12. package/dist/commands/doctor.js +14 -11
  13. package/dist/commands/doctor.js.map +1 -1
  14. package/dist/commands/init.d.ts.map +1 -1
  15. package/dist/commands/init.js +95 -33
  16. package/dist/commands/init.js.map +1 -1
  17. package/dist/commands/login.d.ts.map +1 -1
  18. package/dist/commands/login.js +47 -57
  19. package/dist/commands/login.js.map +1 -1
  20. package/dist/commands/plan.d.ts +2 -0
  21. package/dist/commands/plan.d.ts.map +1 -1
  22. package/dist/commands/plan.js +245 -11
  23. package/dist/commands/plan.js.map +1 -1
  24. package/dist/commands/revert.d.ts.map +1 -1
  25. package/dist/commands/revert.js +82 -0
  26. package/dist/commands/revert.js.map +1 -1
  27. package/dist/commands/session.d.ts +29 -0
  28. package/dist/commands/session.d.ts.map +1 -0
  29. package/dist/commands/session.js +382 -0
  30. package/dist/commands/session.js.map +1 -0
  31. package/dist/commands/verify.d.ts.map +1 -1
  32. package/dist/commands/verify.js +177 -8
  33. package/dist/commands/verify.js.map +1 -1
  34. package/dist/commands/watch.d.ts.map +1 -1
  35. package/dist/commands/watch.js +20 -15
  36. package/dist/commands/watch.js.map +1 -1
  37. package/dist/index.js +78 -3
  38. package/dist/index.js.map +1 -1
  39. package/dist/services/integrations/TicketService.d.ts +68 -0
  40. package/dist/services/integrations/TicketService.d.ts.map +1 -0
  41. package/dist/services/integrations/TicketService.js +151 -0
  42. package/dist/services/integrations/TicketService.js.map +1 -0
  43. package/dist/services/security/SecurityGuard.d.ts +88 -0
  44. package/dist/services/security/SecurityGuard.d.ts.map +1 -0
  45. package/dist/services/security/SecurityGuard.js +576 -0
  46. package/dist/services/security/SecurityGuard.js.map +1 -0
  47. package/dist/services/watch/Syncer.d.ts.map +1 -1
  48. package/dist/services/watch/Syncer.js +22 -1
  49. package/dist/services/watch/Syncer.js.map +1 -1
  50. package/dist/utils/ROILogger.d.ts +16 -0
  51. package/dist/utils/ROILogger.d.ts.map +1 -0
  52. package/dist/utils/ROILogger.js +45 -0
  53. package/dist/utils/ROILogger.js.map +1 -0
  54. package/dist/utils/box.d.ts +16 -0
  55. package/dist/utils/box.d.ts.map +1 -0
  56. package/dist/utils/box.js +85 -0
  57. package/dist/utils/box.js.map +1 -0
  58. package/dist/utils/messages.d.ts +81 -0
  59. package/dist/utils/messages.d.ts.map +1 -0
  60. package/dist/utils/messages.js +306 -0
  61. package/dist/utils/messages.js.map +1 -0
  62. package/dist/utils/tier.d.ts +21 -0
  63. package/dist/utils/tier.d.ts.map +1 -0
  64. package/dist/utils/tier.js +150 -0
  65. package/dist/utils/tier.js.map +1 -0
  66. package/dist/utils/user-context.d.ts +28 -0
  67. package/dist/utils/user-context.d.ts.map +1 -0
  68. package/dist/utils/user-context.js +68 -0
  69. package/dist/utils/user-context.js.map +1 -0
  70. package/package.json +4 -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;AAgCH,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;AAuCD,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,iBAsgBzD"}
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,iBAilBzD"}
@@ -4,6 +4,39 @@
4
4
  *
5
5
  * Compares current work (git diff) against an Architect Plan to measure adherence and detect bloat.
6
6
  */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
7
40
  Object.defineProperty(exports, "__esModule", { value: true });
8
41
  exports.verifyCommand = verifyCommand;
9
42
  const child_process_1 = require("child_process");
@@ -13,6 +46,8 @@ const api_client_1 = require("../api-client");
13
46
  const path_1 = require("path");
14
47
  const fs_1 = require("fs");
15
48
  const state_1 = require("../utils/state");
49
+ const ROILogger_1 = require("../utils/ROILogger");
50
+ const box_1 = require("../utils/box");
16
51
  // Import chalk with fallback
17
52
  let chalk;
18
53
  try {
@@ -56,6 +91,25 @@ function isExcludedFile(filePath) {
56
91
  if (normalizedPath === '.DS_Store' || normalizedPath.endsWith('/.DS_Store')) {
57
92
  return true;
58
93
  }
94
+ // Exclude common meta-configuration files (gitignore, npmignore, dockerignore, etc.)
95
+ // These are project configuration files and shouldn't be part of scope checking
96
+ const configFilePatterns = [
97
+ /^\.gitignore$/,
98
+ /\.gitignore$/,
99
+ /^\.npmignore$/,
100
+ /\.npmignore$/,
101
+ /^\.dockerignore$/,
102
+ /\.dockerignore$/,
103
+ /^\.prettierignore$/,
104
+ /\.prettierignore$/,
105
+ /^\.eslintignore$/,
106
+ /\.eslintignore$/,
107
+ ];
108
+ for (const pattern of configFilePatterns) {
109
+ if (pattern.test(normalizedPath)) {
110
+ return true;
111
+ }
112
+ }
59
113
  return false;
60
114
  }
61
115
  async function verifyCommand(options) {
@@ -251,6 +305,8 @@ async function verifyCommand(options) {
251
305
  const modifiedFiles = diffFiles.map(f => f.path);
252
306
  // Step B: Fetch Plan and Session Data
253
307
  const planData = await client.getPlan(finalPlanId);
308
+ // Extract original intent from plan (for constraint checking)
309
+ const originalIntent = planData.intent || '';
254
310
  // Get approved files from plan (only files with action CREATE or MODIFY)
255
311
  const planFiles = planData.content.files
256
312
  .filter(f => f.action === 'CREATE' || f.action === 'MODIFY')
@@ -350,6 +406,37 @@ async function verifyCommand(options) {
350
406
  console.log('');
351
407
  }
352
408
  }
409
+ // Check user tier - Policy Compliance and A-F Grading are PRO features
410
+ const { getUserTier } = await Promise.resolve().then(() => __importStar(require('../utils/tier')));
411
+ const tier = await getUserTier();
412
+ if (tier === 'FREE') {
413
+ // FREE users get basic file-change summary only
414
+ if (!options.json) {
415
+ console.log(chalk.cyan('\n📊 File Change Summary\n'));
416
+ console.log('━'.repeat(50));
417
+ console.log(` Files changed: ${summary.totalFiles}`);
418
+ console.log(` Lines added: ${summary.totalAdded}`);
419
+ console.log(` Lines removed: ${summary.totalRemoved}`);
420
+ console.log('━'.repeat(50));
421
+ console.log(chalk.yellow('\n📊 Upgrade to PRO for Automated Policy Verification and A-F Grading.'));
422
+ console.log(chalk.dim(' Upgrade at: https://www.neurcode.com/dashboard/purchase-plan\n'));
423
+ }
424
+ else {
425
+ console.log(JSON.stringify({
426
+ grade: 'N/A',
427
+ adherenceScore: 0,
428
+ verdict: 'INFO',
429
+ bloatCount: 0,
430
+ bloatFiles: [],
431
+ plannedFilesModified: 0,
432
+ totalPlannedFiles: 0,
433
+ message: 'Basic file change summary (PRO required for policy verification)',
434
+ scopeGuardPassed: false,
435
+ tier: 'FREE',
436
+ }, null, 2));
437
+ }
438
+ process.exit(0);
439
+ }
353
440
  // Prepare diff stats and changed files for API
354
441
  const diffStats = {
355
442
  totalAdded: summary.totalAdded,
@@ -380,14 +467,55 @@ async function verifyCommand(options) {
380
467
  console.log(chalk.dim(' Sending to Neurcode API...\n'));
381
468
  }
382
469
  try {
383
- const verifyResult = await client.verifyPlan(finalPlanId, diffStats, changedFiles, projectId);
470
+ // Extract original intent from plan for constraint checking
471
+ let intentConstraints;
472
+ try {
473
+ const planData = await client.getPlan(finalPlanId);
474
+ intentConstraints = planData.intent || undefined;
475
+ }
476
+ catch {
477
+ // If we can't get plan, continue without constraints
478
+ }
479
+ // Call verifyPlan with intentConstraints
480
+ const verifyResult = await client.verifyPlan(finalPlanId, diffStats, changedFiles, projectId, intentConstraints);
384
481
  // Calculate grade from verdict and score
482
+ // CRITICAL: 0/0 planned files = 'F' (Incomplete), not 'B'
483
+ // Bloat automatically drops grade by at least one letter
385
484
  let grade;
386
- if (verifyResult.verdict === 'PASS') {
485
+ // Special case: If no planned files were modified and total planned files is 0, it's incomplete (F)
486
+ if (verifyResult.totalPlannedFiles === 0 && verifyResult.plannedFilesModified === 0) {
487
+ grade = 'F';
488
+ }
489
+ else if (verifyResult.verdict === 'PASS') {
387
490
  grade = 'A';
491
+ // Log ROI event for PASS verification (Grade A) - non-blocking
492
+ try {
493
+ (0, ROILogger_1.logROIEvent)('VERIFY_PASS', {
494
+ planId: finalPlanId,
495
+ adherenceScore: verifyResult.adherenceScore,
496
+ plannedFilesModified: verifyResult.plannedFilesModified,
497
+ totalPlannedFiles: verifyResult.totalPlannedFiles,
498
+ }, projectId || null).catch(() => {
499
+ // Silently ignore - ROI logging should never block user workflows
500
+ });
501
+ }
502
+ catch {
503
+ // Silently ignore - ROI logging should never block user workflows
504
+ }
388
505
  }
389
506
  else if (verifyResult.verdict === 'WARN') {
390
- grade = verifyResult.adherenceScore >= 70 ? 'B' : verifyResult.adherenceScore >= 50 ? 'C' : 'D';
507
+ // Base grade calculation
508
+ let baseGrade = verifyResult.adherenceScore >= 70 ? 'B' : verifyResult.adherenceScore >= 50 ? 'C' : 'D';
509
+ // Bloat drops grade by one letter (B -> C, C -> D, D -> F)
510
+ if (verifyResult.bloatCount > 0) {
511
+ if (baseGrade === 'B')
512
+ baseGrade = 'C';
513
+ else if (baseGrade === 'C')
514
+ baseGrade = 'D';
515
+ else if (baseGrade === 'D')
516
+ baseGrade = 'F';
517
+ }
518
+ grade = baseGrade;
391
519
  }
392
520
  else {
393
521
  grade = 'F';
@@ -685,23 +813,64 @@ async function reportVerification(grade, violations, verifyResult, apiKey, apiUr
685
813
  * Display verification results in a formatted report card
686
814
  */
687
815
  function displayVerifyResults(result) {
688
- console.log(chalk.bold.cyan('📋 Plan Adherence Report\n'));
689
- console.log(''.repeat(50));
690
- // Display grade/score
816
+ // Calculate grade/score
817
+ // CRITICAL: 0/0 planned files = 'F' (Incomplete)
818
+ // Bloat automatically drops grade by at least one letter
691
819
  let grade;
692
820
  let gradeColor;
693
- if (result.verdict === 'PASS') {
821
+ if (result.totalPlannedFiles === 0 && result.plannedFilesModified === 0) {
822
+ // Special case: No planned files = Incomplete (F)
823
+ grade = 'F';
824
+ gradeColor = chalk.red;
825
+ }
826
+ else if (result.verdict === 'PASS') {
694
827
  grade = 'A';
695
828
  gradeColor = chalk.green;
696
829
  }
697
830
  else if (result.verdict === 'WARN') {
698
- grade = result.adherenceScore >= 70 ? 'B' : result.adherenceScore >= 50 ? 'C' : 'D';
831
+ // Base grade calculation
832
+ let baseGrade = result.adherenceScore >= 70 ? 'B' : result.adherenceScore >= 50 ? 'C' : 'D';
833
+ // Bloat drops grade by one letter (B -> C, C -> D, D -> F)
834
+ if (result.bloatCount > 0) {
835
+ if (baseGrade === 'B')
836
+ baseGrade = 'C';
837
+ else if (baseGrade === 'C')
838
+ baseGrade = 'D';
839
+ else if (baseGrade === 'D')
840
+ baseGrade = 'F';
841
+ }
842
+ grade = baseGrade;
699
843
  gradeColor = chalk.yellow;
700
844
  }
701
845
  else {
702
846
  grade = 'F';
703
847
  gradeColor = chalk.red;
704
848
  }
849
+ // Calculate estimated time saved (5 minutes per VERIFY_PASS)
850
+ const estimatedMinutesSaved = result.verdict === 'PASS' ? 5 : 0;
851
+ // Calculate policy compliance percentage
852
+ const policyCompliance = result.bloatCount === 0 ? 100 : Math.max(0, 100 - (result.bloatCount * 10));
853
+ // Display Governance Badge for PASS and FAIL verdicts (high visibility)
854
+ if (result.verdict === 'PASS' || result.verdict === 'FAIL') {
855
+ console.log('\n');
856
+ const borderColor = result.verdict === 'PASS' ? 'green' : 'red';
857
+ const gradeColorFunc = result.verdict === 'PASS' ? chalk.green.bold : chalk.red.bold;
858
+ const badgeContent = [
859
+ `${chalk.bold.white('Governance Badge')}`,
860
+ '',
861
+ `${chalk.cyan('Grade:')} ${gradeColorFunc(grade)} ${chalk.dim(`(${result.adherenceScore}%)`)}`,
862
+ result.verdict === 'PASS' ? `${chalk.cyan('Estimated Time Saved:')} ${chalk.green.bold(`${estimatedMinutesSaved}m`)}` : '',
863
+ `${chalk.cyan('Policy Compliance:')} ${result.verdict === 'PASS' ? chalk.green.bold(`${policyCompliance}%`) : chalk.red.bold(`${policyCompliance}%`)}`,
864
+ ].filter(line => line !== '').join('\n');
865
+ console.log((0, box_1.createBox)(badgeContent, {
866
+ borderColor,
867
+ titleColor: 'white',
868
+ padding: 2,
869
+ }));
870
+ console.log('');
871
+ }
872
+ console.log(chalk.bold.cyan('📋 Plan Adherence Report\n'));
873
+ console.log('━'.repeat(50));
705
874
  const scoreDisplay = gradeColor(`Grade: ${grade} (${result.adherenceScore}%)`);
706
875
  if (result.verdict === 'PASS') {
707
876
  console.log(chalk.green('✅'), scoreDisplay);