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.
Files changed (134) hide show
  1. package/ARCVISION_DIRECTORY_STRUCTURE.md +104 -0
  2. package/CLI_STRUCTURE.md +110 -0
  3. package/CONFIGURATION.md +119 -0
  4. package/IMPLEMENTATION_SUMMARY.md +99 -0
  5. package/README.md +149 -89
  6. package/architecture.authority.ledger.json +46 -0
  7. package/arcvision-0.2.3.tgz +0 -0
  8. package/arcvision-0.2.4.tgz +0 -0
  9. package/arcvision-0.2.5.tgz +0 -0
  10. package/arcvision.context.diff.json +2181 -0
  11. package/arcvision.context.json +1021 -0
  12. package/arcvision.context.v1.json +2163 -0
  13. package/arcvision.context.v2.json +2173 -0
  14. package/arcvision_context/README.md +93 -0
  15. package/arcvision_context/architecture.authority.ledger.json +83 -0
  16. package/arcvision_context/arcvision.context.json +6884 -0
  17. package/debug-cycle-detection.js +56 -0
  18. package/dist/index.js +1626 -25
  19. package/docs/ENHANCED_ACCURACY_SAFETY_PROTOCOL.md +172 -0
  20. package/docs/accuracy-enhancement-artifacts/enhanced-validation-config.json +98 -0
  21. package/docs/acig-robustness-guide.md +164 -0
  22. package/docs/authoritative-gate-implementation.md +168 -0
  23. package/docs/cli-strengthening-summary.md +232 -0
  24. package/docs/invariant-system-summary.md +100 -0
  25. package/docs/invariant-system.md +112 -0
  26. package/generate_large_test.js +42 -0
  27. package/large_test_repo.json +1 -0
  28. package/output1.json +2163 -0
  29. package/output2.json +2163 -0
  30. package/package.json +46 -36
  31. package/scan_calcom_report.txt +0 -0
  32. package/scan_leafmint_report.txt +0 -0
  33. package/scan_output.txt +0 -0
  34. package/scan_trigger_report.txt +0 -0
  35. package/schema/arcvision_context_schema_v1.json +136 -1
  36. package/src/arcvision-guard.js +433 -0
  37. package/src/core/authority-core-detector.js +382 -0
  38. package/src/core/authority-ledger.js +300 -0
  39. package/src/core/blastRadius.js +299 -0
  40. package/src/core/call-resolver.js +196 -0
  41. package/src/core/change-evaluator.js +509 -0
  42. package/src/core/change-evaluator.js.backup +424 -0
  43. package/src/core/change-evaluator.ts +285 -0
  44. package/src/core/chunked-uploader.js +180 -0
  45. package/src/core/circular-dependency-detector.js +404 -0
  46. package/src/core/cli-error-handler.js +458 -0
  47. package/src/core/cli-validator.js +458 -0
  48. package/src/core/compression.js +64 -0
  49. package/src/core/context_builder.js +741 -0
  50. package/src/core/dependency-manager.js +134 -0
  51. package/src/core/di-detector.js +202 -0
  52. package/src/core/diff-analyzer.js +76 -0
  53. package/src/core/example-invariants.js +135 -0
  54. package/src/core/failure-mode-synthesizer.js +341 -0
  55. package/src/core/invariant-analyzer.js +294 -0
  56. package/src/core/invariant-detector.js +548 -0
  57. package/src/core/invariant-enforcer.js +171 -0
  58. package/src/core/invariant-evaluation-utils.js +172 -0
  59. package/src/core/invariant-hooks.js +152 -0
  60. package/src/core/invariant-integration-example.js +186 -0
  61. package/src/core/invariant-registry.js +298 -0
  62. package/src/core/invariant-registry.ts +100 -0
  63. package/src/core/invariant-types.js +66 -0
  64. package/src/core/invariants-index.js +88 -0
  65. package/src/core/method-tracker.js +170 -0
  66. package/src/core/override-handler.js +304 -0
  67. package/src/core/ownership-resolver.js +227 -0
  68. package/src/core/parser-enhanced.js +80 -0
  69. package/src/core/parser.js +610 -0
  70. package/src/core/path-resolver.js +240 -0
  71. package/src/core/pattern-matcher.js +246 -0
  72. package/src/core/progress-tracker.js +71 -0
  73. package/src/core/react-nextjs-detector.js +245 -0
  74. package/src/core/readme-generator.js +167 -0
  75. package/src/core/retry-handler.js +57 -0
  76. package/src/core/scanner.js +289 -0
  77. package/src/core/semantic-analyzer.js +204 -0
  78. package/src/core/structural-context-owner.js +442 -0
  79. package/src/core/symbol-indexer.js +164 -0
  80. package/src/core/tsconfig-utils.js +73 -0
  81. package/src/core/type-analyzer.js +272 -0
  82. package/src/core/watcher.js +18 -0
  83. package/src/core/workspace-scanner.js +88 -0
  84. package/src/engine/context_builder.js +280 -0
  85. package/src/engine/context_sorter.js +59 -0
  86. package/src/engine/context_validator.js +200 -0
  87. package/src/engine/id-generator.js +16 -0
  88. package/src/engine/pass1_facts.js +260 -0
  89. package/src/engine/pass2_semantics.js +333 -0
  90. package/src/engine/pass3_lifter.js +99 -0
  91. package/src/engine/pass4_signals.js +201 -0
  92. package/src/index.js +830 -0
  93. package/src/plugins/express-plugin.js +48 -0
  94. package/src/plugins/plugin-manager.js +58 -0
  95. package/src/plugins/react-plugin.js +54 -0
  96. package/temp_original.js +0 -0
  97. package/test/determinism-test.js +83 -0
  98. package/test-authoritative-context.js +53 -0
  99. package/test-real-authoritative-context.js +118 -0
  100. package/test-upload-enhancements.js +111 -0
  101. package/test_repos/allowed-clean-architecture/.arcvision/invariants.json +57 -0
  102. package/test_repos/allowed-clean-architecture/adapters/controllers/UserController.js +95 -0
  103. package/test_repos/allowed-clean-architecture/adapters/http/HttpServer.js +78 -0
  104. package/test_repos/allowed-clean-architecture/application/dtos/CreateUserRequest.js +37 -0
  105. package/test_repos/allowed-clean-architecture/application/services/UserService.js +61 -0
  106. package/test_repos/allowed-clean-architecture/arcvision_context/README.md +93 -0
  107. package/test_repos/allowed-clean-architecture/arcvision_context/arcvision.context.json +2796 -0
  108. package/test_repos/allowed-clean-architecture/domain/interfaces/UserRepository.js +25 -0
  109. package/test_repos/allowed-clean-architecture/domain/models/User.js +39 -0
  110. package/test_repos/allowed-clean-architecture/index.js +45 -0
  111. package/test_repos/allowed-clean-architecture/infrastructure/database/DatabaseConnection.js +56 -0
  112. package/test_repos/allowed-clean-architecture/infrastructure/repositories/InMemoryUserRepository.js +61 -0
  113. package/test_repos/allowed-clean-architecture/package.json +15 -0
  114. package/test_repos/blocked-legacy-monolith/.arcvision/invariants.json +78 -0
  115. package/test_repos/blocked-legacy-monolith/arcvision_context/README.md +93 -0
  116. package/test_repos/blocked-legacy-monolith/arcvision_context/arcvision.context.json +2882 -0
  117. package/test_repos/blocked-legacy-monolith/database/dbConnection.js +35 -0
  118. package/test_repos/blocked-legacy-monolith/index.js +38 -0
  119. package/test_repos/blocked-legacy-monolith/modules/emailService.js +31 -0
  120. package/test_repos/blocked-legacy-monolith/modules/paymentProcessor.js +37 -0
  121. package/test_repos/blocked-legacy-monolith/package.json +15 -0
  122. package/test_repos/blocked-legacy-monolith/shared/utils.js +19 -0
  123. package/test_repos/blocked-legacy-monolith/utils/helpers.js +23 -0
  124. package/test_repos/risky-microservices-concerns/.arcvision/invariants.json +69 -0
  125. package/test_repos/risky-microservices-concerns/arcvision_context/README.md +93 -0
  126. package/test_repos/risky-microservices-concerns/arcvision_context/arcvision.context.json +3070 -0
  127. package/test_repos/risky-microservices-concerns/common/utils.js +77 -0
  128. package/test_repos/risky-microservices-concerns/gateways/apiGateway.js +84 -0
  129. package/test_repos/risky-microservices-concerns/index.js +20 -0
  130. package/test_repos/risky-microservices-concerns/libs/deprecatedHelper.js +36 -0
  131. package/test_repos/risky-microservices-concerns/package.json +15 -0
  132. package/test_repos/risky-microservices-concerns/services/orderService.js +42 -0
  133. package/test_repos/risky-microservices-concerns/services/userService.js +48 -0
  134. package/verify_engine.js +116 -0
