arcvision 0.2.14 ā 0.2.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCVISION_DIRECTORY_STRUCTURE.md +104 -0
- package/CLI_STRUCTURE.md +110 -0
- package/CONFIGURATION.md +119 -0
- package/IMPLEMENTATION_SUMMARY.md +99 -0
- package/README.md +149 -89
- package/architecture.authority.ledger.json +46 -0
- package/arcvision-0.2.3.tgz +0 -0
- package/arcvision-0.2.4.tgz +0 -0
- package/arcvision-0.2.5.tgz +0 -0
- package/arcvision.context.diff.json +2181 -0
- package/arcvision.context.json +1021 -0
- package/arcvision.context.v1.json +2163 -0
- package/arcvision.context.v2.json +2173 -0
- package/arcvision_context/README.md +93 -0
- package/arcvision_context/architecture.authority.ledger.json +83 -0
- package/arcvision_context/arcvision.context.json +6884 -0
- package/debug-cycle-detection.js +56 -0
- package/dist/index.js +1626 -25
- package/docs/ENHANCED_ACCURACY_SAFETY_PROTOCOL.md +172 -0
- package/docs/accuracy-enhancement-artifacts/enhanced-validation-config.json +98 -0
- package/docs/acig-robustness-guide.md +164 -0
- package/docs/authoritative-gate-implementation.md +168 -0
- package/docs/cli-strengthening-summary.md +232 -0
- package/docs/invariant-system-summary.md +100 -0
- package/docs/invariant-system.md +112 -0
- package/generate_large_test.js +42 -0
- package/large_test_repo.json +1 -0
- package/output1.json +2163 -0
- package/output2.json +2163 -0
- package/package.json +46 -36
- package/scan_calcom_report.txt +0 -0
- package/scan_leafmint_report.txt +0 -0
- package/scan_output.txt +0 -0
- package/scan_trigger_report.txt +0 -0
- package/schema/arcvision_context_schema_v1.json +136 -1
- package/src/arcvision-guard.js +433 -0
- package/src/core/authority-core-detector.js +382 -0
- package/src/core/authority-ledger.js +300 -0
- package/src/core/blastRadius.js +299 -0
- package/src/core/call-resolver.js +196 -0
- package/src/core/change-evaluator.js +509 -0
- package/src/core/change-evaluator.js.backup +424 -0
- package/src/core/change-evaluator.ts +285 -0
- package/src/core/chunked-uploader.js +180 -0
- package/src/core/circular-dependency-detector.js +404 -0
- package/src/core/cli-error-handler.js +458 -0
- package/src/core/cli-validator.js +458 -0
- package/src/core/compression.js +64 -0
- package/src/core/context_builder.js +741 -0
- package/src/core/dependency-manager.js +134 -0
- package/src/core/di-detector.js +202 -0
- package/src/core/diff-analyzer.js +76 -0
- package/src/core/example-invariants.js +135 -0
- package/src/core/failure-mode-synthesizer.js +341 -0
- package/src/core/invariant-analyzer.js +294 -0
- package/src/core/invariant-detector.js +548 -0
- package/src/core/invariant-enforcer.js +171 -0
- package/src/core/invariant-evaluation-utils.js +172 -0
- package/src/core/invariant-hooks.js +152 -0
- package/src/core/invariant-integration-example.js +186 -0
- package/src/core/invariant-registry.js +298 -0
- package/src/core/invariant-registry.ts +100 -0
- package/src/core/invariant-types.js +66 -0
- package/src/core/invariants-index.js +88 -0
- package/src/core/method-tracker.js +170 -0
- package/src/core/override-handler.js +304 -0
- package/src/core/ownership-resolver.js +227 -0
- package/src/core/parser-enhanced.js +80 -0
- package/src/core/parser.js +610 -0
- package/src/core/path-resolver.js +240 -0
- package/src/core/pattern-matcher.js +246 -0
- package/src/core/progress-tracker.js +71 -0
- package/src/core/react-nextjs-detector.js +245 -0
- package/src/core/readme-generator.js +167 -0
- package/src/core/retry-handler.js +57 -0
- package/src/core/scanner.js +289 -0
- package/src/core/semantic-analyzer.js +204 -0
- package/src/core/structural-context-owner.js +442 -0
- package/src/core/symbol-indexer.js +164 -0
- package/src/core/tsconfig-utils.js +73 -0
- package/src/core/type-analyzer.js +272 -0
- package/src/core/watcher.js +18 -0
- package/src/core/workspace-scanner.js +88 -0
- package/src/engine/context_builder.js +280 -0
- package/src/engine/context_sorter.js +59 -0
- package/src/engine/context_validator.js +200 -0
- package/src/engine/id-generator.js +16 -0
- package/src/engine/pass1_facts.js +260 -0
- package/src/engine/pass2_semantics.js +333 -0
- package/src/engine/pass3_lifter.js +99 -0
- package/src/engine/pass4_signals.js +201 -0
- package/src/index.js +830 -0
- package/src/plugins/express-plugin.js +48 -0
- package/src/plugins/plugin-manager.js +58 -0
- package/src/plugins/react-plugin.js +54 -0
- package/temp_original.js +0 -0
- package/test/determinism-test.js +83 -0
- package/test-authoritative-context.js +53 -0
- package/test-real-authoritative-context.js +118 -0
- package/test-upload-enhancements.js +111 -0
- package/test_repos/allowed-clean-architecture/.arcvision/invariants.json +57 -0
- package/test_repos/allowed-clean-architecture/adapters/controllers/UserController.js +95 -0
- package/test_repos/allowed-clean-architecture/adapters/http/HttpServer.js +78 -0
- package/test_repos/allowed-clean-architecture/application/dtos/CreateUserRequest.js +37 -0
- package/test_repos/allowed-clean-architecture/application/services/UserService.js +61 -0
- package/test_repos/allowed-clean-architecture/arcvision_context/README.md +93 -0
- package/test_repos/allowed-clean-architecture/arcvision_context/arcvision.context.json +2796 -0
- package/test_repos/allowed-clean-architecture/domain/interfaces/UserRepository.js +25 -0
- package/test_repos/allowed-clean-architecture/domain/models/User.js +39 -0
- package/test_repos/allowed-clean-architecture/index.js +45 -0
- package/test_repos/allowed-clean-architecture/infrastructure/database/DatabaseConnection.js +56 -0
- package/test_repos/allowed-clean-architecture/infrastructure/repositories/InMemoryUserRepository.js +61 -0
- package/test_repos/allowed-clean-architecture/package.json +15 -0
- package/test_repos/blocked-legacy-monolith/.arcvision/invariants.json +78 -0
- package/test_repos/blocked-legacy-monolith/arcvision_context/README.md +93 -0
- package/test_repos/blocked-legacy-monolith/arcvision_context/arcvision.context.json +2882 -0
- package/test_repos/blocked-legacy-monolith/database/dbConnection.js +35 -0
- package/test_repos/blocked-legacy-monolith/index.js +38 -0
- package/test_repos/blocked-legacy-monolith/modules/emailService.js +31 -0
- package/test_repos/blocked-legacy-monolith/modules/paymentProcessor.js +37 -0
- package/test_repos/blocked-legacy-monolith/package.json +15 -0
- package/test_repos/blocked-legacy-monolith/shared/utils.js +19 -0
- package/test_repos/blocked-legacy-monolith/utils/helpers.js +23 -0
- package/test_repos/risky-microservices-concerns/.arcvision/invariants.json +69 -0
- package/test_repos/risky-microservices-concerns/arcvision_context/README.md +93 -0
- package/test_repos/risky-microservices-concerns/arcvision_context/arcvision.context.json +3070 -0
- package/test_repos/risky-microservices-concerns/common/utils.js +77 -0
- package/test_repos/risky-microservices-concerns/gateways/apiGateway.js +84 -0
- package/test_repos/risky-microservices-concerns/index.js +20 -0
- package/test_repos/risky-microservices-concerns/libs/deprecatedHelper.js +36 -0
- package/test_repos/risky-microservices-concerns/package.json +15 -0
- package/test_repos/risky-microservices-concerns/services/orderService.js +42 -0
- package/test_repos/risky-microservices-concerns/services/userService.js +48 -0
- package/verify_engine.js +116 -0
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Error Handler - Comprehensive error management for ArcVision CLI
|
|
3
|
+
* Provides authoritative error reporting and recovery mechanisms
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const chalk = require('chalk');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
class CLIErrorHandler {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.errorCategories = {
|
|
13
|
+
FILE_SYSTEM: 'FILE_SYSTEM',
|
|
14
|
+
NETWORK: 'NETWORK',
|
|
15
|
+
VALIDATION: 'VALIDATION',
|
|
16
|
+
PARSING: 'PARSING',
|
|
17
|
+
CONFIGURATION: 'CONFIGURATION',
|
|
18
|
+
PERMISSION: 'PERMISSION',
|
|
19
|
+
TIMEOUT: 'TIMEOUT',
|
|
20
|
+
UNKNOWN: 'UNKNOWN'
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
this.recoveryStrategies = {
|
|
24
|
+
RETRY: 'RETRY',
|
|
25
|
+
FALLBACK: 'FALLBACK',
|
|
26
|
+
SKIP: 'SKIP',
|
|
27
|
+
ABORT: 'ABORT',
|
|
28
|
+
MANUAL_INTERVENTION: 'MANUAL_INTERVENTION'
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Categorize and handle errors based on type
|
|
34
|
+
*/
|
|
35
|
+
handleError(error, context = {}) {
|
|
36
|
+
const categorizedError = this.categorizeError(error);
|
|
37
|
+
|
|
38
|
+
// Log the error with context
|
|
39
|
+
this.logError(categorizedError, context);
|
|
40
|
+
|
|
41
|
+
// Apply recovery strategy
|
|
42
|
+
const recoveryResult = this.applyRecoveryStrategy(categorizedError, context);
|
|
43
|
+
|
|
44
|
+
// Format user-friendly message
|
|
45
|
+
const userMessage = this.formatUserMessage(categorizedError, recoveryResult);
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
...categorizedError,
|
|
49
|
+
recovery: recoveryResult,
|
|
50
|
+
userMessage
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Categorize error based on its properties and message
|
|
56
|
+
*/
|
|
57
|
+
categorizeError(error) {
|
|
58
|
+
const errorInfo = {
|
|
59
|
+
original: error,
|
|
60
|
+
message: error.message || 'Unknown error',
|
|
61
|
+
code: error.code || null,
|
|
62
|
+
type: error.constructor.name,
|
|
63
|
+
stack: error.stack || null
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// File system errors
|
|
67
|
+
if (error.code && ['ENOENT', 'EACCES', 'EPERM', 'EISDIR', 'ENOTDIR'].includes(error.code)) {
|
|
68
|
+
errorInfo.category = this.errorCategories.FILE_SYSTEM;
|
|
69
|
+
errorInfo.subtype = this.getFileSubtype(error.code);
|
|
70
|
+
}
|
|
71
|
+
// Network errors
|
|
72
|
+
else if (error.code && ['ENOTFOUND', 'ECONNREFUSED', 'ECONNRESET', 'ETIMEDOUT'].includes(error.code)) {
|
|
73
|
+
errorInfo.category = this.errorCategories.NETWORK;
|
|
74
|
+
errorInfo.subtype = this.getNetworkSubtype(error.code);
|
|
75
|
+
}
|
|
76
|
+
// Validation errors
|
|
77
|
+
else if (error.message && (
|
|
78
|
+
error.message.includes('validation') ||
|
|
79
|
+
error.message.includes('schema') ||
|
|
80
|
+
error.message.includes('invalid')
|
|
81
|
+
)) {
|
|
82
|
+
errorInfo.category = this.errorCategories.VALIDATION;
|
|
83
|
+
}
|
|
84
|
+
// Parsing errors
|
|
85
|
+
else if (error.message && (
|
|
86
|
+
error.message.includes('parse') ||
|
|
87
|
+
error.message.includes('syntax') ||
|
|
88
|
+
error.message.includes('JSON')
|
|
89
|
+
)) {
|
|
90
|
+
errorInfo.category = this.errorCategories.PARSING;
|
|
91
|
+
}
|
|
92
|
+
// Permission errors
|
|
93
|
+
else if (error.message && error.message.includes('permission')) {
|
|
94
|
+
errorInfo.category = this.errorCategories.PERMISSION;
|
|
95
|
+
}
|
|
96
|
+
// Timeout errors
|
|
97
|
+
else if (error.name === 'AbortError' || error.message.includes('timeout')) {
|
|
98
|
+
errorInfo.category = this.errorCategories.TIMEOUT;
|
|
99
|
+
}
|
|
100
|
+
// Configuration errors
|
|
101
|
+
else if (error.message && (
|
|
102
|
+
error.message.includes('config') ||
|
|
103
|
+
error.message.includes('token') ||
|
|
104
|
+
error.message.includes('missing')
|
|
105
|
+
)) {
|
|
106
|
+
errorInfo.category = this.errorCategories.CONFIGURATION;
|
|
107
|
+
}
|
|
108
|
+
// Unknown errors
|
|
109
|
+
else {
|
|
110
|
+
errorInfo.category = this.errorCategories.UNKNOWN;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return errorInfo;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
getFileSubtype(errorCode) {
|
|
117
|
+
const subtypeMap = {
|
|
118
|
+
'ENOENT': 'FILE_NOT_FOUND',
|
|
119
|
+
'EACCES': 'ACCESS_DENIED',
|
|
120
|
+
'EPERM': 'PERMISSION_DENIED',
|
|
121
|
+
'EISDIR': 'IS_DIRECTORY',
|
|
122
|
+
'ENOTDIR': 'NOT_DIRECTORY'
|
|
123
|
+
};
|
|
124
|
+
return subtypeMap[errorCode] || 'FILE_SYSTEM_ERROR';
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
getNetworkSubtype(errorCode) {
|
|
128
|
+
const subtypeMap = {
|
|
129
|
+
'ENOTFOUND': 'HOST_NOT_FOUND',
|
|
130
|
+
'ECONNREFUSED': 'CONNECTION_REFUSED',
|
|
131
|
+
'ECONNRESET': 'CONNECTION_RESET',
|
|
132
|
+
'ETIMEDOUT': 'TIMEOUT'
|
|
133
|
+
};
|
|
134
|
+
return subtypeMap[errorCode] || 'NETWORK_ERROR';
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Log error with detailed context
|
|
139
|
+
*/
|
|
140
|
+
logError(errorInfo, context) {
|
|
141
|
+
const timestamp = new Date().toISOString();
|
|
142
|
+
const logEntry = {
|
|
143
|
+
timestamp,
|
|
144
|
+
error: {
|
|
145
|
+
category: errorInfo.category,
|
|
146
|
+
subtype: errorInfo.subtype,
|
|
147
|
+
message: errorInfo.message,
|
|
148
|
+
code: errorInfo.code,
|
|
149
|
+
type: errorInfo.type
|
|
150
|
+
},
|
|
151
|
+
context: {
|
|
152
|
+
operation: context.operation,
|
|
153
|
+
directory: context.directory,
|
|
154
|
+
file: context.file,
|
|
155
|
+
...context.additional
|
|
156
|
+
},
|
|
157
|
+
stack: errorInfo.stack
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// Write to error log file
|
|
161
|
+
try {
|
|
162
|
+
const logDir = path.join(process.cwd(), '.arcvision', 'logs');
|
|
163
|
+
if (!fs.existsSync(logDir)) {
|
|
164
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const logFile = path.join(logDir, 'errors.log');
|
|
168
|
+
const logLine = JSON.stringify(logEntry) + '\n';
|
|
169
|
+
fs.appendFileSync(logFile, logLine);
|
|
170
|
+
} catch (logError) {
|
|
171
|
+
// Silently fail if we can't write logs
|
|
172
|
+
console.warn('Could not write error log:', logError.message);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Apply appropriate recovery strategy based on error type
|
|
178
|
+
*/
|
|
179
|
+
applyRecoveryStrategy(errorInfo, context) {
|
|
180
|
+
const strategy = this.determineRecoveryStrategy(errorInfo, context);
|
|
181
|
+
|
|
182
|
+
switch (strategy) {
|
|
183
|
+
case this.recoveryStrategies.RETRY:
|
|
184
|
+
return this.handleRetry(errorInfo, context);
|
|
185
|
+
|
|
186
|
+
case this.recoveryStrategies.FALLBACK:
|
|
187
|
+
return this.handleFallback(errorInfo, context);
|
|
188
|
+
|
|
189
|
+
case this.recoveryStrategies.SKIP:
|
|
190
|
+
return this.handleSkip(errorInfo, context);
|
|
191
|
+
|
|
192
|
+
case this.recoveryStrategies.MANUAL_INTERVENTION:
|
|
193
|
+
return this.handleManualIntervention(errorInfo, context);
|
|
194
|
+
|
|
195
|
+
case this.recoveryStrategies.ABORT:
|
|
196
|
+
default:
|
|
197
|
+
return { strategy: 'ABORT', canContinue: false };
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Determine the best recovery strategy for an error
|
|
203
|
+
*/
|
|
204
|
+
determineRecoveryStrategy(errorInfo, context) {
|
|
205
|
+
// Network errors - retry with exponential backoff
|
|
206
|
+
if (errorInfo.category === this.errorCategories.NETWORK) {
|
|
207
|
+
if (context.retryCount && context.retryCount < 3) {
|
|
208
|
+
return this.recoveryStrategies.RETRY;
|
|
209
|
+
}
|
|
210
|
+
return this.recoveryStrategies.FALLBACK;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// File not found - abort if critical, skip if optional
|
|
214
|
+
if (errorInfo.subtype === 'FILE_NOT_FOUND') {
|
|
215
|
+
if (context.isCritical) {
|
|
216
|
+
return this.recoveryStrategies.ABORT;
|
|
217
|
+
}
|
|
218
|
+
return this.recoveryStrategies.SKIP;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Permission errors - manual intervention required
|
|
222
|
+
if (errorInfo.category === this.errorCategories.PERMISSION) {
|
|
223
|
+
return this.recoveryStrategies.MANUAL_INTERVENTION;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Parsing errors - skip problematic files
|
|
227
|
+
if (errorInfo.category === this.errorCategories.PARSING) {
|
|
228
|
+
return this.recoveryStrategies.SKIP;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Validation errors - depends on severity
|
|
232
|
+
if (errorInfo.category === this.errorCategories.VALIDATION) {
|
|
233
|
+
if (context.allowInvalid) {
|
|
234
|
+
return this.recoveryStrategies.FALLBACK;
|
|
235
|
+
}
|
|
236
|
+
return this.recoveryStrategies.ABORT;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Timeout errors - retry once
|
|
240
|
+
if (errorInfo.category === this.errorCategories.TIMEOUT) {
|
|
241
|
+
if (context.retryCount && context.retryCount < 1) {
|
|
242
|
+
return this.recoveryStrategies.RETRY;
|
|
243
|
+
}
|
|
244
|
+
return this.recoveryStrategies.ABORT;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Default - abort for unknown errors
|
|
248
|
+
return this.recoveryStrategies.ABORT;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Handle retry strategy
|
|
253
|
+
*/
|
|
254
|
+
handleRetry(errorInfo, context) {
|
|
255
|
+
const retryCount = (context.retryCount || 0) + 1;
|
|
256
|
+
const delay = Math.min(1000 * Math.pow(2, retryCount), 10000); // Max 10s
|
|
257
|
+
|
|
258
|
+
return {
|
|
259
|
+
strategy: 'RETRY',
|
|
260
|
+
canContinue: true,
|
|
261
|
+
retryCount,
|
|
262
|
+
delay,
|
|
263
|
+
message: `Retrying in ${delay}ms... (attempt ${retryCount})`
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Handle fallback strategy
|
|
269
|
+
*/
|
|
270
|
+
handleFallback(errorInfo, context) {
|
|
271
|
+
return {
|
|
272
|
+
strategy: 'FALLBACK',
|
|
273
|
+
canContinue: true,
|
|
274
|
+
message: 'Using fallback mechanism to continue operation'
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Handle skip strategy
|
|
280
|
+
*/
|
|
281
|
+
handleSkip(errorInfo, context) {
|
|
282
|
+
return {
|
|
283
|
+
strategy: 'SKIP',
|
|
284
|
+
canContinue: true,
|
|
285
|
+
message: `Skipping ${context.file || 'resource'} due to error`
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Handle manual intervention strategy
|
|
291
|
+
*/
|
|
292
|
+
handleManualIntervention(errorInfo, context) {
|
|
293
|
+
return {
|
|
294
|
+
strategy: 'MANUAL_INTERVENTION',
|
|
295
|
+
canContinue: false,
|
|
296
|
+
message: 'Manual intervention required - operation cannot continue automatically'
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Format user-friendly error message
|
|
302
|
+
*/
|
|
303
|
+
formatUserMessage(errorInfo, recoveryResult) {
|
|
304
|
+
let message = '';
|
|
305
|
+
|
|
306
|
+
// Error category header
|
|
307
|
+
switch (errorInfo.category) {
|
|
308
|
+
case this.errorCategories.FILE_SYSTEM:
|
|
309
|
+
message += chalk.red('š File System Error: ');
|
|
310
|
+
break;
|
|
311
|
+
case this.errorCategories.NETWORK:
|
|
312
|
+
message += chalk.red('š Network Error: ');
|
|
313
|
+
break;
|
|
314
|
+
case this.errorCategories.VALIDATION:
|
|
315
|
+
message += chalk.red('ā Validation Error: ');
|
|
316
|
+
break;
|
|
317
|
+
case this.errorCategories.PARSING:
|
|
318
|
+
message += chalk.red('š Parsing Error: ');
|
|
319
|
+
break;
|
|
320
|
+
case this.errorCategories.PERMISSION:
|
|
321
|
+
message += chalk.red('š Permission Error: ');
|
|
322
|
+
break;
|
|
323
|
+
case this.errorCategories.TIMEOUT:
|
|
324
|
+
message += chalk.red('ā° Timeout Error: ');
|
|
325
|
+
break;
|
|
326
|
+
case this.errorCategories.CONFIGURATION:
|
|
327
|
+
message += chalk.red('āļø Configuration Error: ');
|
|
328
|
+
break;
|
|
329
|
+
default:
|
|
330
|
+
message += chalk.red('š„ Unknown Error: ');
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Specific error message
|
|
334
|
+
message += errorInfo.message + '\n';
|
|
335
|
+
|
|
336
|
+
// Recovery information
|
|
337
|
+
if (recoveryResult.canContinue) {
|
|
338
|
+
message += chalk.yellow(`š Recovery: ${recoveryResult.message}\n`);
|
|
339
|
+
} else {
|
|
340
|
+
message += chalk.red(`š Cannot continue: ${recoveryResult.message}\n`);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Helpful suggestions
|
|
344
|
+
message += this.getSuggestions(errorInfo);
|
|
345
|
+
|
|
346
|
+
return message;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Get helpful suggestions based on error type
|
|
351
|
+
*/
|
|
352
|
+
getSuggestions(errorInfo) {
|
|
353
|
+
const suggestions = [];
|
|
354
|
+
|
|
355
|
+
switch (errorInfo.category) {
|
|
356
|
+
case this.errorCategories.FILE_SYSTEM:
|
|
357
|
+
if (errorInfo.subtype === 'FILE_NOT_FOUND') {
|
|
358
|
+
suggestions.push('⢠Check if the file path is correct');
|
|
359
|
+
suggestions.push('⢠Verify the file exists in the specified location');
|
|
360
|
+
} else if (errorInfo.subtype === 'ACCESS_DENIED') {
|
|
361
|
+
suggestions.push('⢠Check file permissions');
|
|
362
|
+
suggestions.push('⢠Ensure you have read/write access to the file/directory');
|
|
363
|
+
}
|
|
364
|
+
break;
|
|
365
|
+
|
|
366
|
+
case this.errorCategories.NETWORK:
|
|
367
|
+
suggestions.push('⢠Check your internet connection');
|
|
368
|
+
suggestions.push('⢠Verify the API endpoint is accessible');
|
|
369
|
+
suggestions.push('⢠Try again in a few minutes');
|
|
370
|
+
break;
|
|
371
|
+
|
|
372
|
+
case this.errorCategories.VALIDATION:
|
|
373
|
+
suggestions.push('⢠Check the structure of your configuration files');
|
|
374
|
+
suggestions.push('⢠Ensure JSON files are properly formatted');
|
|
375
|
+
suggestions.push('⢠Refer to documentation for correct schema');
|
|
376
|
+
break;
|
|
377
|
+
|
|
378
|
+
case this.errorCategories.PARSING:
|
|
379
|
+
suggestions.push('⢠Check for syntax errors in the file');
|
|
380
|
+
suggestions.push('⢠Verify the file encoding is UTF-8');
|
|
381
|
+
suggestions.push('⢠Ensure the file contains valid content for its type');
|
|
382
|
+
break;
|
|
383
|
+
|
|
384
|
+
case this.errorCategories.PERMISSION:
|
|
385
|
+
suggestions.push('⢠Run the command with appropriate permissions');
|
|
386
|
+
suggestions.push('⢠Check if the file/directory is locked by another process');
|
|
387
|
+
suggestions.push('⢠Verify your user account has necessary access rights');
|
|
388
|
+
break;
|
|
389
|
+
|
|
390
|
+
case this.errorCategories.TIMEOUT:
|
|
391
|
+
suggestions.push('⢠Check network connectivity');
|
|
392
|
+
suggestions.push('⢠Try with a smaller dataset');
|
|
393
|
+
suggestions.push('⢠Increase timeout settings if available');
|
|
394
|
+
break;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return suggestions.length > 0
|
|
398
|
+
? chalk.dim('\nš” Suggestions:\n' + suggestions.map(s => ` ${s}`).join('\n') + '\n')
|
|
399
|
+
: '';
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Display error to user with appropriate formatting
|
|
404
|
+
*/
|
|
405
|
+
displayError(errorInfo) {
|
|
406
|
+
console.error('\n' + '='.repeat(60));
|
|
407
|
+
console.error(chalk.bold.red('ARCVISION CLI ERROR REPORT'));
|
|
408
|
+
console.error('='.repeat(60));
|
|
409
|
+
console.error('');
|
|
410
|
+
console.error(errorInfo.userMessage);
|
|
411
|
+
|
|
412
|
+
// Show stack trace for debugging in verbose mode
|
|
413
|
+
if (process.env.DEBUG || process.argv.includes('--debug')) {
|
|
414
|
+
console.error(chalk.dim('\nš§ Debug Information:'));
|
|
415
|
+
console.error(chalk.dim(`Category: ${errorInfo.category}`));
|
|
416
|
+
console.error(chalk.dim(`Type: ${errorInfo.type}`));
|
|
417
|
+
console.error(chalk.dim(`Code: ${errorInfo.code || 'N/A'}`));
|
|
418
|
+
if (errorInfo.stack) {
|
|
419
|
+
console.error(chalk.dim(`Stack:\n${errorInfo.stack}`));
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
console.error('='.repeat(60) + '\n');
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Handle fatal errors that should terminate the process
|
|
428
|
+
*/
|
|
429
|
+
handleFatalError(error, context = {}) {
|
|
430
|
+
const errorInfo = this.handleError(error, context);
|
|
431
|
+
this.displayError(errorInfo);
|
|
432
|
+
|
|
433
|
+
// Log additional fatal error information
|
|
434
|
+
console.error(chalk.red.bold('š FATAL ERROR - Terminating process'));
|
|
435
|
+
|
|
436
|
+
process.exit(1);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Handle recoverable errors that allow continuation
|
|
441
|
+
*/
|
|
442
|
+
handleRecoverableError(error, context = {}) {
|
|
443
|
+
const errorInfo = this.handleError(error, context);
|
|
444
|
+
|
|
445
|
+
if (errorInfo.recovery.canContinue) {
|
|
446
|
+
console.warn('\n' + chalk.yellow('ā ļø Recoverable Error:'));
|
|
447
|
+
console.warn(errorInfo.userMessage);
|
|
448
|
+
return true; // Can continue
|
|
449
|
+
} else {
|
|
450
|
+
this.displayError(errorInfo);
|
|
451
|
+
return false; // Cannot continue
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Export singleton instance
|
|
457
|
+
const cliErrorHandler = new CLIErrorHandler();
|
|
458
|
+
module.exports = { CLIErrorHandler, cliErrorHandler };
|