arcvision 0.2.2 → 0.2.4

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/dist/index.js CHANGED
@@ -4582,6 +4582,124 @@ var require_source = __commonJS({
4582
4582
  }
4583
4583
  });
4584
4584
 
4585
+ // src/core/tsconfig-utils.js
4586
+ var require_tsconfig_utils = __commonJS({
4587
+ "src/core/tsconfig-utils.js"(exports2, module2) {
4588
+ var fs2 = require("fs");
4589
+ var path2 = require("path");
4590
+ function loadTSConfig(startDir) {
4591
+ let currentDir = startDir;
4592
+ const root = path2.parse(currentDir).root;
4593
+ while (currentDir) {
4594
+ const tsconfigPaths = [
4595
+ path2.join(currentDir, "tsconfig.json"),
4596
+ path2.join(currentDir, "jsconfig.json")
4597
+ ];
4598
+ for (const tsconfigPath of tsconfigPaths) {
4599
+ if (fs2.existsSync(tsconfigPath)) {
4600
+ try {
4601
+ let content = fs2.readFileSync(tsconfigPath, "utf-8");
4602
+ if (content.charCodeAt(0) === 65279)
4603
+ content = content.slice(1);
4604
+ let parsed = null;
4605
+ try {
4606
+ parsed = JSON.parse(content);
4607
+ } catch (e) {
4608
+ const stripped = content.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, "$1").replace(/,\s*([\]}])/g, "$1");
4609
+ parsed = JSON.parse(stripped);
4610
+ }
4611
+ if (parsed) {
4612
+ return {
4613
+ options: parsed.compilerOptions || {},
4614
+ configDir: currentDir
4615
+ };
4616
+ }
4617
+ } catch (error) {
4618
+ console.warn(`Warning: Could not parse ${tsconfigPath}:`, error.message);
4619
+ }
4620
+ }
4621
+ }
4622
+ if (currentDir === root)
4623
+ break;
4624
+ currentDir = path2.dirname(currentDir);
4625
+ }
4626
+ return { options: null, configDir: startDir };
4627
+ }
4628
+ module2.exports = { loadTSConfig };
4629
+ }
4630
+ });
4631
+
4632
+ // src/core/workspace-scanner.js
4633
+ var require_workspace_scanner = __commonJS({
4634
+ "src/core/workspace-scanner.js"(exports2, module2) {
4635
+ var fs2 = require("fs");
4636
+ var path2 = require("path");
4637
+ var { loadTSConfig } = require_tsconfig_utils();
4638
+ var WorkspaceScanner = class {
4639
+ constructor(rootPath) {
4640
+ this.rootPath = path2.resolve(rootPath);
4641
+ this.workspaceMap = /* @__PURE__ */ new Map();
4642
+ this.tsconfigMap = /* @__PURE__ */ new Map();
4643
+ }
4644
+ /**
4645
+ * Performs the scan and returns the context.
4646
+ * @returns {Object} { workspaceMap, tsconfigMap }
4647
+ */
4648
+ scan() {
4649
+ console.log(`Starting workspace scan at ${this.rootPath}`);
4650
+ this._scanRecursively(this.rootPath);
4651
+ const sortedWorkspaceMap = new Map([...this.workspaceMap.entries()].sort());
4652
+ const sortedTsconfigMap = new Map([...this.tsconfigMap.entries()].sort());
4653
+ console.log(`Workspace scan complete. Found ${sortedWorkspaceMap.size} packages.`);
4654
+ return {
4655
+ workspaceMap: sortedWorkspaceMap,
4656
+ tsconfigMap: sortedTsconfigMap
4657
+ };
4658
+ }
4659
+ _scanRecursively(currentPath) {
4660
+ let entries;
4661
+ try {
4662
+ entries = fs2.readdirSync(currentPath, { withFileTypes: true });
4663
+ } catch (e) {
4664
+ console.error(`Failed to read directory ${currentPath}: ${e.message}`);
4665
+ return;
4666
+ }
4667
+ entries.sort((a, b) => a.name.localeCompare(b.name));
4668
+ const tsConfig = loadTSConfig(currentPath);
4669
+ if (tsConfig) {
4670
+ this.tsconfigMap.set(currentPath, tsConfig);
4671
+ }
4672
+ for (const entry of entries) {
4673
+ const fullPath = path2.join(currentPath, entry.name);
4674
+ if (entry.isDirectory()) {
4675
+ if (entry.name === "node_modules" || entry.name.startsWith(".")) {
4676
+ continue;
4677
+ }
4678
+ this._scanRecursively(fullPath);
4679
+ } else if (entry.name === "package.json") {
4680
+ this._processPackageJson(fullPath);
4681
+ }
4682
+ }
4683
+ }
4684
+ _processPackageJson(packageJsonPath) {
4685
+ try {
4686
+ const content = fs2.readFileSync(packageJsonPath, "utf-8");
4687
+ const pkg = JSON.parse(content);
4688
+ if (pkg.name) {
4689
+ if (this.workspaceMap.has(pkg.name)) {
4690
+ } else {
4691
+ this.workspaceMap.set(pkg.name, path2.dirname(packageJsonPath));
4692
+ }
4693
+ }
4694
+ } catch (e) {
4695
+ console.warn(`Failed to parse package.json at ${packageJsonPath}: ${e.message}`);
4696
+ }
4697
+ }
4698
+ };
4699
+ module2.exports = { WorkspaceScanner };
4700
+ }
4701
+ });
4702
+
4585
4703
  // node_modules/balanced-match/index.js
4586
4704
  var require_balanced_match = __commonJS({
4587
4705
  "node_modules/balanced-match/index.js"(exports2, module2) {
@@ -56320,12 +56438,15 @@ var require_parser = __commonJS({
56320
56438
  }
56321
56439
  const metadata = {
56322
56440
  id: filePath,
56441
+ ast,
56442
+ // Include AST for enhanced analyzers
56323
56443
  imports: [],
56324
56444
  exports: [],
56325
56445
  functions: [],
56326
56446
  apiCalls: [],
56327
56447
  classes: [],
56328
56448
  variables: [],
56449
+ types: [],
56329
56450
  dependencies: []
56330
56451
  };
56331
56452
  traverse(ast, {
@@ -56419,6 +56540,18 @@ var require_parser = __commonJS({
56419
56540
  });
56420
56541
  }
56421
56542
  });
56543
+ } else if (node.declaration.type === "TSInterfaceDeclaration" && node.declaration.id) {
56544
+ metadata.exports.push({
56545
+ name: node.declaration.id.name,
56546
+ type: "interface",
56547
+ loc: node.declaration.loc
56548
+ });
56549
+ } else if (node.declaration.type === "TSTypeAliasDeclaration" && node.declaration.id) {
56550
+ metadata.exports.push({
56551
+ name: node.declaration.id.name,
56552
+ type: "type",
56553
+ loc: node.declaration.loc
56554
+ });
56422
56555
  }
56423
56556
  }
56424
56557
  },
@@ -56472,13 +56605,30 @@ var require_parser = __commonJS({
56472
56605
  });
56473
56606
  }
56474
56607
  },