@@ -0,0 +1,433 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { Command } = require('commander');
4
+ const chalk = require('chalk');
5
+ const path = require('path');
6
+ const fs = require('fs');
7
+ const crypto = require('crypto');
8
+ const { execSync } = require('child_process');
9
+
10
+ const program = new Command();
11
+
12
+ program
13
+ .name('arcvision-guard')
14
+ .description('ArcVision Impact Guard - Enforce architectural safety')
15
+ .version('1.0.0');
16
+
17
+ program
18
+ .command('check')
19
+ .description('Check current changes against architectural invariants')
20
+ .option('-d, --dir <directory>', 'Working directory', '.')
21
+ .option('-v, --verbose', 'Show detailed output')
22
+ .option('--fail-on-warnings', 'Exit with error code on warnings')
23
+ .option('--bypass-token <token>', 'Bypass token for overriding critical violations')
24
+ .action((options) => {
25
+ console.log(chalk.blue('🛡️ ArcVision Impact Guard'));
26
+ console.log(chalk.blue('Checking architectural safety...\n'));
27
+
28
+ try {
29
+ // Load configuration
30
+ const config = loadConfig(options.dir);
31
+
32
+ // Check for bypass token
33
+ const bypassToken = options.bypassToken || process.env.ARCVISION_BYPASS_TOKEN;
34
+ let bypassValid = false;
35
+
36
+ if (bypassToken) {
37
+ bypassValid = validateBypassToken(bypassToken, options.dir);
38
+ if (bypassValid) {
39
+ console.log(chalk.yellow('⚠️ Bypass token detected - proceeding with caution'));
40
+ } else {
41
+ console.log(chalk.red('❌ Invalid bypass token - continuing with normal validation'));
42
+ }
43
+ }
44
+
45
+ // Generate current context
46
+ console.log(chalk.gray('Generating current architectural context...'));
47
+ execSync('arcvision scan --output current-check.json', { stdio: 'inherit' });
48
+
49
+ // Check for git changes if in a repo
50
+ let hasChanges = false;
51
+ try {
52
+ execSync('git diff --quiet HEAD', { stdio: 'pipe' });
53
+ } catch (error) {
54
+ hasChanges = true;
55
+ }
56
+
57
+ if (hasChanges) {
58
+ console.log(chalk.gray('Comparing with HEAD context...'));
59
+ execSync('git stash push -m "temp-for-guard-check"', { stdio: 'pipe' });
60
+ execSync('git checkout HEAD --quiet');
61
+ execSync('arcvision scan --output head-context.json', { stdio: 'inherit' });
62
+ execSync('git stash pop --quiet', { stdio: 'pipe' });
63
+
64
+ // Generate diff
65
+ execSync('arcvision diff head-context.json current-check.json --output guard-report.json', { stdio: 'inherit' });
66
+ } else {
67
+ // No changes, just validate current state
68
+ execSync('cp current-check.json guard-report.json', { stdio: 'inherit' });
69
+ }
70
+
71
+ // Analyze report
72
+ const report = JSON.parse(fs.readFileSync('guard-report.json', 'utf8'));
73
+ const analysis = analyzeReport(report, config);
74
+
75
+ // Display results
76
+ displayResults(analysis, options.verbose);
77
+
78
+ // Handle bypass logic
79
+ if (analysis.criticalIssues.length > 0 && !bypassValid) {
80
+ console.log(chalk.red('\n❌ Critical architectural violations detected!'));
81
+ console.log(chalk.yellow('\nTo bypass this check (USE WITH EXTREME CAUTION):'));
82
+ console.log(chalk.yellow('1. Generate bypass token: arcvision-guard bypass-request'));
83
+ console.log(chalk.yellow('2. Use token: arcvision-guard check --bypass-token <generated_token>'));
84
+ console.log(chalk.red('\n⚠️ WARNING: Bypassing critical violations can break your system!'));
85
+ process.exit(1);
86
+ } else if (options.failOnWarnings && analysis.warnings.length > 0 && !bypassValid) {
87
+ console.log(chalk.yellow('\n⚠️ Warnings present (failing due to --fail-on-warnings)'));
88
+ process.exit(1);
89
+ } else if (analysis.warnings.length > 0 && !bypassValid) {
90
+ console.log(chalk.yellow('\n⚠️ Architectural warnings detected - review recommended'));
91
+ process.exit(0);
92
+ } else {
93
+ console.log(chalk.green('\n✅ No architectural issues detected'));
94
+ process.exit(0);
95
+ }
96
+
97
+ // Cleanup
98
+ cleanupFiles(['current-check.json', 'head-context.json', 'guard-report.json']);
99
+
100
+ } catch (error) {
101
+ console.error(chalk.red('Guard check failed:'), error.message);
102
+ process.exit(1);
103
+ }
104
+ });
105
+
106
+ program
107
+ .command('bypass-request')
108
+ .description('Request a one-time bypass token for critical changes')
109
+ .option('-d, --dir <directory>', 'Working directory', '.')
110
+ .option('-r, --reason <reason>', 'Reason for bypass request')
111
+ .action((options) => {
112
+ console.log(chalk.blue('🛡️ ArcVision Bypass Request'));
113
+
114
+ const reason = options.reason || 'No reason provided';
115
+ const timestamp = new Date().toISOString();
116
+ const hashInput = `${timestamp}-${reason}-${Math.random()}`;
117
+ const token = crypto.createHash('sha256').update(hashInput).digest('hex').substring(0, 32);
118
+
119
+ // Store token info for validation
120
+ const tokenInfo = {
121
+ token: token,
122
+ reason: reason,
123
+ created: timestamp,
124
+ used: false,
125
+ expires: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString() // 24 hours
126
+ };
127
+
128
+ const tokensDir = path.join(options.dir, '.arcvision', 'tokens');
129
+ if (!fs.existsSync(tokensDir)) {
130
+ fs.mkdirSync(tokensDir, { recursive: true });
131
+ }
132
+
133
+ const tokenFile = path.join(tokensDir, `${token}.json`);
134
+ fs.writeFileSync(tokenFile, JSON.stringify(tokenInfo, null, 2));
135
+
136
+ console.log(chalk.green('\n✅ Bypass token generated!'));
137
+ console.log(chalk.yellow('\nToken:'), chalk.bold(token));
138
+ console.log(chalk.yellow('Reason:'), reason);
139
+ console.log(chalk.yellow('Expires:'), tokenInfo.expires);
140
+ console.log(chalk.red('\n⚠️ CRITICAL: This token can only be used ONCE and expires in 24 hours'));
141
+ console.log(chalk.red('⚠️ Use only for absolutely necessary architectural changes'));
142
+ console.log(chalk.yellow('\nUsage: arcvision-guard check --bypass-token'), chalk.bold(token));
143
+ });
144
+
145
+ program
146
+ .command('bypass-status')
147
+ .description('Check status of bypass tokens')
148
+ .option('-d, --dir <directory>', 'Working directory', '.')
149
+ .action((options) => {
150
+ const tokensDir = path.join(options.dir, '.arcvision', 'tokens');
151
+
152
+ if (!fs.existsSync(tokensDir)) {
153
+ console.log(chalk.yellow('No bypass tokens found'));
154
+ return;
155
+ }
156
+
157
+ const tokenFiles = fs.readdirSync(tokensDir).filter(f => f.endsWith('.json'));
158
+
159
+ if (tokenFiles.length === 0) {
160
+ console.log(chalk.yellow('No bypass tokens found'));
161
+ return;
162
+ }
163
+
164
+ console.log(chalk.blue('🛡️ ArcVision Bypass Token Status'));
165
+ console.log(chalk.blue('==================================='));
166
+
167
+ tokenFiles.forEach(file => {
168
+ const tokenInfo = JSON.parse(fs.readFileSync(path.join(tokensDir, file), 'utf8'));
169
+ const status = tokenInfo.used ? chalk.red('USED') :
170
+ new Date(tokenInfo.expires) < new Date() ? chalk.gray('EXPIRED') :
171
+ chalk.green('ACTIVE');
172
+
173
+ console.log(`\nToken: ${file.replace('.json', '')}`);
174
+ console.log(`Status: ${status}`);
175
+ console.log(`Reason: ${tokenInfo.reason}`);
176
+ console.log(`Created: ${tokenInfo.created}`);
177
+ console.log(`Expires: ${tokenInfo.expires}`);
178
+ console.log(`Used: ${tokenInfo.used ? 'Yes' : 'No'}`);
179
+ });
180
+ });
181
+
182
+ program
183
+ .command('setup')
184
+ .description('Initialize ArcVision Impact Guard in current repository')
185
+ .option('-f, --force', 'Force re-initialization')
186
+ .action((options) => {
187
+ console.log(chalk.blue('🔧 Setting up ArcVision Impact Guard...\n'));
188
+
189
+ const arcDir = path.join('.', '.arcvision');
190
+
191
+ // Check if already initialized
192
+ if (fs.existsSync(arcDir) && !options.force) {
193
+ console.log(chalk.yellow('ArcVision Impact Guard is already initialized.'));
194
+ console.log(chalk.yellow('Use --force to reinitialize.'));
195
+ return;
196
+ }
197
+
198
+ // Create directory structure
199
+ if (!fs.existsSync(arcDir)) {
200
+ fs.mkdirSync(arcDir, { recursive: true });
201
+ }
202
+
203
+ // Create tokens directory
204
+ const tokensDir = path.join(arcDir, 'tokens');
205
+ if (!fs.existsSync(tokensDir)) {
206
+ fs.mkdirSync(tokensDir, { recursive: true });
207
+ }
208
+
209
+ // Copy configuration templates
210
+ const templateDir = path.join(__dirname, '..', '.arcvision');
211
+ if (fs.existsSync(templateDir)) {
212
+ copyFile(path.join(templateDir, 'config.json'), path.join(arcDir, 'config.json'));
213
+ copyFile(path.join(templateDir, 'invariants.json'), path.join(arcDir, 'invariants.json'));
214
+ console.log(chalk.green('✅ Configuration files created'));
215
+ }
216
+
217
+ // Update .gitignore
218
+ updateGitIgnore();
219
+
220
+ // Add to package.json if it exists
221
+ updatePackageJson();
222
+
223
+ console.log(chalk.green('\n🎉 ArcVision Impact Guard initialized successfully!'));
224
+ console.log(chalk.yellow('\nNext steps:'));
225
+ console.log(chalk.yellow('1. Review .arcvision/config.json for project settings'));
226
+ console.log(chalk.yellow('2. Customize .arcvision/invariants.json with your architectural rules'));
227
+ console.log(chalk.yellow('3. Run: arcvision-guard check'));
228
+ console.log(chalk.yellow('4. For critical changes: arcvision-guard bypass-request --reason "your reason"'));
229
+ });
230
+
231
+ program
232
+ .command('add-invariant')
233
+ .description('Add a custom architectural invariant')
234
+ .argument('<name>', 'Invariant name')
235
+ .argument('<description>', 'Invariant description')
236
+ .option('-s, --severity <level>', 'Severity (critical|warning)', 'warning')
237
+ .option('-c, --category <category>', 'Category (structural|domain|architectural|integration)', 'architectural')
238
+ .action((name, description, options) => {
239
+ const invariant = {
240
+ id: name.toLowerCase().replace(/\s+/g, '_'),
241
+ name: name,
242
+ description: description,
243
+ category: options.category,
244
+ severity: options.severity,
245
+ detection_pattern: "custom_pattern",
246
+ remediation: "Define appropriate remediation steps"
247
+ };
248
+
249
+ const invariantsPath = path.join('.arcvision', 'invariants.json');
250
+ if (!fs.existsSync(invariantsPath)) {
251
+ console.log(chalk.red('❌ ArcVision not initialized. Run "arcvision-guard setup" first.'));
252
+ process.exit(1);
253
+ }
254
+
255
+ const invariants = JSON.parse(fs.readFileSync(invariantsPath, 'utf8'));
256
+ invariants.project_specific_invariants.push(invariant);
257
+
258
+ fs.writeFileSync(invariantsPath, JSON.stringify(invariants, null, 2));
259
+ console.log(chalk.green(`✅ Added invariant: ${name}`));
260
+ });
261
+
262
+ // Helper functions
263
+ function loadConfig(dir) {
264
+ const configPath = path.join(dir, '.arcvision', 'config.json');
265
+ if (fs.existsSync(configPath)) {
266
+ return JSON.parse(fs.readFileSync(configPath, 'utf8'));
267
+ }
268
+ return { guard_rules: {} };
269
+ }
270
+
271
+ function validateBypassToken(token, dir) {
272
+ const tokenFile = path.join(dir, '.arcvision', 'tokens', `${token}.json`);
273
+
274
+ if (!fs.existsSync(tokenFile)) {
275
+ return false;
276
+ }
277
+
278
+ const tokenInfo = JSON.parse(fs.readFileSync(tokenFile, 'utf8'));
279
+
280
+ // Check if expired
281
+ if (new Date(tokenInfo.expires) < new Date()) {
282
+ return false;
283
+ }
284
+
285
+ // Check if already used
286
+ if (tokenInfo.used) {
287
+ return false;
288
+ }
289
+
290
+ // Mark as used
291
+ tokenInfo.used = true;
292
+ fs.writeFileSync(tokenFile, JSON.stringify(tokenInfo, null, 2));
293
+
294
+ return true;
295
+ }
296
+
297
+ function analyzeReport(report, config) {
298
+ const criticalIssues = [];
299
+ const warnings = [];
300
+
301
+ // Check blast radius changes
302
+ if (report.blast_radius_changes) {
303
+ report.blast_radius_changes.forEach(change => {
304
+ const threshold = config.guard_rules?.blast_radius?.critical_threshold || 50;
305
+ if (change.percentage_increase > threshold) {
306
+ criticalIssues.push({
307
+ type: 'blast_radius',
308
+ message: `High blast radius increase: ${change.file} (+${change.percentage_increase}%)`,
309
+ file: change.file
310
+ });
311
+ } else if (change.percentage_increase > 20) {
312
+ warnings.push({
313
+ type: 'blast_radius',
314
+ message: `Moderate blast radius increase: ${change.file} (+${change.percentage_increase}%)`,
315
+ file: change.file
316
+ });
317
+ }
318
+ });
319
+ }
320
+
321
+ // Check invariant violations
322
+ if (report.invariant_violations) {
323
+ report.invariant_violations.forEach(violation => {
324
+ const issue = {
325
+ type: 'invariant',
326
+ message: `${violation.invariant_id}: ${violation.description}`,
327
+ file: violation.file
328
+ };
329
+
330
+ if (violation.severity === 'critical') {
331
+ criticalIssues.push(issue);
332
+ } else {
333
+ warnings.push(issue);
334
+ }
335
+ });
336
+ }
337
+
338
+ // Check authority core changes
339
+ if (report.authority_core_changes) {
340
+ report.authority_core_changes.forEach(change => {
341
+ criticalIssues.push({
342
+ type: 'authority_core',
343
+ message: `Authority core modified: ${change.file} - ${change.reason}`,
344
+ file: change.file
345
+ });
346
+ });
347
+ }
348
+
349
+ return { criticalIssues, warnings };
350
+ }
351
+
352
+ function displayResults(analysis, verbose) {
353
+ if (analysis.criticalIssues.length === 0 && analysis.warnings.length === 0) {
354
+ console.log(chalk.green('✅ No architectural issues detected'));
355
+ return;
356
+ }
357
+
358
+ if (analysis.criticalIssues.length > 0) {
359
+ console.log(chalk.red(`\n❌ Critical Issues (${analysis.criticalIssues.length}):`));
360
+ analysis.criticalIssues.forEach(issue => {
361
+ console.log(chalk.red(` • ${issue.message}`));
362
+ if (verbose && issue.file) {
363
+ console.log(chalk.gray(` File: ${issue.file}`));
364
+ }
365
+ });
366
+ }
367
+
368
+ if (analysis.warnings.length > 0) {
369
+ console.log(chalk.yellow(`\n⚠️ Warnings (${analysis.warnings.length}):`));
370
+ analysis.warnings.forEach(warning => {
371
+ console.log(chalk.yellow(` • ${warning.message}`));
372
+ if (verbose && warning.file) {
373
+ console.log(chalk.gray(` File: ${warning.file}`));
374
+ }
375
+ });
376
+ }
377
+ }
378
+
379
+ function updateGitIgnore() {
380
+ const gitignorePath = '.gitignore';
381
+ const ignoreEntries = [
382
+ '# ArcVision Impact Guard',
383
+ '.arcvision/temp/',
384
+ '.arcvision/cache/',
385
+ '.arcvision/tokens/',
386
+ '*-check.json',
387
+ '*-context.json',
388
+ 'guard-report.json'
389
+ ];
390
+
391
+ let content = '';
392
+ if (fs.existsSync(gitignorePath)) {
393
+ content = fs.readFileSync(gitignorePath, 'utf8');
394
+ }
395
+
396
+ const newEntries = ignoreEntries.filter(entry => !content.includes(entry));
397
+ if (newEntries.length > 0) {
398
+ fs.appendFileSync(gitignorePath, '\n' + newEntries.join('\n') + '\n');
399
+ console.log(chalk.green('✅ Updated .gitignore'));
400
+ }
401
+ }
402
+
403
+ function updatePackageJson() {
404
+ const pkgPath = 'package.json';
405
+ if (fs.existsSync(pkgPath)) {
406
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
407
+ pkg.scripts = pkg.scripts || {};
408
+
409
+ if (!pkg.scripts['arcvision:check']) {
410
+ pkg.scripts['arcvision:check'] = 'arcvision-guard check';
411
+ pkg.scripts['arcvision:setup'] = 'arcvision-guard setup';
412
+ pkg.scripts['arcvision:bypass'] = 'arcvision-guard bypass-request';
413
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
414
+ console.log(chalk.green('✅ Updated package.json scripts'));
415
+ }
416
+ }
417
+ }
418
+
419
+ function copyFile(src, dest) {
420
+ if (fs.existsSync(src)) {
421
+ fs.copyFileSync(src, dest);
422
+ }
423
+ }
424
+
425
+ function cleanupFiles(files) {
426
+ files.forEach(file => {
427
+ if (fs.existsSync(file)) {
428
+ fs.unlinkSync(file);
429
+ }
430
+ });
431
+ }
432
+
433
+ program.parse();