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.
- package/.arcvision/logs/errors.log +5 -0
- package/arcvision_context/architecture.authority.ledger.json +6 -63
- package/bin/arcvision.js +12 -0
- package/package.json +3 -2
- package/src/core/artifact-manager.js +143 -0
- package/src/core/command-base.js +107 -0
- package/src/core/config-validator.js +199 -0
- package/src/core/error-handler.js +106 -0
- package/src/core/feature-manager.js +218 -0
- package/src/core/feedback-generator.js +260 -0
- package/src/core/invariant-analyzer.js +22 -2
- package/src/core/invariant-detector.js +236 -3
- package/src/core/parser.js +85 -1
- package/src/core/scanner.js +18 -6
- package/src/engine/context_builder.js +21 -3
- package/src/engine/context_validator.js +7 -1
- package/src/engine/pass1_facts.js +2 -2
- package/src/index.js +41 -13
- package/test-block-functionality.js +40 -0
- package/test-dev-project/.arcvision/invariants.json +19 -0
- package/{arcvision_context → test-dev-project/arcvision_context}/README.md +9 -9
- package/test-dev-project/arcvision_context/architecture.authority.ledger.json +45 -0
- package/{arcvision.context.json → test-dev-project/arcvision_context/arcvision.context.json} +498 -496
- package/test-dev-project/src/core/data-service.js +0 -0
- package/test-dev-project/src/ui/user-profile.js +0 -0
- package/test-dev-project/src/utils/helpers.js +0 -0
- package/ARCVISION_DIRECTORY_STRUCTURE.md +0 -104
- package/CLI_STRUCTURE.md +0 -110
- package/CONFIGURATION.md +0 -119
- package/IMPLEMENTATION_SUMMARY.md +0 -99
- package/README.md +0 -149
- package/architecture.authority.ledger.json +0 -46
- package/arcvision-0.2.3.tgz +0 -0
- package/arcvision-0.2.4.tgz +0 -0
- package/arcvision-0.2.5.tgz +0 -0
- package/arcvision.context.diff.json +0 -2181
- package/arcvision.context.v1.json +0 -2163
- package/arcvision.context.v2.json +0 -2173
- package/arcvision_context/arcvision.context.json +0 -6884
- package/debug-cycle-detection.js +0 -56
- package/docs/ENHANCED_ACCURACY_SAFETY_PROTOCOL.md +0 -172
- package/docs/accuracy-enhancement-artifacts/enhanced-validation-config.json +0 -98
- package/docs/acig-robustness-guide.md +0 -164
- package/docs/authoritative-gate-implementation.md +0 -168
- package/docs/blast-radius-implementation.md +0 -76
- package/docs/blast-radius.md +0 -44
- package/docs/cli-strengthening-summary.md +0 -232
- package/docs/invariant-system-summary.md +0 -100
- package/docs/invariant-system.md +0 -112
- package/generate_large_test.js +0 -42
- package/large_test_repo.json +0 -1
- package/output1.json +0 -2163
- package/output2.json +0 -2163
- package/scan_calcom_report.txt +0 -0
- package/scan_leafmint_report.txt +0 -0
- package/scan_output.txt +0 -0
- package/scan_trigger_report.txt +0 -0
- package/temp_original.js +0 -0
- package/test/determinism-test.js +0 -83
- package/test-authoritative-context.js +0 -53
- package/test-real-authoritative-context.js +0 -118
- package/test-upload-enhancements.js +0 -111
- 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-
|
|
4
|
+
"created_at": "2026-01-25T01:42:21.875Z",
|
|
5
5
|
"ledger": [
|
|
6
6
|
{
|
|
7
|
-
"event_id": "
|
|
8
|
-
"timestamp": "2026-01-
|
|
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-
|
|
16
|
-
"description": "
|
|
17
|
-
"system": "
|
|
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
|
],
|
package/bin/arcvision.js
ADDED
|
@@ -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.
|
|
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": "
|
|
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 };
|