arcvision 0.2.17 → 0.2.21

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 (65) hide show
  1. package/.arcvision/logs/errors.log +7 -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/arcvision-guard.js +17 -17
  6. package/src/core/artifact-manager.js +131 -0
  7. package/src/core/command-base.js +107 -0
  8. package/src/core/config-validator.js +192 -0
  9. package/src/core/context_builder.js +3 -2
  10. package/src/core/error-handler.js +106 -0
  11. package/src/core/feature-manager.js +232 -0
  12. package/src/core/feedback-generator.js +260 -0
  13. package/src/core/invariant-analyzer.js +22 -2
  14. package/src/core/invariant-detector.js +254 -3
  15. package/src/core/parser.js +85 -1
  16. package/src/core/scanner.js +20 -7
  17. package/src/engine/context_builder.js +21 -3
  18. package/src/engine/context_validator.js +7 -1
  19. package/src/engine/pass1_facts.js +2 -2
  20. package/src/index.js +79 -21
  21. package/test-block-functionality.js +40 -0
  22. package/test-dev-project/.arcvision/invariants.json +19 -0
  23. package/{arcvision_context → test-dev-project/arcvision_context}/README.md +9 -9
  24. package/test-dev-project/arcvision_context/architecture.authority.ledger.json +45 -0
  25. package/{arcvision.context.json → test-dev-project/arcvision_context/arcvision.context.json} +498 -496
  26. package/test-dev-project/src/core/data-service.js +0 -0
  27. package/test-dev-project/src/ui/user-profile.js +0 -0
  28. package/test-dev-project/src/utils/helpers.js +0 -0
  29. package/ARCVISION_DIRECTORY_STRUCTURE.md +0 -104
  30. package/CLI_STRUCTURE.md +0 -110
  31. package/CONFIGURATION.md +0 -119
  32. package/IMPLEMENTATION_SUMMARY.md +0 -99
  33. package/README.md +0 -149
  34. package/architecture.authority.ledger.json +0 -46
  35. package/arcvision-0.2.3.tgz +0 -0
  36. package/arcvision-0.2.4.tgz +0 -0
  37. package/arcvision-0.2.5.tgz +0 -0
  38. package/arcvision.context.diff.json +0 -2181
  39. package/arcvision.context.v1.json +0 -2163
  40. package/arcvision.context.v2.json +0 -2173
  41. package/arcvision_context/arcvision.context.json +0 -6884
  42. package/debug-cycle-detection.js +0 -56
  43. package/docs/ENHANCED_ACCURACY_SAFETY_PROTOCOL.md +0 -172
  44. package/docs/accuracy-enhancement-artifacts/enhanced-validation-config.json +0 -98
  45. package/docs/acig-robustness-guide.md +0 -164
  46. package/docs/authoritative-gate-implementation.md +0 -168
  47. package/docs/blast-radius-implementation.md +0 -76
  48. package/docs/blast-radius.md +0 -44
  49. package/docs/cli-strengthening-summary.md +0 -232
  50. package/docs/invariant-system-summary.md +0 -100
  51. package/docs/invariant-system.md +0 -112
  52. package/generate_large_test.js +0 -42
  53. package/large_test_repo.json +0 -1
  54. package/output1.json +0 -2163
  55. package/output2.json +0 -2163
  56. package/scan_calcom_report.txt +0 -0
  57. package/scan_leafmint_report.txt +0 -0
  58. package/scan_output.txt +0 -0
  59. package/scan_trigger_report.txt +0 -0
  60. package/temp_original.js +0 -0
  61. package/test/determinism-test.js +0 -83
  62. package/test-authoritative-context.js +0 -53
  63. package/test-real-authoritative-context.js +0 -118
  64. package/test-upload-enhancements.js +0 -111
  65. package/verify_engine.js +0 -116
