arcvision 0.2.17 → 0.2.20

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 (63) hide show
  1. package/.arcvision/logs/errors.log +5 -0
  2. package/arcvision_context/architecture.authority.ledger.json +6 -63
  3. package/bin/arcvision.js +12 -0
  4. package/package.json +3 -2
  5. package/src/core/artifact-manager.js +143 -0
  6. package/src/core/command-base.js +107 -0
  7. package/src/core/config-validator.js +199 -0
  8. package/src/core/error-handler.js +106 -0
  9. package/src/core/feature-manager.js +218 -0
  10. package/src/core/feedback-generator.js +260 -0
  11. package/src/core/invariant-analyzer.js +22 -2
  12. package/src/core/invariant-detector.js +236 -3
  13. package/src/core/parser.js +85 -1
  14. package/src/core/scanner.js +18 -6
  15. package/src/engine/context_builder.js +21 -3
  16. package/src/engine/context_validator.js +7 -1
  17. package/src/engine/pass1_facts.js +2 -2
  18. package/src/index.js +41 -13
  19. package/test-block-functionality.js +40 -0
  20. package/test-dev-project/.arcvision/invariants.json +19 -0
  21. package/{arcvision_context → test-dev-project/arcvision_context}/README.md +9 -9
  22. package/test-dev-project/arcvision_context/architecture.authority.ledger.json +45 -0
  23. package/{arcvision.context.json → test-dev-project/arcvision_context/arcvision.context.json} +498 -496
  24. package/test-dev-project/src/core/data-service.js +0 -0
  25. package/test-dev-project/src/ui/user-profile.js +0 -0
  26. package/test-dev-project/src/utils/helpers.js +0 -0
  27. package/ARCVISION_DIRECTORY_STRUCTURE.md +0 -104
  28. package/CLI_STRUCTURE.md +0 -110
  29. package/CONFIGURATION.md +0 -119
  30. package/IMPLEMENTATION_SUMMARY.md +0 -99
  31. package/README.md +0 -149
  32. package/architecture.authority.ledger.json +0 -46
  33. package/arcvision-0.2.3.tgz +0 -0
  34. package/arcvision-0.2.4.tgz +0 -0
  35. package/arcvision-0.2.5.tgz +0 -0
  36. package/arcvision.context.diff.json +0 -2181
  37. package/arcvision.context.v1.json +0 -2163
  38. package/arcvision.context.v2.json +0 -2173
  39. package/arcvision_context/arcvision.context.json +0 -6884
  40. package/debug-cycle-detection.js +0 -56
  41. package/docs/ENHANCED_ACCURACY_SAFETY_PROTOCOL.md +0 -172
  42. package/docs/accuracy-enhancement-artifacts/enhanced-validation-config.json +0 -98
  43. package/docs/acig-robustness-guide.md +0 -164
  44. package/docs/authoritative-gate-implementation.md +0 -168
  45. package/docs/blast-radius-implementation.md +0 -76
  46. package/docs/blast-radius.md +0 -44
  47. package/docs/cli-strengthening-summary.md +0 -232
  48. package/docs/invariant-system-summary.md +0 -100
  49. package/docs/invariant-system.md +0 -112
  50. package/generate_large_test.js +0 -42
  51. package/large_test_repo.json +0 -1
  52. package/output1.json +0 -2163
  53. package/output2.json +0 -2163
  54. package/scan_calcom_report.txt +0 -0
  55. package/scan_leafmint_report.txt +0 -0
  56. package/scan_output.txt +0 -0
  57. package/scan_trigger_report.txt +0 -0
  58. package/temp_original.js +0 -0
  59. package/test/determinism-test.js +0 -83
  60. package/test-authoritative-context.js +0 -53
  61. package/test-real-authoritative-context.js +0 -118
  62. package/test-upload-enhancements.js +0 -111
  63. package/verify_engine.js +0 -116
