depwire-cli 0.9.29 → 1.0.0

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.
@@ -32,7 +32,8 @@ function scanDirectory(rootDir, baseDir = rootDir) {
32
32
  const isGo = entry.endsWith(".go") && !entry.endsWith("_test.go");
33
33
  const isRust = entry.endsWith(".rs");
34
34
  const isC = entry.endsWith(".c") || entry.endsWith(".h");
35
- if (isTypeScript || isJavaScript || isPython || isGo || isRust || isC) {
35
+ const isCSharp = entry.endsWith(".cs") || entry.endsWith(".csx") || entry.endsWith(".csproj");
36
+ if (isTypeScript || isJavaScript || isPython || isGo || isRust || isC || isCSharp) {
36
37
  files.push(relative(rootDir, fullPath));
37
38
  }
38
39
  }
@@ -103,11 +104,11 @@ function findProjectRoot(startDir = process.cwd()) {
103
104
  }
104
105
 
105
106
  // src/parser/index.ts
106
- import { readFileSync as readFileSync5, statSync as statSync2 } from "fs";
107
- import { join as join8, resolve as resolve3 } from "path";
107
+ import { readFileSync as readFileSync6, statSync as statSync3 } from "fs";
108
+ import { join as join9, resolve as resolve4 } from "path";
108
109
 
109
110
  // src/parser/detect.ts
110
- import { extname as extname3 } from "path";
111
+ import { extname as extname4 } from "path";
111
112
 
112
113
  // src/parser/wasm-init.ts
113
114
  import { Parser, Language } from "web-tree-sitter";
@@ -134,7 +135,8 @@ async function initParser() {
134
135
  "python": "tree-sitter-python.wasm",
135
136
  "go": "tree-sitter-go.wasm",
136
137
  "rust": "tree-sitter-rust.wasm",
137
- "c": "tree-sitter-c.wasm"
138
+ "c": "tree-sitter-c.wasm",
139
+ "c_sharp": "tree-sitter-c_sharp.wasm"
138
140
  };
139
141
  for (const [name, file] of Object.entries(grammarFiles)) {
140
142
  const wasmPath = path.join(grammarsDir, file);
@@ -2782,6 +2784,564 @@ var cParser = {
2782
2784
  parseFile: parseCFile
2783
2785
  };
2784
2786
 
2787
+ // src/parser/csharp.ts
2788
+ import { dirname as dirname7, join as join8, resolve as resolve3, basename } from "path";
2789
+ import { existsSync as existsSync8, readdirSync as readdirSync5, statSync as statSync2 } from "fs";
2790
+ function parseCSharpFile(filePath, sourceCode, projectRoot) {
2791
+ if (filePath.endsWith(".csproj")) {
2792
+ return parseCsprojFile(filePath, sourceCode, projectRoot);
2793
+ }
2794
+ const parser = getParser("c_sharp");
2795
+ const tree = parser.parse(sourceCode, null, { bufferSize: 1024 * 1024 });
2796
+ const context = {
2797
+ filePath,
2798
+ projectRoot,
2799
+ sourceCode,
2800
+ symbols: [],
2801
+ edges: [],
2802
+ currentScope: [],
2803
+ currentClass: null,
2804
+ currentNamespace: null,
2805
+ imports: /* @__PURE__ */ new Map(),
2806
+ isCsproj: false
2807
+ };
2808
+ walkNode7(tree.rootNode, context);
2809
+ return {
2810
+ filePath,
2811
+ symbols: context.symbols,
2812
+ edges: context.edges
2813
+ };
2814
+ }
2815
+ function walkNode7(node, context) {
2816
+ processNode7(node, context);
2817
+ for (let i = 0; i < node.childCount; i++) {
2818
+ const child = node.child(i);
2819
+ if (child) {
2820
+ walkNode7(child, context);
2821
+ }
2822
+ }
2823
+ }
2824
+ function processNode7(node, context) {
2825
+ switch (node.type) {
2826
+ case "namespace_declaration":
2827
+ processNamespaceDeclaration(node, context);
2828
+ break;
2829
+ case "file_scoped_namespace_declaration":
2830
+ processFileScopedNamespace(node, context);
2831
+ break;
2832
+ case "class_declaration":
2833
+ processClassDeclaration3(node, context);
2834
+ break;
2835
+ case "interface_declaration":
2836
+ processInterfaceDeclaration2(node, context);
2837
+ break;
2838
+ case "struct_declaration":
2839
+ processStructDeclaration(node, context);
2840
+ break;
2841
+ case "enum_declaration":
2842
+ processEnumDeclaration2(node, context);
2843
+ break;
2844
+ case "record_declaration":
2845
+ processRecordDeclaration(node, context);
2846
+ break;
2847
+ case "delegate_declaration":
2848
+ processDelegateDeclaration(node, context);
2849
+ break;
2850
+ case "method_declaration":
2851
+ processMethodDeclaration2(node, context);
2852
+ break;
2853
+ case "constructor_declaration":
2854
+ processConstructorDeclaration(node, context);
2855
+ break;
2856
+ case "property_declaration":
2857
+ processPropertyDeclaration(node, context);
2858
+ break;
2859
+ case "event_field_declaration":
2860
+ processEventFieldDeclaration(node, context);
2861
+ break;
2862
+ case "indexer_declaration":
2863
+ processIndexerDeclaration(node, context);
2864
+ break;
2865
+ case "using_directive":
2866
+ processUsingDirective(node, context);
2867
+ break;
2868
+ case "global_statement":
2869
+ processGlobalStatement(node, context);
2870
+ break;
2871
+ case "invocation_expression":
2872
+ processCallExpression7(node, context);
2873
+ break;
2874
+ }
2875
+ }
2876
+ function processNamespaceDeclaration(node, context) {
2877
+ const nameNode = node.childForFieldName("name");
2878
+ if (!nameNode) return;
2879
+ const name = nodeText6(nameNode, context);
2880
+ const symbolId = `${context.filePath}::${name}`;
2881
+ context.symbols.push({
2882
+ id: symbolId,
2883
+ name,
2884
+ kind: "module",
2885
+ filePath: context.filePath,
2886
+ startLine: node.startPosition.row + 1,
2887
+ endLine: node.endPosition.row + 1,
2888
+ exported: true
2889
+ });
2890
+ const oldNamespace = context.currentNamespace;
2891
+ context.currentNamespace = name;
2892
+ context.currentScope.push(name);
2893
+ const body = findChildByType7(node, "declaration_list");
2894
+ if (body) {
2895
+ walkNode7(body, context);
2896
+ }
2897
+ context.currentScope.pop();
2898
+ context.currentNamespace = oldNamespace;
2899
+ }
2900
+ function processFileScopedNamespace(node, context) {
2901
+ const nameNode = node.childForFieldName("name");
2902
+ if (!nameNode) return;
2903
+ const name = nodeText6(nameNode, context);
2904
+ const symbolId = `${context.filePath}::${name}`;
2905
+ context.symbols.push({
2906
+ id: symbolId,
2907
+ name,
2908
+ kind: "module",
2909
+ filePath: context.filePath,
2910
+ startLine: node.startPosition.row + 1,
2911
+ endLine: node.endPosition.row + 1,
2912
+ exported: true
2913
+ });
2914
+ context.currentNamespace = name;
2915
+ }
2916
+ function processClassDeclaration3(node, context) {
2917
+ processTypeDeclaration2(node, context, "class");
2918
+ }
2919
+ function processInterfaceDeclaration2(node, context) {
2920
+ processTypeDeclaration2(node, context, "interface");
2921
+ }
2922
+ function processStructDeclaration(node, context) {
2923
+ processTypeDeclaration2(node, context, "class");
2924
+ }
2925
+ function processRecordDeclaration(node, context) {
2926
+ processTypeDeclaration2(node, context, "class");
2927
+ }
2928
+ function processTypeDeclaration2(node, context, kind) {
2929
+ const nameNode = node.childForFieldName("name");
2930
+ if (!nameNode) return;
2931
+ let name = nodeText6(nameNode, context);
2932
+ const angleBracketIdx = name.indexOf("<");
2933
+ if (angleBracketIdx > 0) {
2934
+ name = name.substring(0, angleBracketIdx);
2935
+ }
2936
+ const exported = hasModifier(node, context, "public") || hasModifier(node, context, "internal");
2937
+ const scope = context.currentClass || void 0;
2938
+ const symbolId = `${context.filePath}::${name}`;
2939
+ context.symbols.push({
2940
+ id: symbolId,
2941
+ name,
2942
+ kind,
2943
+ filePath: context.filePath,
2944
+ startLine: node.startPosition.row + 1,
2945
+ endLine: node.endPosition.row + 1,
2946
+ exported,
2947
+ scope
2948
+ });
2949
+ const baseList = findChildByType7(node, "base_list");
2950
+ if (baseList) {
2951
+ for (let i = 0; i < baseList.childCount; i++) {
2952
+ const child = baseList.child(i);
2953
+ if (!child) continue;
2954
+ if (child.type === "simple_base_type" || child.type === "identifier" || child.type === "generic_name" || child.type === "qualified_name") {
2955
+ let baseName = extractBaseTypeName(child, context);
2956
+ if (baseName) {
2957
+ const baseId = resolveSymbol6(baseName, context);
2958
+ if (baseId) {
2959
+ const edgeKind = baseName.startsWith("I") && baseName.length > 1 && baseName[1] === baseName[1].toUpperCase() ? "implements" : "inherits";
2960
+ context.edges.push({
2961
+ source: symbolId,
2962
+ target: baseId,
2963
+ kind: edgeKind,
2964
+ filePath: context.filePath,
2965
+ line: child.startPosition.row + 1
2966
+ });
2967
+ }
2968
+ }
2969
+ }
2970
+ }
2971
+ }
2972
+ const oldClass = context.currentClass;
2973
+ context.currentClass = name;
2974
+ context.currentScope.push(name);
2975
+ const body = findChildByType7(node, "declaration_list");
2976
+ if (body) {
2977
+ walkNode7(body, context);
2978
+ }
2979
+ context.currentScope.pop();
2980
+ context.currentClass = oldClass;
2981
+ }
2982
+ function processEnumDeclaration2(node, context) {
2983
+ const nameNode = node.childForFieldName("name");
2984
+ if (!nameNode) return;
2985
+ const name = nodeText6(nameNode, context);
2986
+ const exported = hasModifier(node, context, "public") || hasModifier(node, context, "internal");
2987
+ const symbolId = `${context.filePath}::${name}`;
2988
+ context.symbols.push({
2989
+ id: symbolId,
2990
+ name,
2991
+ kind: "enum",
2992
+ filePath: context.filePath,
2993
+ startLine: node.startPosition.row + 1,
2994
+ endLine: node.endPosition.row + 1,
2995
+ exported
2996
+ });
2997
+ const body = findChildByType7(node, "enum_member_declaration_list");
2998
+ if (body) {
2999
+ const members = findChildrenByType2(body, "enum_member_declaration");
3000
+ for (const member of members) {
3001
+ const memberNameNode = member.childForFieldName("name");
3002
+ if (!memberNameNode) continue;
3003
+ const memberName = nodeText6(memberNameNode, context);
3004
+ const memberId = `${context.filePath}::${name}.${memberName}`;
3005
+ context.symbols.push({
3006
+ id: memberId,
3007
+ name: memberName,
3008
+ kind: "constant",
3009
+ filePath: context.filePath,
3010
+ startLine: member.startPosition.row + 1,
3011
+ endLine: member.endPosition.row + 1,
3012
+ exported,
3013
+ scope: name
3014
+ });
3015
+ }
3016
+ }
3017
+ }
3018
+ function processDelegateDeclaration(node, context) {
3019
+ const nameNode = node.childForFieldName("name");
3020
+ if (!nameNode) return;
3021
+ let name = nodeText6(nameNode, context);
3022
+ const angleBracketIdx = name.indexOf("<");
3023
+ if (angleBracketIdx > 0) name = name.substring(0, angleBracketIdx);
3024
+ const exported = hasModifier(node, context, "public") || hasModifier(node, context, "internal");
3025
+ const symbolId = `${context.filePath}::${name}`;
3026
+ context.symbols.push({
3027
+ id: symbolId,
3028
+ name,
3029
+ kind: "type_alias",
3030
+ filePath: context.filePath,
3031
+ startLine: node.startPosition.row + 1,
3032
+ endLine: node.endPosition.row + 1,
3033
+ exported
3034
+ });
3035
+ }
3036
+ function processMethodDeclaration2(node, context) {
3037
+ const nameNode = node.childForFieldName("name");
3038
+ if (!nameNode) return;
3039
+ const name = nodeText6(nameNode, context);
3040
+ const exported = hasModifier(node, context, "public");
3041
+ const scope = context.currentClass || void 0;
3042
+ const symbolId = scope ? `${context.filePath}::${scope}.${name}` : `${context.filePath}::${name}`;
3043
+ context.symbols.push({
3044
+ id: symbolId,
3045
+ name,
3046
+ kind: context.currentClass ? "method" : "function",
3047
+ filePath: context.filePath,
3048
+ startLine: node.startPosition.row + 1,
3049
+ endLine: node.endPosition.row + 1,
3050
+ exported,
3051
+ scope
3052
+ });
3053
+ const scopeName = scope ? `${scope}.${name}` : name;
3054
+ context.currentScope.push(scopeName);
3055
+ const body = node.childForFieldName("body");
3056
+ if (body) {
3057
+ walkNode7(body, context);
3058
+ }
3059
+ context.currentScope.pop();
3060
+ }
3061
+ function processConstructorDeclaration(node, context) {
3062
+ const nameNode = node.childForFieldName("name");
3063
+ if (!nameNode) return;
3064
+ const name = nodeText6(nameNode, context);
3065
+ const exported = hasModifier(node, context, "public");
3066
+ const scope = context.currentClass || void 0;
3067
+ const symbolId = scope ? `${context.filePath}::${scope}.${name}` : `${context.filePath}::${name}`;
3068
+ context.symbols.push({
3069
+ id: symbolId,
3070
+ name,
3071
+ kind: "method",
3072
+ filePath: context.filePath,
3073
+ startLine: node.startPosition.row + 1,
3074
+ endLine: node.endPosition.row + 1,
3075
+ exported,
3076
+ scope
3077
+ });
3078
+ const scopeName = scope ? `${scope}.${name}` : name;
3079
+ context.currentScope.push(scopeName);
3080
+ const body = node.childForFieldName("body");
3081
+ if (body) {
3082
+ walkNode7(body, context);
3083
+ }
3084
+ context.currentScope.pop();
3085
+ }
3086
+ function processPropertyDeclaration(node, context) {
3087
+ const nameNode = node.childForFieldName("name");
3088
+ if (!nameNode) return;
3089
+ const name = nodeText6(nameNode, context);
3090
+ const exported = hasModifier(node, context, "public");
3091
+ const scope = context.currentClass || void 0;
3092
+ const symbolId = scope ? `${context.filePath}::${scope}.${name}` : `${context.filePath}::${name}`;
3093
+ context.symbols.push({
3094
+ id: symbolId,
3095
+ name,
3096
+ kind: "property",
3097
+ filePath: context.filePath,
3098
+ startLine: node.startPosition.row + 1,
3099
+ endLine: node.endPosition.row + 1,
3100
+ exported,
3101
+ scope
3102
+ });
3103
+ }
3104
+ function processEventFieldDeclaration(node, context) {
3105
+ const varDecl = findChildByType7(node, "variable_declaration");
3106
+ if (!varDecl) return;
3107
+ const declarator = findChildByType7(varDecl, "variable_declarator");
3108
+ if (!declarator) return;
3109
+ const nameNode = declarator.childForFieldName("name") || findChildByType7(declarator, "identifier");
3110
+ if (!nameNode) return;
3111
+ const name = nodeText6(nameNode, context);
3112
+ const exported = hasModifier(node, context, "public");
3113
+ const scope = context.currentClass || void 0;
3114
+ const symbolId = scope ? `${context.filePath}::${scope}.${name}` : `${context.filePath}::${name}`;
3115
+ context.symbols.push({
3116
+ id: symbolId,
3117
+ name,
3118
+ kind: "property",
3119
+ filePath: context.filePath,
3120
+ startLine: node.startPosition.row + 1,
3121
+ endLine: node.endPosition.row + 1,
3122
+ exported,
3123
+ scope
3124
+ });
3125
+ }
3126
+ function processIndexerDeclaration(node, context) {
3127
+ const exported = hasModifier(node, context, "public");
3128
+ const scope = context.currentClass || void 0;
3129
+ const name = "this[]";
3130
+ const symbolId = scope ? `${context.filePath}::${scope}.${name}` : `${context.filePath}::${name}`;
3131
+ context.symbols.push({
3132
+ id: symbolId,
3133
+ name,
3134
+ kind: "property",
3135
+ filePath: context.filePath,
3136
+ startLine: node.startPosition.row + 1,
3137
+ endLine: node.endPosition.row + 1,
3138
+ exported,
3139
+ scope
3140
+ });
3141
+ }
3142
+ function processUsingDirective(node, context) {
3143
+ const nameNode = node.childForFieldName("name");
3144
+ if (!nameNode) return;
3145
+ const name = nodeText6(nameNode, context);
3146
+ const resolvedPath = resolveCSharpNamespace(name, context.filePath, context.projectRoot);
3147
+ if (resolvedPath) {
3148
+ const sourceId = `${context.filePath}::__file__`;
3149
+ const targetId = `${resolvedPath}::__file__`;
3150
+ context.edges.push({
3151
+ source: sourceId,
3152
+ target: targetId,
3153
+ kind: "imports",
3154
+ filePath: context.filePath,
3155
+ line: node.startPosition.row + 1
3156
+ });
3157
+ }
3158
+ }
3159
+ function processGlobalStatement(node, context) {
3160
+ const symbolId = `${context.filePath}::__toplevel__`;
3161
+ if (context.symbols.find((s) => s.id === symbolId)) return;
3162
+ context.symbols.push({
3163
+ id: symbolId,
3164
+ name: "__toplevel__",
3165
+ kind: "function",
3166
+ filePath: context.filePath,
3167
+ startLine: node.startPosition.row + 1,
3168
+ endLine: node.endPosition.row + 1,
3169
+ exported: true
3170
+ });
3171
+ }
3172
+ function processCallExpression7(node, context) {
3173
+ const functionNode = node.childForFieldName("function");
3174
+ if (!functionNode) return;
3175
+ let calleeName = null;
3176
+ if (functionNode.type === "identifier") {
3177
+ calleeName = nodeText6(functionNode, context);
3178
+ } else if (functionNode.type === "member_access_expression") {
3179
+ const nameNode = functionNode.childForFieldName("name");
3180
+ if (nameNode) {
3181
+ calleeName = nodeText6(nameNode, context);
3182
+ }
3183
+ }
3184
+ if (!calleeName) return;
3185
+ const builtins = ["ToString", "Equals", "GetHashCode", "GetType", "Console", "Write", "WriteLine", "Format", "Parse", "TryParse"];
3186
+ if (builtins.includes(calleeName)) return;
3187
+ const callerId = getCurrentSymbolId7(context);
3188
+ if (!callerId) return;
3189
+ const calleeId = resolveSymbol6(calleeName, context);
3190
+ if (calleeId) {
3191
+ context.edges.push({
3192
+ source: callerId,
3193
+ target: calleeId,
3194
+ kind: "calls",
3195
+ filePath: context.filePath,
3196
+ line: node.startPosition.row + 1
3197
+ });
3198
+ }
3199
+ }
3200
+ function parseCsprojFile(filePath, sourceCode, projectRoot) {
3201
+ const symbols = [];
3202
+ const edges = [];
3203
+ const lines = sourceCode.split("\n");
3204
+ const projectName = basename(filePath, ".csproj");
3205
+ symbols.push({
3206
+ id: `${filePath}::${projectName}`,
3207
+ name: projectName,
3208
+ kind: "module",
3209
+ filePath,
3210
+ startLine: 1,
3211
+ endLine: lines.length,
3212
+ exported: true
3213
+ });
3214
+ for (let i = 0; i < lines.length; i++) {
3215
+ const line = lines[i];
3216
+ const lineNum = i + 1;
3217
+ const projectRefMatch = line.match(/<ProjectReference\s+Include\s*=\s*"([^"]+)"/);
3218
+ if (projectRefMatch) {
3219
+ const refPath = projectRefMatch[1];
3220
+ const csprojDir = dirname7(join8(projectRoot, filePath));
3221
+ const resolvedRef = resolve3(csprojDir, refPath);
3222
+ const relativeRef = resolvedRef.startsWith(projectRoot + "/") ? resolvedRef.substring(projectRoot.length + 1) : null;
3223
+ if (relativeRef && existsSync8(resolvedRef)) {
3224
+ edges.push({
3225
+ source: `${filePath}::__file__`,
3226
+ target: `${relativeRef}::__file__`,
3227
+ kind: "imports",
3228
+ filePath,
3229
+ line: lineNum
3230
+ });
3231
+ }
3232
+ }
3233
+ const packageRefMatch = line.match(/<PackageReference\s+Include\s*=\s*"([^"]+)"/);
3234
+ if (packageRefMatch) {
3235
+ const packageName = packageRefMatch[1];
3236
+ const versionMatch = line.match(/Version\s*=\s*"([^"]+)"/);
3237
+ const version = versionMatch ? versionMatch[1] : "unknown";
3238
+ symbols.push({
3239
+ id: `${filePath}::pkg:${packageName}`,
3240
+ name: `${packageName}@${version}`,
3241
+ kind: "import",
3242
+ filePath,
3243
+ startLine: lineNum,
3244
+ endLine: lineNum,
3245
+ exported: false
3246
+ });
3247
+ }
3248
+ }
3249
+ return { filePath, symbols, edges };
3250
+ }
3251
+ function resolveCSharpNamespace(namespace, currentFile, projectRoot) {
3252
+ const namespacePath = namespace.replace(/\./g, "/");
3253
+ const candidates = [
3254
+ join8(projectRoot, namespacePath),
3255
+ join8(projectRoot, "src", namespacePath)
3256
+ ];
3257
+ for (const candidate of candidates) {
3258
+ if (existsSync8(candidate)) {
3259
+ try {
3260
+ const stats = statSync2(candidate);
3261
+ if (stats.isDirectory()) {
3262
+ const csFiles = readdirSync5(candidate).filter((f) => f.endsWith(".cs"));
3263
+ if (csFiles.length > 0) {
3264
+ const fullPath = join8(candidate, csFiles[0]);
3265
+ return fullPath.substring(projectRoot.length + 1);
3266
+ }
3267
+ }
3268
+ } catch {
3269
+ }
3270
+ }
3271
+ }
3272
+ return null;
3273
+ }
3274
+ function resolveSymbol6(name, context) {
3275
+ if (context.imports.has(name)) {
3276
+ return context.imports.get(name) || null;
3277
+ }
3278
+ const currentFileId = `${context.filePath}::${name}`;
3279
+ if (context.symbols.find((s) => s.id === currentFileId)) {
3280
+ return currentFileId;
3281
+ }
3282
+ if (context.currentClass) {
3283
+ const classMethodId = `${context.filePath}::${context.currentClass}.${name}`;
3284
+ if (context.symbols.find((s) => s.id === classMethodId)) {
3285
+ return classMethodId;
3286
+ }
3287
+ }
3288
+ return null;
3289
+ }
3290
+ function hasModifier(node, context, modifier) {
3291
+ for (let i = 0; i < node.childCount; i++) {
3292
+ const child = node.child(i);
3293
+ if (child && child.type === "modifier" && nodeText6(child, context) === modifier) {
3294
+ return true;
3295
+ }
3296
+ }
3297
+ if (modifier === "internal") {
3298
+ const hasExplicitAccess = ["public", "private", "protected", "internal"].some((m) => {
3299
+ for (let i = 0; i < node.childCount; i++) {
3300
+ const child = node.child(i);
3301
+ if (child && child.type === "modifier" && nodeText6(child, context) === m) return true;
3302
+ }
3303
+ return false;
3304
+ });
3305
+ return !hasExplicitAccess;
3306
+ }
3307
+ return false;
3308
+ }
3309
+ function extractBaseTypeName(node, context) {
3310
+ const text = nodeText6(node, context).trim();
3311
+ if (!text || text === ":" || text === ",") return null;
3312
+ const angleBracketIdx = text.indexOf("<");
3313
+ const name = angleBracketIdx > 0 ? text.substring(0, angleBracketIdx) : text;
3314
+ const dotIdx = name.lastIndexOf(".");
3315
+ return dotIdx >= 0 ? name.substring(dotIdx + 1) : name;
3316
+ }
3317
+ function findChildByType7(node, type) {
3318
+ for (let i = 0; i < node.childCount; i++) {
3319
+ const child = node.child(i);
3320
+ if (child && child.type === type) return child;
3321
+ }
3322
+ return null;
3323
+ }
3324
+ function findChildrenByType2(node, type) {
3325
+ const results = [];
3326
+ for (let i = 0; i < node.childCount; i++) {
3327
+ const child = node.child(i);
3328
+ if (child && child.type === type) results.push(child);
3329
+ }
3330
+ return results;
3331
+ }
3332
+ function nodeText6(node, context) {
3333
+ return context.sourceCode.substring(node.startIndex, node.endIndex);
3334
+ }
3335
+ function getCurrentSymbolId7(context) {
3336
+ if (context.currentScope.length === 0) return null;
3337
+ return `${context.filePath}::${context.currentScope[context.currentScope.length - 1]}`;
3338
+ }
3339
+ var csharpParser = {
3340
+ name: "csharp",
3341
+ extensions: [".cs", ".csx", ".csproj"],
3342
+ parseFile: parseCSharpFile
3343
+ };
3344
+
2785
3345
  // src/parser/detect.ts