@@ -0,0 +1,7 @@
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)"}
6
+ {"timestamp":"2026-01-25T10:28:14.750Z","error":{"category":"UNKNOWN","message":"Failed to initiate upload session","code":null,"type":"Error"},"context":{"operation":"chunked_upload"},"stack":"Error: Failed to initiate upload session\n at ChunkedUploader.uploadInChunks (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\core\\chunked-uploader.js:58:13)\n at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n at async C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\index.js:177:18\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:176:24)\n at async Command.<anonymous> (C:\\Users\\AHMAD RAZA\\Downloads\\ArcVision\\cli\\src\\index.js:473:9)"}
7
+ {"timestamp":"2026-01-25T14:09:23.628Z","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:341: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:473: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.17",
3
+ "version": "0.2.21",
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",
@@ -206,11 +206,17 @@ program
206
206
  fs.mkdirSync(tokensDir, { recursive: true });
207
207
  }
208
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'));
209
+ // Create default configuration (no longer using separate invariants file as they're stored in context)
210
+ const configPath = path.join(arcDir, 'config.json');
211
+ if (!fs.existsSync(configPath)) {
212
+ const defaultConfig = {
213
+ guard_rules: {
214
+ blast_radius: {
215
+ critical_threshold: 50
216
+ }
217
+ }
218
+ };
219
+ fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2));
214
220
  console.log(chalk.green('✅ Configuration files created'));
215
221
  }
216
222
 
@@ -223,7 +229,7 @@ program
223
229
  console.log(chalk.green('\n🎉 ArcVision Impact Guard initialized successfully!'));
224
230
  console.log(chalk.yellow('\nNext steps:'));
225
231
  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'));
232
+ console.log(chalk.yellow('2. Auto-detect architectural invariants by running: arcvision scan'));
227
233
  console.log(chalk.yellow('3. Run: arcvision-guard check'));
228
234
  console.log(chalk.yellow('4. For critical changes: arcvision-guard bypass-request --reason "your reason"'));
229
235
  });
@@ -246,17 +252,11 @@ program
246
252
  remediation: "Define appropriate remediation steps"
247
253
  };
