arcvision 0.2.16 → 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,5 @@
1
+ {"timestamp":"2026-01-25T01:45:35.206Z","error":{"category":"UNKNOWN","message":"Missing required artifacts: arcvision_context/arcvision.context.json","code":null,"type":"Error"},"context":{"operation":"scan","directory":"C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\test-dev-project"},"stack":"Error: Missing required artifacts: arcvision_context/arcvision.context.json\n at ArtifactManager.validateArtifacts (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\core\\artifact-manager.js:87:13)\n at ArtifactManager.ensureArtifacts (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\core\\artifact-manager.js:26:10)\n at Command.<anonymous> (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\index.js:413:23)\n at process.processTicksAndRejections (node:internal/process/task_queues:95:5)"}
2
+ {"timestamp":"2026-01-25T01:53:22.074Z","error":{"category":"UNKNOWN","message":"Missing required artifacts: arcvision_context/arcvision.context.json","code":null,"type":"Error"},"context":{"operation":"scan","directory":"C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\test-dev-project"},"stack":"Error: Missing required artifacts: arcvision_context/arcvision.context.json\n at ArtifactManager.validateArtifacts (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\core\\artifact-manager.js:87:13)\n at ArtifactManager.ensureArtifacts (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\core\\artifact-manager.js:26:10)\n at Command.<anonymous> (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\index.js:413:23)\n at process.processTicksAndRejections (node:internal/process/task_queues:95:5)"}
3
+ {"timestamp":"2026-01-25T02:04:57.719Z","error":{"category":"UNKNOWN","message":"Invalid ledger structure","code":null,"type":"Error"},"context":{"operation":"evaluate","directory":"C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\test-dev-project"},"stack":"Error: Invalid ledger structure\n at AuthorityLedger.readLedger (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\core\\authority-ledger.js:203:15)\n at AuthorityLedger.appendEvent (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\core\\authority-ledger.js:176:27)\n at AuthorityLedger.recordBlocked (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\core\\authority-ledger.js:81:10)\n at Command.<anonymous> (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\index.js:662:35)\n at process.processTicksAndRejections (node:internal/process/task_queues:95:5)"}
4
+ {"timestamp":"2026-01-25T02:05:38.566Z","error":{"category":"UNKNOWN","message":"Invalid ledger structure","code":null,"type":"Error"},"context":{"operation":"evaluate","directory":"C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\test-dev-project"},"stack":"Error: Invalid ledger structure\n at AuthorityLedger.readLedger (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\core\\authority-ledger.js:203:15)\n at AuthorityLedger.appendEvent (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\core\\authority-ledger.js:176:27)\n at AuthorityLedger.recordBlocked (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\core\\authority-ledger.js:81:10)\n at Command.<anonymous> (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\index.js:662:35)\n at process.processTicksAndRejections (node:internal/process/task_queues:95:5)"}
5
+ {"timestamp":"2026-01-25T03:16:17.596Z","error":{"category":"CONFIGURATION","message":"Invalid or revoked token","code":null,"type":"Error"},"context":{"operation":"standard_upload"},"stack":"Error: Invalid or revoked token\n at C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\index.js:330:19\n at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n at async RetryHandler.executeWithRetry (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\core\\retry-handler.js:23:24)\n at async uploadToDatabase (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\index.js:294:24)\n at async Command.<anonymous> (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\index.js:462:9)"}
@@ -1,77 +1,20 @@
1
1
  {
2
2
  "schema_version": "1.0",
3
3
  "system_id": "cli",
4
- "created_at": "2026-01-21T10:36:12.455Z",
4
+ "created_at": "2026-01-25T01:42:21.875Z",
5
5
  "ledger": [
6
6
  {
7
- "event_id": "evt_1769063005574_7anyjl7bo",
8
- "timestamp": "2026-01-22T06:23:25.574Z",
7
+ "event_id": "evt_1769306597736_165d6ogio",
8
+ "timestamp": "2026-01-25T02:03:17.736Z",
9
9
  "decision": "BLOCKED",
10
10
  "commit": "HEAD",
11
11
  "branch": "unknown",
12
12
  "author": "unknown",
13
13
  "violations": [
14
14
  {
15
- "id": "no-circular-dependencies",
16
- "description": "Circular dependencies between modules are forbidden",
17
- "system": "blocked-legacy-monolith",
18
- "severity": "block"
19
- }
20
- ],
21
- "blast_radius": 0,
22
- "affected_nodes": 0,
23
- "override": false
24
- },
25
- {
26
- "event_id": "evt_1769074540287_n0z3a3fy3",
27
- "timestamp": "2026-01-22T09:35:40.287Z",
28
- "decision": "BLOCKED",
29
- "commit": "HEAD",
30
- "branch": "unknown",
31
- "author": "unknown",
32
- "violations": [
33
- {
34
- "id": "no-circular-dependencies",
35
- "description": "Circular dependencies between modules are forbidden",
36
- "system": "blocked-legacy-monolith",
37
- "severity": "block"
38
- }
39
- ],
40
- "blast_radius": 0,
41
- "affected_nodes": 0,
42
- "override": false
43
- },
44
- {
45
- "event_id": "evt_1769074680315_phm7zyzp4",
46
- "timestamp": "2026-01-22T09:38:00.315Z",
47
- "decision": "BLOCKED",
48
- "commit": "HEAD",
49
- "branch": "unknown",
50
- "author": "unknown",
51
- "violations": [
52
- {
53
- "id": "no-circular-dependencies",
54
- "description": "Circular dependencies between modules are forbidden",
55
- "system": "blocked-legacy-monolith",
56
- "severity": "block"
57
- }
58
- ],
59
- "blast_radius": 0,
60
- "affected_nodes": 0,
61
- "override": false
62
- },
63
- {
64
- "event_id": "evt_1769089584032_49cj329l0",
65
- "timestamp": "2026-01-22T13:46:24.032Z",
66
- "decision": "BLOCKED",
67
- "commit": "HEAD",
68
- "branch": "unknown",
69
- "author": "unknown",
70
- "violations": [
71
- {
72
- "id": "no-circular-dependencies",
73
- "description": "Circular dependencies between modules are forbidden",
74
- "system": "blocked-legacy-monolith",
15
+ "id": "no-ui-imports-core",
16
+ "description": "UI components should not import from core modules",
17
+ "system": "layering",
75
18
  "severity": "block"
76
19
  }
77
20
  ],
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+
3
+ // ArcVision CLI Entry Point
4
+ // This file serves as the executable binary for the ArcVision CLI
5
+
6
+ try {
7
+ // Require the main CLI module
8
+ require('../src/index.js');
9
+ } catch (error) {
10
+ console.error('Failed to start ArcVision CLI:', error.message);
11
+ process.exit(1);
12
+ }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "arcvision",
3
- "version": "0.2.16",
3
+ "version": "0.2.20",
4
4
  "description": "ArcVision CLI - Architectural Governance and Invariant Detection Tool",
5
5
  "main": "src/index.js",
6
6
  "bin": {
7
- "arcvision": "src/index.js"
7
+ "arcvision": "./bin/arcvision.js"
8
8
  },
9
9
  "scripts": {
10
10
  "start": "node src/index.js",
@@ -28,6 +28,7 @@
28
28
  "@babel/parser": "^7.24.0",
29
29
  "@babel/traverse": "^7.24.0",
30
30
  "ajv": "^8.12.0",
31
+ "ajv-formats": "^3.0.1",
31
32
  "chalk": "^4.1.2",
32
33
  "commander": "^9.4.1",
33
34
  "fast-glob": "^3.2.12",
@@ -0,0 +1,143 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ class ArtifactManager {
5
+ constructor(projectRoot) {
6
+ this.projectRoot = projectRoot;
7
+ this.requiredDirs = ['.arcvision', 'arcvision_context'];
8
+ this.requiredFiles = {
9
+ context: 'arcvision_context/arcvision.context.json',
10
+ ledger: 'arcvision_context/architecture.authority.ledger.json',
11
+ invariants: '.arcvision/invariants.json'
12
+ };
13
+ }
14
+
15
+ /**
16
+ * Ensures all required artifacts exist with proper structure
17
+ */
18
+ ensureArtifacts() {
19
+ // Create required directories
20
+ this.createDirectories();
21
+
22
+ // Create required files with defaults if missing
23
+ this.createMissingFiles();
24
+
25
+ // Validate artifact integrity (excluding context file which is created by scanner)
26
+ this.validateArtifactsExceptContext();
27
+ }
28
+
29
+ /**
30
+ * Creates required directories if they don't exist
31
+ */
32
+ createDirectories() {
33
+ this.requiredDirs.forEach(dir => {
34
+ const fullPath = path.join(this.projectRoot, dir);
35
+ if (!fs.existsSync(fullPath)) {
36
+ fs.mkdirSync(fullPath, { recursive: true });
37
+ this.logCreation(dir);
38
+ }
39
+ });
40
+ }
41
+
42
+ /**
43
+ * Creates missing files with default content
44
+ */
45
+ createMissingFiles() {
46
+ // Create default invariants file if missing
47
+ const invariantsPath = path.join(this.projectRoot, this.requiredFiles.invariants);
48
+ if (!fs.existsSync(invariantsPath)) {
49
+ const defaultInvariants = {
50
+ version: '1.0',
51
+ project_specific_invariants: [],
52
+ generated_at: new Date().toISOString()
53
+ };
54
+
55
+ fs.writeFileSync(invariantsPath, JSON.stringify(defaultInvariants, null, 2));
56
+ this.logCreation(this.requiredFiles.invariants);
57
+ }
58
+
59
+ // Create default ledger if missing
60
+ const ledgerPath = path.join(this.projectRoot, this.requiredFiles.ledger);
61
+ if (!fs.existsSync(ledgerPath)) {
62
+ const defaultLedger = {
63
+ schema_version: '1.0',
64
+ system_id: path.basename(this.projectRoot),
65
+ created_at: new Date().toISOString(),
66
+ ledger: []
67
+ };
68
+
69
+ fs.writeFileSync(ledgerPath, JSON.stringify(defaultLedger, null, 2));
70
+ this.logCreation(this.requiredFiles.ledger);
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Validates that all required artifacts exist and are accessible
76
+ */
77
+ validateArtifacts() {
78
+ const missingArtifacts = [];
79
+
80
+ Object.entries(this.requiredFiles).forEach(([name, relativePath]) => {
81
+ const fullPath = path.join(this.projectRoot, relativePath);
82
+ if (!fs.existsSync(fullPath)) {
83
+ missingArtifacts.push(relativePath);
84
+ }
85
+ });
86
+
87
+ if (missingArtifacts.length > 0) {
88
+ throw new Error(`Missing required artifacts: ${missingArtifacts.join(', ')}`);
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Validates artifacts except context file (which is created by scanner)
94
+ */
95
+ validateArtifactsExceptContext() {
96
+ const missingArtifacts = [];
97
+
98
+ Object.entries(this.requiredFiles).forEach(([name, relativePath]) => {
99
+ // Skip context file validation as it's created by scanner
100
+ if (name === 'context') return;
101
+
102
+ const fullPath = path.join(this.projectRoot, relativePath);
103
+ if (!fs.existsSync(fullPath)) {
104
+ missingArtifacts.push(relativePath);
105
+ }
106
+ });
107
+
108
+ if (missingArtifacts.length > 0) {
109
+ throw new Error(`Missing required artifacts: ${missingArtifacts.join(', ')}`);
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Checks if artifacts exist
115
+ */
116
+ artifactsExist() {
117
+ try {
118
+ this.validateArtifacts();
119
+ return true;
120
+ } catch (error) {
121
+ return false;
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Gets the path for a specific artifact
127
+ */
128
+ getArtifactPath(artifactName) {
129
+ if (this.requiredFiles[artifactName]) {
130
+ return path.join(this.projectRoot, this.requiredFiles[artifactName]);
131
+ }
132
+ throw new Error(`Unknown artifact: ${artifactName}`);
133
+ }
134
+
135
+ /**
136
+ * Logs artifact creation
137
+ */
138
+ logCreation(artifact) {
139
+ console.log(`📁 Created required artifact: ${artifact}`);
140
+ }
141
+ }
142
+
143
+ module.exports = { ArtifactManager };
@@ -0,0 +1,107 @@
1
+ const path = require('path');
2
+
3
+ class ArcVisionCommand {
4
+ constructor(options) {
5
+ this.options = options || {};
6
+ this.projectRoot = options.projectRoot || '.';
7
+ this.operation = options.operation || 'unknown';
8
+
9
+ // Initialize core components
10
+ const { ArtifactManager } = require('./artifact-manager');
11
+ const { ErrorHandler } = require('./error-handler');
12
+ const { ConfigValidator } = require('./config-validator');
13
+ const { FeatureManager } = require('./feature-manager');
14
+ const { FeedbackGenerator } = require('./feedback-generator');
15
+
16
+ this.artifactManager = new ArtifactManager(this.projectRoot);
17
+ this.errorHandler = ErrorHandler;
18
+ this.validator = ConfigValidator;
19
+ this.featureManager = FeatureManager;
20
+ this.feedbackGenerator = FeedbackGenerator;
21
+ }
22
+
23
+ /**
24
+ * Execute the command with standardized flow
25
+ */
26
+ async execute() {
27
+ try {
28
+ // Pre-execution validation
29
+ await this.validate();
30
+
31
+ // Ensure required artifacts exist
32
+ this.artifactManager.ensureArtifacts();
33
+
34
+ // Execute command-specific logic
35
+ const result = await this.run();
36
+
37
+ // Generate feedback based on result
38
+ const feedback = this.generateFeedback(result);
39
+
40
+ // Return comprehensive result
41
+ return {
42
+ success: true,
43
+ result,
44
+ feedback,
45
+ operation: this.operation
46
+ };
47
+
48
+ } catch (error) {
49
+ // Handle error with standardized approach
50
+ return this.errorHandler.handle(error, this.operation);
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Validate command-specific requirements
56
+ */
57
+ async validate() {
58
+ // Command-specific validation - to be implemented by subclasses
59
+ throw new Error('Must implement validate() method');
60
+ }
61
+
62
+ /**
63
+ * Execute command-specific logic
64
+ */
65
+ async run() {
66
+ // Command-specific execution - to be implemented by subclasses
67
+ throw new Error('Must implement run() method');
68
+ }
69
+
70
+ /**
71
+ * Generate command-specific feedback
72
+ */
73
+ generateFeedback(result) {
74
+ // Command-specific feedback generation - to be implemented by subclasses
75
+ throw new Error('Must implement generateFeedback() method');
76
+ }
77
+
78
+ /**
79
+ * Get current feature availability
80
+ */
81
+ getAvailableFeatures() {
82
+ return this.featureManager.getAvailableFeatures(this.projectRoot);
83
+ }
84
+
85
+ /**
86
+ * Get recommendations for this project
87
+ */
88
+ getRecommendations() {
89
+ return this.featureManager.getRecommendations(this.projectRoot);
90
+ }
91
+
92
+ /**
93
+ * Get next steps for this project
94
+ */
95
+ getNextSteps() {
96
+ return this.featureManager.getNextSteps(this.projectRoot);
97
+ }
98
+
99
+ /**
100
+ * Generate user report
101
+ */
102
+ generateUserReport() {
103
+ return this.featureManager.generateUserReport(this.projectRoot);
104
+ }
105
+ }
106
+
107
+ module.exports = { ArcVisionCommand };
@@ -0,0 +1,199 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ class ConfigValidator {
5
+ /**
6
+ * Validates that the project has the required ArcVision artifacts
7
+ */
8
+ static validateProjectStructure(projectPath) {
9
+ const requiredPaths = [
10
+ path.join(projectPath, 'arcvision_context'),
11
+ path.join(projectPath, '.arcvision')
12
+ ];
13
+
14
+ const optionalPaths = [
15
+ path.join(projectPath, 'arcvision_context', 'arcvision.context.json'),
16
+ path.join(projectPath, '.arcvision', 'invariants.json'),
17
+ path.join(projectPath, 'arcvision_context', 'architecture.authority.ledger.json')
18
+ ];
19
+
20
+ const validation = {
21
+ isValid: true,
22
+ errors: [],
23
+ warnings: [],
24
+ requiredPaths: {},
25
+ optionalPaths: {}
26
+ };
27
+
28
+ // Validate required paths exist
29
+ requiredPaths.forEach(requiredPath => {
30
+ const exists = fs.existsSync(requiredPath);
31
+ validation.requiredPaths[requiredPath] = exists;
32
+ if (!exists) {
33
+ validation.isValid = false;
34
+ validation.errors.push(`Required path does not exist: ${requiredPath}`);
35
+ }
36
+ });
37
+
38
+ // Check optional paths
39
+ optionalPaths.forEach(optionalPath => {
40
+ const exists = fs.existsSync(optionalPath);
41
+ validation.optionalPaths[optionalPath] = exists;
42
+ if (!exists) {
43
+ validation.warnings.push(`Optional path does not exist: ${optionalPath}`);
44
+ }
45
+ });
46
+
47
+ return validation;
48
+ }
49
+
50
+ /**
51
+ * Validates invariant file structure
52
+ */
53
+ static validateInvariantsFile(filePath) {
54
+ if (!fs.existsSync(filePath)) {
55
+ return {
56
+ isValid: false,
57
+ error: 'File does not exist'
58
+ };
59
+ }
60
+
61
+ try {
62
+ const content = fs.readFileSync(filePath, 'utf8');
63
+ const data = JSON.parse(content);
64
+
65
+ const validation = {
66
+ isValid: true,
67
+ errors: []
68
+ };
69
+
70
+ // Check for required structure
71
+ if (!data.project_specific_invariants) {
72
+ validation.isValid = false;
73
+ validation.errors.push('Missing project_specific_invariants array');
74
+ } else if (!Array.isArray(data.project_specific_invariants)) {
75
+ validation.isValid = false;
76
+ validation.errors.push('project_specific_invariants must be an array');
77
+ } else {
78
+ // Validate each invariant
79
+ data.project_specific_invariants.forEach((invariant, index) => {
80
+ if (!invariant.id) {
81
+ validation.errors.push(`Invariant at index ${index} missing id`);
82
+ }
83
+ if (!invariant.system) {
84
+ validation.errors.push(`Invariant at index ${index} missing system`);
85
+ }
86
+ if (!invariant.description) {
87
+ validation.errors.push(`Invariant at index ${index} missing description`);
88
+ }
89
+ if (!invariant.severity || !['block', 'risk'].includes(invariant.severity)) {
90
+ validation.errors.push(`Invariant at index ${index} has invalid severity (must be 'block' or 'risk')`);
91
+ }
92
+ if (!invariant.scope) {
93
+ validation.errors.push(`Invariant at index ${index} missing scope`);
94
+ }
95
+ if (!invariant.rule) {
96
+ validation.errors.push(`Invariant at index ${index} missing rule`);
97
+ }
98
+ });
99
+ }
100
+
101
+ if (validation.errors.length > 0) {
102
+ validation.isValid = false;
103
+ }
104
+
105
+ return validation;
106
+ } catch (error) {
107
+ return {
108
+ isValid: false,
109
+ error: `Invalid JSON: ${error.message}`
110
+ };
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Validates context file structure
116
+ */
117
+ static validateContextFile(filePath) {
118
+ if (!fs.existsSync(filePath)) {
119
+ return {
120
+ isValid: false,
121
+ error: 'File does not exist'
122
+ };
123
+ }
124
+
125
+ try {
126
+ const content = fs.readFileSync(filePath, 'utf8');
127
+ const data = JSON.parse(content);
128
+
129
+ const validation = {
130
+ isValid: true,
131
+ errors: []
132
+ };
133
+
134
+ // Basic structure validation
135
+ if (!data.schema_version) {
136
+ validation.errors.push('Missing schema_version');
137
+ }
138
+ if (!data.nodes) {
139
+ validation.errors.push('Missing nodes array');
140
+ }
141
+ if (!Array.isArray(data.nodes)) {
142
+ validation.errors.push('nodes must be an array');
143
+ }
144
+ if (!data.edges) {
145
+ validation.errors.push('Missing edges array');
146
+ }
147
+ if (!Array.isArray(data.edges)) {
148
+ validation.errors.push('edges must be an array');
149
+ }
150
+
151
+ if (validation.errors.length > 0) {
152
+ validation.isValid = false;
153
+ }
154
+
155
+ return validation;
156
+ } catch (error) {
157
+ return {
158
+ isValid: false,
159
+ error: `Invalid JSON: ${error.message}`
160
+ };
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Validates the entire ArcVision configuration
166
+ */
167
+ static validateConfiguration(projectPath) {
168
+ const projectValidation = this.validateProjectStructure(projectPath);
169
+
170
+ const configValidation = {
171
+ projectStructure: projectValidation,
172
+ invariantsFile: null,
173
+ contextFile: null,
174
+ isValid: projectValidation.isValid
175
+ };
176
+
177
+ // Validate invariants file if it exists
178
+ const invariantsPath = path.join(projectPath, '.arcvision', 'invariants.json');
179
+ if (fs.existsSync(invariantsPath)) {
180
+ configValidation.invariantsFile = this.validateInvariantsFile(invariantsPath);
181
+ if (!configValidation.invariantsFile.isValid) {
182
+ configValidation.isValid = false;
183
+ }
184
+ }
185
+
186
+ // Validate context file if it exists
187
+ const contextPath = path.join(projectPath, 'arcvision_context', 'arcvision.context.json');
188
+ if (fs.existsSync(contextPath)) {
189
+ configValidation.contextFile = this.validateContextFile(contextPath);
190
+ if (!configValidation.contextFile.isValid) {
191
+ configValidation.isValid = false;
192
+ }
193
+ }
194
+
195
+ return configValidation;
196
+ }
197
+ }
198
+
199
+ module.exports = { ConfigValidator };
@@ -0,0 +1,106 @@
1
+ class ArcVisionError extends Error {
2
+ constructor(type, message, recoveryStrategy, context) {
3
+ super(message);
4
+ this.name = 'ArcVisionError';
5
+ this.type = type; // FATAL, RECOVERABLE, WARNING
6
+ this.recoveryStrategy = recoveryStrategy; // CONTINUE, SKIP, ABORT
7
+ this.context = context;
8
+ }
9
+ }
10
+
11
+ class ErrorHandler {
12
+ static handle(error, operation = '') {
13
+ // If it's already an ArcVisionError, use its strategy
14
+ if (error instanceof ArcVisionError) {
15
+ return this.executeRecoveryStrategy(error);
16
+ }
17
+
18
+ // For regular errors, classify them based on error type
19
+ const classifiedError = this.classifyError(error, operation);
20
+ return this.executeRecoveryStrategy(classifiedError);
21
+ }
22
+
23
+ static classifyError(error, operation) {
24
+ // Classify based on error type and message
25
+ const message = error.message || String(error);
26
+
27
+ // Check for specific error patterns
28
+ if (message.includes('Cannot read properties of undefined') ||
29
+ message.includes('reading')) {
30
+ return new ArcVisionError(
31
+ 'RECOVERABLE',
32
+ `Property access error during ${operation}: ${message}`,
33
+ 'SKIP',
34
+ { operation, errorType: 'PROPERTY_ACCESS_ERROR' }
35
+ );
36
+ }
37
+
38
+ if (message.includes('ENOENT') || message.includes('no such file')) {
39
+ return new ArcVisionError(
40
+ 'RECOVERABLE',
41
+ `File not found during ${operation}: ${message}`,
42
+ 'SKIP',
43
+ { operation, errorType: 'FILE_NOT_FOUND' }
44
+ );
45
+ }
46
+
47
+ if (message.includes('EACCES') || message.includes('permission denied')) {
48
+ return new ArcVisionError(
49
+ 'FATAL',
50
+ `Permission error during ${operation}: ${message}`,
51
+ 'ABORT',
52
+ { operation, errorType: 'PERMISSION_ERROR' }
53
+ );
54
+ }
55
+
56
+ // Default classification for unknown errors
57
+ return new ArcVisionError(
58
+ 'FATAL',
59
+ `Unexpected error during ${operation}: ${message}`,
60
+ 'ABORT',
61
+ { operation, errorType: 'UNKNOWN_ERROR', originalError: error }
62
+ );
63
+ }
64
+
65
+ static executeRecoveryStrategy(error) {
66
+ const strategy = error.recoveryStrategy || 'ABORT';
67
+
68
+ switch(strategy) {
69
+ case 'CONTINUE':
70
+ console.warn(`⚠️ ${error.message}`);
71
+ return {
72
+ success: true,
73
+ result: null,
74
+ error: error,
75
+ shouldContinue: true
76
+ };
77
+
78
+ case 'SKIP':
79
+ console.warn(`⏭️ Skipping due to: ${error.message}`);
80
+ return {
81
+ success: true,
82
+ result: 'skipped',
83
+ error: error,
84
+ shouldContinue: true
85
+ };
86
+
87
+ case 'ABORT':
88
+ default:
89
+ console.error(`💥 ${error.message}`);
90
+ console.error(`Context:`, error.context);
91
+ process.exit(1);
92
+ }
93
+ }
94
+
95
+ static createError(type, message, recoveryStrategy = 'ABORT', context = {}) {
96
+ return new ArcVisionError(type, message, recoveryStrategy, context);
97
+ }
98
+
99
+ static handleAsync(promise, operation = '') {
100
+ return promise.catch(error => {
101
+ return this.handle(error, operation);
102
+ });
103
+ }
104
+ }
105
+
106
+ module.exports = { ErrorHandler, ArcVisionError };