2786
3346
  var parsers = [
2787
3347
  typescriptParser,
@@ -2789,10 +3349,11 @@ var parsers = [
2789
3349
  javascriptParser,
2790
3350
  goParser,
2791
3351
  rustParser,
2792
- cParser
3352
+ cParser,
3353
+ csharpParser
2793
3354
  ];
2794
3355
  function getParserForFile(filePath) {
2795
- const ext = extname3(filePath).toLowerCase();
3356
+ const ext = extname4(filePath).toLowerCase();
2796
3357
  return parsers.find((p) => p.extensions.includes(ext)) || null;
2797
3358
  }
2798
3359
 
@@ -2801,7 +3362,7 @@ import { minimatch } from "minimatch";
2801
3362
  var MAX_FILE_SIZE = 1e6;
2802
3363
  function shouldParseFile(fullPath) {
2803
3364
  try {
2804
- const stats = statSync2(fullPath);
3365
+ const stats = statSync3(fullPath);
2805
3366
  if (stats.size > MAX_FILE_SIZE) {
2806
3367
  console.error(`[Parser] Skipping ${fullPath} \u2014 file too large (${(stats.size / 1024).toFixed(0)}KB)`);
2807
3368
  return false;
@@ -2819,8 +3380,8 @@ async function parseProject(projectRoot, options) {
2819
3380
  let errorFiles = 0;
2820
3381
  for (const file of files) {
2821
3382
  try {
2822
- const fullPath = join8(projectRoot, file);
2823
- if (!resolve3(fullPath).startsWith(resolve3(projectRoot))) {
3383
+ const fullPath = join9(projectRoot, file);
3384
+ if (!resolve4(fullPath).startsWith(resolve4(projectRoot))) {
2824
3385
  skippedFiles++;
2825
3386
  continue;
2826
3387
  }
@@ -2849,7 +3410,7 @@ async function parseProject(projectRoot, options) {
2849
3410
  skippedFiles++;
2850
3411
  continue;
2851
3412
  }
2852
- const sourceCode = readFileSync5(fullPath, "utf-8");
3413
+ const sourceCode = readFileSync6(fullPath, "utf-8");
2853
3414
  const parsed = parser.parseFile(file, sourceCode, projectRoot);
2854
3415
  parsedFiles.push(parsed);
2855
3416
  } catch (err) {
@@ -2872,13 +3433,14 @@ async function parseProject(projectRoot, options) {
2872
3433
  }
2873
3434
 
2874
3435
  // src/cross-language/detectors/rest-api.ts
2875
- import { readFileSync as readFileSync6 } from "fs";
2876
- import { join as join9, resolve as resolve4 } from "path";
3436
+ import { readFileSync as readFileSync7 } from "fs";
3437
+ import { join as join10, resolve as resolve5 } from "path";
2877
3438
  function getLanguage(filePath) {
2878
3439
  if (filePath.endsWith(".ts") || filePath.endsWith(".tsx")) return "typescript";
2879
3440
  if (filePath.endsWith(".js") || filePath.endsWith(".jsx") || filePath.endsWith(".mjs") || filePath.endsWith(".cjs")) return "javascript";
2880
3441
  if (filePath.endsWith(".py")) return "python";
2881
3442
  if (filePath.endsWith(".go")) return "go";
3443
+ if (filePath.endsWith(".cs") || filePath.endsWith(".csx")) return "csharp";
2882
3444
  return "unknown";
2883
3445
  }
2884
3446
  function normalizePath(routePath) {
@@ -3015,6 +3577,49 @@ function extractRouteDefinitions(source, filePath) {
3015
3577
  }
3016
3578
  }
3017
3579
  }
3580
+ if (lang === "csharp") {
3581
+ const attrMatch = line.match(/\[\s*Http(Get|Post|Put|Delete|Patch)\s*\(\s*"([^"]+)"\s*\)\s*\]/);
3582
+ if (attrMatch) {
3583
+ routes.push({
3584
+ method: attrMatch[1].toUpperCase(),
3585
+ path: attrMatch[2],
3586
+ normalizedPath: normalizePath(attrMatch[2]),
3587
+ file: filePath,
3588
+ line: i + 1
3589
+ });
3590
+ }
3591
+ const routeAttrMatch = line.match(/\[\s*Route\s*\(\s*"([^"]+)"\s*\)\s*\]/);
3592
+ if (routeAttrMatch) {
3593
+ let routePath = routeAttrMatch[1];
3594
+ if (routePath.includes("[controller]")) {
3595
+ const classMatch = source.match(/class\s+(\w+?)Controller\s/);
3596
+ if (classMatch) {
3597
+ routePath = routePath.replace("[controller]", classMatch[1].toLowerCase());
3598
+ }
3599
+ }
3600
+ if (!routePath.startsWith("/")) routePath = "/" + routePath;
3601
+ routes.push({
3602
+ method: "ANY",
3603
+ path: routePath,
3604
+ normalizedPath: normalizePath(routePath),
3605
+ file: filePath,
3606
+ line: i + 1
3607
+ });
3608
+ }
3609
+ const minimalMatch = line.match(/app\s*\.\s*Map(Get|Post|Put|Delete|Patch)\s*\(\s*"([^"]+)"/);
3610
+ if (minimalMatch) {
3611
+ const path6 = minimalMatch[2];
3612
+ if (path6.startsWith("/")) {
3613
+ routes.push({
3614
+ method: minimalMatch[1].toUpperCase(),
3615
+ path: path6,
3616
+ normalizedPath: normalizePath(path6),
3617
+ file: filePath,
3618
+ line: i + 1
3619
+ });
3620
+ }
3621
+ }
3622
+ }
3018
3623
  }
3019
3624
  return routes;
3020
3625
  }
@@ -3042,7 +3647,7 @@ function getConfidence(callPath, callMethod, routePath, routeMethod) {
3042
3647
  const normalizedCall = normalizePath(stripTrailingSlash(callPath));
3043
3648
  const normalizedRoute = normalizePath(stripTrailingSlash(routePath));
3044
3649
  const exactPath = normalizedCall === normalizedRoute;
3045
- const methodMatch = callMethod === routeMethod;
3650
+ const methodMatch = callMethod === routeMethod || routeMethod === "ANY";
3046
3651
  if (exactPath && methodMatch) return "high";
3047
3652
  if (exactPath) return "medium";
3048
3653
  if (methodMatch) return "medium";
@@ -3053,11 +3658,11 @@ function detectRestApiEdges(files, projectRoot) {
3053
3658
  const allCalls = [];
3054
3659
  const allRoutes = [];
3055
3660
  for (const file of files) {
3056
- const fullPath = join9(projectRoot, file.filePath);
3057
- if (!resolve4(fullPath).startsWith(resolve4(projectRoot))) continue;
3661
+ const fullPath = join10(projectRoot, file.filePath);
3662
+ if (!resolve5(fullPath).startsWith(resolve5(projectRoot))) continue;
3058
3663
  let source;
3059
3664
  try {
3060
- source = readFileSync6(fullPath, "utf-8");
3665
+ source = readFileSync7(fullPath, "utf-8");
3061
3666
  } catch {
3062
3667
  continue;
3063
3668
  }
@@ -3093,8 +3698,8 @@ function detectRestApiEdges(files, projectRoot) {
3093
3698
  }
3094
3699
 
3095
3700
  // src/cross-language/detectors/subprocess.ts
3096
- import { readFileSync as readFileSync7 } from "fs";
3097
- import { join as join10, resolve as resolve5, basename } from "path";
3701
+ import { readFileSync as readFileSync8 } from "fs";
3702
+ import { join as join11, resolve as resolve6, basename as basename2 } from "path";
3098
3703
  var SCRIPT_EXTENSIONS = [".py", ".js", ".ts", ".go", ".rs"];
3099
3704
  function getLanguage2(filePath) {
3100
3705
  if (filePath.endsWith(".ts") || filePath.endsWith(".tsx")) return "typescript";
@@ -3193,16 +3798,16 @@ function detectSubprocessEdges(files, projectRoot) {
3193
3798
  const knownFiles = new Set(files.map((f) => f.filePath));
3194
3799
  const basenameMap = /* @__PURE__ */ new Map();
3195
3800
  for (const f of files) {
3196
- const base = basename(f.filePath);
3801
+ const base = basename2(f.filePath);
3197
3802
  if (!basenameMap.has(base)) basenameMap.set(base, []);
3198
3803
  basenameMap.get(base).push(f.filePath);
3199
3804
  }
3200
3805
  for (const file of files) {
3201
- const fullPath = join10(projectRoot, file.filePath);
3202
- if (!resolve5(fullPath).startsWith(resolve5(projectRoot))) continue;
3806
+ const fullPath = join11(projectRoot, file.filePath);
3807
+ if (!resolve6(fullPath).startsWith(resolve6(projectRoot))) continue;
3203
3808
  let source;
3204
3809
  try {
3205
- source = readFileSync7(fullPath, "utf-8");
3810
+ source = readFileSync8(fullPath, "utf-8");
3206
3811
  } catch {
3207
3812
  continue;
3208
3813
  }
@@ -3214,7 +3819,7 @@ function detectSubprocessEdges(files, projectRoot) {
3214
3819
  targetFile = call.calledFile;
3215
3820
  confidence = "high";
3216
3821
  } else {
3217
- const base = basename(call.calledFile);
3822
+ const base = basename2(call.calledFile);
3218
3823
  const candidates = basenameMap.get(base);
3219
3824
  if (candidates && candidates.length > 0) {
3220
3825
  const exactCandidate = candidates.find((c) => c.endsWith(call.calledFile));
@@ -3593,7 +4198,7 @@ function getArchitectureSummary(graph) {
3593
4198
  }
3594
4199
 
3595
4200
  // src/health/metrics.ts
3596
- import { dirname as dirname7 } from "path";
4201
+ import { dirname as dirname8 } from "path";
3597
4202
  function scoreToGrade(score) {
3598
4203
  if (score >= 90) return "A";
3599
4204
  if (score >= 80) return "B";
@@ -3626,8 +4231,8 @@ function calculateCouplingScore(graph) {
3626
4231
  totalEdges++;
3627
4232
  fileConnections.set(sourceAttrs.filePath, (fileConnections.get(sourceAttrs.filePath) || 0) + 1);
3628
4233
  fileConnections.set(targetAttrs.filePath, (fileConnections.get(targetAttrs.filePath) || 0) + 1);
3629
- const sourceDir = dirname7(sourceAttrs.filePath).split("/")[0];
3630
- const targetDir = dirname7(targetAttrs.filePath).split("/")[0];
4234
+ const sourceDir = dirname8(sourceAttrs.filePath).split("/")[0];
4235
+ const targetDir = dirname8(targetAttrs.filePath).split("/")[0];
3631
4236
  if (sourceDir !== targetDir) {
3632
4237
  crossDirEdges++;
3633
4238
  }
@@ -3674,8 +4279,8 @@ function calculateCohesionScore(graph) {
3674
4279
  const sourceAttrs = graph.getNodeAttributes(source);
3675
4280
  const targetAttrs = graph.getNodeAttributes(target);
3676
4281
  if (sourceAttrs.filePath !== targetAttrs.filePath) {
3677
- const sourceDir = dirname7(sourceAttrs.filePath);
3678
- const targetDir = dirname7(targetAttrs.filePath);
4282
+ const sourceDir = dirname8(sourceAttrs.filePath);
4283
+ const targetDir = dirname8(targetAttrs.filePath);
3679
4284
  if (!dirEdges.has(sourceDir)) {
3680
4285
  dirEdges.set(sourceDir, { internal: 0, total: 0 });
3681
4286
  }
@@ -3957,8 +4562,8 @@ function calculateDepthScore(graph) {
3957
4562
  }
3958
4563
 
3959
4564
  // src/health/index.ts
3960
- import { readFileSync as readFileSync8, writeFileSync, existsSync as existsSync8, mkdirSync } from "fs";
3961
- import { dirname as dirname8, resolve as resolve6 } from "path";
4565
+ import { readFileSync as readFileSync9, writeFileSync, existsSync as existsSync9, mkdirSync } from "fs";
4566
+ import { dirname as dirname9, resolve as resolve7 } from "path";
3962
4567
  function calculateHealthScore(graph, projectRoot) {
3963
4568
  const coupling = calculateCouplingScore(graph);
3964
4569
  const cohesion = calculateCohesionScore(graph);
@@ -4057,8 +4662,8 @@ function getHealthTrend(projectRoot, currentScore) {
4057
4662
  }
4058
4663
  }
4059
4664
  function saveHealthHistory(projectRoot, report) {
4060
- const resolvedRoot = resolve6(projectRoot);
4061
- const historyFile = resolve6(resolvedRoot, ".depwire", "health-history.json");
4665
+ const resolvedRoot = resolve7(projectRoot);
4666
+ const historyFile = resolve7(resolvedRoot, ".depwire", "health-history.json");
4062
4667
  if (!historyFile.startsWith(resolvedRoot)) {
4063
4668
  return;
4064
4669
  }
@@ -4073,10 +4678,10 @@ function saveHealthHistory(projectRoot, report) {
4073
4678
  }))
4074
4679
  };
4075
4680
  let history = [];
4076
- if (existsSync8(historyFile)) {
4681
+ if (existsSync9(historyFile)) {
4077
4682
  try {
4078
4683
  if (!historyFile.startsWith(resolvedRoot)) return;
4079
- const content = readFileSync8(historyFile, "utf-8");
4684
+ const content = readFileSync9(historyFile, "utf-8");
4080
4685
  history = JSON.parse(content);
4081
4686
  } catch {
4082
4687
  }
@@ -4085,19 +4690,19 @@ function saveHealthHistory(projectRoot, report) {
4085
4690
  if (history.length > 50) {
4086
4691
  history = history.slice(-50);
4087
4692
  }
4088
- mkdirSync(dirname8(historyFile), { recursive: true });
4693
+ mkdirSync(dirname9(historyFile), { recursive: true });
4089
4694
  if (!historyFile.startsWith(resolvedRoot)) return;
4090
4695
  writeFileSync(historyFile, JSON.stringify(history, null, 2), "utf-8");
4091
4696
  }
4092
4697
  function loadHealthHistory(projectRoot) {
4093
- const resolvedRoot = resolve6(projectRoot);
4094
- const historyFile = resolve6(resolvedRoot, ".depwire", "health-history.json");
4095
- if (!historyFile.startsWith(resolvedRoot) || !existsSync8(historyFile)) {
4698
+ const resolvedRoot = resolve7(projectRoot);
4699
+ const historyFile = resolve7(resolvedRoot, ".depwire", "health-history.json");
4700
+ if (!historyFile.startsWith(resolvedRoot) || !existsSync9(historyFile)) {
4096
4701
  return [];
4097
4702
  }
4098
4703
  try {
4099
4704
  if (!historyFile.startsWith(resolvedRoot)) return [];
4100
- const content = readFileSync8(historyFile, "utf-8");
4705
+ const content = readFileSync9(historyFile, "utf-8");
4101
4706
  return JSON.parse(content);
4102
4707
  } catch {
4103
4708
  return [];
@@ -4106,7 +4711,7 @@ function loadHealthHistory(projectRoot) {
4106
4711
 
4107
4712
  // src/dead-code/detector.ts
4108
4713
  import path2 from "path";
4109
- import { readFileSync as readFileSync9, existsSync as existsSync9 } from "fs";
4714
+ import { readFileSync as readFileSync10, existsSync as existsSync10 } from "fs";
4110
4715
  function findDeadSymbols(graph, projectRoot, includeTests = false, debug = false) {
4111
4716
  const deadSymbols = [];
4112
4717
  const context = { graph, projectRoot };
@@ -4218,8 +4823,10 @@ function isRelevantForDeadCodeDetection(attrs) {
4218
4823
  "class",
4219
4824
  "interface",
4220
4825
  "type",
4826
+ "type_alias",
4221
4827
  "enum",
4222
4828
  "const",
4829
+ "constant",
4223
4830
  "let",
4224
4831
  "var",
4225
4832
  "method",
@@ -4237,11 +4844,11 @@ function getPackageEntryPoints(projectRoot) {
4237
4844
  const entryPoints = /* @__PURE__ */ new Set();
4238
4845
  const resolvedRoot = path2.resolve(projectRoot);
4239
4846
  const packageJsonPath = path2.resolve(resolvedRoot, "package.json");
4240
- if (!packageJsonPath.startsWith(resolvedRoot) || !existsSync9(packageJsonPath)) {
4847
+ if (!packageJsonPath.startsWith(resolvedRoot) || !existsSync10(packageJsonPath)) {
4241
4848
  return entryPoints;
4242
4849
  }
4243
4850
  try {
4244
- const packageJson = JSON.parse(readFileSync9(packageJsonPath, "utf-8"));
4851
+ const packageJson = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
4245
4852
  if (packageJson.main) {
4246
4853
  entryPoints.add(path2.resolve(projectRoot, packageJson.main));
4247
4854
  }
@@ -4314,7 +4921,7 @@ function isTypeDeclarationFile(filePath) {
4314
4921
  return filePath.endsWith(".d.ts");
4315
4922
  }
4316
4923
  function isFrameworkAutoLoadedFile(filePath) {
4317
- return filePath.includes("/pages/") || filePath.includes("/routes/") || filePath.includes("/middleware/") || filePath.includes("/commands/") || filePath.includes("/api/") || filePath.includes("/app/");
4924
+ return filePath.includes("/pages/") || filePath.includes("/routes/") || filePath.includes("/middleware/") || filePath.includes("/commands/") || filePath.includes("/api/") || filePath.includes("/app/") || filePath.includes("/Controllers/") || filePath.includes("/Hubs/") || filePath.includes("/Migrations/");
4318
4925
  }
4319
4926
 
4320
4927
  // src/dead-code/classifier.ts
@@ -4382,8 +4989,8 @@ function generateReason(symbol, confidence) {
4382
4989
  return "Potentially unused";
4383
4990
  }
4384
4991
  function isBarrelFile(filePath) {
4385
- const basename5 = path3.basename(filePath);
4386
- return basename5 === "index.ts" || basename5 === "index.js";
4992
+ const basename6 = path3.basename(filePath);
4993
+ return basename6 === "index.ts" || basename6 === "index.js";
4387
4994
  }
4388
4995
  function isTestFile2(filePath) {
4389
4996
  return filePath.includes("__tests__/") || filePath.includes(".test.") || filePath.includes(".spec.") || filePath.includes("/test/") || filePath.includes("/tests/");
@@ -4562,11 +5169,11 @@ function filterByConfidence(symbols, minConfidence) {
4562
5169
  }
4563
5170
 
4564
5171
  // src/docs/generator.ts
4565
- import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync12 } from "fs";
4566
- import { join as join14 } from "path";
5172
+ import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync13 } from "fs";
5173
+ import { join as join15 } from "path";
4567
5174
 
4568
5175
  // src/docs/architecture.ts
4569
- import { dirname as dirname9 } from "path";
5176
+ import { dirname as dirname10 } from "path";
4570
5177
 
4571
5178
  // src/docs/templates.ts
4572
5179
  function header(text, level = 1) {
@@ -4717,7 +5324,7 @@ function generateModuleStructure(graph) {
4717
5324
  function getDirectoryStats(graph) {
4718
5325
  const dirMap = /* @__PURE__ */ new Map();
4719
5326
  graph.forEachNode((node, attrs) => {
4720
- const dir = dirname9(attrs.filePath);
5327
+ const dir = dirname10(attrs.filePath);
4721
5328
  if (dir === ".") return;
4722
5329
  if (!dirMap.has(dir)) {
4723
5330
  dirMap.set(dir, {
@@ -4742,7 +5349,7 @@ function getDirectoryStats(graph) {
4742
5349
  });
4743
5350
  const filesPerDir = /* @__PURE__ */ new Map();
4744
5351
  graph.forEachNode((node, attrs) => {
4745
- const dir = dirname9(attrs.filePath);
5352
+ const dir = dirname10(attrs.filePath);
4746
5353
  if (!filesPerDir.has(dir)) {
4747
5354
  filesPerDir.set(dir, /* @__PURE__ */ new Set());
4748
5355
  }
@@ -4757,8 +5364,8 @@ function getDirectoryStats(graph) {
4757
5364
  graph.forEachEdge((edge, attrs, source, target) => {
4758
5365
  const sourceAttrs = graph.getNodeAttributes(source);
4759
5366
  const targetAttrs = graph.getNodeAttributes(target);
4760
- const sourceDir = dirname9(sourceAttrs.filePath);
4761
- const targetDir = dirname9(targetAttrs.filePath);
5367
+ const sourceDir = dirname10(sourceAttrs.filePath);
5368
+ const targetDir = dirname10(targetAttrs.filePath);
4762
5369
  if (sourceDir !== targetDir) {
4763
5370
  if (!dirEdges.has(sourceDir)) {
4764
5371
  dirEdges.set(sourceDir, { in: 0, out: 0 });
@@ -4965,7 +5572,7 @@ function detectCycles(graph) {
4965
5572
  }
4966
5573
 
4967
5574
  // src/docs/conventions.ts
4968
- import { basename as basename2, extname as extname4 } from "path";
5575
+ import { basename as basename3, extname as extname5 } from "path";
4969
5576
  function generateConventions(graph, projectRoot, version) {
4970
5577
  let output = "";
4971
5578
  const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
@@ -5003,7 +5610,7 @@ function generateFileOrganization(graph) {
5003
5610
  graph.forEachNode((node, attrs) => {
5004
5611
  if (!files.has(attrs.filePath)) {
5005
5612
  files.add(attrs.filePath);
5006
- const fileName = basename2(attrs.filePath);
5613
+ const fileName = basename3(attrs.filePath);
5007
5614
  if (fileName === "index.ts" || fileName === "index.js" || fileName === "index.tsx" || fileName === "index.jsx") {
5008
5615
  barrelFileCount++;
5009
5616
  }
@@ -5062,7 +5669,7 @@ function generateNamingPatterns(graph) {
5062
5669
  graph.forEachNode((node, attrs) => {
5063
5670
  if (!files.has(attrs.filePath)) {
5064
5671
  files.add(attrs.filePath);
5065
- const fileName = basename2(attrs.filePath, extname4(attrs.filePath));
5672
+ const fileName = basename3(attrs.filePath, extname5(attrs.filePath));
5066
5673
  if (isCamelCase(fileName)) patterns.files.camelCase++;
5067
5674
  else if (isPascalCase(fileName)) patterns.files.PascalCase++;
5068
5675
  else if (isKebabCase(fileName)) patterns.files.kebabCase++;
@@ -5739,7 +6346,7 @@ function detectCyclesDetailed(graph) {
5739
6346
  }
5740
6347
 
5741
6348
  // src/docs/onboarding.ts
5742
- import { dirname as dirname10 } from "path";
6349
+ import { dirname as dirname11 } from "path";
5743
6350
  function generateOnboarding(graph, projectRoot, version) {
5744
6351
  let output = "";
5745
6352
  const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
@@ -5798,7 +6405,7 @@ function generateQuickOrientation(graph) {
5798
6405
  const primaryLang = Object.entries(languages2).sort((a, b) => b[1] - a[1])[0];
5799
6406
  const dirs = /* @__PURE__ */ new Set();
5800
6407
  graph.forEachNode((node, attrs) => {
5801
- const dir = dirname10(attrs.filePath);
6408
+ const dir = dirname11(attrs.filePath);
5802
6409
  if (dir !== ".") {
5803
6410
  const topLevel = dir.split("/")[0];
5804
6411
  dirs.add(topLevel);
@@ -5902,7 +6509,7 @@ function generateModuleMap(graph) {
5902
6509
  function getDirectoryStats2(graph) {
5903
6510
  const dirMap = /* @__PURE__ */ new Map();
5904
6511
  graph.forEachNode((node, attrs) => {
5905
- const dir = dirname10(attrs.filePath);
6512
+ const dir = dirname11(attrs.filePath);
5906
6513
  if (dir === ".") return;
5907
6514
  if (!dirMap.has(dir)) {
5908
6515
  dirMap.set(dir, {
@@ -5917,7 +6524,7 @@ function getDirectoryStats2(graph) {
5917
6524
  });
5918
6525
  const filesPerDir = /* @__PURE__ */ new Map();
5919
6526
  graph.forEachNode((node, attrs) => {
5920
- const dir = dirname10(attrs.filePath);
6527
+ const dir = dirname11(attrs.filePath);
5921
6528
  if (!filesPerDir.has(dir)) {
5922
6529
  filesPerDir.set(dir, /* @__PURE__ */ new Set());
5923
6530
  }
@@ -5932,8 +6539,8 @@ function getDirectoryStats2(graph) {
5932
6539
  graph.forEachEdge((edge, attrs, source, target) => {
5933
6540
  const sourceAttrs = graph.getNodeAttributes(source);
5934
6541
  const targetAttrs = graph.getNodeAttributes(target);
5935
- const sourceDir = dirname10(sourceAttrs.filePath);
5936
- const targetDir = dirname10(targetAttrs.filePath);
6542
+ const sourceDir = dirname11(sourceAttrs.filePath);
6543
+ const targetDir = dirname11(targetAttrs.filePath);
5937
6544
  if (sourceDir !== targetDir) {
5938
6545
  if (!dirEdges.has(sourceDir)) {
5939
6546
  dirEdges.set(sourceDir, { in: 0, out: 0 });
@@ -6014,7 +6621,7 @@ function detectClusters(graph) {
6014
6621
  const dirFiles = /* @__PURE__ */ new Map();
6015
6622
  const fileEdges = /* @__PURE__ */ new Map();
6016
6623
  graph.forEachNode((node, attrs) => {
6017
- const dir = dirname10(attrs.filePath);
6624
+ const dir = dirname11(attrs.filePath);
6018
6625
  if (!dirFiles.has(dir)) {
6019
6626
  dirFiles.set(dir, /* @__PURE__ */ new Set());
6020
6627
  }
@@ -6068,8 +6675,8 @@ function inferClusterName(files) {
6068
6675
  if (sortedWords.length > 0 && sortedWords[0][1] > 1) {
6069
6676
  return capitalizeFirst2(sortedWords[0][0]);
6070
6677
  }
6071
- const commonDir = dirname10(files[0]);
6072
- if (files.every((f) => dirname10(f) === commonDir)) {
6678
+ const commonDir = dirname11(files[0]);
6679
+ if (files.every((f) => dirname11(f) === commonDir)) {
6073
6680
  return capitalizeFirst2(commonDir.split("/").pop() || "Core");
6074
6681
  }
6075
6682
  return "Core";
@@ -6127,7 +6734,7 @@ function generateDepwireUsage(projectRoot) {
6127
6734
  }
6128
6735
 
6129
6736
  // src/docs/files.ts
6130
- import { dirname as dirname11, basename as basename3 } from "path";
6737
+ import { dirname as dirname12, basename as basename4 } from "path";
6131
6738
  function generateFiles(graph, projectRoot, version) {
6132
6739
  let output = "";
6133
6740
  const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
@@ -6231,7 +6838,7 @@ function generateDirectoryBreakdown(graph) {
6231
6838
  const fileStats = getFileStats2(graph);
6232
6839
  const dirMap = /* @__PURE__ */ new Map();
6233
6840
  for (const file of fileStats) {
6234
- const dir = dirname11(file.filePath);
6841
+ const dir = dirname12(file.filePath);
6235
6842
  const topDir = dir === "." ? "." : dir.split("/")[0];
6236
6843
  if (!dirMap.has(topDir)) {
6237
6844
  dirMap.set(topDir, {
@@ -6246,7 +6853,7 @@ function generateDirectoryBreakdown(graph) {
6246
6853
  dirStats.symbolCount += file.symbolCount;
6247
6854
  if (file.totalConnections > dirStats.maxConnections) {
6248
6855
  dirStats.maxConnections = file.totalConnections;
6249
- dirStats.mostConnectedFile = basename3(file.filePath);
6856
+ dirStats.mostConnectedFile = basename4(file.filePath);
6250
6857
  }
6251
6858
  }
6252
6859
  if (dirMap.size === 0) {
@@ -6874,7 +7481,7 @@ function generateRecommendations(graph) {
6874
7481
  }
6875
7482
 
6876
7483
  // src/docs/tests.ts
6877
- import { basename as basename4, dirname as dirname12 } from "path";
7484
+ import { basename as basename5, dirname as dirname13 } from "path";
6878
7485
  function generateTests(graph, projectRoot, version) {
6879
7486
  let output = "";
6880
7487
  const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
@@ -6902,8 +7509,8 @@ function getFileCount8(graph) {
6902
7509
  return files.size;
6903
7510
  }
6904
7511
  function isTestFile3(filePath) {
6905
- const fileName = basename4(filePath).toLowerCase();
6906
- const dirPath = dirname12(filePath).toLowerCase();
7512
+ const fileName = basename5(filePath).toLowerCase();
7513
+ const dirPath = dirname13(filePath).toLowerCase();
6907
7514
  if (dirPath.includes("test") || dirPath.includes("spec") || dirPath.includes("__tests__")) {
6908
7515
  return true;
6909
7516
  }
@@ -6961,13 +7568,13 @@ function generateTestFileInventory(graph) {
6961
7568
  return output;
6962
7569
  }
6963
7570
  function matchTestToSource(testFile) {
6964
- const testFileName = basename4(testFile);
6965
- const testDir = dirname12(testFile);
7571
+ const testFileName = basename5(testFile);
7572
+ const testDir = dirname13(testFile);
6966
7573
  let sourceFileName = testFileName.replace(/\.test\./g, ".").replace(/\.spec\./g, ".").replace(/_test\./g, ".").replace(/_spec\./g, ".");
6967
7574
  const possiblePaths = [];
6968
7575
  possiblePaths.push(testDir + "/" + sourceFileName);
6969
7576
  if (testDir.endsWith("/test") || testDir.endsWith("/tests") || testDir.endsWith("/__tests__")) {
6970
- const parentDir = dirname12(testDir);
7577
+ const parentDir = dirname13(testDir);
6971
7578
  possiblePaths.push(parentDir + "/" + sourceFileName);
6972
7579
  }
6973
7580
  if (testDir.includes("test")) {
@@ -7123,7 +7730,7 @@ function generateTestCoverageMap(graph) {
7123
7730
  const rows = mappings.slice(0, 30).map((m) => [
7124
7731
  `\`${m.sourceFile}\``,
7125
7732
  m.hasTest ? "\u2705" : "\u274C",
7126
- m.testFile ? `\`${basename4(m.testFile)}\`` : "-",
7733
+ m.testFile ? `\`${basename5(m.testFile)}\`` : "-",
7127
7734
  formatNumber(m.symbolCount)
7128
7735
  ]);
7129
7736
  let output = table(headers, rows);
@@ -7164,7 +7771,7 @@ function generateTestStatistics(graph) {
7164
7771
  `;
7165
7772
  const dirTestCoverage = /* @__PURE__ */ new Map();
7166
7773
  for (const sourceFile of sourceFiles) {
7167
- const dir = dirname12(sourceFile).split("/")[0];
7774
+ const dir = dirname13(sourceFile).split("/")[0];
7168
7775
  if (!dirTestCoverage.has(dir)) {
7169
7776
  dirTestCoverage.set(dir, { total: 0, tested: 0 });
7170
7777
  }
@@ -7187,7 +7794,7 @@ function generateTestStatistics(graph) {
7187
7794
  }
7188
7795
 
7189
7796
  // src/docs/history.ts
7190
- import { dirname as dirname13 } from "path";
7797
+ import { dirname as dirname14 } from "path";
7191
7798
  import { execSync } from "child_process";
7192
7799
  function generateHistory(graph, projectRoot, version) {
7193
7800
  let output = "";
@@ -7468,7 +8075,7 @@ function generateFeatureClusters(graph) {
7468
8075
  const dirFiles = /* @__PURE__ */ new Map();
7469
8076
  const fileEdges = /* @__PURE__ */ new Map();
7470
8077
  graph.forEachNode((node, attrs) => {
7471
- const dir = dirname13(attrs.filePath);
8078
+ const dir = dirname14(attrs.filePath);
7472
8079
  if (!dirFiles.has(dir)) {
7473
8080
  dirFiles.set(dir, /* @__PURE__ */ new Set());
7474
8081
  }
@@ -7550,7 +8157,7 @@ function capitalizeFirst3(str) {
7550
8157
  }
7551
8158
 
7552
8159
  // src/docs/current.ts
7553
- import { dirname as dirname14 } from "path";
8160
+ import { dirname as dirname15 } from "path";
7554
8161
  function generateCurrent(graph, projectRoot, version) {
7555
8162
  let output = "";
7556
8163
  const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
@@ -7688,7 +8295,7 @@ function generateCompleteFileIndex(graph) {
7688
8295
  fileInfos.sort((a, b) => a.filePath.localeCompare(b.filePath));
7689
8296
  const dirGroups = /* @__PURE__ */ new Map();
7690
8297
  for (const info of fileInfos) {
7691
- const dir = dirname14(info.filePath);
8298
+ const dir = dirname15(info.filePath);
7692
8299
  const topDir = dir === "." ? "root" : dir.split("/")[0];
7693
8300
  if (!dirGroups.has(topDir)) {
7694
8301
  dirGroups.set(topDir, []);
@@ -7899,8 +8506,8 @@ function getTopLevelDir2(filePath) {
7899
8506
  }
7900
8507
 
7901
8508
  // src/docs/status.ts
7902
- import { readFileSync as readFileSync10, existsSync as existsSync10 } from "fs";
7903
- import { resolve as resolve7 } from "path";
8509
+ import { readFileSync as readFileSync11, existsSync as existsSync11 } from "fs";
8510
+ import { resolve as resolve8 } from "path";
7904
8511
  function generateStatus(graph, projectRoot, version) {
7905
8512
  let output = "";
7906
8513
  const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
@@ -7933,16 +8540,16 @@ function getFileCount11(graph) {
7933
8540
  }
7934
8541
  function extractComments(projectRoot, filePath) {
7935
8542
  const comments = [];
7936
- const resolvedRoot = resolve7(projectRoot);
7937
- const fullPath = resolve7(resolvedRoot, filePath);
8543
+ const resolvedRoot = resolve8(projectRoot);
8544
+ const fullPath = resolve8(resolvedRoot, filePath);
7938
8545
  if (!fullPath.startsWith(resolvedRoot)) {
7939
8546
  return comments;
7940
8547
  }
7941
- if (!existsSync10(fullPath)) {
8548
+ if (!existsSync11(fullPath)) {
7942
8549
  return comments;
7943
8550
  }
7944
8551
  try {
7945
- const content = readFileSync10(fullPath, "utf-8");
8552
+ const content = readFileSync11(fullPath, "utf-8");
7946
8553
  const lines = content.split("\n");
7947
8554
  const patterns = [
7948
8555
  { type: "TODO", regex: /(?:\/\/|#|\/\*)\s*TODO:?\s*(.+)/i },
@@ -8521,16 +9128,16 @@ function generateConfidenceSection(title, description, symbols, projectRoot) {
8521
9128
  }
8522
9129
 
8523
9130
  // src/docs/metadata.ts
8524
- import { existsSync as existsSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync2 } from "fs";
8525
- import { resolve as resolve8 } from "path";
9131
+ import { existsSync as existsSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync2 } from "fs";
9132
+ import { resolve as resolve9 } from "path";
8526
9133
  function loadMetadata(outputDir) {
8527
- const resolvedDir = resolve8(outputDir);
8528
- const metadataPath = resolve8(resolvedDir, "metadata.json");
8529
- if (!metadataPath.startsWith(resolvedDir) || !existsSync11(metadataPath)) {
9134
+ const resolvedDir = resolve9(outputDir);
9135
+ const metadataPath = resolve9(resolvedDir, "metadata.json");
9136
+ if (!metadataPath.startsWith(resolvedDir) || !existsSync12(metadataPath)) {
8530
9137
  return null;
8531
9138
  }
8532
9139
  try {
8533
- const content = readFileSync11(metadataPath, "utf-8");
9140
+ const content = readFileSync12(metadataPath, "utf-8");
8534
9141
  return JSON.parse(content);
8535
9142
  } catch (err) {
8536
9143
  console.error("Failed to load metadata:", err);
@@ -8538,8 +9145,8 @@ function loadMetadata(outputDir) {
8538
9145
  }
8539
9146
  }
8540
9147
  function saveMetadata(outputDir, metadata) {
8541
- const resolvedDir = resolve8(outputDir);
8542
- const metadataPath = resolve8(resolvedDir, "metadata.json");
9148
+ const resolvedDir = resolve9(outputDir);
9149
+ const metadataPath = resolve9(resolvedDir, "metadata.json");
8543
9150
  if (!metadataPath.startsWith(resolvedDir)) {
8544
9151
  throw new Error(`Path traversal attempt blocked: ${metadataPath}`);
8545
9152
  }
@@ -8585,7 +9192,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
8585
9192
  const generated = [];
8586
9193
  const errors = [];
8587
9194
  try {
8588
- if (!existsSync12(options.outputDir)) {
9195
+ if (!existsSync13(options.outputDir)) {
8589
9196
  mkdirSync2(options.outputDir, { recursive: true });
8590
9197
  if (options.verbose) {
8591
9198
  console.log(`Created output directory: ${options.outputDir}`);
@@ -8624,7 +9231,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
8624
9231
  try {
8625
9232
  if (options.verbose) console.log("Generating ARCHITECTURE.md...");
8626
9233
  const content = generateArchitecture(graph, projectRoot, version, parseTime);
8627
- const filePath = join14(options.outputDir, "ARCHITECTURE.md");
9234
+ const filePath = join15(options.outputDir, "ARCHITECTURE.md");
8628
9235
  writeFileSync3(filePath, content, "utf-8");
8629
9236
  generated.push("ARCHITECTURE.md");
8630
9237
  } catch (err) {
@@ -8635,7 +9242,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
8635
9242
  try {
8636
9243
  if (options.verbose) console.log("Generating CONVENTIONS.md...");
8637
9244
  const content = generateConventions(graph, projectRoot, version);
8638
- const filePath = join14(options.outputDir, "CONVENTIONS.md");
9245
+ const filePath = join15(options.outputDir, "CONVENTIONS.md");
8639
9246
  writeFileSync3(filePath, content, "utf-8");
8640
9247
  generated.push("CONVENTIONS.md");
8641
9248
  } catch (err) {
@@ -8646,7 +9253,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
8646
9253
  try {
8647
9254
  if (options.verbose) console.log("Generating DEPENDENCIES.md...");
8648
9255
  const content = generateDependencies(graph, projectRoot, version);
8649
- const filePath = join14(options.outputDir, "DEPENDENCIES.md");
9256
+ const filePath = join15(options.outputDir, "DEPENDENCIES.md");
8650
9257
  writeFileSync3(filePath, content, "utf-8");
8651
9258
  generated.push("DEPENDENCIES.md");
8652
9259
  } catch (err) {
@@ -8657,7 +9264,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
8657
9264
  try {
8658
9265
  if (options.verbose) console.log("Generating ONBOARDING.md...");
8659
9266
  const content = generateOnboarding(graph, projectRoot, version);
8660
- const filePath = join14(options.outputDir, "ONBOARDING.md");
9267
+ const filePath = join15(options.outputDir, "ONBOARDING.md");
8661
9268
  writeFileSync3(filePath, content, "utf-8");
8662
9269
  generated.push("ONBOARDING.md");
8663
9270
  } catch (err) {
@@ -8668,7 +9275,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
8668
9275
  try {
8669
9276
  if (options.verbose) console.log("Generating FILES.md...");
8670
9277
  const content = generateFiles(graph, projectRoot, version);
8671
- const filePath = join14(options.outputDir, "FILES.md");
9278
+ const filePath = join15(options.outputDir, "FILES.md");
8672
9279
  writeFileSync3(filePath, content, "utf-8");
8673
9280
  generated.push("FILES.md");
8674
9281
  } catch (err) {
@@ -8679,7 +9286,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
8679
9286
  try {
8680
9287
  if (options.verbose) console.log("Generating API_SURFACE.md...");
8681
9288
  const content = generateApiSurface(graph, projectRoot, version);
8682
- const filePath = join14(options.outputDir, "API_SURFACE.md");
9289
+ const filePath = join15(options.outputDir, "API_SURFACE.md");
8683
9290
  writeFileSync3(filePath, content, "utf-8");
8684
9291
  generated.push("API_SURFACE.md");
8685
9292
  } catch (err) {
@@ -8690,7 +9297,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
8690
9297
  try {
8691
9298
  if (options.verbose) console.log("Generating ERRORS.md...");
8692
9299
  const content = generateErrors(graph, projectRoot, version);
8693
- const filePath = join14(options.outputDir, "ERRORS.md");
9300
+ const filePath = join15(options.outputDir, "ERRORS.md");
8694
9301
  writeFileSync3(filePath, content, "utf-8");
8695
9302
  generated.push("ERRORS.md");
8696
9303
  } catch (err) {
@@ -8701,7 +9308,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
8701
9308
  try {
8702
9309
  if (options.verbose) console.log("Generating TESTS.md...");
8703
9310
  const content = generateTests(graph, projectRoot, version);
8704
- const filePath = join14(options.outputDir, "TESTS.md");
9311
+ const filePath = join15(options.outputDir, "TESTS.md");
8705
9312
  writeFileSync3(filePath, content, "utf-8");
8706
9313
  generated.push("TESTS.md");
8707
9314
  } catch (err) {
@@ -8712,7 +9319,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
8712
9319
  try {
8713
9320
  if (options.verbose) console.log("Generating HISTORY.md...");
8714
9321
  const content = generateHistory(graph, projectRoot, version);
8715
- const filePath = join14(options.outputDir, "HISTORY.md");
9322
+ const filePath = join15(options.outputDir, "HISTORY.md");
8716
9323
  writeFileSync3(filePath, content, "utf-8");
8717
9324
  generated.push("HISTORY.md");
8718
9325
  } catch (err) {
@@ -8723,7 +9330,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
8723
9330
  try {
8724
9331
  if (options.verbose) console.log("Generating CURRENT.md...");
8725
9332
  const content = generateCurrent(graph, projectRoot, version);
8726
- const filePath = join14(options.outputDir, "CURRENT.md");
9333
+ const filePath = join15(options.outputDir, "CURRENT.md");
8727
9334
  writeFileSync3(filePath, content, "utf-8");
8728
9335
  generated.push("CURRENT.md");
8729
9336
  } catch (err) {
@@ -8734,7 +9341,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
8734
9341
  try {
8735
9342
  if (options.verbose) console.log("Generating STATUS.md...");
8736
9343
  const content = generateStatus(graph, projectRoot, version);
8737
- const filePath = join14(options.outputDir, "STATUS.md");
9344
+ const filePath = join15(options.outputDir, "STATUS.md");
8738
9345
  writeFileSync3(filePath, content, "utf-8");
8739
9346
  generated.push("STATUS.md");
8740
9347
  } catch (err) {
@@ -8745,7 +9352,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
8745
9352
  try {
8746
9353
  if (options.verbose) console.log("Generating HEALTH.md...");
8747
9354
  const content = generateHealth(graph, projectRoot, version);
8748
- const filePath = join14(options.outputDir, "HEALTH.md");
9355
+ const filePath = join15(options.outputDir, "HEALTH.md");
8749
9356
  writeFileSync3(filePath, content, "utf-8");
8750
9357
  generated.push("HEALTH.md");
8751
9358
  } catch (err) {
@@ -8756,7 +9363,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
8756
9363
  try {
8757
9364
  if (options.verbose) console.log("Generating DEAD_CODE.md...");
8758
9365
  const content = generateDeadCode(graph, projectRoot, version);
8759
- const filePath = join14(options.outputDir, "DEAD_CODE.md");
9366
+ const filePath = join15(options.outputDir, "DEAD_CODE.md");
8760
9367
  writeFileSync3(filePath, content, "utf-8");
8761
9368
  generated.push("DEAD_CODE.md");
8762
9369
  } catch (err) {
@@ -8800,7 +9407,7 @@ function getFileCount13(graph) {
8800
9407
  }
8801
9408
 
8802
9409
  // src/simulation/engine.ts
8803
- import { dirname as dirname15, join as join15 } from "path";
9410
+ import { dirname as dirname16, join as join16 } from "path";
8804
9411
  function normalizePath2(p) {
8805
9412
  return p.replace(/^\.\//, "").replace(/\/+$/, "");
8806
9413
  }
@@ -8931,7 +9538,7 @@ var SimulationEngine = class {
8931
9538
  }
8932
9539
  }
8933
9540
  applyRename(clone, target, newName, brokenImports) {
8934
- const destination = join15(dirname15(target), newName);
9541
+ const destination = join16(dirname16(target), newName);
8935
9542
  this.applyMove(clone, target, destination, brokenImports);
8936
9543
  }
8937
9544
  applySplit(clone, target, newFile, symbols, brokenImports) {
@@ -9131,13 +9738,13 @@ var SimulationEngine = class {
9131
9738
  };
9132
9739
 
9133
9740
  // src/security/scanner.ts
9134
- import { existsSync as existsSync14 } from "fs";
9135
- import { join as join25 } from "path";
9741
+ import { existsSync as existsSync15 } from "fs";
9742
+ import { join as join26 } from "path";
9136
9743
 
9137
9744
  // src/security/checks/dependencies.ts
9138
9745
  import { execSync as execSync2 } from "child_process";
9139
- import { existsSync as existsSync13, readFileSync as readFileSync12, readdirSync as readdirSync5 } from "fs";
9140
- import { join as join16 } from "path";
9746
+ import { existsSync as existsSync14, readFileSync as readFileSync13, readdirSync as readdirSync6 } from "fs";
9747
+ import { join as join17 } from "path";
9141
9748
  function cvssToSeverity(score) {
9142
9749
  if (score >= 9) return "critical";
9143
9750
  if (score >= 7) return "high";
@@ -9147,18 +9754,18 @@ function cvssToSeverity(score) {
9147
9754
  async function checkDependencies(_files, projectRoot) {
9148
9755
  const findings = [];
9149
9756
  try {
9150
- if (existsSync13(join16(projectRoot, "package.json"))) {
9757
+ if (existsSync14(join17(projectRoot, "package.json"))) {
9151
9758
  findings.push(...checkNpmAudit(projectRoot));
9152
9759
  findings.push(...checkPackageJsonPatterns(projectRoot));
9153
9760
  findings.push(...checkPostinstallScripts(projectRoot));
9154
9761
  }
9155
- if (existsSync13(join16(projectRoot, "requirements.txt")) || existsSync13(join16(projectRoot, "pyproject.toml"))) {
9762
+ if (existsSync14(join17(projectRoot, "requirements.txt")) || existsSync14(join17(projectRoot, "pyproject.toml"))) {
9156
9763
  findings.push(...checkPipAudit(projectRoot));
9157
9764
  }
9158
- if (existsSync13(join16(projectRoot, "Cargo.toml"))) {
9765
+ if (existsSync14(join17(projectRoot, "Cargo.toml"))) {
9159
9766
  findings.push(...checkCargoAudit(projectRoot));
9160
9767
  }
9161
- if (existsSync13(join16(projectRoot, "go.mod"))) {
9768
+ if (existsSync14(join17(projectRoot, "go.mod"))) {
9162
9769
  findings.push(...checkGoVerify(projectRoot));
9163
9770
  }
9164
9771
  } catch (err) {
@@ -9247,8 +9854,8 @@ function checkNpmAudit(projectRoot) {
9247
9854
  function checkPackageJsonPatterns(projectRoot) {
9248
9855
  const findings = [];
9249
9856
  try {
9250
- const pkgPath = join16(projectRoot, "package.json");
9251
- const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
9857
+ const pkgPath = join17(projectRoot, "package.json");
9858
+ const pkg = JSON.parse(readFileSync13(pkgPath, "utf-8"));
9252
9859
  const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
9253
9860
  for (const [name, version] of Object.entries(allDeps)) {
9254
9861
  if (version.startsWith("^") || version.startsWith("~")) {
@@ -9270,15 +9877,15 @@ function checkPackageJsonPatterns(projectRoot) {
9270
9877
  }
9271
9878
  function checkPostinstallScripts(projectRoot) {
9272
9879
  const findings = [];
9273
- const nodeModules = join16(projectRoot, "node_modules");
9274
- if (!existsSync13(nodeModules)) return findings;
9880
+ const nodeModules = join17(projectRoot, "node_modules");
9881
+ if (!existsSync14(nodeModules)) return findings;
9275
9882
  try {
9276
- const topLevelDeps = readdirSync5(nodeModules).filter((d) => !d.startsWith("."));
9883
+ const topLevelDeps = readdirSync6(nodeModules).filter((d) => !d.startsWith("."));
9277
9884
  for (const dep of topLevelDeps) {
9278
- const depPkgPath = join16(nodeModules, dep, "package.json");
9279
- if (!existsSync13(depPkgPath)) continue;
9885
+ const depPkgPath = join17(nodeModules, dep, "package.json");
9886
+ if (!existsSync14(depPkgPath)) continue;
9280
9887
  try {
9281
- const depPkg = JSON.parse(readFileSync12(depPkgPath, "utf-8"));
9888
+ const depPkg = JSON.parse(readFileSync13(depPkgPath, "utf-8"));
9282
9889
  const scripts = depPkg.scripts || {};
9283
9890
  if (scripts.postinstall || scripts.preinstall || scripts.install) {
9284
9891
  const scriptName = scripts.postinstall ? "postinstall" : scripts.preinstall ? "preinstall" : "install";
@@ -9316,7 +9923,7 @@ function checkPipAudit(projectRoot) {
9316
9923
  id: "",
9317
9924
  severity: cvssToSeverity(vuln.cvss?.score || 5),
9318
9925
  vulnerabilityClass: "dependency-cve",
9319
- file: existsSync13(join16(projectRoot, "requirements.txt")) ? "requirements.txt" : "pyproject.toml",
9926
+ file: existsSync14(join17(projectRoot, "requirements.txt")) ? "requirements.txt" : "pyproject.toml",
9320
9927
  title: `Vulnerable Python dependency: ${vuln.name}`,
9321
9928
  description: `${vuln.name}@${vuln.version} \u2014 ${vuln.id}: ${vuln.description || "Known vulnerability"}`,
9322
9929
  attackScenario: `An attacker could exploit the vulnerability in ${vuln.name}.`,
@@ -9413,8 +10020,8 @@ function checkGoVerify(projectRoot) {
9413
10020
  }
9414
10021
 
9415
10022
  // src/security/checks/injection.ts
9416
- import { readFileSync as readFileSync13 } from "fs";
9417
- import { join as join17 } from "path";
10023
+ import { readFileSync as readFileSync14 } from "fs";
10024
+ import { join as join18 } from "path";
9418
10025
  var SKIP_DIRS = ["node_modules/", "dist/", ".git/", ".wrangler/", "src/security/checks/"];
9419
10026
  var TEST_PATTERNS = ["test", "spec", "fixture", "mock", "__tests__", "__mocks__"];
9420
10027
  var USER_INPUT_NAMES = /(?:input|user|name|path|query|branch|hash|cmd|command|req\.|params|body|args|url|dir|file|subdirectory)/i;
@@ -9515,7 +10122,7 @@ async function checkInjection(files, projectRoot) {
9515
10122
  if (shouldSkip(file.filePath) || isTestFile4(file.filePath)) continue;
9516
10123
  let content;
9517
10124
  try {
9518
- content = readFileSync13(join17(projectRoot, file.filePath), "utf-8");
10125
+ content = readFileSync14(join18(projectRoot, file.filePath), "utf-8");
9519
10126
  } catch {
9520
10127
  continue;
9521
10128
  }
@@ -9553,8 +10160,8 @@ async function checkInjection(files, projectRoot) {
9553
10160
  }
9554
10161
 
9555
10162
  // src/security/checks/secrets.ts
9556
- import { readFileSync as readFileSync14 } from "fs";
9557
- import { join as join18 } from "path";
10163
+ import { readFileSync as readFileSync15 } from "fs";
10164
+ import { join as join19 } from "path";
9558
10165
  var SKIP_DIRS2 = ["node_modules/", "dist/", ".git/", ".wrangler/", "src/security/checks/"];
9559
10166
  var TEST_PATTERNS2 = ["test", "spec", "fixture", "mock", "__tests__", "__mocks__", ".example", ".sample"];
9560
10167
  var SECRET_PATTERNS = [
@@ -9587,7 +10194,7 @@ async function checkSecrets(files, projectRoot) {
9587
10194
  if (shouldSkip2(file.filePath) || isTestFile5(file.filePath)) continue;
9588
10195
  let content;
9589
10196
  try {
9590
- content = readFileSync14(join18(projectRoot, file.filePath), "utf-8");
10197
+ content = readFileSync15(join19(projectRoot, file.filePath), "utf-8");
9591
10198
  } catch {
9592
10199
  continue;
9593
10200
  }
@@ -9620,8 +10227,8 @@ async function checkSecrets(files, projectRoot) {
9620
10227
  }
9621
10228
 
9622
10229
  // src/security/checks/path-traversal.ts
9623
- import { readFileSync as readFileSync15 } from "fs";
9624
- import { join as join19 } from "path";
10230
+ import { readFileSync as readFileSync16 } from "fs";
10231
+ import { join as join20 } from "path";
9625
10232
  var SKIP_DIRS3 = ["node_modules/", "dist/", ".git/", ".wrangler/", "src/security/checks/"];
9626
10233
  var USER_INPUT_VARS = /(?:req\.|params|query|body|input|path|dir|subdirectory|file|userInput|fileName|filePath)/i;
9627
10234
  var PATTERNS2 = [
@@ -9668,7 +10275,7 @@ async function checkPathTraversal(files, projectRoot) {
9668
10275
  if (shouldSkip3(file.filePath)) continue;
9669
10276
  let content;
9670
10277
  try {
9671
- content = readFileSync15(join19(projectRoot, file.filePath), "utf-8");
10278
+ content = readFileSync16(join20(projectRoot, file.filePath), "utf-8");
9672
10279
  } catch {
9673
10280
  continue;
9674
10281
  }
@@ -9710,8 +10317,8 @@ async function checkPathTraversal(files, projectRoot) {
9710
10317
  }
9711
10318
 
9712
10319
  // src/security/checks/auth.ts
9713
- import { readFileSync as readFileSync16 } from "fs";
9714
- import { join as join20 } from "path";
10320
+ import { readFileSync as readFileSync17 } from "fs";
10321
+ import { join as join21 } from "path";
9715
10322
  var SKIP_DIRS4 = ["node_modules/", "dist/", ".git/", ".wrangler/", "src/security/checks/"];
9716
10323
  function shouldSkip4(filePath) {
9717
10324
  return SKIP_DIRS4.some((d) => filePath.includes(d));
@@ -9727,7 +10334,7 @@ async function checkAuth(files, projectRoot) {
9727
10334
  if (shouldSkip4(file.filePath)) continue;
9728
10335
  let content;
9729
10336
  try {
9730
- content = readFileSync16(join20(projectRoot, file.filePath), "utf-8");
10337
+ content = readFileSync17(join21(projectRoot, file.filePath), "utf-8");
9731
10338
  } catch {
9732
10339
  continue;
9733
10340
  }
@@ -9818,8 +10425,8 @@ async function checkAuth(files, projectRoot) {
9818
10425
  }
9819
10426
 
9820
10427
  // src/security/checks/input-validation.ts
9821
- import { readFileSync as readFileSync17 } from "fs";
9822
- import { join as join21 } from "path";
10428
+ import { readFileSync as readFileSync18 } from "fs";
10429
+ import { join as join22 } from "path";
9823
10430
  var SKIP_DIRS5 = ["node_modules/", "dist/", ".git/", ".wrangler/", "src/security/checks/"];
9824
10431
  function shouldSkip5(filePath) {
9825
10432
  return SKIP_DIRS5.some((d) => filePath.includes(d));
@@ -9831,7 +10438,7 @@ async function checkInputValidation(files, projectRoot) {
9831
10438
  if (shouldSkip5(file.filePath)) continue;
9832
10439
  let content;
9833
10440
  try {
9834
- content = readFileSync17(join21(projectRoot, file.filePath), "utf-8");
10441
+ content = readFileSync18(join22(projectRoot, file.filePath), "utf-8");
9835
10442
  } catch {
9836
10443
  continue;
9837
10444
  }
@@ -9908,8 +10515,8 @@ async function checkInputValidation(files, projectRoot) {
9908
10515
  }
9909
10516
 
9910
10517
  // src/security/checks/information-disclosure.ts
9911
- import { readFileSync as readFileSync18 } from "fs";
9912
- import { join as join22 } from "path";
10518
+ import { readFileSync as readFileSync19 } from "fs";
10519
+ import { join as join23 } from "path";
9913
10520
  var SKIP_DIRS6 = ["node_modules/", "dist/", ".git/", ".wrangler/", "src/security/checks/"];
9914
10521
  function shouldSkip6(filePath) {
9915
10522
  return SKIP_DIRS6.some((d) => filePath.includes(d));
@@ -9921,7 +10528,7 @@ async function checkInformationDisclosure(files, projectRoot) {
9921
10528
  if (shouldSkip6(file.filePath)) continue;
9922
10529
  let content;
9923
10530
  try {
9924
- content = readFileSync18(join22(projectRoot, file.filePath), "utf-8");
10531
+ content = readFileSync19(join23(projectRoot, file.filePath), "utf-8");
9925
10532
  } catch {
9926
10533
  continue;
9927
10534
  }
@@ -9991,8 +10598,8 @@ async function checkInformationDisclosure(files, projectRoot) {
9991
10598
  }
9992
10599
 
9993
10600
  // src/security/checks/cryptography.ts
9994
- import { readFileSync as readFileSync19 } from "fs";
9995
- import { join as join23 } from "path";
10601
+ import { readFileSync as readFileSync20 } from "fs";
10602
+ import { join as join24 } from "path";
9996
10603
  var SKIP_DIRS7 = ["node_modules/", "dist/", ".git/", ".wrangler/", "src/security/checks/"];
9997
10604
  function shouldSkip7(filePath) {
9998
10605
  return SKIP_DIRS7.some((d) => filePath.includes(d));
@@ -10008,7 +10615,7 @@ async function checkCryptography(files, projectRoot) {
10008
10615
  if (shouldSkip7(file.filePath)) continue;
10009
10616
  let content;
10010
10617
  try {
10011
- content = readFileSync19(join23(projectRoot, file.filePath), "utf-8");
10618
+ content = readFileSync20(join24(projectRoot, file.filePath), "utf-8");
10012
10619
  } catch {
10013
10620
  continue;
10014
10621
  }
@@ -10090,8 +10697,8 @@ async function checkCryptography(files, projectRoot) {
10090
10697
  }
10091
10698
 
10092
10699
  // src/security/checks/frontend.ts
10093
- import { readFileSync as readFileSync20 } from "fs";
10094
- import { join as join24 } from "path";
10700
+ import { readFileSync as readFileSync21 } from "fs";
10701
+ import { join as join25 } from "path";
10095
10702
  var SKIP_DIRS8 = ["node_modules/", "dist/", ".git/", ".wrangler/", "src/security/checks/"];
10096
10703
  function shouldSkip8(filePath) {
10097
10704
  return SKIP_DIRS8.some((d) => filePath.includes(d));
@@ -10107,7 +10714,7 @@ async function checkFrontend(files, projectRoot) {
10107
10714
  if (!isFrontendFile(file.filePath)) continue;
10108
10715
  let content;
10109
10716
  try {
10110
- content = readFileSync20(join24(projectRoot, file.filePath), "utf-8");
10717
+ content = readFileSync21(join25(projectRoot, file.filePath), "utf-8");
10111
10718
  } catch {
10112
10719
  continue;
10113
10720
  }
@@ -10567,11 +11174,11 @@ async function scanSecurity(projectRoot, graph, options = {}) {
10567
11174
  };
10568
11175
  }
10569
11176
  function detectPackageManager(projectRoot) {
10570
- if (existsSync14(join25(projectRoot, "package.json"))) return "npm";
10571
- if (existsSync14(join25(projectRoot, "requirements.txt"))) return "pip";
10572
- if (existsSync14(join25(projectRoot, "pyproject.toml"))) return "pip";
10573
- if (existsSync14(join25(projectRoot, "Cargo.toml"))) return "cargo";
10574
- if (existsSync14(join25(projectRoot, "go.mod"))) return "go";
11177
+ if (existsSync15(join26(projectRoot, "package.json"))) return "npm";
11178
+ if (existsSync15(join26(projectRoot, "requirements.txt"))) return "pip";
11179
+ if (existsSync15(join26(projectRoot, "pyproject.toml"))) return "pip";
11180
+ if (existsSync15(join26(projectRoot, "Cargo.toml"))) return "cargo";
11181
+ if (existsSync15(join26(projectRoot, "go.mod"))) return "go";
10575
11182
  return "unknown";
10576
11183
  }
10577
11184