arcvision 0.2.14 → 0.2.16
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_DIRECTORY_STRUCTURE.md +104 -0
- package/CLI_STRUCTURE.md +110 -0
- package/CONFIGURATION.md +119 -0
- package/IMPLEMENTATION_SUMMARY.md +99 -0
- package/README.md +149 -89
- package/architecture.authority.ledger.json +46 -0
- 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 +2181 -0
- package/arcvision.context.json +1021 -0
- package/arcvision.context.v1.json +2163 -0
- package/arcvision.context.v2.json +2173 -0
- package/arcvision_context/README.md +93 -0
- package/arcvision_context/architecture.authority.ledger.json +83 -0
- package/arcvision_context/arcvision.context.json +6884 -0
- package/debug-cycle-detection.js +56 -0
- package/dist/index.js +1626 -25
- package/docs/ENHANCED_ACCURACY_SAFETY_PROTOCOL.md +172 -0
- package/docs/accuracy-enhancement-artifacts/enhanced-validation-config.json +98 -0
- package/docs/acig-robustness-guide.md +164 -0
- package/docs/authoritative-gate-implementation.md +168 -0
- package/docs/cli-strengthening-summary.md +232 -0
- package/docs/invariant-system-summary.md +100 -0
- package/docs/invariant-system.md +112 -0
- package/generate_large_test.js +42 -0
- package/large_test_repo.json +1 -0
- package/output1.json +2163 -0
- package/output2.json +2163 -0
- package/package.json +46 -36
- 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/schema/arcvision_context_schema_v1.json +136 -1
- package/src/arcvision-guard.js +433 -0
- package/src/core/authority-core-detector.js +382 -0
- package/src/core/authority-ledger.js +300 -0
- package/src/core/blastRadius.js +299 -0
- package/src/core/call-resolver.js +196 -0
- package/src/core/change-evaluator.js +509 -0
- package/src/core/change-evaluator.js.backup +424 -0
- package/src/core/change-evaluator.ts +285 -0
- package/src/core/chunked-uploader.js +180 -0
- package/src/core/circular-dependency-detector.js +404 -0
- package/src/core/cli-error-handler.js +458 -0
- package/src/core/cli-validator.js +458 -0
- package/src/core/compression.js +64 -0
- package/src/core/context_builder.js +741 -0
- package/src/core/dependency-manager.js +134 -0
- package/src/core/di-detector.js +202 -0
- package/src/core/diff-analyzer.js +76 -0
- package/src/core/example-invariants.js +135 -0
- package/src/core/failure-mode-synthesizer.js +341 -0
- package/src/core/invariant-analyzer.js +294 -0
- package/src/core/invariant-detector.js +548 -0
- package/src/core/invariant-enforcer.js +171 -0
- package/src/core/invariant-evaluation-utils.js +172 -0
- package/src/core/invariant-hooks.js +152 -0
- package/src/core/invariant-integration-example.js +186 -0
- package/src/core/invariant-registry.js +298 -0
- package/src/core/invariant-registry.ts +100 -0
- package/src/core/invariant-types.js +66 -0
- package/src/core/invariants-index.js +88 -0
- package/src/core/method-tracker.js +170 -0
- package/src/core/override-handler.js +304 -0
- package/src/core/ownership-resolver.js +227 -0
- package/src/core/parser-enhanced.js +80 -0
- package/src/core/parser.js +610 -0
- package/src/core/path-resolver.js +240 -0
- package/src/core/pattern-matcher.js +246 -0
- package/src/core/progress-tracker.js +71 -0
- package/src/core/react-nextjs-detector.js +245 -0
- package/src/core/readme-generator.js +167 -0
- package/src/core/retry-handler.js +57 -0
- package/src/core/scanner.js +289 -0
- package/src/core/semantic-analyzer.js +204 -0
- package/src/core/structural-context-owner.js +442 -0
- package/src/core/symbol-indexer.js +164 -0
- package/src/core/tsconfig-utils.js +73 -0
- package/src/core/type-analyzer.js +272 -0
- package/src/core/watcher.js +18 -0
- package/src/core/workspace-scanner.js +88 -0
- package/src/engine/context_builder.js +280 -0
- package/src/engine/context_sorter.js +59 -0
- package/src/engine/context_validator.js +200 -0
- package/src/engine/id-generator.js +16 -0
- package/src/engine/pass1_facts.js +260 -0
- package/src/engine/pass2_semantics.js +333 -0
- package/src/engine/pass3_lifter.js +99 -0
- package/src/engine/pass4_signals.js +201 -0
- package/src/index.js +830 -0
- package/src/plugins/express-plugin.js +48 -0
- package/src/plugins/plugin-manager.js +58 -0
- package/src/plugins/react-plugin.js +54 -0
- package/temp_original.js +0 -0
- package/test/determinism-test.js +83 -0
- package/test-authoritative-context.js +53 -0
- package/test-real-authoritative-context.js +118 -0
- package/test-upload-enhancements.js +111 -0
- package/test_repos/allowed-clean-architecture/.arcvision/invariants.json +57 -0
- package/test_repos/allowed-clean-architecture/adapters/controllers/UserController.js +95 -0
- package/test_repos/allowed-clean-architecture/adapters/http/HttpServer.js +78 -0
- package/test_repos/allowed-clean-architecture/application/dtos/CreateUserRequest.js +37 -0
- package/test_repos/allowed-clean-architecture/application/services/UserService.js +61 -0
- package/test_repos/allowed-clean-architecture/arcvision_context/README.md +93 -0
- package/test_repos/allowed-clean-architecture/arcvision_context/arcvision.context.json +2796 -0
- package/test_repos/allowed-clean-architecture/domain/interfaces/UserRepository.js +25 -0
- package/test_repos/allowed-clean-architecture/domain/models/User.js +39 -0
- package/test_repos/allowed-clean-architecture/index.js +45 -0
- package/test_repos/allowed-clean-architecture/infrastructure/database/DatabaseConnection.js +56 -0
- package/test_repos/allowed-clean-architecture/infrastructure/repositories/InMemoryUserRepository.js +61 -0
- package/test_repos/allowed-clean-architecture/package.json +15 -0
- package/test_repos/blocked-legacy-monolith/.arcvision/invariants.json +78 -0
- package/test_repos/blocked-legacy-monolith/arcvision_context/README.md +93 -0
- package/test_repos/blocked-legacy-monolith/arcvision_context/arcvision.context.json +2882 -0
- package/test_repos/blocked-legacy-monolith/database/dbConnection.js +35 -0
- package/test_repos/blocked-legacy-monolith/index.js +38 -0
- package/test_repos/blocked-legacy-monolith/modules/emailService.js +31 -0
- package/test_repos/blocked-legacy-monolith/modules/paymentProcessor.js +37 -0
- package/test_repos/blocked-legacy-monolith/package.json +15 -0
- package/test_repos/blocked-legacy-monolith/shared/utils.js +19 -0
- package/test_repos/blocked-legacy-monolith/utils/helpers.js +23 -0
- package/test_repos/risky-microservices-concerns/.arcvision/invariants.json +69 -0
- package/test_repos/risky-microservices-concerns/arcvision_context/README.md +93 -0
- package/test_repos/risky-microservices-concerns/arcvision_context/arcvision.context.json +3070 -0
- package/test_repos/risky-microservices-concerns/common/utils.js +77 -0
- package/test_repos/risky-microservices-concerns/gateways/apiGateway.js +84 -0
- package/test_repos/risky-microservices-concerns/index.js +20 -0
- package/test_repos/risky-microservices-concerns/libs/deprecatedHelper.js +36 -0
- package/test_repos/risky-microservices-concerns/package.json +15 -0
- package/test_repos/risky-microservices-concerns/services/orderService.js +42 -0
- package/test_repos/risky-microservices-concerns/services/userService.js +48 -0
- package/verify_engine.js +116 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Third-party Dependency Manager
|
|
3
|
+
* Provides resilient error handling for external dependencies
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class DependencyManager {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.cache = new Map();
|
|
9
|
+
this.failedImports = new Set();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Safely import a module with fallbacks
|
|
14
|
+
*/
|
|
15
|
+
safeImport(moduleName, fallbackValue = null, options = {}) {
|
|
16
|
+
const cacheKey = `${moduleName}_${!!options.useCache}`;
|
|
17
|
+
|
|
18
|
+
// Return cached value if available and caching is enabled
|
|
19
|
+
if (options.useCache && this.cache.has(cacheKey)) {
|
|
20
|
+
return this.cache.get(cacheKey);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Skip if module previously failed to import
|
|
24
|
+
if (this.failedImports.has(moduleName)) {
|
|
25
|
+
return fallbackValue;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const module = require(moduleName);
|
|
30
|
+
|
|
31
|
+
// Cache successful imports
|
|
32
|
+
if (options.useCache) {
|
|
33
|
+
this.cache.set(cacheKey, module);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return module;
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.warn(`⚠️ Failed to import module "${moduleName}":`, error.message);
|
|
39
|
+
|
|
40
|
+
// Mark as failed to avoid repeated attempts
|
|
41
|
+
this.failedImports.add(moduleName);
|
|
42
|
+
|
|
43
|
+
return fallbackValue;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Execute a function with dependency fallbacks
|
|
49
|
+
*/
|
|
50
|
+
withDependency(moduleName, executor, fallbackExecutor, options = {}) {
|
|
51
|
+
const module = this.safeImport(moduleName, null, options);
|
|
52
|
+
|
|
53
|
+
if (module) {
|
|
54
|
+
try {
|
|
55
|
+
return executor(module);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.warn(`⚠️ Error executing with ${moduleName}:`, error.message);
|
|
58
|
+
if (fallbackExecutor) {
|
|
59
|
+
return fallbackExecutor(error);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
if (fallbackExecutor) {
|
|
64
|
+
return fallbackExecutor(new Error(`Module ${moduleName} not available`));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Async version of withDependency
|
|
73
|
+
*/
|
|
74
|
+
async withDependencyAsync(moduleName, executor, fallbackExecutor, options = {}) {
|
|
75
|
+
const module = this.safeImport(moduleName, null, options);
|
|
76
|
+
|
|
77
|
+
if (module) {
|
|
78
|
+
try {
|
|
79
|
+
return await executor(module);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.warn(`⚠️ Error executing with ${moduleName}:`, error.message);
|
|
82
|
+
if (fallbackExecutor) {
|
|
83
|
+
return await fallbackExecutor(error);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
if (fallbackExecutor) {
|
|
88
|
+
return await fallbackExecutor(new Error(`Module ${moduleName} not available`));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Safe method call with fallback
|
|
97
|
+
*/
|
|
98
|
+
safeCall(obj, methodName, args = [], fallbackValue = null) {
|
|
99
|
+
if (!obj || typeof obj[methodName] !== 'function') {
|
|
100
|
+
return fallbackValue;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
return obj[methodName](...args);
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.warn(`⚠️ Error calling ${methodName}:`, error.message);
|
|
107
|
+
return fallbackValue;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Clear caches (for testing or refresh)
|
|
113
|
+
*/
|
|
114
|
+
clearCache() {
|
|
115
|
+
this.cache.clear();
|
|
116
|
+
this.failedImports.clear();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Get diagnostic information
|
|
121
|
+
*/
|
|
122
|
+
getDiagnostics() {
|
|
123
|
+
return {
|
|
124
|
+
cachedModules: Array.from(this.cache.keys()),
|
|
125
|
+
failedImports: Array.from(this.failedImports),
|
|
126
|
+
cacheSize: this.cache.size
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Singleton instance
|
|
132
|
+
const dependencyManager = new DependencyManager();
|
|
133
|
+
|
|
134
|
+
module.exports = { DependencyManager, dependencyManager };
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency Injection Detector
|
|
3
|
+
*
|
|
4
|
+
* Detects various dependency injection patterns including:
|
|
5
|
+
* - Constructor injection
|
|
6
|
+
* - React Context usage (useContext, Provider, Consumer)
|
|
7
|
+
* - Custom hook dependencies
|
|
8
|
+
* - Service locator patterns
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const traverse = require('@babel/traverse').default;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Detect constructor injection patterns
|
|
15
|
+
* @param {Object} ast - Babel AST
|
|
16
|
+
* @returns {Array} Array of constructor injection dependencies
|
|
17
|
+
*/
|
|
18
|
+
function detectConstructorInjection(ast) {
|
|
19
|
+
const injections = [];
|
|
20
|
+
|
|
21
|
+
traverse(ast, {
|
|
22
|
+
ClassDeclaration(path) {
|
|
23
|
+
const className = path.node.id ? path.node.id.name : 'Anonymous';
|
|
24
|
+
|
|
25
|
+
// Find constructor
|
|
26
|
+
const constructor = path.node.body.body.find(
|
|
27
|
+
member => member.kind === 'constructor'
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
if (constructor && constructor.params) {
|
|
31
|
+
constructor.params.forEach(param => {
|
|
32
|
+
let paramName = null;
|
|
33
|
+
let paramType = null;
|
|
34
|
+
|
|
35
|
+
// Handle TypeScript parameter properties
|
|
36
|
+
if (param.type === 'TSParameterProperty') {
|
|
37
|
+
if (param.parameter.type === 'Identifier') {
|
|
38
|
+
paramName = param.parameter.name;
|
|
39
|
+
if (param.parameter.typeAnnotation) {
|
|
40
|
+
paramType = extractTypeName(param.parameter.typeAnnotation);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
} else if (param.type === 'Identifier') {
|
|
44
|
+
paramName = param.name;
|
|
45
|
+
if (param.typeAnnotation) {
|
|
46
|
+
paramType = extractTypeName(param.typeAnnotation);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (paramName) {
|
|
51
|
+
injections.push({
|
|
52
|
+
className,
|
|
53
|
+
paramName,
|
|
54
|
+
paramType,
|
|
55
|
+
pattern: 'constructor_injection',
|
|
56
|
+
loc: constructor.loc
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
return injections;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Detect React Context usage patterns
|
|
69
|
+
* @param {Object} ast - Babel AST
|
|
70
|
+
* @returns {Array} Array of context dependencies
|
|
71
|
+
*/
|
|
72
|
+
function detectReactContextUsage(ast) {
|
|
73
|
+
const contextUsages = [];
|
|
74
|
+
|
|
75
|
+
traverse(ast, {
|
|
76
|
+
// Detect useContext hook calls
|
|
77
|
+
CallExpression(path) {
|
|
78
|
+
if (path.node.callee.name === 'useContext' && path.node.arguments.length > 0) {
|
|
79
|
+
const contextArg = path.node.arguments[0];
|
|
80
|
+
let contextName = null;
|
|
81
|
+
|
|
82
|
+
if (contextArg.type === 'Identifier') {
|
|
83
|
+
contextName = contextArg.name;
|
|
84
|
+
} else if (contextArg.type === 'MemberExpression') {
|
|
85
|
+
contextName = extractMemberExpressionName(contextArg);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (contextName) {
|
|
89
|
+
contextUsages.push({
|
|
90
|
+
type: 'useContext',
|
|
91
|
+
contextName,
|
|
92
|
+
pattern: 'context_consumer',
|
|
93
|
+
loc: path.node.loc
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
// Detect Context.Provider usage in JSX
|
|
100
|
+
JSXElement(path) {
|
|
101
|
+
const openingElement = path.node.openingElement;
|
|
102
|
+
if (openingElement.name.type === 'JSXMemberExpression') {
|
|
103
|
+
const objectName = openingElement.name.object.name;
|
|
104
|
+
const propertyName = openingElement.name.property.name;
|
|
105
|
+
|
|
106
|
+
if (propertyName === 'Provider' || propertyName === 'Consumer') {
|
|
107
|
+
contextUsages.push({
|
|
108
|
+
type: 'JSXProvider',
|
|
109
|
+
contextName: objectName,
|
|
110
|
+
pattern: propertyName === 'Provider' ? 'context_provider' : 'context_consumer',
|
|
111
|
+
loc: path.node.loc
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
return contextUsages;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Detect custom hook dependencies
|
|
123
|
+
* @param {Object} ast - Babel AST
|
|
124
|
+
* @returns {Array} Array of hook dependencies
|
|
125
|
+
*/
|
|
126
|
+
function detectHookDependencies(ast) {
|
|
127
|
+
const hookDeps = [];
|
|
128
|
+
|
|
129
|
+
traverse(ast, {
|
|
130
|
+
CallExpression(path) {
|
|
131
|
+
const calleeName = path.node.callee.name;
|
|
132
|
+
|
|
133
|
+
// Check if it's a custom hook (starts with 'use')
|
|
134
|
+
if (calleeName && calleeName.startsWith('use') && calleeName !== 'useContext') {
|
|
135
|
+
hookDeps.push({
|
|
136
|
+
hookName: calleeName,
|
|
137
|
+
pattern: 'custom_hook',
|
|
138
|
+
loc: path.node.loc
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
return hookDeps;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Detect all DI patterns in a file
|
|
149
|
+
* @param {Object} ast - Babel AST
|
|
150
|
+
* @returns {Object} All detected DI patterns
|
|
151
|
+
*/
|
|
152
|
+
function detectDependencyInjection(ast) {
|
|
153
|
+
if (!ast) {
|
|
154
|
+
return {
|
|
155
|
+
constructorInjections: [],
|
|
156
|
+
contextUsages: [],
|
|
157
|
+
hookDependencies: []
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
constructorInjections: detectConstructorInjection(ast),
|
|
163
|
+
contextUsages: detectReactContextUsage(ast),
|
|
164
|
+
hookDependencies: detectHookDependencies(ast)
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Helper: Extract type name from TypeScript type annotation
|
|
170
|
+
*/
|
|
171
|
+
function extractTypeName(typeAnnotation) {
|
|
172
|
+
if (!typeAnnotation) return null;
|
|
173
|
+
|
|
174
|
+
const annotation = typeAnnotation.typeAnnotation || typeAnnotation;
|
|
175
|
+
|
|
176
|
+
if (annotation.type === 'TSTypeReference' && annotation.typeName) {
|
|
177
|
+
if (annotation.typeName.type === 'Identifier') {
|
|
178
|
+
return annotation.typeName.name;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Helper: Extract name from member expression
|
|
187
|
+
*/
|
|
188
|
+
function extractMemberExpressionName(node) {
|
|
189
|
+
if (node.type === 'MemberExpression') {
|
|
190
|
+
const object = node.object.name || '';
|
|
191
|
+
const property = node.property.name || '';
|
|
192
|
+
return object + '.' + property;
|
|
193
|
+
}
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
module.exports = {
|
|
198
|
+
detectConstructorInjection,
|
|
199
|
+
detectReactContextUsage,
|
|
200
|
+
detectHookDependencies,
|
|
201
|
+
detectDependencyInjection
|
|
202
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compare two context artifacts and generate a structural diff summary
|
|
3
|
+
* @param {Object} oldContext - Previous context artifact
|
|
4
|
+
* @param {Object} newContext - New context artifact
|
|
5
|
+
* @returns {Object} Diff summary with node/edge/role changes
|
|
6
|
+
*/
|
|
7
|
+
function generateDiffSummary(oldContext, newContext) {
|
|
8
|
+
const diffSummary = {
|
|
9
|
+
nodes_added: 0,
|
|
10
|
+
nodes_removed: 0,
|
|
11
|
+
edges_added: 0,
|
|
12
|
+
edges_removed: 0,
|
|
13
|
+
roles_changed: 0,
|
|
14
|
+
blast_radius_changes: 0
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// Compare nodes
|
|
18
|
+
const oldNodeMap = new Map(oldContext.nodes.map(node => [node.path, node]));
|
|
19
|
+
const newNodeMap = new Map(newContext.nodes.map(node => [node.path, node]));
|
|
20
|
+
|
|
21
|
+
// Count added and removed nodes
|
|
22
|
+
for (const [path, node] of newNodeMap) {
|
|
23
|
+
if (!oldNodeMap.has(path)) {
|
|
24
|
+
diffSummary.nodes_added++;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
for (const [path, node] of oldNodeMap) {
|
|
29
|
+
if (!newNodeMap.has(path)) {
|
|
30
|
+
diffSummary.nodes_removed++;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Compare edges
|
|
35
|
+
const oldEdgeMap = new Map(
|
|
36
|
+
oldContext.edges.map(edge => [`${edge.from}::${edge.to}::${edge.relation}`, edge])
|
|
37
|
+
);
|
|
38
|
+
const newEdgeMap = new Map(
|
|
39
|
+
newContext.edges.map(edge => [`${edge.from}::${edge.to}::${edge.relation}`, edge])
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
// Count added and removed edges
|
|
43
|
+
for (const [key, edge] of newEdgeMap) {
|
|
44
|
+
if (!oldEdgeMap.has(key)) {
|
|
45
|
+
diffSummary.edges_added++;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
for (const [key, edge] of oldEdgeMap) {
|
|
50
|
+
if (!newEdgeMap.has(key)) {
|
|
51
|
+
diffSummary.edges_removed++;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Compare roles
|
|
56
|
+
for (const newNode of newContext.nodes) {
|
|
57
|
+
const oldNode = oldNodeMap.get(newNode.path);
|
|
58
|
+
if (oldNode && oldNode.role !== newNode.role) {
|
|
59
|
+
diffSummary.roles_changed++;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Compare blast radius values
|
|
64
|
+
for (const newNode of newContext.nodes) {
|
|
65
|
+
const oldNode = oldNodeMap.get(newNode.path);
|
|
66
|
+
if (oldNode && oldNode.blast_radius !== newNode.blast_radius) {
|
|
67
|
+
diffSummary.blast_radius_changes++;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
diff_summary: diffSummary
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = { generateDiffSummary };
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example Invariants - Demonstrates the invariant system
|
|
3
|
+
* These represent realistic architectural constraints for ArcVision
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { invariantRegistry } = require('./invariant-registry');
|
|
7
|
+
|
|
8
|
+
// Example 1: Critical Path Invariant - Context Schema Validation
|
|
9
|
+
// Ensures that all context objects conform to the defined schema
|
|
10
|
+
const CONTEXT_SCHEMA_INVARIANT = {
|
|
11
|
+
id: 'context-schema-conformance',
|
|
12
|
+
description: 'All context objects must conform to the defined schema to ensure predictable system behavior',
|
|
13
|
+
scope: 'system',
|
|
14
|
+
critical_path: true, // Violating this could cause unpredictable behavior across the system
|
|
15
|
+
assertion: function(context) {
|
|
16
|
+
// Check that context has required top-level properties
|
|
17
|
+
if (!context || typeof context !== 'object') {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Check for required schema properties
|
|
22
|
+
const requiredProps = ['nodes', 'edges', 'metadata'];
|
|
23
|
+
return requiredProps.every(prop => context.hasOwnProperty(prop));
|
|
24
|
+
},
|
|
25
|
+
on_violation: function(violationEvent) {
|
|
26
|
+
console.error('Context schema violation detected - this will affect system reliability');
|
|
27
|
+
// Could log to monitoring system, send alerts, etc.
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Example 2: Boundary Invariant - File Path Resolution
|
|
32
|
+
// Ensures file paths are properly resolved and don't escape allowed boundaries
|
|
33
|
+
const FILE_PATH_BOUNDARY_INVARIANT = {
|
|
34
|
+
id: 'file-path-boundary',
|
|
35
|
+
description: 'File paths must be properly resolved and not escape the project boundary',
|
|
36
|
+
scope: 'boundary',
|
|
37
|
+
critical_path: true, // Security risk if violated
|
|
38
|
+
assertion: function(context) {
|
|
39
|
+
if (!context.filePath) return true;
|
|
40
|
+
|
|
41
|
+
const path = context.filePath;
|
|
42
|
+
const normalizedPath = require('path').normalize(path);
|
|
43
|
+
|
|
44
|
+
// Ensure path doesn't escape project root (no ../.. patterns leading outside)
|
|
45
|
+
return !normalizedPath.includes('..') ||
|
|
46
|
+
!normalizedPath.startsWith('../') ||
|
|
47
|
+
!normalizedPath.startsWith('..\\');
|
|
48
|
+
},
|
|
49
|
+
on_violation: function(violationEvent) {
|
|
50
|
+
console.error('Potential security violation: File path escapes allowed boundary');
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Example 3: Module Invariant - Dependency Consistency
|
|
55
|
+
// Ensures that when a module declares dependencies, they exist in the system
|
|
56
|
+
const DEPENDENCY_CONSISTENCY_INVARIANT = {
|
|
57
|
+
id: 'dependency-consistency',
|
|
58
|
+
description: 'Module dependencies must exist in the system to maintain integrity',
|
|
59
|
+
scope: 'module',
|
|
60
|
+
critical_path: false, // Non-critical but important for maintainability
|
|
61
|
+
assertion: function(context) {
|
|
62
|
+
if (!context.dependencies || !Array.isArray(context.dependencies)) {
|
|
63
|
+
return true; // Nothing to validate
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!context.availableModules || !Array.isArray(context.availableModules)) {
|
|
67
|
+
return true; // Can't validate without available modules
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Check that all declared dependencies exist in available modules
|
|
71
|
+
return context.dependencies.every(dep =>
|
|
72
|
+
context.availableModules.some(module => module.name === dep.name)
|
|
73
|
+
);
|
|
74
|
+
},
|
|
75
|
+
on_violation: function(violationEvent) {
|
|
76
|
+
console.warn('Detected missing dependencies:', violationEvent.context.dependencies);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// Example 4: System Invariant - Parser State Integrity
|
|
81
|
+
// Ensures parser state maintains consistency during processing
|
|
82
|
+
const PARSER_STATE_INTEGRITY_INVARIANT = {
|
|
83
|
+
id: 'parser-state-integrity',
|
|
84
|
+
description: 'Parser state must maintain consistency during AST processing to prevent corruption',
|
|
85
|
+
scope: 'system',
|
|
86
|
+
critical_path: true, // Parser corruption affects the entire system
|
|
87
|
+
assertion: function(context) {
|
|
88
|
+
// Check that parser state is valid
|
|
89
|
+
if (!context.parserState) return true;
|
|
90
|
+
|
|
91
|
+
// Ensure parser state has required properties
|
|
92
|
+
const requiredStateProps = ['currentFile', 'dependencies', 'ast'];
|
|
93
|
+
const hasRequiredProps = requiredStateProps.every(prop =>
|
|
94
|
+
context.parserState.hasOwnProperty(prop)
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
if (!hasRequiredProps) return false;
|
|
98
|
+
|
|
99
|
+
// Ensure current file is valid
|
|
100
|
+
if (context.parserState.currentFile &&
|
|
101
|
+
(typeof context.parserState.currentFile !== 'string' ||
|
|
102
|
+
context.parserState.currentFile.trim() === '')) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Ensure dependencies is an array
|
|
107
|
+
if (!Array.isArray(context.parserState.dependencies)) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return true;
|
|
112
|
+
},
|
|
113
|
+
on_violation: function(violationEvent) {
|
|
114
|
+
console.error('Parser state corruption detected - stopping processing to prevent system damage');
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// Register all example invariants
|
|
119
|
+
function registerExampleInvariants() {
|
|
120
|
+
invariantRegistry.register(CONTEXT_SCHEMA_INVARIANT);
|
|
121
|
+
invariantRegistry.register(FILE_PATH_BOUNDARY_INVARIANT);
|
|
122
|
+
invariantRegistry.register(DEPENDENCY_CONSISTENCY_INVARIANT);
|
|
123
|
+
invariantRegistry.register(PARSER_STATE_INTEGRITY_INVARIANT);
|
|
124
|
+
|
|
125
|
+
console.log(`${invariantRegistry.getAll().length} invariants registered successfully`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Export individual invariants and registration function
|
|
129
|
+
module.exports = {
|
|
130
|
+
CONTEXT_SCHEMA_INVARIANT,
|
|
131
|
+
FILE_PATH_BOUNDARY_INVARIANT,
|
|
132
|
+
DEPENDENCY_CONSISTENCY_INVARIANT,
|
|
133
|
+
PARSER_STATE_INTEGRITY_INVARIANT,
|
|
134
|
+
registerExampleInvariants
|
|
135
|
+
};
|