@@ -0,0 +1,218 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ class FeatureManager {
5
+ /**
6
+ * Determines which ArcVision features are available based on existing artifacts
7
+ */
8
+ static getAvailableFeatures(projectPath) {
9
+ const artifacts = this.checkArtifacts(projectPath);
10
+
11
+ const features = {
12
+ basic_analysis: artifacts.context_exists,
13
+ invariant_checking: artifacts.invariants_exists,
14
+ authority_governance: artifacts.ledger_exists,
15
+ advanced_reporting: artifacts.readme_exists,
16
+ context_visualization: artifacts.context_exists,
17
+ architectural_health: artifacts.context_exists && artifacts.invariants_exists
18
+ };
19
+
20
+ return {
21
+ available: Object.entries(features)
22
+ .filter(([_, available]) => available)
23
+ .map(([feature, _]) => feature),
24
+ all: features,
25
+ artifacts: artifacts
26
+ };
27
+ }
28
+
29
+ /**
30
+ * Checks for the presence of key artifacts
31
+ */
32
+ static checkArtifacts(projectPath) {
33
+ return {
34
+ context_exists: fs.existsSync(path.join(projectPath, 'arcvision_context', 'arcvision.context.json')),
35
+ invariants_exists: fs.existsSync(path.join(projectPath, '.arcvision', 'invariants.json')),
36
+ ledger_exists: fs.existsSync(path.join(projectPath, 'arcvision_context', 'architecture.authority.ledger.json')),
37
+ readme_exists: fs.existsSync(path.join(projectPath, 'arcvision_context', 'README.md')),
38
+ arcvision_dir_exists: fs.existsSync(path.join(projectPath, '.arcvision')),
39
+ context_dir_exists: fs.existsSync(path.join(projectPath, 'arcvision_context'))
40
+ };
41
+ }
42
+
43
+ /**
44
+ * Generates recommendations based on missing features
45
+ */
46
+ static getRecommendations(projectPath) {
47
+ const artifacts = this.checkArtifacts(projectPath);
48
+ const recommendations = [];
49
+
50
+ if (!artifacts.invariants_exists) {
51
+ recommendations.push({
52
+ type: 'SETUP',
53
+ priority: 'HIGH',
54
+ message: 'Define architectural invariants for governance',
55
+ action: 'arcvision init-invariants',
56
+ description: 'Create custom rules to govern your architectural decisions'
57
+ });
58
+ }
59
+
60
+ if (!artifacts.context_exists) {
61
+ recommendations.push({
62
+ type: 'ANALYSIS',
63
+ priority: 'HIGH',
64
+ message: 'Generate structural context',
65
+ action: 'arcvision scan',
66
+ description: 'Analyze your codebase to understand its structure'
67
+ });
68
+ }
69
+
70
+ if (!artifacts.ledger_exists) {
71
+ recommendations.push({
72
+ type: 'GOVERNANCE',
73
+ priority: 'MEDIUM',
74
+ message: 'Enable authority ledger',
75
+ action: 'arcvision acig',
76
+ description: 'Track architectural decisions and violations'
77
+ });
78
+ }
79
+
80
+ if (!artifacts.readme_exists) {
81
+ recommendations.push({
82
+ type: 'DOCUMENTATION',
83
+ priority: 'LOW',
84
+ message: 'Generate documentation',
85
+ action: 'arcvision scan',
86
+ description: 'Create contextual documentation for your architecture'
87
+ });
88
+ }
89
+
90
+ return recommendations;
91
+ }
92
+
93
+ /**
94
+ * Generates next steps for users
95
+ */
96
+ static getNextSteps(projectPath) {
97
+ const features = this.getAvailableFeatures(projectPath);
98
+ const recommendations = this.getRecommendations(projectPath);
99
+
100
+ const steps = [];
101
+
102
+ if (features.available.length === 0) {
103
+ steps.push({
104
+ order: 1,
105
+ action: 'arcvision scan',
106
+ description: 'Start by scanning your project to generate structural context'
107
+ });
108
+ } else if (!features.all.invariant_checking) {
109
+ steps.push({
110
+ order: 1,
111
+ action: 'arcvision init-invariants',
112
+ description: 'Create invariants to govern your architecture'
113
+ });
114
+ steps.push({
115
+ order: 2,
116
+ action: 'arcvision acig',
117
+ description: 'Evaluate your code against the defined invariants'
118
+ });
119
+ } else {
120
+ steps.push({
121
+ order: 1,
122
+ action: 'arcvision acig',
123
+ description: 'Check your code against defined architectural invariants'
124
+ });
125
+ }
126
+
127
+ return steps;
128
+ }
129
+
130
+ /**
131
+ * Gets feature status summary
132
+ */
133
+ static getStatusSummary(projectPath) {
134
+ const features = this.getAvailableFeatures(projectPath);
135
+ const recommendations = this.getRecommendations(projectPath);
136
+ const artifacts = this.checkArtifacts(projectPath);
137
+
138
+ return {
139
+ projectPath,
140
+ featureCount: features.available.length,
141
+ availableFeatures: features.available,
142
+ missingFeatures: Object.entries(features.all)
143
+ .filter(([_, available]) => !available)
144
+ .map(([feature, _]) => feature),
145
+ recommendations: recommendations,
146
+ artifacts: artifacts,
147
+ readinessLevel: this.calculateReadinessLevel(features.available.length),
148
+ nextSteps: this.getNextSteps(projectPath)
149
+ };
150
+ }
151
+
152
+ /**
153
+ * Calculates readiness level based on available features
154
+ */
155
+ static calculateReadinessLevel(featureCount) {
156
+ if (featureCount === 0) return 'STARTER';
157
+ if (featureCount <= 2) return 'BEGINNER';
158
+ if (featureCount <= 4) return 'INTERMEDIATE';
159
+ return 'ADVANCED';
160
+ }
161
+
162
+ /**
163
+ * Generates user-friendly report
164
+ */
165
+ static generateUserReport(projectPath) {
166
+ const status = this.getStatusSummary(projectPath);
167
+
168
+ let report = `🎯 ArcVision Project Status Report\n`;
169
+ report += `====================================\n\n`;
170
+ report += `Project: ${path.basename(projectPath)}\n`;
171
+ report += `Readiness Level: ${status.readinessLevel}\n`;
172
+ report += `Available Features: ${status.featureCount}/6\n\n`;
173
+
174
+ report += `📋 Available Features:\n`;
175
+ status.availableFeatures.forEach(feature => {
176
+ report += ` • ${this.formatFeatureName(feature)}\n`;
177
+ });
178
+
179
+ if (status.missingFeatures.length > 0) {
180
+ report += `\n⚠️ Missing Features:\n`;
181
+ status.missingFeatures.forEach(feature => {
182
+ report += ` • ${this.formatFeatureName(feature)}\n`;
183
+ });
184
+ }
185
+
186
+ if (status.recommendations.length > 0) {
187
+ report += `\n💡 Recommendations:\n`;
188
+ status.recommendations.forEach(rec => {
189
+ report += ` • [${rec.priority}] ${rec.message}\n`;
190
+ report += ` Run: ${rec.action}\n`;
191
+ });
192
+ }
193
+
194
+ report += `\n🚀 Next Steps:\n`;
195
+ status.nextSteps.forEach(step => {
196
+ report += ` ${step.order}. ${step.action}\n ${step.description}\n`;
197
+ });
198
+
199
+ return report;
200
+ }
201
+
202
+ /**
203
+ * Formats feature names for display
204
+ */
205
+ static formatFeatureName(feature) {
206
+ const names = {
207
+ 'basic_analysis': 'Basic Code Analysis',
208
+ 'invariant_checking': 'Invariant Checking',
209
+ 'authority_governance': 'Authority Governance',
210
+ 'advanced_reporting': 'Advanced Reporting',
211
+ 'context_visualization': 'Context Visualization',
212
+ 'architectural_health': 'Architectural Health Assessment'
213
+ };
214
+ return names[feature] || feature.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
215
+ }
216
+ }
217
+
218
+ module.exports = { FeatureManager };
@@ -0,0 +1,260 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ class FeedbackGenerator {
5
+ /**
6
+ * Generates comprehensive scan report with structured feedback
7
+ */
8
+ static generateScanReport(analysisResults, artifactsCreated, projectPath) {
9
+ const { FeatureManager } = require('./feature-manager');
10
+ const features = FeatureManager.getAvailableFeatures(projectPath);
11
+
12
+ return {
13
+ status: 'SUCCESS',
14
+ timestamp: new Date().toISOString(),
15
+ artifacts: {
16
+ created: artifactsCreated,
17
+ existing: analysisResults.existingArtifacts,
18
+ total: artifactsCreated.length + (analysisResults.existingArtifacts?.length || 0)
19
+ },
20
+ analysis: {
21
+ nodes: analysisResults.nodes?.length || 0,
22
+ edges: analysisResults.edges?.length || 0,
23
+ symbols: analysisResults.symbols?.length || 0,
24
+ scanTimeMs: analysisResults.scanTimeMs || 0
25
+ },
26
+ features: features,
27
+ recommendations: this.getRecommendations(analysisResults, projectPath),
28
+ nextSteps: this.getNextSteps(analysisResults, projectPath),
29
+ summary: this.generateSummary(analysisResults, artifactsCreated)
30
+ };
31
+ }
32
+
33
+ /**
34
+ * Generates recommendations based on analysis results
35
+ */
36
+ static getRecommendations(analysisResults, projectPath) {
37
+ const { FeatureManager } = require('./feature-manager');
38
+ const recommendations = FeatureManager.getRecommendations(projectPath);
39
+
40
+ // Add specific analysis-based recommendations
41
+ if (analysisResults.nodes && analysisResults.nodes.length > 100) {
42
+ recommendations.unshift({
43
+ type: 'ARCHITECTURE',
44
+ priority: 'HIGH',
45
+ message: 'Large codebase detected - consider defining architectural invariants',
46
+ action: 'arcvision init-invariants',
47
+ description: 'Protect your architecture as it grows in complexity'
48
+ });
49
+ }
50
+
51
+ if (analysisResults.edges && analysisResults.edges.length > 0) {
52
+ const avgDependencies = analysisResults.edges.length / (analysisResults.nodes?.length || 1);
53
+ if (avgDependencies > 5) {
54
+ recommendations.push({
55
+ type: 'DEPENDENCY',
56
+ priority: 'MEDIUM',
57
+ message: 'High average dependencies per file detected',
58
+ action: 'arcvision acig',
59
+ description: 'Check for potential architectural violations'
60
+ });
61
+ }
62
+ }
63
+
64
+ return recommendations;
65
+ }
66
+
67
+ /**
68
+ * Generates next steps based on analysis
69
+ */
70
+ static getNextSteps(analysisResults, projectPath) {
71
+ const { FeatureManager } = require('./feature-manager');
72
+ const baseSteps = FeatureManager.getNextSteps(projectPath);
73
+
74
+ // Add analysis-specific steps
75
+ if (analysisResults.nodes && analysisResults.nodes.length > 0) {
76
+ baseSteps.push({
77
+ order: baseSteps.length + 1,
78
+ action: 'arcvision acig',
79
+ description: 'Evaluate your codebase against architectural invariants'
80
+ });
81
+ }
82
+
83
+ return baseSteps;
84
+ }
85
+
86
+ /**
87
+ * Generates a summary of the scan results
88
+ */
89
+ static generateSummary(analysisResults, artifactsCreated) {
90
+ const nodeCount = analysisResults.nodes?.length || 0;
91
+ const edgeCount = analysisResults.edges?.length || 0;
92
+ const symbolCount = analysisResults.symbols?.length || 0;
93
+
94
+ let summary = `Scan completed successfully!\n`;
95
+ summary += `- Analyzed ${nodeCount} files\n`;
96
+ summary += `- Found ${edgeCount} dependencies\n`;
97
+ summary += `- Processed ${symbolCount} symbols\n`;
98
+ summary += `- Created ${artifactsCreated.length} new artifacts\n`;
99
+
100
+ if (nodeCount > 100) {
101
+ summary += `- Large project detected (${nodeCount} files)\n`;
102
+ } else if (nodeCount > 20) {
103
+ summary += `- Medium-sized project detected\n`;
104
+ } else {
105
+ summary += `- Small project detected\n`;
106
+ }
107
+
108
+ return summary;
109
+ }
110
+
111
+ /**
112
+ * Generates feedback for ACIG evaluation
113
+ */
114
+ static generateAcigReport(evaluation, artifactsUsed) {
115
+ const decision = evaluation.decision;
116
+
117
+ let report = {
118
+ decision: decision,
119
+ timestamp: new Date().toISOString(),
120
+ artifacts: artifactsUsed,
121
+ violations: evaluation.violations?.length || 0,
122
+ affectedFiles: evaluation.changedFiles?.length || 0,
123
+ invariantCount: evaluation.invariants?.length || 0,
124
+ message: this.generateAcigMessage(decision, evaluation),
125
+ details: evaluation.details || {}
126
+ };
127
+
128
+ return report;
129
+ }
130
+
131
+ /**
132
+ * Generates user-friendly message for ACIG decision
133
+ */
134
+ static generateAcigMessage(decision, evaluation) {
135
+ switch(decision) {
136
+ case 'ALLOWED':
137
+ return '✅ Change allowed - No critical violations detected';
138
+ case 'RISKY':
139
+ return `⚠️ Change is risky - ${evaluation.violations?.length || 0} warnings issued`;
140
+ case 'BLOCKED':
141
+ return `❌ Change blocked - ${evaluation.violations?.length || 0} critical violations detected`;
142
+ default:
143
+ return 'ℹ️ Evaluation completed with neutral result';
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Generates structured feedback for CLI commands
149
+ */
150
+ static generateCliFeedback(command, result, context = {}) {
151
+ const timestamp = new Date().toISOString();
152
+
153
+ switch(command) {
154
+ case 'scan':
155
+ return {
156
+ command: 'scan',
157
+ status: result.success ? 'SUCCESS' : 'FAILURE',
158
+ timestamp,
159
+ details: {
160
+ directory: context.directory,
161
+ filesProcessed: result.analysis?.nodes?.length,
162
+ artifactsCreated: result.artifacts?.created?.length,
163
+ durationMs: result.durationMs
164
+ },
165
+ message: result.success
166
+ ? `✅ Scan completed successfully in ${result.durationMs}ms`
167
+ : `❌ Scan failed: ${result.error}`
168
+ };
169
+
170
+ case 'acig':
171
+ return {
172
+ command: 'acig',
173
+ status: result.success ? 'SUCCESS' : 'FAILURE',
174
+ timestamp,
175
+ details: {
176
+ decision: result.decision,
177
+ violations: result.violations?.length,
178
+ filesEvaluated: result.changedFiles?.length
179
+ },
180
+ message: result.success
181
+ ? `🔒 ACIG evaluation: ${result.decision}`
182
+ : `❌ ACIG evaluation failed: ${result.error}`
183
+ };
184
+
185
+ default:
186
+ return {
187
+ command,
188
+ status: 'UNKNOWN',
189
+ timestamp,
190
+ message: `Command ${command} executed`
191
+ };
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Generates progress indicators for long-running operations
197
+ */
198
+ static generateProgressIndicator(current, total, operation = 'Processing') {
199
+ const percentage = Math.round((current / total) * 100);
200
+ const barLength = 30;
201
+ const filledLength = Math.round((current / total) * barLength);
202
+ const bar = '█'.repeat(filledLength) + '░'.repeat(barLength - filledLength);
203
+
204
+ return {
205
+ percentage,
206
+ bar,
207
+ message: `${operation}: ${current}/${total} (${percentage}%)`,
208
+ isComplete: current >= total
209
+ };
210
+ }
211
+
212
+ /**
213
+ * Generates error feedback with actionable information
214
+ */
215
+ static generateErrorFeedback(error, operation, context = {}) {
216
+ return {
217
+ type: 'ERROR',
218
+ operation,
219
+ timestamp: new Date().toISOString(),
220
+ error: {
221
+ message: error.message,
222
+ stack: error.stack,
223
+ name: error.name
224
+ },
225
+ context,
226
+ suggestion: this.getErrorSuggestion(error, operation)
227
+ };
228
+ }
229
+
230
+ /**
231
+ * Provides actionable suggestions for common errors
232
+ */
233
+ static getErrorSuggestion(error, operation) {
234
+ const message = error.message?.toLowerCase() || '';
235
+
236
+ if (message.includes('no such file') || message.includes('enoent')) {
237
+ return 'Ensure the specified directory exists and contains code files.';
238
+ }
239
+
240
+ if (message.includes('permission') || message.includes('eacces')) {
241
+ return 'Check directory permissions and ensure you have read/write access.';
242
+ }
243
+
244
+ if (message.includes('memory') || message.includes('heap out of memory')) {
245
+ return 'Try scanning a smaller subset of your project or increase Node.js memory limit.';
246
+ }
247
+
248
+ if (operation === 'scan' && message.includes('property') && message.includes('undefined')) {
249
+ return 'This may be a parsing issue with certain file types. Try excluding problematic files.';
250
+ }
251
+
252
+ if (operation === 'acig' && message.includes('invariant')) {
253
+ return 'Check your invariants file (.arcvision/invariants.json) for correct format.';
254
+ }
255
+
256
+ return 'Review the error message above and check the ArcVision documentation for troubleshooting tips.';
257
+ }
258
+ }
259
+
260
+ module.exports = { FeedbackGenerator };
@@ -77,7 +77,17 @@ class InvariantAnalyzer {
77
77
  }
78
78
 
79
79
  if (invariant.scope) {
80
- const scopeKey = invariant.scope.toLowerCase();
80
+ // Handle both old string format and new object format for scope
81
+ let scopeKey;
82
+ if (typeof invariant.scope === 'string') {
83
+ scopeKey = invariant.scope.toLowerCase();
84
+ } else if (typeof invariant.scope === 'object' && invariant.scope.files) {
85
+ // For object format with files array, categorize based on presence of files
86
+ scopeKey = 'module'; // Default to module for file-based scopes
87
+ } else {
88
+ scopeKey = 'module'; // Default fallback
89
+ }
90
+
81
91
  if (categorized.by_scope[scopeKey]) {
82
92
  categorized.by_scope[scopeKey].push(invariant);
83
93
  }
@@ -253,7 +263,17 @@ class InvariantAnalyzer {
253
263
  score += Math.min(criticalCount * 10, 30); // Up to 30 points for critical invariants
254
264
 
255
265
  // Boost for system scope invariants
256
- const systemCount = invariants.filter(inv => inv.scope === 'system').length;
266
+ const systemCount = invariants.filter(inv => {
267
+ if (typeof inv.scope === 'string') {
268
+ return inv.scope === 'system';
269
+ } else if (typeof inv.scope === 'object') {
270
+ // Consider as system scope if it has system-level characteristics
271
+ return inv.scope.files && Array.isArray(inv.scope.files) && inv.scope.files.some(file =>
272
+ file && typeof file === 'string' && (file.includes('/core/') || file.includes('/lib/') || file.includes('/shared/'))
273
+ );
274
+ }
275
+ return false;
276
+ }).length;
257
277
  score += Math.min(systemCount * 5, 20); // Up to 20 points for system invariants
258
278
 
259
279
  // Cap the score