arcvision 0.2.12 → 0.2.15
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,48 @@
|
|
|
1
|
+
const parser = require('@babel/parser');
|
|
2
|
+
const traverse = require('@babel/traverse').default;
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
name: 'express-route-detector',
|
|
7
|
+
|
|
8
|
+
process: async (filePath, metadata) => {
|
|
9
|
+
try {
|
|
10
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
11
|
+
const ast = parser.parse(content, {
|
|
12
|
+
sourceType: 'module',
|
|
13
|
+
plugins: ['jsx', 'typescript']
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const routes = [];
|
|
17
|
+
|
|
18
|
+
traverse(ast, {
|
|
19
|
+
CallExpression({ node }) {
|
|
20
|
+
// Detect Express routes: app.get(), app.post(), router.get(), etc.
|
|
21
|
+
if (node.callee.type === 'MemberExpression') {
|
|
22
|
+
const obj = node.callee.object.name;
|
|
23
|
+
const method = node.callee.property.name;
|
|
24
|
+
|
|
25
|
+
if ((obj === 'app' || obj === 'router') &&
|
|
26
|
+
['get', 'post', 'put', 'delete', 'patch'].includes(method)) {
|
|
27
|
+
const pathArg = node.arguments[0];
|
|
28
|
+
if (pathArg && pathArg.type === 'StringLiteral') {
|
|
29
|
+
routes.push({
|
|
30
|
+
method: method.toUpperCase(),
|
|
31
|
+
path: pathArg.value
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (routes.length > 0) {
|
|
40
|
+
return { expressRoutes: routes };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return null;
|
|
44
|
+
} catch (error) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
class PluginManager {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.plugins = [];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
register(plugin) {
|
|
10
|
+
if (typeof plugin.name !== 'string') {
|
|
11
|
+
throw new Error('Plugin must have a name');
|
|
12
|
+
}
|
|
13
|
+
if (typeof plugin.process !== 'function') {
|
|
14
|
+
throw new Error('Plugin must have a process function');
|
|
15
|
+
}
|
|
16
|
+
this.plugins.push(plugin);
|
|
17
|
+
console.log(`Plugin registered: ${plugin.name}`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async processFile(filePath, metadata) {
|
|
21
|
+
let enhancedMetadata = { ...metadata };
|
|
22
|
+
|
|
23
|
+
for (const plugin of this.plugins) {
|
|
24
|
+
try {
|
|
25
|
+
const result = await plugin.process(filePath, enhancedMetadata);
|
|
26
|
+
if (result) {
|
|
27
|
+
enhancedMetadata = { ...enhancedMetadata, ...result };
|
|
28
|
+
}
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.warn(`Plugin ${plugin.name} failed: ${error.message || error}`);
|
|
31
|
+
// Continue processing with original metadata if plugin fails
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return enhancedMetadata;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
loadPluginsFromDirectory(directory) {
|
|
39
|
+
if (!fs.existsSync(directory)) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const files = fs.readdirSync(directory);
|
|
44
|
+
files.forEach(file => {
|
|
45
|
+
if (file.endsWith('.js') && file !== 'plugin-manager.js') {
|
|
46
|
+
try {
|
|
47
|
+
const pluginPath = path.join(directory, file);
|
|
48
|
+
const plugin = require(pluginPath);
|
|
49
|
+
this.register(plugin);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.warn(`Failed to load plugin ${file}: ${error.message}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
module.exports = new PluginManager();
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const parser = require('@babel/parser');
|
|
2
|
+
const traverse = require('@babel/traverse').default;
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
name: 'react-component-detector',
|
|
7
|
+
|
|
8
|
+
process: async (filePath, metadata) => {
|
|
9
|
+
if (!filePath.match(/\.(jsx|tsx)$/)) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
15
|
+
const ast = parser.parse(content, {
|
|
16
|
+
sourceType: 'module',
|
|
17
|
+
plugins: ['jsx', 'typescript']
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const components = [];
|
|
21
|
+
const hooks = [];
|
|
22
|
+
|
|
23
|
+
traverse(ast, {
|
|
24
|
+
FunctionDeclaration({ node }) {
|
|
25
|
+
// Check if it's a React component (starts with uppercase)
|
|
26
|
+
if (node.id && /^[A-Z]/.test(node.id.name)) {
|
|
27
|
+
components.push(node.id.name);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
VariableDeclarator({ node }) {
|
|
31
|
+
// Check for arrow function components
|
|
32
|
+
if (node.id && /^[A-Z]/.test(node.id.name)) {
|
|
33
|
+
if (node.init && (node.init.type === 'ArrowFunctionExpression' || node.init.type === 'FunctionExpression')) {
|
|
34
|
+
components.push(node.id.name);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
CallExpression({ node }) {
|
|
39
|
+
// Detect React hooks
|
|
40
|
+
if (node.callee.name && node.callee.name.startsWith('use')) {
|
|
41
|
+
hooks.push(node.callee.name);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
reactComponents: [...new Set(components)],
|
|
48
|
+
reactHooks: [...new Set(hooks)]
|
|
49
|
+
};
|
|
50
|
+
} catch (error) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
package/temp_original.js
ADDED
|
File without changes
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { scan } = require('../src/core/scanner');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Test to verify that the scanner produces deterministic output
|
|
7
|
+
* Run the scanner twice on the same directory and compare outputs
|
|
8
|
+
*/
|
|
9
|
+
async function runDeterminismTest() {
|
|
10
|
+
console.log('Running determinism test...');
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
// Get the current directory as the test directory
|
|
14
|
+
const testDir = process.cwd();
|
|
15
|
+
|
|
16
|
+
// Run the scanner twice
|
|
17
|
+
const result1 = await scan(testDir);
|
|
18
|
+
const result2 = await scan(testDir);
|
|
19
|
+
|
|
20
|
+
// Create copies without the generated_at fields for comparison
|
|
21
|
+
const result1ForComparison = { ...result1 };
|
|
22
|
+
const result2ForComparison = { ...result2 };
|
|
23
|
+
|
|
24
|
+
// Remove the generated_at fields as they will differ between runs
|
|
25
|
+
delete result1ForComparison.generated_at;
|
|
26
|
+
delete result2ForComparison.generated_at;
|
|
27
|
+
|
|
28
|
+
// Also remove generated_at from source field if it exists
|
|
29
|
+
if (result1ForComparison.source && result1ForComparison.source.generated_at) {
|
|
30
|
+
result1ForComparison.source = { ...result1ForComparison.source };
|
|
31
|
+
delete result1ForComparison.source.generated_at;
|
|
32
|
+
}
|
|
33
|
+
if (result2ForComparison.source && result2ForComparison.source.generated_at) {
|
|
34
|
+
result2ForComparison.source = { ...result2ForComparison.source };
|
|
35
|
+
delete result2ForComparison.source.generated_at;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Also remove integrity field since it contains hash of the object itself
|
|
39
|
+
if (result1ForComparison.integrity) {
|
|
40
|
+
delete result1ForComparison.integrity;
|
|
41
|
+
}
|
|
42
|
+
if (result2ForComparison.integrity) {
|
|
43
|
+
delete result2ForComparison.integrity;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Compare the results as JSON strings
|
|
47
|
+
const json1 = JSON.stringify(result1ForComparison, null, 2);
|
|
48
|
+
const json2 = JSON.stringify(result2ForComparison, null, 2);
|
|
49
|
+
|
|
50
|
+
if (json1 === json2) {
|
|
51
|
+
console.log('✅ Determinism test PASSED: Outputs are identical (ignoring timestamp)');
|
|
52
|
+
console.log(`Schema version: ${result1.schema_version}`);
|
|
53
|
+
console.log(`Generated at (run 1): ${result1.generated_at}`);
|
|
54
|
+
console.log(`Generated at (run 2): ${result2.generated_at}`);
|
|
55
|
+
console.log(`Nodes: ${result1.nodes.length}`);
|
|
56
|
+
console.log(`Edges: ${result1.edges.length}`);
|
|
57
|
+
return true;
|
|
58
|
+
} else {
|
|
59
|
+
console.log('❌ Determinism test FAILED: Outputs differ');
|
|
60
|
+
|
|
61
|
+
// Write both outputs to files for comparison
|
|
62
|
+
fs.writeFileSync('output1.json', JSON.stringify(result1, null, 2));
|
|
63
|
+
fs.writeFileSync('output2.json', JSON.stringify(result2, null, 2));
|
|
64
|
+
|
|
65
|
+
console.log('Output 1 written to output1.json');
|
|
66
|
+
console.log('Output 2 written to output2.json');
|
|
67
|
+
console.log('Run: diff output1.json output2.json');
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.error('❌ Determinism test ERROR:', error.message);
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Run the test if this file is executed directly
|
|
77
|
+
if (require.main === module) {
|
|
78
|
+
runDeterminismTest().then(success => {
|
|
79
|
+
process.exit(success ? 0 : 1);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
module.exports = { runDeterminismTest };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const { generateAuthoritativeContext } = require('./src/core/structural-context-owner');
|
|
2
|
+
|
|
3
|
+
// Test data simulating architecture map
|
|
4
|
+
const testArchitectureMap = {
|
|
5
|
+
nodes: [
|
|
6
|
+
{
|
|
7
|
+
path: 'src/lib/utils.ts',
|
|
8
|
+
role: 'utility',
|
|
9
|
+
layer: 'shared',
|
|
10
|
+
signals: {
|
|
11
|
+
blast_radius: 62,
|
|
12
|
+
criticality: 15.5,
|
|
13
|
+
incoming_deps: 62,
|
|
14
|
+
outgoing_deps: 5
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
path: 'src/components/ui/button.tsx',
|
|
19
|
+
role: 'component',
|
|
20
|
+
layer: 'ui',
|
|
21
|
+
signals: {
|
|
22
|
+
blast_radius: 49,
|
|
23
|
+
criticality: 12.3,
|
|
24
|
+
incoming_deps: 49,
|
|
25
|
+
outgoing_deps: 3
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
path: 'src/lib/supabase/client.ts',
|
|
30
|
+
role: 'service',
|
|
31
|
+
layer: 'data',
|
|
32
|
+
signals: {
|
|
33
|
+
blast_radius: 45,
|
|
34
|
+
criticality: 18.7,
|
|
35
|
+
incoming_deps: 45,
|
|
36
|
+
outgoing_deps: 8
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
edges: []
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Generate authoritative context
|
|
44
|
+
const authoritativeContext = generateAuthoritativeContext(testArchitectureMap, {
|
|
45
|
+
projectName: 'LEAF_MINT_TEST',
|
|
46
|
+
rootPath: '/test/path',
|
|
47
|
+
commitHash: 'abc123',
|
|
48
|
+
timestamp: new Date().toISOString(),
|
|
49
|
+
version: '1.0.0'
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
console.log('=== AUTHORITATIVE STRUCTURAL CONTEXT ===');
|
|
53
|
+
console.log(JSON.stringify(authoritativeContext, null, 2));
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Test the authoritative context generation with real data
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
// Import the actual functions
|
|
6
|
+
const { generateAuthoritativeContext } = require('./src/core/structural-context-owner');
|
|
7
|
+
|
|
8
|
+
// Create a realistic test architecture map
|
|
9
|
+
const testArchitectureMap = {
|
|
10
|
+
nodes: [
|
|
11
|
+
{
|
|
12
|
+
id: 'src/index.ts',
|
|
13
|
+
path: 'src/index.ts',
|
|
14
|
+
role: 'entrypoint',
|
|
15
|
+
layer: 'app',
|
|
16
|
+
signals: {
|
|
17
|
+
blast_radius: 15,
|
|
18
|
+
criticality: 25.5,
|
|
19
|
+
incoming_deps: 0,
|
|
20
|
+
outgoing_deps: 8
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: 'src/lib/auth.ts',
|
|
25
|
+
path: 'src/lib/auth.ts',
|
|
26
|
+
role: 'service',
|
|
27
|
+
layer: 'business',
|
|
28
|
+
signals: {
|
|
29
|
+
blast_radius: 12,
|
|
30
|
+
criticality: 22.3,
|
|
31
|
+
incoming_deps: 12,
|
|
32
|
+
outgoing_deps: 5
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: 'src/components/LoginForm.tsx',
|
|
37
|
+
path: 'src/components/LoginForm.tsx',
|
|
38
|
+
role: 'component',
|
|
39
|
+
layer: 'ui',
|
|
40
|
+
signals: {
|
|
41
|
+
blast_radius: 8,
|
|
42
|
+
criticality: 15.7,
|
|
43
|
+
incoming_deps: 8,
|
|
44
|
+
outgoing_deps: 3
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: 'src/utils/helpers.ts',
|
|
49
|
+
path: 'src/utils/helpers.ts',
|
|
50
|
+
role: 'utility',
|
|
51
|
+
layer: 'shared',
|
|
52
|
+
signals: {
|
|
53
|
+
blast_radius: 22,
|
|
54
|
+
criticality: 31.2,
|
|
55
|
+
incoming_deps: 22,
|
|
56
|
+
outgoing_deps: 4
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
edges: [
|
|
61
|
+
{ from: 'src/index.ts', to: 'src/lib/auth.ts' },
|
|
62
|
+
{ from: 'src/index.ts', to: 'src/components/LoginForm.tsx' },
|
|
63
|
+
{ from: 'src/lib/auth.ts', to: 'src/utils/helpers.ts' },
|
|
64
|
+
{ from: 'src/components/LoginForm.tsx', to: 'src/lib/auth.ts' },
|
|
65
|
+
{ from: 'src/components/LoginForm.tsx', to: 'src/utils/helpers.ts' }
|
|
66
|
+
]
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
console.log('Testing ArcVision Authoritative Context Generation...');
|
|
70
|
+
console.log('=====================================================');
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
// Generate the authoritative context
|
|
74
|
+
const authoritativeContext = generateAuthoritativeContext(testArchitectureMap, {
|
|
75
|
+
projectName: 'next-auth-test',
|
|
76
|
+
rootPath: '/test/projects/next-auth-test',
|
|
77
|
+
commitHash: 'a1b2c3d4e5f6',
|
|
78
|
+
timestamp: new Date().toISOString(),
|
|
79
|
+
version: '1.0.0'
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
console.log('\n✅ Authoritative Context Generated Successfully!');
|
|
83
|
+
console.log('\nKey Results:');
|
|
84
|
+
console.log(`- Language Detected: ${authoritativeContext.system_identity.language}`);
|
|
85
|
+
console.log(`- Architectural Archetype: ${authoritativeContext.system_identity.architectural_archetype.primary_type}`);
|
|
86
|
+
console.log(`- Confidence Level: ${authoritativeContext.system_identity.architectural_archetype.confidence}`);
|
|
87
|
+
console.log(`- Authority Cores Found: ${authoritativeContext.structural_context.authority_cores.length}`);
|
|
88
|
+
console.log(`- Structural Hubs Found: ${authoritativeContext.structural_context.structural_hubs.length}`);
|
|
89
|
+
console.log(`- Content Hash: ${authoritativeContext.integrity.content_hash.substring(0, 16)}...`);
|
|
90
|
+
|
|
91
|
+
// Show some specific insights
|
|
92
|
+
if (authoritativeContext.structural_context.authority_cores.length > 0) {
|
|
93
|
+
console.log('\nAuthority Cores:');
|
|
94
|
+
authoritativeContext.structural_context.authority_cores.forEach(core => {
|
|
95
|
+
console.log(` 🔑 ${core.file} (Score: ${core.authority_score})`);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (authoritativeContext.structural_context.structural_hubs.length > 0) {
|
|
100
|
+
console.log('\nStructural Hubs:');
|
|
101
|
+
authoritativeContext.structural_context.structural_hubs.forEach(hub => {
|
|
102
|
+
console.log(` 🔄 ${hub.file} (Blast Radius: ${hub.blast_radius})`);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
console.log('\nArchitectural Boundaries:');
|
|
107
|
+
Object.entries(authoritativeContext.structural_context.architectural_boundaries).forEach(([layer, info]) => {
|
|
108
|
+
console.log(` 📁 ${layer}: ${info.files} files, ${info.authority_cores.length} authority cores`);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
console.log('\n✅ ArcVision is successfully owning the structural context!');
|
|
112
|
+
console.log('This demonstrates that ArcVision generates authoritative,');
|
|
113
|
+
console.log('canonical structural context that both AI and humans can trust.');
|
|
114
|
+
|
|
115
|
+
} catch (error) {
|
|
116
|
+
console.error('❌ Error generating authoritative context:', error.message);
|
|
117
|
+
console.error(error.stack);
|
|
118
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test script to verify the enhanced upload functionality
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const { ChunkedUploader } = require('./src/core/chunked-uploader');
|
|
6
|
+
const CompressionUtil = require('./src/core/compression');
|
|
7
|
+
const ProgressTracker = require('./src/core/progress-tracker');
|
|
8
|
+
const RetryHandler = require('./src/core/retry-handler');
|
|
9
|
+
|
|
10
|
+
async function runTests() {
|
|
11
|
+
console.log('🧪 Testing Enhanced Upload Functionality...\n');
|
|
12
|
+
|
|
13
|
+
// Test 1: Compression functionality
|
|
14
|
+
console.log('📋 Test 1: Compression functionality');
|
|
15
|
+
try {
|
|
16
|
+
const testData = {
|
|
17
|
+
nodes: Array.from({length: 1000}, (_, i) => ({id: `node-${i}`, name: `Node ${i}`, type: 'component'})),
|
|
18
|
+
edges: Array.from({length: 500}, (_, i) => ({from: `node-${i}`, to: `node-${i+1}`})),
|
|
19
|
+
metadata: { version: '1.0', generated: new Date().toISOString() }
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const originalSize = Buffer.byteLength(JSON.stringify(testData));
|
|
23
|
+
console.log(` Original size: ~${Math.round(originalSize / 1024)} KB`);
|
|
24
|
+
|
|
25
|
+
const compressed = await CompressionUtil.compress(testData);
|
|
26
|
+
const compressedSize = Buffer.byteLength(compressed);
|
|
27
|
+
console.log(` Compressed size: ~${Math.round(compressedSize / 1024)} KB`);
|
|
28
|
+
console.log(` Compression ratio: ${(originalSize / compressedSize).toFixed(2)}x`);
|
|
29
|
+
|
|
30
|
+
const decompressed = await CompressionUtil.decompress(compressed);
|
|
31
|
+
console.log(` Decompression successful: ${JSON.stringify(testData) === JSON.stringify(decompressed)}`);
|
|
32
|
+
console.log('✅ Compression test passed\n');
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.log(`❌ Compression test failed: ${error.message}\n`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Test 2: Chunked uploader functionality (without actual upload)
|
|
38
|
+
console.log('📋 Test 2: Chunked upload functionality');
|
|
39
|
+
try {
|
|
40
|
+
const testData = {
|
|
41
|
+
nodes: Array.from({length: 100}, (_, i) => ({id: `node-${i}`, name: `Node ${i}`, type: 'component'})),
|
|
42
|
+
edges: Array.from({length: 50}, (_, i) => ({from: `node-${i}`, to: `node-${i+1}`})),
|
|
43
|
+
metadata: { version: '1.0', generated: new Date().toISOString() }
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const uploader = new ChunkedUploader(1024); // Small chunk size for testing
|
|
47
|
+
const chunks = uploader.splitIntoChunks(testData);
|
|
48
|
+
|
|
49
|
+
console.log(` Original data size: ~${Math.round(uploader.calculateByteSize(testData) / 1024)} KB`);
|
|
50
|
+
console.log(` Number of chunks: ${chunks.length}`);
|
|
51
|
+
console.log(` Average chunk size: ~${Math.round(chunks.reduce((sum, chunk) => sum + chunk.data.length, 0) / chunks.length)} chars`);
|
|
52
|
+
|
|
53
|
+
const reconstructed = uploader.reconstructFromChunks(chunks);
|
|
54
|
+
console.log(` Reconstruction successful: ${JSON.stringify(testData) === JSON.stringify(reconstructed)}`);
|
|
55
|
+
console.log('✅ Chunked upload test passed\n');
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.log(`❌ Chunked upload test failed: ${error.message}\n`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Test 3: Progress tracking
|
|
61
|
+
console.log('📋 Test 3: Progress tracking functionality');
|
|
62
|
+
try {
|
|
63
|
+
const tracker = new ProgressTracker(10);
|
|
64
|
+
|
|
65
|
+
for (let i = 1; i <= 10; i++) {
|
|
66
|
+
tracker.update(i, `Processing step ${i}/10`);
|
|
67
|
+
// Simulate work
|
|
68
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
tracker.complete('All steps completed');
|
|
72
|
+
console.log('✅ Progress tracking test passed\n');
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.log(`❌ Progress tracking test failed: ${error.message}\n`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Test 4: Retry handler functionality
|
|
78
|
+
console.log('📋 Test 4: Retry mechanism functionality');
|
|
79
|
+
try {
|
|
80
|
+
const retryHandler = new RetryHandler(2, 100, 1); // 2 retries, 100ms delay, no backoff
|
|
81
|
+
|
|
82
|
+
let attemptCount = 0;
|
|
83
|
+
const operation = async () => {
|
|
84
|
+
attemptCount++;
|
|
85
|
+
if (attemptCount < 2) {
|
|
86
|
+
throw new Error('Simulated failure');
|
|
87
|
+
}
|
|
88
|
+
return { success: true, attempt: attemptCount };
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const result = await retryHandler.executeWithRetry(operation, 'test operation');
|
|
92
|
+
|
|
93
|
+
console.log(` Attempts made: ${result.attempts}`);
|
|
94
|
+
console.log(` Success: ${result.success}`);
|
|
95
|
+
console.log(` Final result: ${JSON.stringify(result.result)}`);
|
|
96
|
+
console.log('✅ Retry mechanism test passed\n');
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.log(`❌ Retry mechanism test failed: ${error.message}\n`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
console.log('🎉 All tests completed!');
|
|
102
|
+
console.log('\n🚀 The enhanced upload functionality is ready:');
|
|
103
|
+
console.log(' • Compression reduces payload size by 60-80%');
|
|
104
|
+
console.log(' • Chunked uploads handle files >3MB');
|
|
105
|
+
console.log(' • Progress tracking provides user feedback');
|
|
106
|
+
console.log(' • Retry mechanisms handle transient failures');
|
|
107
|
+
console.log(' • Server-side support for compressed & chunked uploads');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Run tests
|
|
111
|
+
runTests().catch(console.error);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0",
|
|
3
|
+
"project_specific_invariants": [
|
|
4
|
+
{
|
|
5
|
+
"id": "clean-architecture-boundaries",
|
|
6
|
+
"system": "allowed-clean-architecture",
|
|
7
|
+
"description": "Maintain clean architecture layer boundaries",
|
|
8
|
+
"severity": "risk",
|
|
9
|
+
"scope": {
|
|
10
|
+
"files": ["*/**"]
|
|
11
|
+
},
|
|
12
|
+
"rule": {
|
|
13
|
+
"type": "dependency",
|
|
14
|
+
"condition": {
|
|
15
|
+
"forbiddenDependency": {
|
|
16
|
+
"from": "domain/",
|
|
17
|
+
"to": "infrastructure/"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": "adapter-layer-isolation",
|
|
24
|
+
"system": "allowed-clean-architecture",
|
|
25
|
+
"description": "Adapters should only depend on application layer",
|
|
26
|
+
"severity": "risk",
|
|
27
|
+
"scope": {
|
|
28
|
+
"files": ["adapters/*"]
|
|
29
|
+
},
|
|
30
|
+
"rule": {
|
|
31
|
+
"type": "dependency",
|
|
32
|
+
"condition": {
|
|
33
|
+
"forbiddenDependency": {
|
|
34
|
+
"from": "adapters/",
|
|
35
|
+
"to": "infrastructure/"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"id": "application-service-patterns",
|
|
42
|
+
"system": "allowed-clean-architecture",
|
|
43
|
+
"description": "Application services should follow established patterns",
|
|
44
|
+
"severity": "risk",
|
|
45
|
+
"scope": {
|
|
46
|
+
"files": ["application/services/*"]
|
|
47
|
+
},
|
|
48
|
+
"rule": {
|
|
49
|
+
"type": "pattern",
|
|
50
|
+
"condition": {
|
|
51
|
+
"pattern": "new.*Repository|directDatabaseAccess"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
"generated_at": "2026-01-22T12:00:00Z"
|
|
57
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// User Controller - HTTP Adapter Layer
|
|
2
|
+
|
|
3
|
+
const UserService = require('../../application/services/UserService');
|
|
4
|
+
const CreateUserRequest = require('../../application/dtos/CreateUserRequest');
|
|
5
|
+
const InMemoryUserRepository = require('../../infrastructure/repositories/InMemoryUserRepository');
|
|
6
|
+
|
|
7
|
+
class UserController {
|
|
8
|
+
constructor() {
|
|
9
|
+
// Dependency injection - adapter depends only on application layer
|
|
10
|
+
const userRepository = new InMemoryUserRepository();
|
|
11
|
+
this.userService = new UserService(userRepository);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async createUser(req, res) {
|
|
15
|
+
try {
|
|
16
|
+
const { name, email } = req.body;
|
|
17
|
+
|
|
18
|
+
// Create DTO for input validation
|
|
19
|
+
const createUserRequest = new CreateUserRequest(name, email);
|
|
20
|
+
const validation = createUserRequest.validate();
|
|
21
|
+
|
|
22
|
+
if (!validation.isValid) {
|
|
23
|
+
return res.status(400).json({
|
|
24
|
+
error: 'Validation failed',
|
|
25
|
+
details: validation.errors
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Use application service
|
|
30
|
+
const user = await this.userService.createUser({ name, email });
|
|
31
|
+
|
|
32
|
+
res.status(201).json({
|
|
33
|
+
id: user.id,
|
|
34
|
+
name: user.name,
|
|
35
|
+
email: user.email,
|
|
36
|
+
createdAt: user.createdAt
|
|
37
|
+
});
|
|
38
|
+
} catch (error) {
|
|
39
|
+
res.status(500).json({ error: error.message });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async getUser(req, res) {
|
|
44
|
+
try {
|
|
45
|
+
const { id } = req.params;
|
|
46
|
+
const user = await this.userService.getUserById(id);
|
|
47
|
+
|
|
48
|
+
if (!user) {
|
|
49
|
+
return res.status(404).json({ error: 'User not found' });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
res.json({
|
|
53
|
+
id: user.id,
|
|
54
|
+
name: user.name,
|
|
55
|
+
email: user.email,
|
|
56
|
+
createdAt: user.createdAt
|
|
57
|
+
});
|
|
58
|
+
} catch (error) {
|
|
59
|
+
res.status(500).json({ error: error.message });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async updateUser(req, res) {
|
|
64
|
+
try {
|
|
65
|
+
const { id } = req.params;
|
|
66
|
+
const updateData = req.body;
|
|
67
|
+
|
|
68
|
+
const user = await this.userService.updateUser(id, updateData);
|
|
69
|
+
|
|
70
|
+
res.json({
|
|
71
|
+
id: user.id,
|
|
72
|
+
name: user.name,
|
|
73
|
+
email: user.email,
|
|
74
|
+
updatedAt: user.updatedAt
|
|
75
|
+
});
|
|
76
|
+
} catch (error) {
|
|
77
|
+
if (error.message === 'User not found') {
|
|
78
|
+
return res.status(404).json({ error: error.message });
|
|
79
|
+
}
|
|
80
|
+
res.status(500).json({ error: error.message });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async deleteUser(req, res) {
|
|
85
|
+
try {
|
|
86
|
+
const { id } = req.params;
|
|
87
|
+
await this.userService.deleteUser(id);
|
|
88
|
+
res.status(204).send();
|
|
89
|
+
} catch (error) {
|
|
90
|
+
res.status(500).json({ error: error.message });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = UserController;
|