56475
- ArrowFunctionExpression({ node }) {
56608
+ ArrowFunctionExpression(path3) {
56609
+ const parent = path3.parent;
56610
+ if (parent.type === "VariableDeclarator" && parent.id.type === "Identifier") {
56611
+ metadata.functions.push({
56612
+ name: parent.id.name,
56613
+ params: path3.node.params.map((p) => p.name || "?"),
56614
+ loc: parent.loc
56615
+ });
56616
+ }
56617
+ },
56618
+ TSInterfaceDeclaration({ node }) {
56619
+ if (node.id && node.id.name) {
56620
+ metadata.types.push({
56621
+ name: node.id.name,
56622
+ kind: "interface",
56623
+ loc: node.loc
56624
+ });
56625
+ }
56476
56626
  },
56477
- ClassDeclaration({ node }) {
56627
+ TSTypeAliasDeclaration({ node }) {
56478
56628
  if (node.id && node.id.name) {
56479
- metadata.classes.push({
56629
+ metadata.types.push({
56480
56630
  name: node.id.name,
56481
- superClass: node.superClass ? node.superClass.name : null,
56631
+ kind: "type",
56482
56632
  loc: node.loc
56483
56633
  });
56484
56634
  }
@@ -56486,11 +56636,23 @@ var require_parser = __commonJS({
56486
56636
  VariableDeclaration({ node }) {
56487
56637
  node.declarations.forEach((decl) => {
56488
56638
  if (decl.id.name) {
56489
- metadata.variables.push({
56639
+ const variableData = {
56490
56640
  name: decl.id.name,
56491
56641
  type: "variable",
56492
56642
  loc: decl.loc
56493
- });
56643
+ };
56644
+ if (decl.init && decl.init.type === "ObjectExpression") {
56645
+ variableData.properties = decl.init.properties.map((p) => {
56646
+ if (p.key && (p.key.name || p.key.value)) {
56647
+ return {
56648
+ name: p.key.name || p.key.value,
56649
+ loc: p.loc
56650
+ };
56651
+ }
56652
+ return null;
56653
+ }).filter(Boolean);
56654
+ }
56655
+ metadata.variables.push(variableData);
56494
56656
  } else if (decl.id.type === "ObjectPattern") {
56495
56657
  decl.id.properties.forEach((prop) => {
56496
56658
  if (prop.key && prop.key.name) {
@@ -56553,9 +56715,27 @@ var require_parser = __commonJS({
56553
56715
  },
56554
56716
  VariableDeclarator({ node }) {
56555
56717
  if (node.init && node.init.type === "CallExpression" && node.init.callee.name === "require" && node.init.arguments.length > 0 && node.init.arguments[0].type === "StringLiteral") {
56718
+ const specifiers = [];
56719
+ if (node.id.type === "ObjectPattern") {
56720
+ node.id.properties.forEach((prop) => {
56721
+ const importedName = prop.key && (prop.key.name || prop.key.value) || null;
56722
+ const localName = prop.value && prop.value.name || importedName;
56723
+ if (importedName) {
56724
+ specifiers.push({
56725
+ imported: importedName,
56726
+ local: localName
56727
+ });
56728
+ }
56729
+ });
56730
+ } else if (node.id.type === "Identifier") {
56731
+ specifiers.push({
56732
+ imported: "default",
56733
+ local: node.id.name
56734
+ });
56735
+ }
56556
56736
  metadata.imports.push({
56557
56737
  source: node.init.arguments[0].value,
56558
- specifiers: [],
56738
+ specifiers,
56559
56739
  type: "require-assignment"
56560
56740
  });
56561
56741
  }
@@ -56569,6 +56749,688 @@ var require_parser = __commonJS({
56569
56749
  }
56570
56750
  });
56571
56751
 
56752
+ // src/core/di-detector.js
56753
+ var require_di_detector = __commonJS({
56754
+ "src/core/di-detector.js"(exports2, module2) {
56755
+ var traverse = require_lib8().default;
56756
+ function detectConstructorInjection(ast) {
56757
+ const injections = [];
56758
+ traverse(ast, {
56759
+ ClassDeclaration(path2) {
56760
+ const className = path2.node.id ? path2.node.id.name : "Anonymous";
56761
+ const constructor = path2.node.body.body.find(
56762
+ (member) => member.kind === "constructor"
56763
+ );
56764
+ if (constructor && constructor.params) {
56765
+ constructor.params.forEach((param) => {
56766
+ let paramName = null;
56767
+ let paramType = null;
56768
+ if (param.type === "TSParameterProperty") {
56769
+ if (param.parameter.type === "Identifier") {
56770
+ paramName = param.parameter.name;
56771
+ if (param.parameter.typeAnnotation) {
56772
+ paramType = extractTypeName(param.parameter.typeAnnotation);
56773
+ }
56774
+ }
56775
+ } else if (param.type === "Identifier") {
56776
+ paramName = param.name;
56777
+ if (param.typeAnnotation) {
56778
+ paramType = extractTypeName(param.typeAnnotation);
56779
+ }
56780
+ }
56781
+ if (paramName) {
56782
+ injections.push({
56783
+ className,
56784
+ paramName,
56785
+ paramType,
56786
+ pattern: "constructor_injection",
56787
+ loc: constructor.loc
56788
+ });
56789
+ }
56790
+ });
56791
+ }
56792
+ }
56793
+ });
56794
+ return injections;
56795
+ }
56796
+ function detectReactContextUsage(ast) {
56797
+ const contextUsages = [];
56798
+ traverse(ast, {
56799
+ // Detect useContext hook calls
56800
+ CallExpression(path2) {
56801
+ if (path2.node.callee.name === "useContext" && path2.node.arguments.length > 0) {
56802
+ const contextArg = path2.node.arguments[0];
56803
+ let contextName = null;
56804
+ if (contextArg.type === "Identifier") {
56805
+ contextName = contextArg.name;
56806
+ } else if (contextArg.type === "MemberExpression") {
56807
+ contextName = extractMemberExpressionName(contextArg);
56808
+ }
56809
+ if (contextName) {
56810
+ contextUsages.push({
56811
+ type: "useContext",
56812
+ contextName,
56813
+ pattern: "context_consumer",
56814
+ loc: path2.node.loc
56815
+ });
56816
+ }
56817
+ }
56818
+ },
56819
+ // Detect Context.Provider usage in JSX
56820
+ JSXElement(path2) {
56821
+ const openingElement = path2.node.openingElement;
56822
+ if (openingElement.name.type === "JSXMemberExpression") {
56823
+ const objectName = openingElement.name.object.name;
56824
+ const propertyName = openingElement.name.property.name;
56825
+ if (propertyName === "Provider" || propertyName === "Consumer") {
56826
+ contextUsages.push({
56827
+ type: "JSXProvider",
56828
+ contextName: objectName,
56829
+ pattern: propertyName === "Provider" ? "context_provider" : "context_consumer",
56830
+ loc: path2.node.loc
56831
+ });
56832
+ }
56833
+ }
56834
+ }
56835
+ });
56836
+ return contextUsages;
56837
+ }
56838
+ function detectHookDependencies(ast) {
56839
+ const hookDeps = [];
56840
+ traverse(ast, {
56841
+ CallExpression(path2) {
56842
+ const calleeName = path2.node.callee.name;
56843
+ if (calleeName && calleeName.startsWith("use") && calleeName !== "useContext") {
56844
+ hookDeps.push({
56845
+ hookName: calleeName,
56846
+ pattern: "custom_hook",
56847
+ loc: path2.node.loc
56848
+ });
56849
+ }
56850
+ }
56851
+ });
56852
+ return hookDeps;
56853
+ }
56854
+ function detectDependencyInjection(ast) {
56855
+ if (!ast) {
56856
+ return {
56857
+ constructorInjections: [],
56858
+ contextUsages: [],
56859
+ hookDependencies: []
56860
+ };
56861
+ }
56862
+ return {
56863
+ constructorInjections: detectConstructorInjection(ast),
56864
+ contextUsages: detectReactContextUsage(ast),
56865
+ hookDependencies: detectHookDependencies(ast)
56866
+ };
56867
+ }
56868
+ function extractTypeName(typeAnnotation) {
56869
+ if (!typeAnnotation)
56870
+ return null;
56871
+ const annotation = typeAnnotation.typeAnnotation || typeAnnotation;
56872
+ if (annotation.type === "TSTypeReference" && annotation.typeName) {
56873
+ if (annotation.typeName.type === "Identifier") {
56874
+ return annotation.typeName.name;
56875
+ }
56876
+ }
56877
+ return null;
56878
+ }
56879
+ function extractMemberExpressionName(node) {
56880
+ if (node.type === "MemberExpression") {
56881
+ const object = node.object.name || "";
56882
+ const property = node.property.name || "";
56883
+ return object + "." + property;
56884
+ }
56885
+ return null;
56886
+ }
56887
+ module2.exports = {
56888
+ detectConstructorInjection,
56889
+ detectReactContextUsage,
56890
+ detectHookDependencies,
56891
+ detectDependencyInjection
56892
+ };
56893
+ }
56894
+ });
56895
+
56896
+ // src/core/method-tracker.js
56897
+ var require_method_tracker = __commonJS({
56898
+ "src/core/method-tracker.js"(exports2, module2) {
56899
+ var traverse = require_lib8().default;
56900
+ function trackMethodCalls(ast, imports = []) {
56901
+ const functionCalls = [];
56902
+ const methodCalls = [];
56903
+ const constructorCalls = [];
56904
+ if (!ast) {
56905
+ return { functionCalls, methodCalls, constructorCalls };
56906
+ }
56907
+ const importedSymbols = /* @__PURE__ */ new Set();
56908
+ imports.forEach((imp) => {
56909
+ if (imp.specifiers && Array.isArray(imp.specifiers)) {
56910
+ imp.specifiers.forEach((spec) => {
56911
+ const localName = spec.local || spec.imported || spec;
56912
+ if (typeof localName === "string") {
56913
+ importedSymbols.add(localName);
56914
+ }
56915
+ });
56916
+ }
56917
+ });
56918
+ traverse(ast, {
56919
+ CallExpression(path2) {
56920
+ const callee = path2.node.callee;
56921
+ if (callee.type === "Identifier") {
56922
+ const functionName = callee.name;
56923
+ functionCalls.push({
56924
+ name: functionName,
56925
+ type: "function_call",
56926
+ loc: path2.node.loc
56927
+ });
56928
+ } else if (callee.type === "MemberExpression") {
56929
+ const objectName = extractObjectName(callee.object);
56930
+ const methodName = callee.property.name || callee.property.value;
56931
+ if (objectName && methodName) {
56932
+ methodCalls.push({
56933
+ object: objectName,
56934
+ method: methodName,
56935
+ type: "method_call",
56936
+ loc: path2.node.loc
56937
+ });
56938
+ }
56939
+ }
56940
+ },
56941
+ // Track constructor calls: new ClassName()
56942
+ NewExpression(path2) {
56943
+ const callee = path2.node.callee;
56944
+ if (callee.type === "Identifier") {
56945
+ const className = callee.name;
56946
+ constructorCalls.push({
56947
+ className,
56948
+ type: "constructor_call",
56949
+ loc: path2.node.loc
56950
+ });
56951
+ }
56952
+ }
56953
+ });
56954
+ return {
56955
+ functionCalls,
56956
+ methodCalls,
56957
+ constructorCalls
56958
+ };
56959
+ }
56960
+ function buildCallGraph(nodes) {
56961
+ const callEdges = [];
56962
+ nodes.forEach((node) => {
56963
+ const filePath = node.id;
56964
+ const metadata = node.metadata;
56965
+ if (!metadata)
56966
+ return;
56967
+ if (metadata.functionCalls && Array.isArray(metadata.functionCalls)) {
56968
+ metadata.functionCalls.forEach((call) => {
56969
+ callEdges.push({
56970
+ source: filePath,
56971
+ callType: "function",
56972
+ calledSymbol: call.name,
56973
+ loc: call.loc
56974
+ });
56975
+ });
56976
+ }
56977
+ if (metadata.constructorCalls && Array.isArray(metadata.constructorCalls)) {
56978
+ metadata.constructorCalls.forEach((call) => {
56979
+ callEdges.push({
56980
+ source: filePath,
56981
+ callType: "constructor",
56982
+ calledSymbol: call.className,
56983
+ loc: call.loc
56984
+ });
56985
+ });
56986
+ }
56987
+ if (metadata.methodCalls && Array.isArray(metadata.methodCalls)) {
56988
+ metadata.methodCalls.forEach((call) => {
56989
+ callEdges.push({
56990
+ source: filePath,
56991
+ callType: "method",
56992
+ calledSymbol: `${call.object}.${call.method}`,
56993
+ loc: call.loc
56994
+ });
56995
+ });
56996
+ }
56997
+ });
56998
+ return callEdges;
56999
+ }
57000
+ function extractObjectName(node) {
57001
+ if (node.type === "Identifier") {
57002
+ return node.name;
57003
+ } else if (node.type === "ThisExpression") {
57004
+ return "this";
57005
+ } else if (node.type === "MemberExpression") {
57006
+ const object = extractObjectName(node.object);
57007
+ const property = node.property.name || node.property.value;
57008
+ return object && property ? `${object}.${property}` : object;
57009
+ }
57010
+ return null;
57011
+ }
57012
+ module2.exports = {
57013
+ trackMethodCalls,
57014
+ buildCallGraph
57015
+ };
57016
+ }
57017
+ });
57018
+
57019
+ // src/core/type-analyzer.js
57020
+ var require_type_analyzer = __commonJS({
57021
+ "src/core/type-analyzer.js"(exports2, module2) {
57022
+ var traverse = require_lib8().default;
57023
+ function extractTypeImports(ast) {
57024
+ const typeImports = [];
57025
+ if (!ast)
57026
+ return typeImports;
57027
+ traverse(ast, {
57028
+ ImportDeclaration(path2) {
57029
+ const node = path2.node;
57030
+ if (node.importKind === "type") {
57031
+ const specifiers = [];
57032
+ node.specifiers.forEach((spec) => {
57033
+ if (spec.imported) {
57034
+ specifiers.push({
57035
+ imported: spec.imported.name || spec.imported.value,
57036
+ local: spec.local.name
57037
+ });
57038
+ }
57039
+ });
57040
+ typeImports.push({
57041
+ source: node.source.value,
57042
+ specifiers,
57043
+ importKind: "type",
57044
+ loc: node.loc
57045
+ });
57046
+ } else {
57047
+ const typeSpecifiers = [];
57048
+ node.specifiers.forEach((spec) => {
57049
+ if (spec.importKind === "type" && spec.imported) {
57050
+ typeSpecifiers.push({
57051
+ imported: spec.imported.name || spec.imported.value,
57052
+ local: spec.local.name
57053
+ });
57054
+ }
57055
+ });
57056
+ if (typeSpecifiers.length > 0) {
57057
+ typeImports.push({
57058
+ source: node.source.value,
57059
+ specifiers: typeSpecifiers,
57060
+ importKind: "mixed",
57061
+ loc: node.loc
57062
+ });
57063
+ }
57064
+ }
57065
+ }
57066
+ });
57067
+ return typeImports;
57068
+ }
57069
+ function extractInterfaceDependencies(ast) {
57070
+ const interfaceDeps = [];
57071
+ if (!ast)
57072
+ return interfaceDeps;
57073
+ traverse(ast, {
57074
+ // Interface extends
57075
+ TSInterfaceDeclaration(path2) {
57076
+ const node = path2.node;
57077
+ const interfaceName = node.id.name;
57078
+ if (node.extends && node.extends.length > 0) {
57079
+ node.extends.forEach((ext) => {
57080
+ const extendedInterface = extractTypeName(ext.expression);
57081
+ if (extendedInterface) {
57082
+ interfaceDeps.push({
57083
+ interface: interfaceName,
57084
+ extends: extendedInterface,
57085
+ type: "interface_extends",
57086
+ loc: node.loc
57087
+ });
57088
+ }
57089
+ });
57090
+ }
57091
+ },
57092
+ // Class implements
57093
+ ClassDeclaration(path2) {
57094
+ const node = path2.node;
57095
+ const className = node.id ? node.id.name : "Anonymous";
57096
+ if (node.implements && node.implements.length > 0) {
57097
+ node.implements.forEach((impl) => {
57098
+ const implementedInterface = extractTypeName(impl.expression);
57099
+ if (implementedInterface) {
57100
+ interfaceDeps.push({
57101
+ class: className,
57102
+ implements: implementedInterface,
57103
+ type: "class_implements",
57104
+ loc: node.loc
57105
+ });
57106
+ }
57107
+ });
57108
+ }
57109
+ }
57110
+ });
57111
+ return interfaceDeps;
57112
+ }
57113
+ function extractGenericDependencies(ast) {
57114
+ const genericDeps = [];
57115
+ if (!ast)
57116
+ return genericDeps;
57117
+ traverse(ast, {
57118
+ // Function return types
57119
+ FunctionDeclaration(path2) {
57120
+ const node = path2.node;
57121
+ const functionName = node.id ? node.id.name : "anonymous";
57122
+ if (node.returnType) {
57123
+ const returnTypeName = extractComplexTypeName(node.returnType.typeAnnotation);
57124
+ if (returnTypeName) {
57125
+ genericDeps.push({
57126
+ function: functionName,
57127
+ returnType: returnTypeName,
57128
+ type: "return_type",
57129
+ loc: node.loc
57130
+ });
57131
+ }
57132
+ }
57133
+ },
57134
+ // Arrow function return types
57135
+ ArrowFunctionExpression(path2) {
57136
+ const node = path2.node;
57137
+ if (node.returnType) {
57138
+ const returnTypeName = extractComplexTypeName(node.returnType.typeAnnotation);
57139
+ if (returnTypeName) {
57140
+ genericDeps.push({
57141
+ function: "arrow_function",
57142
+ returnType: returnTypeName,
57143
+ type: "return_type",
57144
+ loc: node.loc
57145
+ });
57146
+ }
57147
+ }
57148
+ },
57149
+ // Variable type annotations
57150
+ VariableDeclarator(path2) {
57151
+ const node = path2.node;
57152
+ const varName = node.id.name;
57153
+ if (node.id.typeAnnotation) {
57154
+ const typeName = extractComplexTypeName(node.id.typeAnnotation.typeAnnotation);
57155
+ if (typeName) {
57156
+ genericDeps.push({
57157
+ variable: varName,
57158
+ type: typeName,
57159
+ kind: "variable_type",
57160
+ loc: node.loc
57161
+ });
57162
+ }
57163
+ }
57164
+ }
57165
+ });
57166
+ return genericDeps;
57167
+ }
57168
+ function analyzeTypeDependencies(ast) {
57169
+ if (!ast) {
57170
+ return {
57171
+ typeImports: [],
57172
+ interfaceDependencies: [],
57173
+ genericDependencies: []
57174
+ };
57175
+ }
57176
+ return {
57177
+ typeImports: extractTypeImports(ast),
57178
+ interfaceDependencies: extractInterfaceDependencies(ast),
57179
+ genericDependencies: extractGenericDependencies(ast)
57180
+ };
57181
+ }
57182
+ function extractTypeName(node) {
57183
+ if (!node)
57184
+ return null;
57185
+ if (node.type === "Identifier") {
57186
+ return node.name;
57187
+ } else if (node.type === "TSTypeReference" && node.typeName) {
57188
+ if (node.typeName.type === "Identifier") {
57189
+ return node.typeName.name;
57190
+ }
57191
+ }
57192
+ return null;
57193
+ }
57194
+ function extractComplexTypeName(node) {
57195
+ if (!node)
57196
+ return null;
57197
+ if (node.type === "TSTypeReference" && node.typeName) {
57198
+ let baseName = extractTypeName(node);
57199
+ if (node.typeParameters && node.typeParameters.params) {
57200
+ const params = node.typeParameters.params.map((p) => extractComplexTypeName(p)).filter(Boolean).join(", ");
57201
+ if (params) {
57202
+ baseName += `<${params}>`;
57203
+ }
57204
+ }
57205
+ return baseName;
57206
+ } else if (node.type === "Identifier") {
57207
+ return node.name;
57208
+ } else if (node.type === "TSArrayType") {
57209
+ const elementType = extractComplexTypeName(node.elementType);
57210
+ return elementType ? `${elementType}[]` : null;
57211
+ }
57212
+ return null;
57213
+ }
57214
+ module2.exports = {
57215
+ extractTypeImports,
57216
+ extractInterfaceDependencies,
57217
+ extractGenericDependencies,
57218
+ analyzeTypeDependencies
57219
+ };
57220
+ }
57221
+ });
57222
+
57223
+ // src/core/react-nextjs-detector.js
57224
+ var require_react_nextjs_detector = __commonJS({
57225
+ "src/core/react-nextjs-detector.js"(exports2, module2) {
57226
+ var traverse = require_lib8().default;
57227
+ function detectComponentUsage(ast) {
57228
+ const componentUsages = [];
57229
+ if (!ast)
57230
+ return componentUsages;
57231
+ traverse(ast, {
57232
+ JSXElement(path2) {
57233
+ const openingElement = path2.node.openingElement;
57234
+ let componentName = null;
57235
+ if (openingElement.name.type === "JSXIdentifier") {
57236
+ componentName = openingElement.name.name;
57237
+ if (/^[A-Z]/.test(componentName)) {
57238
+ componentUsages.push({
57239
+ component: componentName,
57240
+ type: "jsx_component",
57241
+ loc: path2.node.loc
57242
+ });
57243
+ }
57244
+ } else if (openingElement.name.type === "JSXMemberExpression") {
57245
+ const object = openingElement.name.object.name;
57246
+ const property = openingElement.name.property.name;
57247
+ componentName = `${object}.${property}`;
57248
+ componentUsages.push({
57249
+ component: componentName,
57250
+ type: "jsx_member_component",
57251
+ loc: path2.node.loc
57252
+ });
57253
+ }
57254
+ }
57255
+ });
57256
+ return componentUsages;
57257
+ }
57258
+ function detectServerClientBoundaries(content) {
57259
+ const boundaries = {
57260
+ isClientComponent: false,
57261
+ isServerComponent: false,
57262
+ isServerAction: false
57263
+ };
57264
+ if (!content)
57265
+ return boundaries;
57266
+ if (/['"]use client['"]/.test(content)) {
57267
+ boundaries.isClientComponent = true;
57268
+ }
57269
+ if (/['"]use server['"]/.test(content)) {
57270
+ boundaries.isServerAction = true;
57271
+ }
57272
+ if (!boundaries.isClientComponent && !boundaries.isServerAction) {
57273
+ boundaries.isServerComponent = true;
57274
+ }
57275
+ return boundaries;
57276
+ }
57277
+ function detectAPIRouteDependencies(ast) {
57278
+ const apiDeps = [];
57279
+ if (!ast)
57280
+ return apiDeps;
57281
+ traverse(ast, {
57282
+ // Detect Next.js API route handlers: export async function GET/POST/etc
57283
+ ExportNamedDeclaration(path2) {
57284
+ const node = path2.node;
57285
+ if (node.declaration && node.declaration.type === "FunctionDeclaration") {
57286
+ const funcName = node.declaration.id ? node.declaration.id.name : null;
57287
+ if (["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"].includes(funcName)) {
57288
+ apiDeps.push({
57289
+ handler: funcName,
57290
+ type: "api_route_handler",
57291
+ loc: node.loc
57292
+ });
57293
+ }
57294
+ }
57295
+ },
57296
+ // Detect fetch calls and database queries within API routes
57297
+ CallExpression(path2) {
57298
+ const callee = path2.node.callee;
57299
+ if (callee.type === "MemberExpression") {
57300
+ const objectName = callee.object.name;
57301
+ const methodName = callee.property.name || callee.property.value;
57302
+ if (objectName === "supabase" || /supabase/i.test(objectName)) {
57303
+ apiDeps.push({
57304
+ service: "supabase",
57305
+ method: methodName,
57306
+ type: "database_query",
57307
+ loc: path2.node.loc
57308
+ });
57309
+ }
57310
+ if (objectName === "prisma" || /prisma/i.test(objectName)) {
57311
+ apiDeps.push({
57312
+ service: "prisma",
57313
+ method: methodName,
57314
+ type: "database_query",
57315
+ loc: path2.node.loc
57316
+ });
57317
+ }
57318
+ }
57319
+ }
57320
+ });
57321
+ return apiDeps;
57322
+ }
57323
+ function detectMiddlewareDependencies(ast, filePath = "") {
57324
+ const middlewareDeps = [];
57325
+ const isMiddleware = /middleware\.(ts|js)$/.test(filePath);
57326
+ if (!isMiddleware || !ast)
57327
+ return middlewareDeps;
57328
+ traverse(ast, {
57329
+ // Detect middleware function export
57330
+ ExportNamedDeclaration(path2) {
57331
+ const node = path2.node;
57332
+ if (node.declaration && node.declaration.type === "FunctionDeclaration") {
57333
+ const funcName = node.declaration.id ? node.declaration.id.name : null;
57334
+ if (funcName === "middleware") {
57335
+ middlewareDeps.push({
57336
+ function: funcName,
57337
+ type: "middleware_function",
57338
+ loc: node.loc
57339
+ });
57340
+ }
57341
+ }
57342
+ },
57343
+ // Detect auth checks and redirects
57344
+ CallExpression(path2) {
57345
+ const callee = path2.node.callee;
57346
+ if (callee.type === "MemberExpression") {
57347
+ const methodName = callee.property.name || callee.property.value;
57348
+ if (methodName === "getUser" || methodName === "getSession") {
57349
+ middlewareDeps.push({
57350
+ service: "auth",
57351
+ method: methodName,
57352
+ type: "auth_check",
57353
+ loc: path2.node.loc
57354
+ });
57355
+ }
57356
+ if (methodName === "redirect" || methodName === "rewrite") {
57357
+ middlewareDeps.push({
57358
+ service: "next",
57359
+ method: methodName,
57360
+ type: "middleware_action",
57361
+ loc: path2.node.loc
57362
+ });
57363
+ }
57364
+ }
57365
+ }
57366
+ });
57367
+ return middlewareDeps;
57368
+ }
57369
+ function detectReactNextJSPatterns(ast, content = "", filePath = "") {
57370
+ return {
57371
+ componentUsages: detectComponentUsage(ast),
57372
+ boundaries: detectServerClientBoundaries(content),
57373
+ apiDependencies: detectAPIRouteDependencies(ast),
57374
+ middlewareDependencies: detectMiddlewareDependencies(ast, filePath)
57375
+ };
57376
+ }
57377
+ module2.exports = {
57378
+ detectComponentUsage,
57379
+ detectServerClientBoundaries,
57380
+ detectAPIRouteDependencies,
57381
+ detectMiddlewareDependencies,
57382
+ detectReactNextJSPatterns
57383
+ };
57384
+ }
57385
+ });
57386
+
57387
+ // src/core/parser-enhanced.js
57388
+ var require_parser_enhanced = __commonJS({
57389
+ "src/core/parser-enhanced.js"(exports2, module2) {
57390
+ var { parseFile: originalParseFile } = require_parser();
57391
+ var { detectDependencyInjection } = require_di_detector();
57392
+ var { trackMethodCalls } = require_method_tracker();
57393
+ var { analyzeTypeDependencies } = require_type_analyzer();
57394
+ var { detectReactNextJSPatterns } = require_react_nextjs_detector();
57395
+ var fs2 = require("fs");
57396
+ function parseFileEnhanced(filePath) {
57397
+ const metadata = originalParseFile(filePath);
57398
+ if (!metadata.ast) {
57399
+ return metadata;
57400
+ }
57401
+ const ast = metadata.ast;
57402
+ const fileContent = fs2.readFileSync(filePath, "utf-8");
57403
+ try {
57404
+ const diPatterns = detectDependencyInjection(ast);
57405
+ metadata.constructorInjections = diPatterns.constructorInjections || [];
57406
+ metadata.contextUsages = diPatterns.contextUsages || [];
57407
+ metadata.hookDependencies = diPatterns.hookDependencies || [];
57408
+ const callTracking = trackMethodCalls(ast, metadata.imports);
57409
+ metadata.functionCalls = callTracking.functionCalls || [];
57410
+ metadata.constructorCalls = callTracking.constructorCalls || [];
57411
+ metadata.methodCalls = callTracking.methodCalls || [];
57412
+ const typeDeps = analyzeTypeDependencies(ast);
57413
+ metadata.typeImports = typeDeps.typeImports || [];
57414
+ metadata.interfaceDependencies = typeDeps.interfaceDependencies || [];
57415
+ metadata.genericDependencies = typeDeps.genericDependencies || [];
57416
+ const reactPatterns = detectReactNextJSPatterns(ast, fileContent, filePath);
57417
+ metadata.componentUsage = reactPatterns.componentUsages || [];
57418
+ metadata.serverClientBoundaries = reactPatterns.boundaries || {};
57419
+ metadata.apiDependencies = reactPatterns.apiDependencies || [];
57420
+ metadata.middlewareDependencies = reactPatterns.middlewareDependencies || [];
57421
+ } catch (error) {
57422
+ console.warn(`\u26A0\uFE0F Enhanced analysis failed for ${filePath}: ${error.message}`);
57423
+ }
57424
+ delete metadata.ast;
57425
+ return metadata;
57426
+ }
57427
+ module2.exports = {
57428
+ parseFile: parseFileEnhanced,
57429
+ parseFileBasic: originalParseFile
57430
+ };
57431
+ }
57432
+ });
57433
+
56572
57434
  // src/plugins/plugin-manager.js
56573
57435
  var require_plugin_manager = __commonJS({
56574
57436
  "src/plugins/plugin-manager.js"(exports2, module2) {
@@ -56624,34 +57486,96 @@ var require_plugin_manager = __commonJS({
56624
57486
  }
56625
57487
  });
56626
57488
 
56627
- // src/core/tsconfig-utils.js
56628
- var require_tsconfig_utils = __commonJS({
56629
- "src/core/tsconfig-utils.js"(exports2, module2) {
56630
- var fs2 = require("fs");
57489
+ // src/engine/pass1_facts.js
57490
+ var require_pass1_facts = __commonJS({
57491
+ "src/engine/pass1_facts.js"(exports2, module2) {
57492
+ var { glob } = require_commonjs5();
56631
57493
  var path2 = require("path");
56632
- function loadTSConfig(projectRoot) {
56633
- const tsconfigPaths = [
56634
- path2.join(projectRoot, "tsconfig.json"),
56635
- path2.join(projectRoot, "jsconfig.json")
56636
- ];
56637
- for (const tsconfigPath of tsconfigPaths) {
56638
- if (fs2.existsSync(tsconfigPath)) {
56639
- try {
56640
- let content = fs2.readFileSync(tsconfigPath, "utf-8");
56641
- if (content.charCodeAt(0) === 65279) {
56642
- content = content.slice(1);
57494
+ var fs2 = require("fs");
57495
+ var parser = require_parser_enhanced();
57496
+ var pluginManager = require_plugin_manager();
57497
+ async function executePass1(directory, options = {}) {
57498
+ console.log("\u{1F9F1} PASS 1: Syntactic Fact Extraction...");
57499
+ const normalize = (p) => p.replace(/\\/g, "/");
57500
+ const scanOptions = {
57501
+ ignore: ["**/node_modules/**", "**/.git/**", "**/dist/**", "**/build/**", ...options.ignore || []],
57502
+ cwd: directory,
57503
+ absolute: true
57504
+ };
57505
+ const pluginDir = path2.join(__dirname, "../plugins");
57506
+ if (fs2.existsSync(pluginDir)) {
57507
+ pluginManager.loadPluginsFromDirectory(pluginDir);
57508
+ }
57509
+ const files = await glob("**/*.{js,jsx,ts,tsx,json}", {
57510
+ ...scanOptions,
57511
+ ignore: [...scanOptions.ignore, "**/*.d.ts", "**/.next/**", "**/coverage/**", "**/arcvision.context.json"]
57512
+ });
57513
+ const rawNodes = [];
57514
+ let totalFacts = 0;
57515
+ for (const file of files) {
57516
+ try {
57517
+ const relativePath = path2.relative(directory, file);
57518
+ const normalizedRelativePath = normalize(relativePath);
57519
+ let metadata = {};
57520
+ if (file.endsWith(".json")) {
57521
+ try {
57522
+ const content = fs2.readFileSync(file, "utf-8");
57523
+ JSON.parse(content);
57524
+ metadata = {
57525
+ id: file,
57526
+ isJson: true,
57527
+ // JSONs might have "imports" in semantic sense (like package.json), but raw syntax is just data
57528
+ raw: content
57529
+ };
57530
+ } catch (e) {
57531
+ console.warn(`\u26A0\uFE0F Invalid JSON in ${normalizedRelativePath}: ${e.message}`);
57532
+ continue;
56643
57533
  }
56644
- const raw = JSON.parse(content);
56645
- return raw.compilerOptions || {};
56646
- } catch (error) {
56647
- console.warn(`Warning: Could not parse ${tsconfigPath}:`, error.message);
56648
- return null;
56649
- }
57534
+ } else {
57535
+ metadata = parser.parseFile(file);
57536
+ }
57537
+ metadata = await pluginManager.processFile(file, metadata);
57538
+ const node = {
57539
+ id: normalizedRelativePath,
57540
+ // Unique ID for this pass
57541
+ filePath: file,
57542
+ type: "file",
57543
+ // The "facts" are the metadata properties
57544
+ facts: {
57545
+ imports: metadata.imports || [],
57546
+ exports: metadata.exports || [],
57547
+ functions: metadata.functions || [],
57548
+ classes: metadata.classes || [],
57549
+ types: metadata.types || [],
57550
+ calls: {
57551
+ functions: metadata.functionCalls || [],
57552
+ methods: metadata.methodCalls || [],
57553
+ constructors: metadata.constructorCalls || []
57554
+ },
57555
+ typeAnalysis: {
57556
+ typeImports: metadata.typeImports || [],
57557
+ interfaceDeps: metadata.interfaceDependencies || [],
57558
+ genericDeps: metadata.genericDependencies || []
57559
+ },
57560
+ di: {
57561
+ injections: metadata.constructorInjections || [],
57562
+ hooks: metadata.hookDependencies || [],
57563
+ context: metadata.contextUsages || []
57564
+ },
57565
+ react: metadata.componentUsage || []
57566
+ }
57567
+ };
57568
+ totalFacts += (metadata.imports?.length || 0) + (metadata.functionCalls?.length || 0);
57569
+ rawNodes.push(node);
57570
+ } catch (e) {
57571
+ console.warn(`\u26A0\uFE0F Pass 1 failed for ${file}: ${e.message}`);
56650
57572
  }
56651
57573
  }
56652
- return null;
57574
+ console.log(` \u2713 Scanned ${rawNodes.length} files`);
57575
+ console.log(` \u2713 Extracted ${totalFacts} raw syntactic facts`);
57576
+ return rawNodes;
56653
57577
  }
56654
- module2.exports = { loadTSConfig };
57578
+ module2.exports = { executePass1 };
56655
57579
  }
56656
57580
  });
56657
57581
 
@@ -56660,7 +57584,7 @@ var require_path_resolver = __commonJS({
56660
57584
  "src/core/path-resolver.js"(exports2, module2) {
56661
57585
  var fs2 = require("fs");
56662
57586
  var path2 = require("path");
56663
- function resolveImport(importPath, importerPath, projectRoot, tsconfig) {
57587
+ function resolveImport(importPath, importerPath, projectRoot, tsconfig, workspaceMap) {
56664
57588
  if (importPath.startsWith("http://") || importPath.startsWith("https://") || importPath.startsWith("data:") || importPath.startsWith("file:")) {
56665
57589
  return null;
56666
57590
  }
@@ -56691,8 +57615,8 @@ var require_path_resolver = __commonJS({
56691
57615
  const aliasTargets = paths[aliasPattern];
56692
57616
  if (aliasPattern.includes("*")) {
56693
57617
  const patternBase = aliasPattern.replace(/\*.*$/, "");
56694
- if (importPath.startsWith(patternBase)) {
56695
- const suffix = importPath.substring(patternBase.length);
57618
+ if (importPath === patternBase.slice(0, -1) || importPath.startsWith(patternBase)) {
57619
+ const suffix = importPath.length >= patternBase.length ? importPath.substring(patternBase.length) : "";
56696
57620
  for (const target of aliasTargets) {
56697
57621
  const targetBase = target.replace(/\*.*$/, "");
56698
57622
  const targetPath = path2.resolve(projectRoot, path2.join(targetBase, suffix));
@@ -56762,6 +57686,51 @@ var require_path_resolver = __commonJS({
56762
57686
  return resolvedPath;
56763
57687
  }
56764
57688
  }
57689
+ if (workspaceMap && workspaceMap.has(importPath)) {
57690
+ const packageRoot = workspaceMap.get(importPath);
57691
+ try {
57692
+ const pkgPath = path2.join(packageRoot, "package.json");
57693
+ if (fs2.existsSync(pkgPath)) {
57694
+ const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf-8"));
57695
+ const mainFile = pkg.main || pkg.module || "index.js";
57696
+ const searchPath = path2.join(packageRoot, mainFile);
57697
+ const extensions = ["", ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".json"];
57698
+ for (const ext of extensions) {
57699
+ const p = searchPath + ext;
57700
+ if (fs2.existsSync(p))
57701
+ return p;
57702
+ }
57703
+ }
57704
+ const indexFiles = ["index.ts", "index.tsx", "index.js", "index.jsx"];
57705
+ for (const idx of indexFiles) {
57706
+ const p = path2.join(packageRoot, idx);
57707
+ if (fs2.existsSync(p))
57708
+ return p;
57709
+ }
57710
+ } catch (e) {
57711
+ }
57712
+ return packageRoot;
57713
+ }
57714
+ if (workspaceMap) {
57715
+ for (const [pkgName, pkgRoot] of workspaceMap.entries()) {
57716
+ if (importPath.startsWith(pkgName + "/")) {
57717
+ const suffix = importPath.substring(pkgName.length + 1);
57718
+ const targetPath = path2.join(pkgRoot, suffix);
57719
+ const extensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".json", ""];
57720
+ for (const ext of extensions) {
57721
+ if (fs2.existsSync(targetPath + ext)) {
57722
+ return targetPath + ext;
57723
+ }
57724
+ }
57725
+ const indexFiles = ["index.ts", "index.tsx", "index.js", "index.jsx"];
57726
+ for (const idx of indexFiles) {
57727
+ const p = path2.join(targetPath, idx);
57728
+ if (fs2.existsSync(p))
57729
+ return p;
57730
+ }
57731
+ }
57732
+ }
57733
+ }
56765
57734
  if (!importPath.startsWith(".")) {
56766
57735
  try {
56767
57736
  const resolved = require.resolve(importPath, { paths: [path2.dirname(importerPath)] });
@@ -56775,6 +57744,509 @@ var require_path_resolver = __commonJS({
56775
57744
  }
56776
57745
  });
56777
57746
 
57747
+ // src/core/symbol-indexer.js
57748
+ var require_symbol_indexer = __commonJS({
57749
+ "src/core/symbol-indexer.js"(exports2, module2) {
57750
+ var crypto = require("crypto");
57751
+ var SymbolIndexer = class {
57752
+ constructor() {
57753
+ this.symbols = /* @__PURE__ */ new Map();
57754
+ this.fileToSymbols = /* @__PURE__ */ new Map();
57755
+ }
57756
+ /**
57757
+ * Build symbol index from raw files
57758
+ * @param {Array<Object>} rawFiles - List of files with metadata from parser
57759
+ * @returns {Object} { symbols, fileToSymbols }
57760
+ */
57761
+ index(rawFiles) {
57762
+ console.log(`Indexing symbols for ${rawFiles.length} files...`);
57763
+ this.reExports = /* @__PURE__ */ new Map();
57764
+ const sortedFiles = [...rawFiles].sort((a, b) => a.id.localeCompare(b.id));
57765
+ for (const file of sortedFiles) {
57766
+ if (!file.metadata)
57767
+ continue;
57768
+ this._indexFile(file);
57769
+ }
57770
+ this._propagateReExports();
57771
+ console.log(`Indexed ${this.symbols.size} symbols.`);
57772
+ return {
57773
+ symbols: this.symbols,
57774
+ fileToSymbols: this.fileToSymbols
57775
+ };
57776
+ }
57777
+ _indexFile(file) {
57778
+ const fileId = file.id;
57779
+ const metadata = file.metadata;
57780
+ const addSymbol = (name, kind, exported = false, loc = null) => {
57781
+ const id = `${fileId}::${name}`;
57782
+ const symbol = { id, name, kind, fileId, exported, loc };
57783
+ this.symbols.set(id, symbol);
57784
+ if (!this.fileToSymbols.has(fileId)) {
57785
+ this.fileToSymbols.set(fileId, /* @__PURE__ */ new Set());
57786
+ }
57787
+ this.fileToSymbols.get(fileId).add(id);
57788
+ return symbol;
57789
+ };
57790
+ if (metadata.exports) {
57791
+ metadata.exports.forEach((exp) => {
57792
+ addSymbol(exp.name, exp.type || "variable", true, exp.loc);
57793
+ if (exp.type === "default" && exp.name !== "default") {
57794
+ addSymbol("default", "default", true, exp.loc);
57795
+ }
57796
+ });
57797
+ }
57798
+ if (metadata.functions) {
57799
+ metadata.functions.forEach((func) => {
57800
+ const id = `${fileId}::${func.name}`;
57801
+ if (!this.symbols.has(id)) {
57802
+ addSymbol(func.name, "function", false, func.loc);
57803
+ } else {
57804
+ const sym = this.symbols.get(id);
57805
+ if (sym.kind === "variable")
57806
+ sym.kind = "function";
57807
+ }
57808
+ });
57809
+ }
57810
+ if (metadata.imports) {
57811
+ metadata.imports.forEach((imp) => {
57812
+ if (imp.type === "export-all" && imp.resolvedPath) {
57813
+ if (!this.reExports.has(fileId))
57814
+ this.reExports.set(fileId, /* @__PURE__ */ new Set());
57815
+ this.reExports.get(fileId).add(imp.resolvedPath);
57816
+ }
57817
+ });
57818
+ }
57819
+ if (metadata.classes) {
57820
+ metadata.classes.forEach((c) => {
57821
+ const id = `${fileId}::${c.name}`;
57822
+ if (this.symbols.has(id)) {
57823
+ this.symbols.get(id).kind = "class";
57824
+ } else {
57825
+ addSymbol(c.name, "class", false, c.loc);
57826
+ }
57827
+ });
57828
+ }
57829
+ if (metadata.types) {
57830
+ metadata.types.forEach((t) => {
57831
+ const id = `${fileId}::${t.name}`;
57832
+ if (this.symbols.has(id)) {
57833
+ this.symbols.get(id).kind = t.kind;
57834
+ } else {
57835
+ addSymbol(t.name, t.kind, false, t.loc);
57836
+ }
57837
+ });
57838
+ }
57839
+ if (metadata.variables) {
57840
+ metadata.variables.forEach((v) => {
57841
+ addSymbol(v.name, "variable", false, v.loc);
57842
+ if (v.properties && v.properties.length > 0) {
57843
+ v.properties.forEach((prop) => {
57844
+ addSymbol(`${v.name}.${prop.name}`, "method", false, prop.loc);
57845
+ });
57846
+ }
57847
+ });
57848
+ }
57849
+ }
57850
+ _propagateReExports() {
57851
+ const visited = /* @__PURE__ */ new Set();
57852
+ const propagate = (fileId) => {
57853
+ if (visited.has(fileId))
57854
+ return;
57855
+ visited.add(fileId);
57856
+ const targets = this.reExports.get(fileId);
57857
+ if (!targets)
57858
+ return;
57859
+ for (const targetPath of targets) {
57860
+ propagate(targetPath);
57861
+ const targetSymbolIds = this.fileToSymbols.get(targetPath);
57862
+ if (targetSymbolIds) {
57863
+ for (const symId of targetSymbolIds) {
57864
+ const originalSym = this.symbols.get(symId);
57865
+ if (originalSym && originalSym.exported) {
57866
+ const localId = `${fileId}::${originalSym.name}`;
57867
+ if (!this.symbols.has(localId)) {
57868
+ const newSym = { ...originalSym, id: localId, fileId };
57869
+ this.symbols.set(localId, newSym);
57870
+ if (!this.fileToSymbols.has(fileId))
57871
+ this.fileToSymbols.set(fileId, /* @__PURE__ */ new Set());
57872
+ this.fileToSymbols.get(fileId).add(localId);
57873
+ }
57874
+ }
57875
+ }
57876
+ }
57877
+ }
57878
+ };
57879
+ for (const fileId of this.reExports.keys()) {
57880
+ propagate(fileId);
57881
+ }
57882
+ }
57883
+ };
57884
+ module2.exports = { SymbolIndexer };
57885
+ }
57886
+ });
57887
+
57888
+ // src/core/call-resolver.js
57889
+ var require_call_resolver = __commonJS({
57890
+ "src/core/call-resolver.js"(exports2, module2) {
57891
+ var CallResolver = class {
57892
+ constructor(symbolIndex, fileMap) {
57893
+ this.symbolIndex = symbolIndex;
57894
+ this.fileMap = fileMap;
57895
+ }
57896
+ /**
57897
+ * Resolve calls in all files
57898
+ * @returns {Array<Object>} List of edges
57899
+ */
57900
+ resolve(rawFiles) {
57901
+ const edges = [];
57902
+ console.log(`Resolving calls for ${rawFiles.length} files...`);
57903
+ for (const file of rawFiles) {
57904
+ const fileEdges = this._resolveFile(file);
57905
+ edges.push(...fileEdges);
57906
+ }
57907
+ console.log(`Resolved ${edges.length} call/instantiate edges.`);
57908
+ return edges;
57909
+ }
57910
+ _resolveFile(file) {
57911
+ const edges = [];
57912
+ if (!file.methodCalls)
57913
+ return edges;
57914
+ const fileId = file.id;
57915
+ const { functionCalls, constructorCalls, methodCalls } = file.methodCalls;
57916
+ const imports = file.metadata.imports || [];
57917
+ const resolveImportedSymbol = (symbolName) => {
57918
+ for (const imp of imports) {
57919
+ if (imp.specifiers) {
57920
+ const spec = imp.specifiers.find((s) => s.local === symbolName);
57921
+ if (spec) {
57922
+ if (imp.resolvedPath) {
57923
+ const targetFileId = imp.resolvedPath;
57924
+ const targetSymbolName = spec.imported === "default" ? "default" : spec.imported;
57925
+ let candidateId = `${targetFileId}::${targetSymbolName}`;
57926
+ if (this.symbolIndex.has(candidateId))
57927
+ return candidateId;
57928
+ if (spec.imported === "default") {
57929
+ candidateId = `${targetFileId}::default`;
57930
+ if (this.symbolIndex.has(candidateId))
57931
+ return candidateId;
57932
+ }
57933
+ }
57934
+ }
57935
+ }
57936
+ }
57937
+ const localId = `${fileId}::${symbolName}`;
57938
+ if (this.symbolIndex.has(localId)) {
57939
+ return localId;
57940
+ }
57941
+ return null;
57942
+ };
57943
+ if (functionCalls) {
57944
+ for (const call of functionCalls) {
57945
+ const targetSymbolId = resolveImportedSymbol(call.name);
57946
+ if (targetSymbolId) {
57947
+ edges.push({
57948
+ sourceFileId: fileId,
57949
+ targetSymbolId,
57950
+ type: "CALLS",
57951
+ line: call.loc ? call.loc.start.line : 0,
57952
+ confidence: 1
57953
+ });
57954
+ }
57955
+ }
57956
+ }
57957
+ if (constructorCalls) {
57958
+ for (const call of constructorCalls) {
57959
+ const targetSymbolId = resolveImportedSymbol(call.className);
57960
+ if (targetSymbolId) {
57961
+ edges.push({
57962
+ sourceFileId: fileId,
57963
+ targetSymbolId,
57964
+ type: "INSTANTIATES",
57965
+ line: call.loc ? call.loc.start.line : 0,
57966
+ confidence: 1
57967
+ });
57968
+ }
57969
+ }
57970
+ }
57971
+ if (methodCalls) {
57972
+ for (const call of methodCalls) {
57973
+ const imp = imports.find((i) => i.specifiers?.some((s) => s.local === call.object));
57974
+ if (imp && imp.resolvedPath) {
57975
+ const targetFileId = imp.resolvedPath;
57976
+ const spec = imp.specifiers.find((s) => s.local === call.object);
57977
+ const importedAs = spec ? spec.imported : null;
57978
+ let candidateId = `${targetFileId}::${call.method}`;
57979
+ if (this.symbolIndex.has(candidateId)) {
57980
+ edges.push({
57981
+ sourceFileId: fileId,
57982
+ targetSymbolId: candidateId,
57983
+ type: "CALLS",
57984
+ line: call.loc ? call.loc.start.line : 0,
57985
+ confidence: 1
57986
+ });
57987
+ continue;
57988
+ }
57989
+ if (importedAs) {
57990
+ const targetSymbolName = importedAs === "default" ? "default" : importedAs;
57991
+ candidateId = `${targetFileId}::${targetSymbolName}.${call.method}`;
57992
+ if (this.symbolIndex.has(candidateId)) {
57993
+ edges.push({
57994
+ sourceFileId: fileId,
57995
+ targetSymbolId: candidateId,
57996
+ type: "CALLS",
57997
+ line: call.loc ? call.loc.start.line : 0,
57998
+ confidence: 1
57999
+ });
58000
+ continue;
58001
+ }
58002
+ }
58003
+ }
58004
+ const localObjectId = `${fileId}::${call.object}.${call.method}`;
58005
+ if (this.symbolIndex.has(localObjectId)) {
58006
+ edges.push({
58007
+ sourceFileId: fileId,
58008
+ targetSymbolId: localObjectId,
58009
+ type: "CALLS",
58010
+ line: call.loc ? call.loc.start.line : 0,
58011
+ confidence: 1
58012
+ });
58013
+ }
58014
+ }
58015
+ }
58016
+ return edges;
58017
+ }
58018
+ };
58019
+ module2.exports = { CallResolver };
58020
+ }
58021
+ });
58022
+
58023
+ // src/engine/pass2_semantics.js
58024
+ var require_pass2_semantics = __commonJS({
58025
+ "src/engine/pass2_semantics.js"(exports2, module2) {
58026
+ var path2 = require("path");
58027
+ var { loadTSConfig } = require_tsconfig_utils();
58028
+ var { resolveImport } = require_path_resolver();
58029
+ var { SymbolIndexer } = require_symbol_indexer();
58030
+ var { CallResolver } = require_call_resolver();
58031
+ async function executePass2(rawNodes, rootDir, workspaceContext) {
58032
+ console.log("\u{1F9E0} PASS 2: Semantic Resolution...");
58033
+ const config = loadTSConfig(rootDir);
58034
+ const tsconfig = config.options;
58035
+ const configRoot = config.configDir;
58036
+ const normalize = (p) => p.replace(/\\/g, "/");
58037
+ const workspaceMap = workspaceContext ? workspaceContext.workspaceMap : null;
58038
+ const fileSet = new Set(rawNodes.map((n) => n.id));
58039
+ const edges = [];
58040
+ const addEdge = (source, target, type, confidence = 1, metadata = {}) => {
58041
+ if (!source || !target)
58042
+ return;
58043
+ if (source === target)
58044
+ return;
58045
+ edges.push({
58046
+ source,
58047
+ target,
58048
+ type,
58049
+ confidence,
58050
+ metadata
58051
+ });
58052
+ };
58053
+ let resolvedImports = 0;
58054
+ for (const node of rawNodes) {
58055
+ if (!node.facts.imports)
58056
+ continue;
58057
+ for (const imp of node.facts.imports) {
58058
+ const importString = imp.source;
58059
+ let targetId = null;
58060
+ let resolvedPath = null;
58061
+ const resolvedAbs = resolveImport(importString, node.filePath, configRoot, tsconfig, workspaceMap);
58062
+ if (resolvedAbs) {
58063
+ targetId = normalize(path2.relative(rootDir, resolvedAbs));
58064
+ resolvedPath = targetId;
58065
+ imp.resolvedPath = targetId;
58066
+ } else {
58067
+ if (importString.startsWith(".")) {
58068
+ try {
58069
+ const nodeDir = path2.dirname(node.filePath);
58070
+ const simpleAbs = path2.resolve(nodeDir, importString);
58071
+ const exts = [".ts", ".tsx", ".js", ".jsx", ".json", "/index.ts", "/index.js"];
58072
+ for (const ext of [""].concat(exts)) {
58073
+ const candidate = normalize(path2.relative(rootDir, simpleAbs + ext));
58074
+ if (fileSet.has(candidate)) {
58075
+ targetId = candidate;
58076
+ imp.resolvedPath = candidate;
58077
+ break;
58078
+ }
58079
+ }
58080
+ } catch (e) {
58081
+ }
58082
+ }
58083
+ }
58084
+ if (targetId && fileSet.has(targetId)) {
58085
+ let type = "imports";
58086
+ if (workspaceContext && workspaceContext.workspaceMap) {
58087
+ }
58088
+ addEdge(node.id, targetId, type, 1, { specifiers: imp.specifiers });
58089
+ resolvedImports++;
58090
+ }
58091
+ }
58092
+ }
58093
+ console.log(` \u2713 Resolved ${resolvedImports} import dependencies`);
58094
+ const symbolIndexer = new SymbolIndexer();
58095
+ const nodesForIndexing = rawNodes.map((n) => ({
58096
+ id: n.id,
58097
+ metadata: n.facts
58098
+ // Indexer expects metadata.exports, etc. (Pass 1 facts structure matches enough)
58099
+ }));
58100
+ const { symbols, fileToSymbols } = symbolIndexer.index(nodesForIndexing);
58101
+ const callResolver = new CallResolver(symbols, null);
58102
+ const nodesForResolution = rawNodes.map((n) => {
58103
+ const combinedFunctions = [
58104
+ ...n.facts.calls.functions || [],
58105
+ ...(n.facts.react || []).map((r) => ({
58106
+ name: r.component,
58107
+ type: "jsx_component",
58108
+ loc: r.loc
58109
+ }))
58110
+ ];
58111
+ return {
58112
+ id: n.id,
58113
+ metadata: n.facts,
58114
+ methodCalls: {
58115
+ functionCalls: combinedFunctions,
58116
+ methodCalls: n.facts.calls.methods,
58117
+ constructorCalls: n.facts.calls.constructors
58118
+ }
58119
+ };
58120
+ });
58121
+ const callEdges = callResolver.resolve(nodesForResolution);
58122
+ let resolvedCalls = 0;
58123
+ for (const edge of callEdges) {
58124
+ const symbol = symbols.get(edge.targetSymbolId);
58125
+ if (symbol) {
58126
+ const targetFileId = symbol.fileId;
58127
+ if (fileSet.has(targetFileId)) {
58128
+ addEdge(edge.sourceFileId, targetFileId, edge.type, edge.confidence, {
58129
+ symbol: symbol.name,
58130
+ symbolId: edge.targetSymbolId,
58131
+ line: edge.line
58132
+ });
58133
+ resolvedCalls++;
58134
+ }
58135
+ }
58136
+ }
58137
+ console.log(` \u2713 Resolved ${resolvedCalls} semantic call edges`);
58138
+ let typeEdgesCount = 0;
58139
+ for (const node of rawNodes) {
58140
+ if (!node.facts.typeAnalysis)
58141
+ continue;
58142
+ const { typeImports, interfaceDeps, genericDeps } = node.facts.typeAnalysis;
58143
+ for (const imp of typeImports) {
58144
+ const resolvedAbs = resolveImport(imp.source, node.filePath, rootDir, tsconfig, workspaceMap);
58145
+ if (resolvedAbs) {
58146
+ const targetId = normalize(path2.relative(rootDir, resolvedAbs));
58147
+ if (fileSet.has(targetId)) {
58148
+ addEdge(node.id, targetId, "depends_on", 0.9, { type: "type_import" });
58149
+ typeEdgesCount++;
58150
+ }
58151
+ }
58152
+ }
58153
+ const allTypeDeps = [...interfaceDeps, ...genericDeps];
58154
+ for (const dep of allTypeDeps) {
58155
+ const typeName = dep.extends || dep.implements || dep.returnType || dep.type;
58156
+ if (!typeName)
58157
+ continue;
58158
+ for (const imp of node.facts.imports || []) {
58159
+ if (imp.resolvedPath) {
58160
+ const targetFileId = imp.resolvedPath;
58161
+ const candidateId = `${targetFileId}::${typeName}`;
58162
+ if (symbols.has(candidateId)) {
58163
+ addEdge(node.id, targetFileId, "depends_on", 1, { type: "type_reference", symbol: typeName });
58164
+ typeEdgesCount++;
58165
+ break;
58166
+ }
58167
+ }
58168
+ }
58169
+ }
58170
+ }
58171
+ console.log(` \u2713 Resolved ${typeEdgesCount} TypeScript type connections`);
58172
+ return {
58173
+ nodes: rawNodes,
58174
+ edges,
58175
+ symbols: Array.from(symbols.values())
58176
+ // Return symbols list for ContextBuilder
58177
+ };
58178
+ }
58179
+ module2.exports = { executePass2 };
58180
+ }
58181
+ });
58182
+
58183
+ // src/engine/pass3_lifter.js
58184
+ var require_pass3_lifter = __commonJS({
58185
+ "src/engine/pass3_lifter.js"(exports2, module2) {
58186
+ async function executePass3(semanticData) {
58187
+ console.log("\u{1F9EC} PASS 3: Structural Lifting...");
58188
+ const { nodes, edges } = semanticData;
58189
+ const liftedNodes = [];
58190
+ let rolesFound = {};
58191
+ for (const node of nodes) {
58192
+ let role = "module";
58193
+ let layer = "generic";
58194
+ const pathLower = node.id.toLowerCase();
58195
+ const filename = node.id.split("/").pop();
58196
+ if (pathLower.includes("service") || filename.endsWith(".service.ts")) {
58197
+ role = "service";
58198
+ layer = "logic";
58199
+ } else if (pathLower.includes("controller") || filename.endsWith(".controller.ts")) {
58200
+ role = "controller";
58201
+ layer = "api";
58202
+ } else if (pathLower.includes("component") || pathLower.includes(".tsx") || pathLower.includes(".jsx")) {
58203
+ role = "component";
58204
+ layer = "ui";
58205
+ } else if (pathLower.includes("store") || pathLower.includes("redux") || pathLower.includes("context")) {
58206
+ role = "store";
58207
+ layer = "state";
58208
+ } else if (pathLower.includes("util") || pathLower.includes("helper")) {
58209
+ role = "utility";
58210
+ layer = "shared";
58211
+ } else if (pathLower.includes("model") || pathLower.includes("entity") || pathLower.includes("dto")) {
58212
+ role = "model";
58213
+ layer = "data";
58214
+ } else if (pathLower.includes("config") || pathLower.includes("env")) {
58215
+ role = "config";
58216
+ } else if (pathLower.includes("hook") || filename.startsWith("use")) {
58217
+ role = "hook";
58218
+ layer = "ui-logic";
58219
+ }
58220
+ if (node.facts.di && (node.facts.di.injections.length > 0 || node.facts.di.context.length > 0)) {
58221
+ if (role === "module")
58222
+ role = "consumer";
58223
+ }
58224
+ if (node.facts.exports.some((e) => e.type === "class")) {
58225
+ if (role === "module")
58226
+ role = "class_def";
58227
+ }
58228
+ rolesFound[role] = (rolesFound[role] || 0) + 1;
58229
+ liftedNodes.push({
58230
+ ...node,
58231
+ structure: {
58232
+ role,
58233
+ layer
58234
+ }
58235
+ });
58236
+ }
58237
+ console.log(` \u2713 Inferred structural roles: ${JSON.stringify(rolesFound)}`);
58238
+ return {
58239
+ nodes: liftedNodes,
58240
+ edges,
58241
+ // Edges passed through
58242
+ symbols: semanticData.symbols
58243
+ // Propagate symbols
58244
+ };
58245
+ }
58246
+ module2.exports = { executePass3 };
58247
+ }
58248
+ });
58249
+
56778
58250
  // src/core/blastRadius.js
56779
58251
  var require_blastRadius = __commonJS({
56780
58252
  "src/core/blastRadius.js"(exports2, module2) {
@@ -56896,7 +58368,12 @@ var require_blastRadius = __commonJS({
56896
58368
  // Consider files with blast radius > 5 as hubs
56897
58369
  });
56898
58370
  }
56899
- return criticalityAnalysis.sort((a, b) => b.criticalityScore - a.criticalityScore);
58371
+ return criticalityAnalysis.sort((a, b) => {
58372
+ if (b.criticalityScore !== a.criticalityScore) {
58373
+ return b.criticalityScore - a.criticalityScore;
58374
+ }
58375
+ return a.file.localeCompare(b.file);
58376
+ });
56900
58377
  }
56901
58378
  function calculateDependencyStrength(reverseGraph, file) {
56902
58379
  if (!reverseGraph[file] || !Array.isArray(reverseGraph[file])) {
@@ -56922,6 +58399,76 @@ var require_blastRadius = __commonJS({
56922
58399
  }
56923
58400
  });
56924
58401
 
58402
+ // src/engine/pass4_signals.js
58403
+ var require_pass4_signals = __commonJS({
58404
+ "src/engine/pass4_signals.js"(exports2, module2) {
58405
+ var { buildReverseDependencyGraph, computeBlastRadius, analyzeCriticality } = require_blastRadius();
58406
+ async function executePass4(liftedData) {
58407
+ console.log("\u{1F9E0} PASS 4: Signal Extraction & Metrics...");
58408
+ const { nodes, edges } = liftedData;
58409
+ const architectureMap = { nodes, edges };
58410
+ const reverseGraph = buildReverseDependencyGraph(architectureMap);
58411
+ const blastRadiusMap = computeBlastRadius(reverseGraph);
58412
+ nodes.forEach((n) => {
58413
+ n.metadata = n.facts;
58414
+ n.metadata.blast_radius = blastRadiusMap[n.id] || 0;
58415
+ });
58416
+ const criticalityList = analyzeCriticality(blastRadiusMap, reverseGraph, nodes);
58417
+ const criticalityMap = new Map(criticalityList.map((c) => [c.file, c]));
58418
+ const finalNodes = nodes.map((node) => {
58419
+ const signals = {
58420
+ blast_radius: blastRadiusMap[node.id] || 0,
58421
+ criticality: criticalityMap.get(node.id)?.criticalityScore || 0,
58422
+ is_hub: criticalityMap.get(node.id)?.isHub || false,
58423
+ // Calculate instability: closer to 1 means "depends on many things" (outgoing edges)
58424
+ // (coupling)
58425
+ outgoing_deps: edges.filter((e) => e.source === node.id).length,
58426
+ incoming_deps: edges.filter((e) => e.target === node.id).length
58427
+ };
58428
+ return {
58429
+ id: node.id,
58430
+ type: node.type,
58431
+ filePath: node.filePath,
58432
+ // Internal absolute path
58433
+ // The 3 Pillars of Arcvision
58434
+ role: node.structure.role,
58435
+ // From Pass 3
58436
+ layer: node.structure.layer,
58437
+ // From Pass 3
58438
+ signals,
58439
+ // From Pass 4
58440
+ // Deep Code Intelligence (from Pass 1 & 2)
58441
+ intelligence: {
58442
+ ...node.facts,
58443
+ // Add resolved outbound connections for easy traversal
58444
+ connections: edges.filter((e) => e.source === node.id).map((e) => ({
58445
+ target: e.target,
58446
+ type: e.type,
58447
+ confidence: e.confidence
58448
+ }))
58449
+ }
58450
+ };
58451
+ });
58452
+ const totalFiles = finalNodes.length;
58453
+ const maxBlast = Math.max(...finalNodes.map((n) => n.signals.blast_radius));
58454
+ console.log(` \u2713 Signals computed. Max Blast Radius: ${maxBlast}`);
58455
+ const contextSurface = criticalityList.slice(0, 5).map((c) => ({
58456
+ file: c.file,
58457
+ score: c.criticalityScore,
58458
+ reason: `Blast: ${c.blastRadius}, Deps: ${c.dependencies}`
58459
+ }));
58460
+ return {
58461
+ nodes: finalNodes,
58462
+ edges,
58463
+ symbols: liftedData.symbols,
58464
+ // Propagate symbols
58465
+ contextSurface
58466
+ };
58467
+ }
58468
+ module2.exports = { executePass4 };
58469
+ }
58470
+ });
58471
+
56925
58472
  // src/engine/id-generator.js
56926
58473
  var require_id_generator = __commonJS({
56927
58474
  "src/engine/id-generator.js"(exports2, module2) {
@@ -56934,81 +58481,109 @@ var require_id_generator = __commonJS({
56934
58481
  }
56935
58482
  });
56936
58483
 
56937
- // src/engine/context_builder.js
58484
+ // src/core/context_builder.js
56938
58485
  var require_context_builder = __commonJS({
56939
- "src/engine/context_builder.js"(exports2, module2) {
58486
+ "src/core/context_builder.js"(exports2, module2) {
56940
58487
  var path2 = require("path");
56941
58488
  var { stableId } = require_id_generator();
56942
- function buildContext(files, edges, options = {}) {
58489
+ function buildContext(fileNodes, edges, symbols, options = {}) {
56943
58490
  const {
56944
58491
  directory = ".",
56945
58492
  projectName = "arcvision",
56946
58493
  language = "javascript"
56947
58494
  } = options;
56948
- const nodes = files.map((file) => {
56949
- const normalizedPath = file.id;
56950
- const hasFunctions = file.metadata.functions && file.metadata.functions.length > 0;
56951
- const hasClasses = file.metadata.classes && file.metadata.classes.length > 0;
56952
- const hasExports = file.metadata.exports && file.metadata.exports.length > 0;
56953
- const hasApiCalls = file.metadata.apiCalls && file.metadata.apiCalls.length > 0;
56954
- let role = "Structure";
56955
- if (hasFunctions || hasClasses || hasApiCalls) {
56956
- role = "Implementation";
56957
- } else if (hasExports) {
56958
- role = "Interface";
56959
- }
58495
+ const nodes = fileNodes.map((file) => {
58496
+ const role = file.role || "Structure";
58497
+ const layer = file.layer || "generic";
56960
58498
  const dependencies = [];
56961
58499
  const uniqueDeps = /* @__PURE__ */ new Set();
56962
- if (file.metadata.imports && Array.isArray(file.metadata.imports)) {
56963
- file.metadata.imports.forEach((imp) => {
56964
- if (imp.source && typeof imp.source === "string") {
56965
- if (!uniqueDeps.has(imp.source)) {
56966
- uniqueDeps.add(imp.source);
56967
- dependencies.push(imp.source);
56968
- }
56969
- }
56970
- });
58500
+ const addDep = (target) => {
58501
+ if (target && !uniqueDeps.has(target)) {
58502
+ uniqueDeps.add(target);
58503
+ dependencies.push(target);
58504
+ }
58505
+ };
58506
+ if (file.intelligence && file.intelligence.connections) {
58507
+ file.intelligence.connections.forEach((c) => addDep(c.target));
58508
+ } else {
58509
+ edges.filter((e) => e.source === file.id).forEach((e) => addDep(e.target));
56971
58510
  }
56972
- return {
56973
- id: stableId(normalizedPath),
58511
+ const nodeObj = {
58512
+ id: stableId(file.id),
56974
58513
  type: "file",
56975
- path: normalizedPath,
58514
+ path: file.id,
56976
58515
  role,
56977
58516
  dependencies,
56978
- blast_radius: file.metadata.blast_radius || 0
58517
+ blast_radius: file.signals && file.signals.blast_radius || 0,
58518
+ // New Schema Extensions (if supported by backend, otherwise ignored)
58519
+ layer,
58520
+ criticality: file.signals ? file.signals.criticality : 0
56979
58521
  };
58522
+ return nodeObj;
56980
58523
  });
56981
- const schemaEdges = [];
58524
+ const nodeMap = new Map(nodes.map((n) => [n.path, n]));
58525
+ const edgeKeyMap = /* @__PURE__ */ new Map();
56982
58526
  for (const edge of edges) {
56983
- const sourceNode = nodes.find((n) => n.path === edge.source);
56984
- const targetNode = nodes.find((n) => n.path === edge.target);
56985
- if (sourceNode) {
58527
+ const sourceNode = nodeMap.get(edge.source);
58528
+ const targetNode = nodeMap.get(edge.target);
58529
+ if (sourceNode && targetNode) {
56986
58530
  let relationType = "imports";
56987
- if (edge.type === "imports" || edge.type === "require" || edge.type === "export-from" || edge.type === "export-all" || edge.type === "dynamic-import" || edge.type === "require-assignment") {
56988
- relationType = "imports";
56989
- } else if (edge.type === "calls") {
56990
- relationType = "calls";
56991
- } else if (edge.type === "owns") {
56992
- relationType = "owns";
56993
- } else if (edge.type === "depends_on") {
56994
- relationType = "depends_on";
56995
- }
56996
- if (targetNode) {
56997
- schemaEdges.push({
58531
+ switch (edge.type) {
58532
+ case "function_call":
58533
+ case "method_call":
58534
+ case "constructor_call":
58535
+ case "calls":
58536
+ case "CALLS":
58537
+ case "instantiates":
58538
+ case "INSTANTIATES":
58539
+ case "jsx_component":
58540
+ relationType = "calls";
58541
+ break;
58542
+ case "injects":
58543
+ case "depends_on":
58544
+ relationType = "depends_on";
58545
+ break;
58546
+ case "owns":
58547
+ relationType = "owns";
58548
+ break;
58549
+ case "imports":
58550
+ case "require":
58551
+ default:
58552
+ relationType = "imports";
58553
+ break;
58554
+ }
58555
+ const key = `${sourceNode.id}::${targetNode.id}::${relationType}`;
58556
+ if (edgeKeyMap.has(key)) {
58557
+ edgeKeyMap.get(key).weight = (edgeKeyMap.get(key).weight || 1) + 1;
58558
+ } else {
58559
+ edgeKeyMap.set(key, {
56998
58560
  from: sourceNode.id,
56999
58561
  to: targetNode.id,
57000
- relation: relationType
58562
+ relation: relationType,
58563
+ weight: 1
57001
58564
  });
57002
- } else {
57003
58565
  }
57004
58566
  }
57005
58567
  }
58568
+ const schemaEdges = Array.from(edgeKeyMap.values()).sort((a, b) => {
58569
+ if (a.from !== b.from)
58570
+ return a.from.localeCompare(b.from);
58571
+ if (a.to !== b.to)
58572
+ return a.to.localeCompare(b.to);
58573
+ return a.relation.localeCompare(b.relation);
58574
+ });
57006
58575
  const metrics = {
57007
58576
  total_files: nodes.length,
57008
58577
  total_nodes: nodes.length,
57009
58578
  total_edges: schemaEdges.length,
57010
- total_imports: schemaEdges.length,
57011
- files_with_functions: nodes.filter((n) => n.role === "Implementation").length
58579
+ total_imports: schemaEdges.filter((edge) => edge.relation === "imports").reduce((sum, e) => sum + (e.weight || 1), 0),
58580
+ total_calls: schemaEdges.filter((edge) => edge.relation === "calls").reduce((sum, e) => sum + (e.weight || 1), 0),
58581
+ total_owns: schemaEdges.filter((edge) => edge.relation === "owns").reduce((sum, e) => sum + (e.weight || 1), 0),
58582
+ total_depends_on: schemaEdges.filter((edge) => edge.relation === "depends_on").reduce((sum, e) => sum + (e.weight || 1), 0),
58583
+ files_with_functions: fileNodes.filter((n) => n.intelligence && n.intelligence.functions && n.intelligence.functions.length > 0).length,
58584
+ // New metrics
58585
+ total_dependencies: schemaEdges.length,
58586
+ files_with_high_blast_radius: nodes.filter((n) => n.blast_radius > 5).length
57012
58587
  };
57013
58588
  const context = {
57014
58589
  schema_version: "1.0.0",
@@ -57020,12 +58595,10 @@ var require_context_builder = __commonJS({
57020
58595
  },
57021
58596
  nodes,
57022
58597
  edges: schemaEdges,
58598
+ symbols: symbols || [],
57023
58599
  metrics,
57024
- contextSurface: options.contextSurface || {}
58600
+ contextSurface: options.contextSurface || []
57025
58601
  };
57026
- context.metrics.files_with_functions = nodes.filter((n) => n.role === "Implementation").length;
57027
- context.metrics.files_with_high_blast_radius = nodes.filter((n) => n.blast_radius > 5).length;
57028
- context.metrics.total_dependencies = schemaEdges.length;
57029
58602
  return context;
57030
58603
  }
57031
58604
  module2.exports = { buildContext };
@@ -63583,374 +65156,53 @@ var require_context_sorter = __commonJS({
63583
65156
  // src/core/scanner.js
63584
65157
  var require_scanner = __commonJS({
63585
65158
  "src/core/scanner.js"(exports2, module2) {
63586
- var { glob } = require_commonjs5();
63587
65159
  var path2 = require("path");
63588
- var fs2 = require("fs");
63589
- var parser = require_parser();
63590
- var pluginManager = require_plugin_manager();
63591
65160
  var { loadTSConfig } = require_tsconfig_utils();
63592
- var { resolveImport } = require_path_resolver();
63593
- var { buildReverseDependencyGraph, computeBlastRadius } = require_blastRadius();
65161
+ var { WorkspaceScanner } = require_workspace_scanner();
65162
+ var { executePass1 } = require_pass1_facts();
65163
+ var { executePass2 } = require_pass2_semantics();
65164
+ var { executePass3 } = require_pass3_lifter();
65165
+ var { executePass4 } = require_pass4_signals();
63594
65166
  var { buildContext } = require_context_builder();
63595
65167
  var { validateContext } = require_context_validator();
63596
65168
  var { sortContext } = require_context_sorter();
63597
65169
  async function scan(directory) {
63598
- const normalize = (p) => p.replace(/\\/g, "/");
63599
- const options = {
63600
- ignore: ["**/node_modules/**", "**/.git/**", "**/dist/**", "**/build/**"],
63601
- cwd: directory,
63602
- absolute: true
63603
- };
65170
+ console.log(`
65171
+ \u{1F680} ARCVISION STRUCTURAL ENGINE (4-PASS)`);
65172
+ console.log(` Target: ${directory}
65173
+ `);
63604
65174
  try {
63605
- const pluginDir = path2.join(__dirname, "../plugins");
63606
- pluginManager.loadPluginsFromDirectory(pluginDir);
63607
- const files = await glob("**/*.{js,jsx,ts,tsx,json}", { ...options, ignore: [...options.ignore, "**/*.d.ts", "**/node_modules/**", "**/.git/**", "**/dist/**", "**/build/**", "**/.next/**", "**/coverage/**"] });
63608
- const architectureMap = {
63609
- nodes: [],
63610
- edges: []
63611
- };
63612
- const fileMap = /* @__PURE__ */ new Map();
63613
- let totalImportsFound = 0;
63614
- for (const file of files) {
63615
- try {
63616
- const relativePath = path2.relative(directory, file);
63617
- const normalizedRelativePath = normalize(relativePath);
63618
- let metadata;
63619
- if (file.endsWith(".json")) {
63620
- try {
63621
- const content = fs2.readFileSync(file, "utf-8");
63622
- JSON.parse(content);
63623
- metadata = {
63624
- id: file,
63625
- imports: [],
63626
- exports: [],
63627
- functions: [],
63628
- apiCalls: [],
63629
- isJson: true
63630
- };
63631
- } catch (jsonError) {
63632
- console.warn(`\u26A0\uFE0F Invalid JSON in ${file} \u2014 file skipped`);
63633
- continue;
63634
- }
63635
- } else {
63636
- metadata = parser.parseFile(file);
63637
- }
63638
- metadata = await pluginManager.processFile(file, metadata);
63639
- if (metadata.imports && Array.isArray(metadata.imports)) {
63640
- totalImportsFound += metadata.imports.length;
63641
- }
63642
- const node = {
63643
- id: normalizedRelativePath,
63644
- type: "file",
63645
- metadata
63646
- };
63647
- architectureMap.nodes.push(node);
63648
- fileMap.set(normalizedRelativePath, metadata);
63649
- } catch (e) {
63650
- console.warn(`\u26A0\uFE0F Failed to process ${file} \u2014 file skipped, you should check manually (${e.message})`);
63651
- }
63652
- }
63653
- const tsconfig = loadTSConfig(directory);
63654
- const allPossiblePaths = /* @__PURE__ */ new Set();
63655
- const pathToNodeIdMap = /* @__PURE__ */ new Map();
63656
- architectureMap.nodes.forEach((node) => {
63657
- const normalizedPath = normalize(node.id);
63658
- allPossiblePaths.add(normalizedPath);
63659
- pathToNodeIdMap.set(normalizedPath, node.id);
63660
- });
63661
- let unresolvedImports = 0;
63662
- let resolvedImports = 0;
63663
- architectureMap.nodes.forEach((node) => {
63664
- if (node.metadata.imports && Array.isArray(node.metadata.imports)) {
63665
- node.metadata.imports.forEach((imp) => {
63666
- if (imp.source && typeof imp.source === "string") {
63667
- let targetFound = false;
63668
- try {
63669
- if (allPossiblePaths.has(imp.source)) {
63670
- architectureMap.edges.push({
63671
- source: normalize(node.id),
63672
- target: imp.source,
63673
- type: imp.type || "import"
63674
- });
63675
- resolvedImports++;
63676
- targetFound = true;
63677
- }
63678
- if (!targetFound) {
63679
- const resolvedPath = resolveImport(
63680
- imp.source,
63681
- path2.join(directory, node.id),
63682
- directory,
63683
- tsconfig
63684
- );
63685
- if (resolvedPath) {
63686
- const relativeResolvedPath = path2.relative(directory, resolvedPath);
63687
- const normalizedResolvedPath = normalize(relativeResolvedPath);
63688
- if (allPossiblePaths.has(normalizedResolvedPath)) {
63689
- architectureMap.edges.push({
63690
- source: normalize(node.id),
63691
- target: normalizedResolvedPath,
63692
- type: imp.type || "import"
63693
- });
63694
- resolvedImports++;
63695
- targetFound = true;
63696
- }
63697
- }
63698
- }
63699
- if (!targetFound) {
63700
- try {
63701
- const baseDir = path2.dirname(path2.join(directory, node.id));
63702
- const calculatedAbsolutePath = path2.resolve(baseDir, imp.source);
63703
- const calculatedRelativePath = path2.relative(directory, calculatedAbsolutePath);
63704
- const calculatedNormalizedPath = normalize(calculatedRelativePath);
63705
- if (allPossiblePaths.has(calculatedNormalizedPath)) {
63706
- architectureMap.edges.push({
63707
- source: normalize(node.id),
63708
- target: calculatedNormalizedPath,
63709
- type: imp.type || "import"
63710
- });
63711
- resolvedImports++;
63712
- targetFound = true;
63713
- }
63714
- } catch (e) {
63715
- console.warn(`\u26A0\uFE0F Path calculation failed for import '${imp.source}' in file '${node.id}': ${e.message}`);
63716
- }
63717
- }
63718
- if (!targetFound) {
63719
- if (imp.source.startsWith("./") || imp.source.startsWith("../")) {
63720
- const extensions = ["", ".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"];
63721
- for (const ext of extensions) {
63722
- let testPath = imp.source;
63723
- if (!imp.source.endsWith(ext)) {
63724
- testPath = imp.source + ext;
63725
- }
63726
- try {
63727
- const baseDir = path2.dirname(path2.join(directory, node.id));
63728
- const calculatedAbsolutePath = path2.resolve(baseDir, testPath);
63729
- const calculatedRelativePath = path2.relative(directory, calculatedAbsolutePath);
63730
- const calculatedNormalizedPath = normalize(calculatedRelativePath);
63731
- if (allPossiblePaths.has(calculatedNormalizedPath)) {
63732
- architectureMap.edges.push({
63733
- source: normalize(node.id),
63734
- target: calculatedNormalizedPath,
63735
- type: imp.type || "import"
63736
- });
63737
- resolvedImports++;
63738
- targetFound = true;
63739
- break;
63740
- }
63741
- } catch (e) {
63742
- console.warn(`\u26A0\uFE0F Extension path calculation failed for import '${imp.source}' with extension '${ext}' in file '${node.id}': ${e.message}`);
63743
- }
63744
- }
63745
- }
63746
- }
63747
- if (!targetFound) {
63748
- if (imp.source.startsWith("./") || imp.source.startsWith("../")) {
63749
- try {
63750
- const baseDir = path2.dirname(path2.join(directory, node.id));
63751
- const calculatedAbsolutePath = path2.resolve(baseDir, imp.source);
63752
- const directoryPath = calculatedAbsolutePath;
63753
- const indexFiles = ["index.js", "index.ts", "index.jsx", "index.tsx", "index.mjs", "index.cjs"];
63754
- for (const indexFile of indexFiles) {
63755
- const indexPath = path2.join(directoryPath, indexFile);
63756
- const indexRelativePath = path2.relative(directory, indexPath);
63757
- const indexNormalizedPath = normalize(indexRelativePath);
63758
- if (allPossiblePaths.has(indexNormalizedPath)) {
63759
- architectureMap.edges.push({
63760
- source: normalize(node.id),
63761
- target: indexNormalizedPath,
63762
- type: imp.type || "import"
63763
- });
63764
- resolvedImports++;
63765
- targetFound = true;
63766
- break;
63767
- }
63768
- }
63769
- } catch (e) {
63770
- console.warn(`\u26A0\uFE0F Index file check failed for import '${imp.source}' in file '${node.id}': ${e.message}`);
63771
- }
63772
- }
63773
- }
63774
- if (!targetFound) {
63775
- if (imp.source.startsWith("@") || imp.source.startsWith("/") || !imp.source.startsWith(".")) {
63776
- const commonSourceDirs = ["src", "app", "lib", "components", "utils", "services", "assets"];
63777
- for (const srcDir of commonSourceDirs) {
63778
- const potentialPath = path2.join(srcDir, imp.source);
63779
- const potentialRelativePath = path2.relative(directory, path2.resolve(directory, potentialPath));
63780
- const potentialNormalizedPath = normalize(potentialRelativePath);
63781
- if (allPossiblePaths.has(potentialNormalizedPath)) {
63782
- architectureMap.edges.push({
63783
- source: normalize(node.id),
63784
- target: potentialNormalizedPath,
63785
- type: imp.type || "import"
63786
- });
63787
- resolvedImports++;
63788
- targetFound = true;
63789
- break;
63790
- }
63791
- const extensions = [
63792
- ".js",
63793
- ".ts",
63794
- ".jsx",
63795
- ".tsx",
63796
- ".mjs",
63797
- ".cjs",
63798
- "index.js",
63799
- "index.ts",
63800
- "index.jsx",
63801
- "index.tsx",
63802
- "index.mjs",
63803
- "index.cjs"
63804
- ];
63805
- for (const ext of extensions) {
63806
- let testPath;
63807
- if (ext.startsWith("index")) {
63808
- testPath = path2.join(srcDir, imp.source, ext);
63809
- } else {
63810
- testPath = path2.join(srcDir, imp.source + ext);
63811
- }
63812
- const testRelativePath = path2.relative(directory, path2.resolve(directory, testPath));
63813
- const testNormalizedPath = normalize(testRelativePath);
63814
- if (allPossiblePaths.has(testNormalizedPath)) {
63815
- architectureMap.edges.push({
63816
- source: normalize(node.id),
63817
- target: testNormalizedPath,
63818
- type: imp.type || "import"
63819
- });
63820
- resolvedImports++;
63821
- targetFound = true;
63822
- break;
63823
- }
63824
- }
63825
- if (targetFound)
63826
- break;
63827
- }
63828
- }
63829
- }
63830
- if (!targetFound) {
63831
- if (imp.source.startsWith("@") || imp.source.startsWith("/")) {
63832
- try {
63833
- const parts = imp.source.split("/");
63834
- if (parts.length > 1) {
63835
- const dirParts = parts.slice(0, -1);
63836
- const fileName = parts[parts.length - 1];
63837
- const dirPath = dirParts.join("/") + "/index";
63838
- const indexFiles = ["index.js", "index.ts", "index.jsx", "index.tsx", "index.mjs", "index.cjs"];
63839
- for (const indexFile of indexFiles) {
63840
- const indexPath = path2.join(dirParts.join("/"), indexFile);
63841
- const indexRelativePath = path2.relative(directory, path2.resolve(directory, indexPath));
63842
- const indexNormalizedPath = normalize(indexRelativePath);
63843
- if (allPossiblePaths.has(indexNormalizedPath)) {
63844
- architectureMap.edges.push({
63845
- source: normalize(node.id),
63846
- target: indexNormalizedPath,
63847
- type: imp.type || "import"
63848
- });
63849
- resolvedImports++;
63850
- targetFound = true;
63851
- break;
63852
- }
63853
- }
63854
- }
63855
- } catch (e) {
63856
- console.warn(`\u26A0\uFE0F Barrel file check failed for import '${imp.source}' in file '${node.id}': ${e.message}`);
63857
- }
63858
- }
63859
- }
63860
- if (!targetFound) {
63861
- for (const possiblePath of allPossiblePaths) {
63862
- if (possiblePath.toLowerCase() === imp.source.toLowerCase()) {
63863
- architectureMap.edges.push({
63864
- source: normalize(node.id),
63865
- target: possiblePath,
63866
- type: imp.type || "import"
63867
- });
63868
- resolvedImports++;
63869
- targetFound = true;
63870
- break;
63871
- }
63872
- }
63873
- }
63874
- } catch (e) {
63875
- console.error(`\u274C Critical error processing import '${imp.source}' in file '${node.id}': ${e.message}`);
63876
- console.error(e.stack);
63877
- unresolvedImports++;
63878
- }
63879
- if (!targetFound) {
63880
- unresolvedImports++;
63881
- }
63882
- }
63883
- });
63884
- }
63885
- });
63886
- console.log("RESOLVED IMPORTS:", resolvedImports);
63887
- console.log("UNRESOLVED IMPORTS:", unresolvedImports);
63888
- console.log("EDGES CREATED:", architectureMap.edges.length);
63889
- const reverseGraph = buildReverseDependencyGraph(architectureMap);
63890
- const blastRadiusMap = computeBlastRadius(reverseGraph);
63891
- architectureMap.nodes.forEach((node) => {
63892
- node.metadata.blast_radius = blastRadiusMap[node.id] || 0;
63893
- });
63894
- console.log("BEFORE DEDUPLICATION EDGES:", architectureMap.edges.length);
63895
- const validEdges = [];
63896
- const edgeSet = /* @__PURE__ */ new Set();
63897
- architectureMap.edges.forEach((edge) => {
63898
- const normalizedSource = normalize(edge.source);
63899
- const normalizedTarget = normalize(edge.target);
63900
- const edgeKey = `${normalizedSource}\u2192${normalizedTarget}`;
63901
- const sourceNodeExists = architectureMap.nodes.some((node) => node.id === normalizedSource);
63902
- const targetNodeExists = architectureMap.nodes.some((node) => node.id === normalizedTarget);
63903
- if (sourceNodeExists && targetNodeExists && !edgeSet.has(edgeKey)) {
63904
- edgeSet.add(edgeKey);
63905
- validEdges.push({
63906
- source: normalizedSource,
63907
- target: normalizedTarget,
63908
- type: edge.type
63909
- });
63910
- }
63911
- });
63912
- console.log("AFTER DEDUPLICATION EDGES:", validEdges.length);
63913
- architectureMap.edges = validEdges;
63914
- const totalFiles = architectureMap.nodes.length;
63915
- const { computeBlastRadiusWithPercentage: computeBlastRadiusWithPercentage2, analyzeCriticality } = require_blastRadius();
63916
- const allFilesWithPercentage = computeBlastRadiusWithPercentage2(blastRadiusMap, totalFiles);
63917
- const criticalityAnalysis = analyzeCriticality(blastRadiusMap, reverseGraph, architectureMap.nodes);
63918
- const topFiles = allFilesWithPercentage.slice(0, 3);
63919
- architectureMap.contextSurface = {
63920
- topBlastRadiusFiles: topFiles,
63921
- criticalityAnalysis: criticalityAnalysis.slice(0, 5)
63922
- // Top 5 most critical files
63923
- };
63924
- let context = buildContext(architectureMap.nodes, architectureMap.edges, {
65175
+ const start = Date.now();
65176
+ const workspaceScanner = new WorkspaceScanner(directory);
65177
+ const workspaceContext = workspaceScanner.scan();
65178
+ const rawNodes = await executePass1(directory);
65179
+ const semanticData = await executePass2(rawNodes, directory, workspaceContext);
65180
+ const liftedData = await executePass3(semanticData);
65181
+ const structuralContext = await executePass4(liftedData);
65182
+ const { nodes, edges, contextSurface, symbols } = structuralContext;
65183
+ console.log(`
65184
+ \u{1F50D} Analysis Complete (${Date.now() - start}ms)`);
65185
+ console.log(` Nodes: ${nodes.length}`);
65186
+ console.log(` Edges: ${edges.length}`);
65187
+ console.log(` Symbols: ${symbols ? symbols.length : 0}`);
65188
+ const contextOptions = {
63925
65189
  directory,
63926
65190
  projectName: path2.basename(directory),
63927
- language: "javascript",
63928
- contextSurface: architectureMap.contextSurface
63929
- });
63930
- console.log("Validating structural context...");
65191
+ contextSurface
65192
+ };
65193
+ let context = buildContext(nodes, edges, symbols, contextOptions);
65194
+ console.log(" Validating structural context...");
63931
65195
  let validation = validateContext(context);
63932
65196
  if (!validation.valid) {
63933
- console.error("VALIDATION FAILED (Attempt 1)");
63934
- validation.errors.forEach((e) => console.error(" -", e));
63935
- console.log("Re-running generation deterministically...");
63936
- context = buildContext(architectureMap.nodes, architectureMap.edges, {
63937
- directory,
63938
- projectName: path2.basename(directory),
63939
- language: "javascript",
63940
- contextSurface: architectureMap.contextSurface
63941
- });
63942
- validation = validateContext(context);
63943
- if (!validation.valid) {
63944
- console.error("VALIDATION FAILED (Attempt 2)");
63945
- validation.errors.forEach((e) => console.error(" -", e));
63946
- console.error("ABORTING. JSON NOT SAVED.");
63947
- process.exit(1);
63948
- }
65197
+ console.error(" \u274C Validation Failed");
65198
+ validation.errors.forEach((e) => console.error(" -", e));
65199
+ throw new Error("Context validation failed");
63949
65200
  }
63950
65201
  const sortedContext = sortContext(context);
63951
- console.log("STRUCTURAL CONTEXT VALIDATED \u2014 READY FOR UPLOAD");
65202
+ console.log(" \u2705 Context Verified & Ready");
63952
65203
  return sortedContext;
63953
65204
  } catch (err) {
65205
+ console.error("\u274C Scanner Failed:", err);
63954
65206
  throw err;
63955
65207
  }
63956
65208
  }
@@ -64180,7 +65432,6 @@ program.command("scan").description("Scan the current directory and generate arc
64180
65432
  const outputFileName = "arcvision.context.json";
64181
65433
  fs2.writeFileSync(outputFileName, JSON.stringify(map, null, 2));
64182
65434
  console.log(chalk.green(`\u2705 Structural context saved to ${outputFileName}`));
64183
- console.log(JSON.stringify(map, null, 2));
64184
65435
  console.log(chalk.dim("\nUse --upload to send to dashboard."));
64185
65436
  }
64186
65437
  } catch (error) {