248
254
 
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}`));
255
+ // Note: Invariants are now automatically detected by scanning and stored in arcvision.context.json
256
+ console.log(chalk.red('❌ Custom invariants are now managed differently.'));
257
+ console.log(chalk.yellow('💡 Run "arcvision scan" to auto-detect invariants from your codebase.'));
258
+ console.log(chalk.yellow('💡 Or manually edit the invariants section in arcvision_context/arcvision.context.json if needed.'));
259
+ process.exit(1);
260
260
  });
261
261
 
262
262
  // Helper functions
@@ -0,0 +1,131 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ class ArtifactManager {
5
+ constructor(projectRoot) {
6
+ this.projectRoot = projectRoot;
7
+ // Remove .arcvision directory as invariants should be in main context file only
8
+ this.requiredDirs = ['arcvision_context'];
9
+ this.requiredFiles = {
10
+ context: 'arcvision_context/arcvision.context.json',
11
+ ledger: 'arcvision_context/architecture.authority.ledger.json'
12
+ // Remove invariants from separate file as they should be in main context per schema
13
+ };
14
+ }
15
+
16
+ /**
17
+ * Ensures all required artifacts exist with proper structure
18
+ */
19
+ ensureArtifacts() {
20
+ // Create required directories
21
+ this.createDirectories();
22
+
23
+ // Create required files with defaults if missing
24
+ this.createMissingFiles();
25
+
26
+ // Validate artifact integrity (excluding context file which is created by scanner)
27
+ this.validateArtifactsExceptContext();
28
+ }
29
+
30
+ /**
31
+ * Creates required directories if they don't exist
32
+ */
33
+ createDirectories() {
34
+ this.requiredDirs.forEach(dir => {
35
+ const fullPath = path.join(this.projectRoot, dir);
36
+ if (!fs.existsSync(fullPath)) {
37
+ fs.mkdirSync(fullPath, { recursive: true });
38
+ this.logCreation(dir);
39
+ }
40
+ });
41
+ }
42
+
43
+ /**
44
+ * Creates missing files with default content
45
+ */
46
+ createMissingFiles() {
47
+ // Create default ledger if missing
48
+ const ledgerPath = path.join(this.projectRoot, this.requiredFiles.ledger);
49
+ if (!fs.existsSync(ledgerPath)) {
50
+ const defaultLedger = {
51
+ schema_version: '1.0',
52
+ system_id: path.basename(this.projectRoot),
53
+ created_at: new Date().toISOString(),
54
+ ledger: []
55
+ };
56
+
57
+ fs.writeFileSync(ledgerPath, JSON.stringify(defaultLedger, null, 2));
58
+ this.logCreation(this.requiredFiles.ledger);
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Validates that all required artifacts exist and are accessible
64
+ */
65
+ validateArtifacts() {
66
+ const missingArtifacts = [];
67
+
68
+ Object.entries(this.requiredFiles).forEach(([name, relativePath]) => {
69
+ const fullPath = path.join(this.projectRoot, relativePath);
70
+ if (!fs.existsSync(fullPath)) {
71
+ missingArtifacts.push(relativePath);
72
+ }
73
+ });
74
+
75
+ if (missingArtifacts.length > 0) {
76
+ throw new Error(`Missing required artifacts: ${missingArtifacts.join(', ')}`);
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Validates artifacts except context file (which is created by scanner)
82
+ */
83
+ validateArtifactsExceptContext() {
84
+ const missingArtifacts = [];
85
+
86
+ Object.entries(this.requiredFiles).forEach(([name, relativePath]) => {
87
+ // Skip context file validation as it's created by scanner
88
+ if (name === 'context') return;
89
+
90
+ const fullPath = path.join(this.projectRoot, relativePath);
91
+ if (!fs.existsSync(fullPath)) {
92
+ missingArtifacts.push(relativePath);
93
+ }
94
+ });
95
+
96
+ if (missingArtifacts.length > 0) {
97
+ throw new Error(`Missing required artifacts: ${missingArtifacts.join(', ')}`);
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Checks if artifacts exist
103
+ */
104
+ artifactsExist() {
105
+ try {
106
+ this.validateArtifacts();
107
+ return true;
108
+ } catch (error) {
109
+ return false;
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Gets the path for a specific artifact
115
+ */
116
+ getArtifactPath(artifactName) {
117
+ if (this.requiredFiles[artifactName]) {
118
+ return path.join(this.projectRoot, this.requiredFiles[artifactName]);
119
+ }
120
+ throw new Error(`Unknown artifact: ${artifactName}`);
121
+ }
122
+
123
+ /**
124
+ * Logs artifact creation
125
+ */
126
+ logCreation(artifact) {
127
+ console.log(`📁 Created required artifact: ${artifact}`);
128
+ }
129
+ }
130
+
131
+ 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,192 @@
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
+ // Removed .arcvision as invariants are now stored in main context file
12
+ ];
13
+
14
+ const optionalPaths = [
15
+ path.join(projectPath, 'arcvision_context', 'arcvision.context.json'),
16
+ // Removed .arcvision/invariants.json as invariants are now stored in main context file
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
+ // No longer validating separate invariants file as they are stored in main context file
178
+
179
+ // Validate context file if it exists
180
+ const contextPath = path.join(projectPath, 'arcvision_context', 'arcvision.context.json');
181
+ if (fs.existsSync(contextPath)) {
182
+ configValidation.contextFile = this.validateContextFile(contextPath);
183
+ if (!configValidation.contextFile.isValid) {
184
+ configValidation.isValid = false;
185
+ }
186
+ }
187
+
188
+ return configValidation;
189
+ }
190
+ }
191
+
192
+ module.exports = { ConfigValidator };
@@ -190,8 +190,9 @@ function buildContext(fileNodes, edges, symbols, options = {}) {
190
190
  structural_hubs: options.structuralHubs || [],
191
191
  architectural_boundaries: options.architecturalBoundaries || {},
192
192
  structural_invariants: options.structuralInvariants || [],
193
- // Include detected invariants from the current scan
194
- invariants: options.detectedInvariants || [],
193
+ // Include detected invariants from the current scan - these should conform to the schema specification
194
+ invariants: Array.isArray(options.autoDetectedInvariants) ? options.autoDetectedInvariants :
195
+ Array.isArray(options.detectedInvariants) ? options.detectedInvariants : [],
195
196
  // Include invariant analysis results
196
197
  invariant_analysis: options.invariantAnalysis || null,
197
198
  // Include architectural health assessment