depwire-cli 0.8.0 → 0.9.1

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.
@@ -29,7 +29,9 @@ function scanDirectory(rootDir, baseDir = rootDir) {
29
29
  const isJavaScript = entry.endsWith(".js") || entry.endsWith(".jsx") || entry.endsWith(".mjs") || entry.endsWith(".cjs");
30
30
  const isPython = entry.endsWith(".py");
31
31
  const isGo = entry.endsWith(".go") && !entry.endsWith("_test.go");
32
- if (isTypeScript || isJavaScript || isPython || isGo) {
32
+ const isRust = entry.endsWith(".rs");
33
+ const isC = entry.endsWith(".c") || entry.endsWith(".h");
34
+ if (isTypeScript || isJavaScript || isPython || isGo || isRust || isC) {
33
35
  files.push(relative(rootDir, fullPath));
34
36
  }
35
37
  }
@@ -54,10 +56,18 @@ function findProjectRoot(startDir = process.cwd()) {
54
56
  // TypeScript
55
57
  "go.mod",
56
58
  // Go
59
+ "Cargo.toml",
60
+ // Rust
57
61
  "pyproject.toml",
58
62
  // Python (modern)
59
63
  "setup.py",
60
64
  // Python (legacy)
65
+ "Makefile",
66
+ // C/C++ (make-based)
67
+ "CMakeLists.txt",
68
+ // C/C++ (cmake-based)
69
+ "configure.ac",
70
+ // C/C++ (autotools)
61
71
  ".git"
62
72
  // Any git repo
63
73
  ];
@@ -80,8 +90,8 @@ function findProjectRoot(startDir = process.cwd()) {
80
90
  }
81
91
 
82
92
  // src/parser/index.ts
83
- import { readFileSync as readFileSync3, statSync as statSync2 } from "fs";
84
- import { join as join6 } from "path";
93
+ import { readFileSync as readFileSync5, statSync as statSync2 } from "fs";
94
+ import { join as join8 } from "path";
85
95
 
86
96
  // src/parser/detect.ts
87
97
  import { extname as extname3 } from "path";
@@ -109,7 +119,9 @@ async function initParser() {
109
119
  "tsx": "tree-sitter-tsx.wasm",
110
120
  "javascript": "tree-sitter-javascript.wasm",
111
121
  "python": "tree-sitter-python.wasm",
112
- "go": "tree-sitter-go.wasm"
122
+ "go": "tree-sitter-go.wasm",
123
+ "rust": "tree-sitter-rust.wasm",
124
+ "c": "tree-sitter-c.wasm"
113
125
  };
114
126
  for (const [name, file] of Object.entries(grammarFiles)) {
115
127
  const wasmPath = path.join(grammarsDir, file);
@@ -1972,12 +1984,799 @@ var goParser = {
1972
1984
  parseFile: parseGoFile
1973
1985
  };
1974
1986
 
1987
+ // src/parser/rust.ts
1988
+ import { existsSync as existsSync6 } from "fs";
1989
+ import { join as join6, dirname as dirname5, relative as relative3 } from "path";
1990
+ function parseRustFile(filePath, sourceCode, projectRoot) {
1991
+ const parser = getParser("rust");
1992
+ const tree = parser.parse(sourceCode, null, { bufferSize: 1024 * 1024 });
1993
+ const context = {
1994
+ filePath,
1995
+ projectRoot,
1996
+ sourceCode,
1997
+ symbols: [],
1998
+ edges: [],
1999
+ currentScope: [],
2000
+ currentModule: []
2001
+ };
2002
+ walkNode5(tree.rootNode, context);
2003
+ return {
2004
+ filePath,
2005
+ symbols: context.symbols,
2006
+ edges: context.edges
2007
+ };
2008
+ }
2009
+ function walkNode5(node, context) {
2010
+ processNode5(node, context);
2011
+ for (let i = 0; i < node.childCount; i++) {
2012
+ const child = node.child(i);
2013
+ if (child) {
2014
+ walkNode5(child, context);
2015
+ }
2016
+ }
2017
+ }
2018
+ function processNode5(node, context) {
2019
+ const type = node.type;
2020
+ switch (type) {
2021
+ case "function_item":
2022
+ processFunctionItem(node, context);
2023
+ break;
2024
+ case "struct_item":
2025
+ processStructItem(node, context);
2026
+ break;
2027
+ case "enum_item":
2028
+ processEnumItem(node, context);
2029
+ break;
2030
+ case "trait_item":
2031
+ processTraitItem(node, context);
2032
+ break;
2033
+ case "impl_item":
2034
+ processImplItem(node, context);
2035
+ break;
2036
+ case "const_item":
2037
+ processConstItem(node, context);
2038
+ break;
2039
+ case "type_item":
2040
+ processTypeItem(node, context);
2041
+ break;
2042
+ case "use_declaration":
2043
+ processUseDeclaration(node, context);
2044
+ break;
2045
+ case "mod_item":
2046
+ processModItem(node, context);
2047
+ break;
2048
+ case "call_expression":
2049
+ processCallExpression5(node, context);
2050
+ break;
2051
+ }
2052
+ }
2053
+ function processFunctionItem(node, context) {
2054
+ const nameNode = node.childForFieldName("name");
2055
+ if (!nameNode) return;
2056
+ const name = nodeText4(nameNode, context);
2057
+ const exported = hasVisibility(node, "pub");
2058
+ const symbolId = `${context.filePath}::${name}`;
2059
+ context.symbols.push({
2060
+ id: symbolId,
2061
+ name,
2062
+ kind: "function",
2063
+ filePath: context.filePath,
2064
+ startLine: node.startPosition.row + 1,
2065
+ endLine: node.endPosition.row + 1,
2066
+ exported
2067
+ });
2068
+ context.currentScope.push(name);
2069
+ const body = node.childForFieldName("body");
2070
+ if (body) {
2071
+ walkNode5(body, context);
2072
+ }
2073
+ context.currentScope.pop();
2074
+ }
2075
+ function processStructItem(node, context) {
2076
+ const nameNode = node.childForFieldName("name");
2077
+ if (!nameNode) return;
2078
+ const name = nodeText4(nameNode, context);
2079
+ const exported = hasVisibility(node, "pub");
2080
+ const symbolId = `${context.filePath}::${name}`;
2081
+ context.symbols.push({
2082
+ id: symbolId,
2083
+ name,
2084
+ kind: "class",
2085
+ // Consistent with other parsers
2086
+ filePath: context.filePath,
2087
+ startLine: node.startPosition.row + 1,
2088
+ endLine: node.endPosition.row + 1,
2089
+ exported
2090
+ });
2091
+ }
2092
+ function processEnumItem(node, context) {
2093
+ const nameNode = node.childForFieldName("name");
2094
+ if (!nameNode) return;
2095
+ const name = nodeText4(nameNode, context);
2096
+ const exported = hasVisibility(node, "pub");
2097
+ const symbolId = `${context.filePath}::${name}`;
2098
+ context.symbols.push({
2099
+ id: symbolId,
2100
+ name,
2101
+ kind: "enum",
2102
+ filePath: context.filePath,
2103
+ startLine: node.startPosition.row + 1,
2104
+ endLine: node.endPosition.row + 1,
2105
+ exported
2106
+ });
2107
+ }
2108
+ function processTraitItem(node, context) {
2109
+ const nameNode = node.childForFieldName("name");
2110
+ if (!nameNode) return;
2111
+ const name = nodeText4(nameNode, context);
2112
+ const exported = hasVisibility(node, "pub");
2113
+ const symbolId = `${context.filePath}::${name}`;
2114
+ context.symbols.push({
2115
+ id: symbolId,
2116
+ name,
2117
+ kind: "interface",
2118
+ filePath: context.filePath,
2119
+ startLine: node.startPosition.row + 1,
2120
+ endLine: node.endPosition.row + 1,
2121
+ exported
2122
+ });
2123
+ }
2124
+ function processImplItem(node, context) {
2125
+ const typeNode = node.childForFieldName("type");
2126
+ if (!typeNode) return;
2127
+ const typeName = extractTypeName2(typeNode, context);
2128
+ if (!typeName) return;
2129
+ for (let i = 0; i < node.childCount; i++) {
2130
+ const child = node.child(i);
2131
+ if (child && child.type === "function_item") {
2132
+ const nameNode = child.childForFieldName("name");
2133
+ if (!nameNode) continue;
2134
+ const name = nodeText4(nameNode, context);
2135
+ const exported = hasVisibility(child, "pub");
2136
+ const symbolId = `${context.filePath}::${typeName}.${name}`;
2137
+ context.symbols.push({
2138
+ id: symbolId,
2139
+ name,
2140
+ kind: "method",
2141
+ filePath: context.filePath,
2142
+ startLine: child.startPosition.row + 1,
2143
+ endLine: child.endPosition.row + 1,
2144
+ exported,
2145
+ scope: typeName
2146
+ });
2147
+ context.currentScope.push(`${typeName}.${name}`);
2148
+ const body = child.childForFieldName("body");
2149
+ if (body) {
2150
+ walkNode5(body, context);
2151
+ }
2152
+ context.currentScope.pop();
2153
+ }
2154
+ }
2155
+ }
2156
+ function processConstItem(node, context) {
2157
+ const nameNode = node.childForFieldName("name");
2158
+ if (!nameNode) return;
2159
+ const name = nodeText4(nameNode, context);
2160
+ const exported = hasVisibility(node, "pub");
2161
+ const symbolId = `${context.filePath}::${name}`;
2162
+ context.symbols.push({
2163
+ id: symbolId,
2164
+ name,
2165
+ kind: "constant",
2166
+ filePath: context.filePath,
2167
+ startLine: node.startPosition.row + 1,
2168
+ endLine: node.endPosition.row + 1,
2169
+ exported
2170
+ });
2171
+ }
2172
+ function processTypeItem(node, context) {
2173
+ const nameNode = node.childForFieldName("name");
2174
+ if (!nameNode) return;
2175
+ const name = nodeText4(nameNode, context);
2176
+ const exported = hasVisibility(node, "pub");
2177
+ const symbolId = `${context.filePath}::${name}`;
2178
+ context.symbols.push({
2179
+ id: symbolId,
2180
+ name,
2181
+ kind: "type_alias",
2182
+ filePath: context.filePath,
2183
+ startLine: node.startPosition.row + 1,
2184
+ endLine: node.endPosition.row + 1,
2185
+ exported
2186
+ });
2187
+ }
2188
+ function processUseDeclaration(node, context) {
2189
+ let pathNode = findChildByType5(node, "scoped_identifier");
2190
+ if (!pathNode) {
2191
+ pathNode = findChildByType5(node, "identifier");
2192
+ }
2193
+ if (!pathNode) {
2194
+ pathNode = findChildByType5(node, "use_as_clause");
2195
+ if (pathNode) {
2196
+ pathNode = pathNode.childForFieldName("path");
2197
+ }
2198
+ }
2199
+ if (!pathNode) {
2200
+ return;
2201
+ }
2202
+ let pathText = nodeText4(pathNode, context);
2203
+ if (!pathText.startsWith("crate::") && !pathText.startsWith("super::") && !pathText.startsWith("self::")) {
2204
+ return;
2205
+ }
2206
+ const segments = pathText.split("::");
2207
+ if (segments.length > 1) {
2208
+ segments.pop();
2209
+ pathText = segments.join("::");
2210
+ }
2211
+ const resolvedFiles = resolveRustImport(pathText, context);
2212
+ if (resolvedFiles.length === 0) return;
2213
+ const sourceId = `${context.filePath}::__file__`;
2214
+ for (const targetFile of resolvedFiles) {
2215
+ const targetId = `${targetFile}::__file__`;
2216
+ context.edges.push({
2217
+ source: sourceId,
2218
+ target: targetId,
2219
+ kind: "imports",
2220
+ filePath: context.filePath,
2221
+ line: node.startPosition.row + 1
2222
+ });
2223
+ }
2224
+ }
2225
+ function processModItem(node, context) {
2226
+ const nameNode = node.childForFieldName("name");
2227
+ if (!nameNode) return;
2228
+ const name = nodeText4(nameNode, context);
2229
+ const body = node.childForFieldName("body");
2230
+ if (!body) {
2231
+ const resolvedFiles = resolveModuleFile(name, context);
2232
+ if (resolvedFiles.length > 0) {
2233
+ const sourceId = `${context.filePath}::__file__`;
2234
+ for (const targetFile of resolvedFiles) {
2235
+ const targetId = `${targetFile}::__file__`;
2236
+ context.edges.push({
2237
+ source: sourceId,
2238
+ target: targetId,
2239
+ kind: "imports",
2240
+ filePath: context.filePath,
2241
+ line: node.startPosition.row + 1
2242
+ });
2243
+ }
2244
+ }
2245
+ }
2246
+ const exported = hasVisibility(node, "pub");
2247
+ const symbolId = `${context.filePath}::${name}`;
2248
+ context.symbols.push({
2249
+ id: symbolId,
2250
+ name,
2251
+ kind: "module",
2252
+ filePath: context.filePath,
2253
+ startLine: node.startPosition.row + 1,
2254
+ endLine: node.endPosition.row + 1,
2255
+ exported
2256
+ });
2257
+ }
2258
+ function processCallExpression5(node, context) {
2259
+ const functionNode = node.childForFieldName("function");
2260
+ if (!functionNode) return;
2261
+ const calleeName = extractCalleeNameFromNode(functionNode, context);
2262
+ if (!calleeName) return;
2263
+ const builtins = ["println!", "print!", "eprintln!", "eprint!", "format!", "panic!", "assert!", "assert_eq!", "assert_ne!", "vec!"];
2264
+ if (builtins.includes(calleeName)) return;
2265
+ const callerId = getCurrentSymbolId5(context);
2266
+ if (!callerId) return;
2267
+ const calleeId = resolveSymbol4(calleeName, context);
2268
+ if (!calleeId) return;
2269
+ context.edges.push({
2270
+ source: callerId,
2271
+ target: calleeId,
2272
+ kind: "calls",
2273
+ filePath: context.filePath,
2274
+ line: node.startPosition.row + 1
2275
+ });
2276
+ }
2277
+ function resolveRustImport(importPath, context) {
2278
+ if (importPath.startsWith("crate::")) {
2279
+ const relativePath = importPath.replace("crate::", "").replace(/::/g, "/");
2280
+ const possibleFiles = [
2281
+ join6(context.projectRoot, "src", `${relativePath}.rs`),
2282
+ join6(context.projectRoot, "src", relativePath, "mod.rs")
2283
+ ];
2284
+ return possibleFiles.filter((f) => existsSync6(f)).map((f) => relative3(context.projectRoot, f));
2285
+ }
2286
+ if (importPath.startsWith("super::")) {
2287
+ const currentFileAbs = join6(context.projectRoot, context.filePath);
2288
+ const currentDir = dirname5(currentFileAbs);
2289
+ const parentDir = dirname5(currentDir);
2290
+ const relativePath = importPath.replace("super::", "").replace(/::/g, "/");
2291
+ const possibleFiles = [
2292
+ join6(parentDir, `${relativePath}.rs`),
2293
+ join6(parentDir, relativePath, "mod.rs")
2294
+ ];
2295
+ return possibleFiles.filter((f) => existsSync6(f)).map((f) => relative3(context.projectRoot, f));
2296
+ }
2297
+ if (importPath.startsWith("self::")) {
2298
+ const currentFileAbs = join6(context.projectRoot, context.filePath);
2299
+ const currentDir = dirname5(currentFileAbs);
2300
+ const relativePath = importPath.replace("self::", "").replace(/::/g, "/");
2301
+ const possibleFiles = [
2302
+ join6(currentDir, `${relativePath}.rs`),
2303
+ join6(currentDir, relativePath, "mod.rs")
2304
+ ];
2305
+ return possibleFiles.filter((f) => existsSync6(f)).map((f) => relative3(context.projectRoot, f));
2306
+ }
2307
+ return [];
2308
+ }
2309
+ function resolveModuleFile(moduleName, context) {
2310
+ const currentFileAbs = join6(context.projectRoot, context.filePath);
2311
+ const currentDir = dirname5(currentFileAbs);
2312
+ const possibleFiles = [
2313
+ join6(currentDir, `${moduleName}.rs`),
2314
+ join6(currentDir, moduleName, "mod.rs")
2315
+ ];
2316
+ return possibleFiles.filter((f) => existsSync6(f)).map((f) => relative3(context.projectRoot, f));
2317
+ }
2318
+ function hasVisibility(node, visibility) {
2319
+ for (let i = 0; i < node.childCount; i++) {
2320
+ const child = node.child(i);
2321
+ if (child && child.type === "visibility_modifier") {
2322
+ const text = nodeText4(child, { sourceCode: node.text });
2323
+ return text === visibility;
2324
+ }
2325
+ }
2326
+ return false;
2327
+ }
2328
+ function extractTypeName2(typeNode, context) {
2329
+ if (typeNode.type === "type_identifier") {
2330
+ return nodeText4(typeNode, context);
2331
+ }
2332
+ if (typeNode.type === "generic_type") {
2333
+ const typeId = findChildByType5(typeNode, "type_identifier");
2334
+ if (typeId) {
2335
+ return nodeText4(typeId, context);
2336
+ }
2337
+ }
2338
+ for (let i = 0; i < typeNode.childCount; i++) {
2339
+ const child = typeNode.child(i);
2340
+ if (child && child.type === "type_identifier") {
2341
+ return nodeText4(child, context);
2342
+ }
2343
+ }
2344
+ return null;
2345
+ }
2346
+ function extractCalleeNameFromNode(functionNode, context) {
2347
+ if (functionNode.type === "identifier") {
2348
+ return nodeText4(functionNode, context);
2349
+ }
2350
+ if (functionNode.type === "field_expression") {
2351
+ const field = functionNode.childForFieldName("field");
2352
+ if (field) {
2353
+ return nodeText4(field, context);
2354
+ }
2355
+ }
2356
+ if (functionNode.type === "scoped_identifier") {
2357
+ const name = functionNode.childForFieldName("name");
2358
+ if (name) {
2359
+ return nodeText4(name, context);
2360
+ }
2361
+ }
2362
+ return null;
2363
+ }
2364
+ function resolveSymbol4(name, context) {
2365
+ const currentFileId = context.filePath;
2366
+ const symbol = context.symbols.find((s) => s.name === name && s.filePath === currentFileId);
2367
+ if (symbol) {
2368
+ return symbol.id;
2369
+ }
2370
+ if (context.currentScope.length > 0) {
2371
+ for (let i = context.currentScope.length - 1; i >= 0; i--) {
2372
+ const scopedId = `${currentFileId}::${context.currentScope[i]}.${name}`;
2373
+ const scopedSymbol = context.symbols.find((s) => s.id === scopedId);
2374
+ if (scopedSymbol) {
2375
+ return scopedId;
2376
+ }
2377
+ }
2378
+ }
2379
+ return null;
2380
+ }
2381
+ function findChildByType5(node, type) {
2382
+ for (let i = 0; i < node.childCount; i++) {
2383
+ const child = node.child(i);
2384
+ if (child && child.type === type) {
2385
+ return child;
2386
+ }
2387
+ }
2388
+ return null;
2389
+ }
2390
+ function nodeText4(node, context) {
2391
+ return context.sourceCode.slice(node.startIndex, node.endIndex);
2392
+ }
2393
+ function getCurrentSymbolId5(context) {
2394
+ if (context.currentScope.length === 0) return null;
2395
+ return `${context.filePath}::${context.currentScope.join(".")}`;
2396
+ }
2397
+ var rustParser = {
2398
+ language: "rust",
2399
+ extensions: [".rs"],
2400
+ parseFile: parseRustFile
2401
+ };
2402
+
2403
+ // src/parser/c.ts
2404
+ import { existsSync as existsSync7 } from "fs";
2405
+ import { join as join7, dirname as dirname6, relative as relative4 } from "path";
2406
+ function parseCFile(filePath, sourceCode, projectRoot) {
2407
+ const parser = getParser("c");
2408
+ const tree = parser.parse(sourceCode, null, { bufferSize: 1024 * 1024 });
2409
+ const context = {
2410
+ filePath,
2411
+ projectRoot,
2412
+ sourceCode,
2413
+ symbols: [],
2414
+ edges: [],
2415
+ currentScope: []
2416
+ };
2417
+ walkNode6(tree.rootNode, context);
2418
+ return {
2419
+ filePath,
2420
+ symbols: context.symbols,
2421
+ edges: context.edges
2422
+ };
2423
+ }
2424
+ function walkNode6(node, context) {
2425
+ processNode6(node, context);
2426
+ for (let i = 0; i < node.childCount; i++) {
2427
+ const child = node.child(i);
2428
+ if (child) {
2429
+ walkNode6(child, context);
2430
+ }
2431
+ }
2432
+ }
2433
+ function processNode6(node, context) {
2434
+ const type = node.type;
2435
+ switch (type) {
2436
+ case "function_definition":
2437
+ processFunctionDefinition2(node, context);
2438
+ break;
2439
+ case "struct_specifier":
2440
+ processStructSpecifier(node, context);
2441
+ break;
2442
+ case "enum_specifier":
2443
+ processEnumSpecifier(node, context);
2444
+ break;
2445
+ case "type_definition":
2446
+ processTypeDefinition(node, context);
2447
+ break;
2448
+ case "declaration":
2449
+ processDeclaration(node, context);
2450
+ break;
2451
+ case "preproc_def":
2452
+ case "preproc_function_def":
2453
+ processMacroDefinition(node, context);
2454
+ break;
2455
+ case "preproc_include":
2456
+ processIncludeDirective(node, context);
2457
+ break;
2458
+ case "call_expression":
2459
+ processCallExpression6(node, context);
2460
+ break;
2461
+ }
2462
+ }
2463
+ function processFunctionDefinition2(node, context) {
2464
+ const declarator = node.childForFieldName("declarator");
2465
+ if (!declarator) return;
2466
+ const nameNode = extractFunctionName(declarator);
2467
+ if (!nameNode) return;
2468
+ const name = nodeText5(nameNode, context);
2469
+ const exported = !hasStorageClass(node, "static", context);
2470
+ const symbolId = `${context.filePath}::${name}`;
2471
+ context.symbols.push({
2472
+ id: symbolId,
2473
+ name,
2474
+ kind: "function",
2475
+ filePath: context.filePath,
2476
+ startLine: node.startPosition.row + 1,
2477
+ endLine: node.endPosition.row + 1,
2478
+ exported
2479
+ });
2480
+ context.currentScope.push(name);
2481
+ const body = node.childForFieldName("body");
2482
+ if (body) {
2483
+ walkNode6(body, context);
2484
+ }
2485
+ context.currentScope.pop();
2486
+ }
2487
+ function processStructSpecifier(node, context) {
2488
+ const parent = node.parent;
2489
+ let name = null;
2490
+ if (parent && parent.type === "type_definition") {
2491
+ const typedefName = parent.childForFieldName("declarator");
2492
+ if (typedefName) {
2493
+ name = extractIdentifierFromDeclarator(typedefName, context);
2494
+ }
2495
+ }
2496
+ if (!name) {
2497
+ const nameNode = node.childForFieldName("name");
2498
+ if (nameNode) {
2499
+ name = nodeText5(nameNode, context);
2500
+ }
2501
+ }
2502
+ if (!name) return;
2503
+ const symbolId = `${context.filePath}::${name}`;
2504
+ context.symbols.push({
2505
+ id: symbolId,
2506
+ name,
2507
+ kind: "class",
2508
+ filePath: context.filePath,
2509
+ startLine: node.startPosition.row + 1,
2510
+ endLine: node.endPosition.row + 1,
2511
+ exported: true
2512
+ });
2513
+ }
2514
+ function processEnumSpecifier(node, context) {
2515
+ const parent = node.parent;
2516
+ let name = null;
2517
+ if (parent && parent.type === "type_definition") {
2518
+ const typedefName = parent.childForFieldName("declarator");
2519
+ if (typedefName) {
2520
+ name = extractIdentifierFromDeclarator(typedefName, context);
2521
+ }
2522
+ }
2523
+ if (!name) {
2524
+ const nameNode = node.childForFieldName("name");
2525
+ if (nameNode) {
2526
+ name = nodeText5(nameNode, context);
2527
+ }
2528
+ }
2529
+ if (!name) return;
2530
+ const symbolId = `${context.filePath}::${name}`;
2531
+ context.symbols.push({
2532
+ id: symbolId,
2533
+ name,
2534
+ kind: "enum",
2535
+ filePath: context.filePath,
2536
+ startLine: node.startPosition.row + 1,
2537
+ endLine: node.endPosition.row + 1,
2538
+ exported: true
2539
+ });
2540
+ }
2541
+ function processTypeDefinition(node, context) {
2542
+ const typeNode = node.childForFieldName("type");
2543
+ if (!typeNode) return;
2544
+ if (typeNode.type === "struct_specifier" || typeNode.type === "enum_specifier") {
2545
+ return;
2546
+ }
2547
+ const declarator = node.childForFieldName("declarator");
2548
+ if (!declarator) return;
2549
+ const name = extractIdentifierFromDeclarator(declarator, context);
2550
+ if (!name) return;
2551
+ const symbolId = `${context.filePath}::${name}`;
2552
+ context.symbols.push({
2553
+ id: symbolId,
2554
+ name,
2555
+ kind: "type_alias",
2556
+ filePath: context.filePath,
2557
+ startLine: node.startPosition.row + 1,
2558
+ endLine: node.endPosition.row + 1,
2559
+ exported: true
2560
+ });
2561
+ }
2562
+ function processDeclaration(node, context) {
2563
+ if (context.currentScope.length > 0) {
2564
+ return;
2565
+ }
2566
+ const parent = node.parent;
2567
+ if (!parent || parent.type !== "translation_unit") {
2568
+ return;
2569
+ }
2570
+ const hasStatic = hasStorageClass(node, "static", context);
2571
+ const declarator = node.childForFieldName("declarator");
2572
+ if (!declarator) return;
2573
+ const name = extractIdentifierFromDeclarator(declarator, context);
2574
+ if (!name) return;
2575
+ const symbolId = `${context.filePath}::${name}`;
2576
+ context.symbols.push({
2577
+ id: symbolId,
2578
+ name,
2579
+ kind: "variable",
2580
+ filePath: context.filePath,
2581
+ startLine: node.startPosition.row + 1,
2582
+ endLine: node.endPosition.row + 1,
2583
+ exported: !hasStatic
2584
+ });
2585
+ }
2586
+ function processMacroDefinition(node, context) {
2587
+ const nameNode = node.childForFieldName("name");
2588
+ if (!nameNode) return;
2589
+ const name = nodeText5(nameNode, context);
2590
+ const kind = node.type === "preproc_function_def" ? "function" : "constant";
2591
+ const symbolId = `${context.filePath}::${name}`;
2592
+ context.symbols.push({
2593
+ id: symbolId,
2594
+ name,
2595
+ kind,
2596
+ filePath: context.filePath,
2597
+ startLine: node.startPosition.row + 1,
2598
+ endLine: node.endPosition.row + 1,
2599
+ exported: true
2600
+ });
2601
+ }
2602
+ function processIncludeDirective(node, context) {
2603
+ const pathNode = node.childForFieldName("path");
2604
+ if (!pathNode) return;
2605
+ const pathText = nodeText5(pathNode, context);
2606
+ const isLocalInclude = pathText.startsWith('"') && pathText.endsWith('"');
2607
+ if (!isLocalInclude) {
2608
+ return;
2609
+ }
2610
+ const includePath = pathText.slice(1, -1);
2611
+ const resolvedFiles = resolveIncludePath(includePath, context.filePath, context.projectRoot);
2612
+ if (resolvedFiles.length === 0) return;
2613
+ const sourceId = `${context.filePath}::__file__`;
2614
+ for (const targetPath of resolvedFiles) {
2615
+ const targetId = `${targetPath}::__file__`;
2616
+ context.edges.push({
2617
+ source: sourceId,
2618
+ target: targetId,
2619
+ kind: "imports",
2620
+ filePath: context.filePath,
2621
+ line: node.startPosition.row + 1
2622
+ });
2623
+ }
2624
+ }
2625
+ function processCallExpression6(node, context) {
2626
+ if (context.currentScope.length === 0) return;
2627
+ const functionNode = node.childForFieldName("function");
2628
+ if (!functionNode) return;
2629
+ const calleeName = nodeText5(functionNode, context);
2630
+ const builtins = /* @__PURE__ */ new Set(["printf", "scanf", "malloc", "free", "memcpy", "strlen", "strcmp", "strcpy", "strcat"]);
2631
+ if (builtins.has(calleeName)) return;
2632
+ const callerId = getCurrentSymbolId6(context);
2633
+ if (!callerId) return;
2634
+ const calleeId = resolveSymbol5(calleeName, context);
2635
+ if (!calleeId) return;
2636
+ context.edges.push({
2637
+ source: callerId,
2638
+ target: calleeId,
2639
+ kind: "calls",
2640
+ filePath: context.filePath,
2641
+ line: node.startPosition.row + 1
2642
+ });
2643
+ }
2644
+ function resolveIncludePath(includePath, currentFile, projectRoot) {
2645
+ const currentFileAbs = join7(projectRoot, currentFile);
2646
+ const currentDir = dirname6(currentFileAbs);
2647
+ const possibleFiles = [
2648
+ join7(currentDir, includePath),
2649
+ join7(projectRoot, includePath)
2650
+ ];
2651
+ const resolvedFiles = [];
2652
+ for (const absPath of possibleFiles) {
2653
+ if (existsSync7(absPath)) {
2654
+ const relPath = relative4(projectRoot, absPath);
2655
+ resolvedFiles.push(relPath);
2656
+ }
2657
+ }
2658
+ return resolvedFiles;
2659
+ }
2660
+ function hasStorageClass(node, className, context) {
2661
+ for (let i = 0; i < node.childCount; i++) {
2662
+ const child = node.child(i);
2663
+ if (child && child.type === "storage_class_specifier") {
2664
+ const text = nodeText5(child, context);
2665
+ if (text === className) {
2666
+ return true;
2667
+ }
2668
+ }
2669
+ }
2670
+ let parent = node.parent;
2671
+ while (parent) {
2672
+ for (let i = 0; i < parent.childCount; i++) {
2673
+ const child = parent.child(i);
2674
+ if (child && child.type === "storage_class_specifier") {
2675
+ const text = nodeText5(child, context);
2676
+ if (text === className) {
2677
+ return true;
2678
+ }
2679
+ }
2680
+ }
2681
+ parent = parent.parent;
2682
+ }
2683
+ return false;
2684
+ }
2685
+ function extractFunctionName(declarator) {
2686
+ if (declarator.type === "identifier") {
2687
+ return declarator;
2688
+ }
2689
+ if (declarator.type === "function_declarator") {
2690
+ const innerDeclarator = declarator.childForFieldName("declarator");
2691
+ if (innerDeclarator) {
2692
+ return extractFunctionName(innerDeclarator);
2693
+ }
2694
+ }
2695
+ if (declarator.type === "pointer_declarator") {
2696
+ const innerDeclarator = declarator.childForFieldName("declarator");
2697
+ if (innerDeclarator) {
2698
+ return extractFunctionName(innerDeclarator);
2699
+ }
2700
+ }
2701
+ for (let i = 0; i < declarator.childCount; i++) {
2702
+ const child = declarator.child(i);
2703
+ if (child && child.type === "identifier") {
2704
+ return child;
2705
+ }
2706
+ }
2707
+ return null;
2708
+ }
2709
+ function extractIdentifierFromDeclarator(declarator, context) {
2710
+ if (declarator.type === "identifier") {
2711
+ return nodeText5(declarator, context);
2712
+ }
2713
+ if (declarator.type === "type_identifier") {
2714
+ return nodeText5(declarator, context);
2715
+ }
2716
+ const identifierNode = findChildByType6(declarator, "identifier");
2717
+ if (identifierNode) {
2718
+ return nodeText5(identifierNode, context);
2719
+ }
2720
+ const typeIdNode = findChildByType6(declarator, "type_identifier");
2721
+ if (typeIdNode) {
2722
+ return nodeText5(typeIdNode, context);
2723
+ }
2724
+ for (let i = 0; i < declarator.childCount; i++) {
2725
+ const child = declarator.child(i);
2726
+ if (child) {
2727
+ const name = extractIdentifierFromDeclarator(child, context);
2728
+ if (name) return name;
2729
+ }
2730
+ }
2731
+ return null;
2732
+ }
2733
+ function resolveSymbol5(name, context) {
2734
+ const currentFileId = `${context.filePath}::__file__`;
2735
+ const symbol = context.symbols.find(
2736
+ (s) => s.name === name && (s.filePath === context.filePath || s.exported)
2737
+ );
2738
+ if (symbol) {
2739
+ return symbol.id;
2740
+ }
2741
+ for (let i = context.currentScope.length - 1; i >= 0; i--) {
2742
+ const scopedId = `${context.filePath}::${context.currentScope.slice(0, i + 1).join("::")}::${name}`;
2743
+ const scopedSymbol = context.symbols.find((s) => s.id === scopedId);
2744
+ if (scopedSymbol) {
2745
+ return scopedSymbol.id;
2746
+ }
2747
+ }
2748
+ return null;
2749
+ }
2750
+ function findChildByType6(node, type) {
2751
+ for (let i = 0; i < node.childCount; i++) {
2752
+ const child = node.child(i);
2753
+ if (child && child.type === type) {
2754
+ return child;
2755
+ }
2756
+ }
2757
+ return null;
2758
+ }
2759
+ function nodeText5(node, context) {
2760
+ return context.sourceCode.slice(node.startIndex, node.endIndex);
2761
+ }
2762
+ function getCurrentSymbolId6(context) {
2763
+ if (context.currentScope.length === 0) return null;
2764
+ return `${context.filePath}::${context.currentScope.join("::")}`;
2765
+ }
2766
+ var cParser = {
2767
+ name: "c",
2768
+ extensions: [".c", ".h"],
2769
+ parseFile: parseCFile
2770
+ };
2771
+
1975
2772
  // src/parser/detect.ts
1976
2773
  var parsers = [
1977
2774
  typescriptParser,
1978
2775
  pythonParser,
1979
2776
  javascriptParser,
1980
- goParser
2777
+ goParser,
2778
+ rustParser,
2779
+ cParser
1981
2780
  ];
1982
2781
  function getParserForFile(filePath) {
1983
2782
  const ext = extname3(filePath).toLowerCase();
@@ -2007,7 +2806,7 @@ async function parseProject(projectRoot, options) {
2007
2806
  let errorFiles = 0;
2008
2807
  for (const file of files) {
2009
2808
  try {
2010
- const fullPath = join6(projectRoot, file);
2809
+ const fullPath = join8(projectRoot, file);
2011
2810
  if (options?.exclude) {
2012
2811
  const shouldExclude2 = options.exclude.some(
2013
2812
  (pattern) => minimatch(file, pattern, { matchBase: true })
@@ -2033,7 +2832,7 @@ async function parseProject(projectRoot, options) {
2033
2832
  skippedFiles++;
2034
2833
  continue;
2035
2834
  }
2036
- const sourceCode = readFileSync3(fullPath, "utf-8");
2835
+ const sourceCode = readFileSync5(fullPath, "utf-8");
2037
2836
  const parsed = parser.parseFile(file, sourceCode, projectRoot);
2038
2837
  parsedFiles.push(parsed);
2039
2838
  } catch (err) {
@@ -2089,6 +2888,18 @@ function buildGraph(parsedFiles) {
2089
2888
  exported: false
2090
2889
  });
2091
2890
  }
2891
+ if (edge.target.endsWith("::__file__") && !fileNodes.has(edge.target)) {
2892
+ fileNodes.add(edge.target);
2893
+ const filePath = edge.target.replace("::__file__", "");
2894
+ graph.addNode(edge.target, {
2895
+ name: "__file__",
2896
+ kind: "import",
2897
+ filePath,
2898
+ startLine: 1,
2899
+ endLine: 1,
2900
+ exported: false
2901
+ });
2902
+ }
2092
2903
  }
2093
2904
  }
2094
2905
  for (const file of parsedFiles) {
@@ -2414,7 +3225,7 @@ function watchProject(projectRoot, callbacks) {
2414
3225
  const watcher = chokidar.watch(projectRoot, watcherOptions);
2415
3226
  console.error("[Watcher] Attaching event listeners...");
2416
3227
  watcher.on("change", (absolutePath) => {
2417
- const validExtensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py", ".go"];
3228
+ const validExtensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py", ".go", ".rs", ".c", ".h"];
2418
3229
  if (!validExtensions.some((ext) => absolutePath.endsWith(ext))) return;
2419
3230
  if (absolutePath.endsWith("_test.go")) return;
2420
3231
  const relativePath = absolutePath.replace(projectRoot + "/", "");
@@ -2422,7 +3233,7 @@ function watchProject(projectRoot, callbacks) {
2422
3233
  callbacks.onFileChanged(relativePath);
2423
3234
  });
2424
3235
  watcher.on("add", (absolutePath) => {
2425
- const validExtensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py", ".go"];
3236
+ const validExtensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py", ".go", ".rs", ".c", ".h"];
2426
3237
  if (!validExtensions.some((ext) => absolutePath.endsWith(ext))) return;
2427
3238
  if (absolutePath.endsWith("_test.go")) return;
2428
3239
  const relativePath = absolutePath.replace(projectRoot + "/", "");
@@ -2430,7 +3241,7 @@ function watchProject(projectRoot, callbacks) {
2430
3241
  callbacks.onFileAdded(relativePath);
2431
3242
  });
2432
3243
  watcher.on("unlink", (absolutePath) => {
2433
- const validExtensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py", ".go"];
3244
+ const validExtensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py", ".go", ".rs", ".c", ".h"];
2434
3245
  if (!validExtensions.some((ext) => absolutePath.endsWith(ext))) return;
2435
3246
  if (absolutePath.endsWith("_test.go")) return;
2436
3247
  const relativePath = absolutePath.replace(projectRoot + "/", "");
@@ -2448,10 +3259,10 @@ function watchProject(projectRoot, callbacks) {
2448
3259
  for (const dir of dirs) {
2449
3260
  const files = watched[dir];
2450
3261
  fileCount += files.filter(
2451
- (f) => f.endsWith(".ts") || f.endsWith(".tsx") || f.endsWith(".js") || f.endsWith(".jsx") || f.endsWith(".mjs") || f.endsWith(".cjs") || f.endsWith(".py") || f.endsWith(".go") && !f.endsWith("_test.go")
3262
+ (f) => f.endsWith(".ts") || f.endsWith(".tsx") || f.endsWith(".js") || f.endsWith(".jsx") || f.endsWith(".mjs") || f.endsWith(".cjs") || f.endsWith(".py") || f.endsWith(".go") && !f.endsWith("_test.go") || f.endsWith(".rs") || f.endsWith(".c") || f.endsWith(".h")
2452
3263
  ).length;
2453
3264
  }
2454
- console.error(`[Watcher] Watching ${fileCount} TypeScript/JavaScript/Python/Go files in ${dirs.length} directories`);
3265
+ console.error(`[Watcher] Watching ${fileCount} TypeScript/JavaScript/Python/Go/Rust/C files in ${dirs.length} directories`);
2455
3266
  });
2456
3267
  return watcher;
2457
3268
  }
@@ -2460,10 +3271,10 @@ function watchProject(projectRoot, callbacks) {
2460
3271
  import express from "express";
2461
3272
  import open from "open";
2462
3273
  import { fileURLToPath as fileURLToPath2 } from "url";
2463
- import { dirname as dirname5, join as join7 } from "path";
3274
+ import { dirname as dirname7, join as join9 } from "path";
2464
3275
  import { WebSocketServer } from "ws";
2465
3276
  var __filename = fileURLToPath2(import.meta.url);
2466
- var __dirname2 = dirname5(__filename);
3277
+ var __dirname2 = dirname7(__filename);
2467
3278
  var activeServer = null;
2468
3279
  async function findAvailablePort(startPort, maxAttempts = 10) {
2469
3280
  const net = await import("net");
@@ -2501,7 +3312,7 @@ async function startVizServer(initialVizData, graph, projectRoot, port = 3333, s
2501
3312
  const availablePort = await findAvailablePort(port);
2502
3313
  const app = express();
2503
3314
  let vizData = initialVizData;
2504
- const publicDir = join7(__dirname2, "viz", "public");
3315
+ const publicDir = join9(__dirname2, "viz", "public");
2505
3316
  app.use(express.static(publicDir));
2506
3317
  app.get("/api/graph", (req, res) => {
2507
3318
  res.json(vizData);
@@ -2617,7 +3428,7 @@ function isProjectLoaded(state) {
2617
3428
  }
2618
3429
 
2619
3430
  // src/graph/updater.ts
2620
- import { join as join8 } from "path";
3431
+ import { join as join10 } from "path";
2621
3432
  function removeFileFromGraph(graph, filePath) {
2622
3433
  const nodesToRemove = [];
2623
3434
  graph.forEachNode((node, attrs) => {
@@ -2661,7 +3472,7 @@ function addFileToGraph(graph, parsedFile) {
2661
3472
  }
2662
3473
  async function updateFileInGraph(graph, projectRoot, relativeFilePath) {
2663
3474
  removeFileFromGraph(graph, relativeFilePath);
2664
- const absolutePath = join8(projectRoot, relativeFilePath);
3475
+ const absolutePath = join10(projectRoot, relativeFilePath);
2665
3476
  try {
2666
3477
  const parsedFile = parseTypeScriptFile(absolutePath, relativeFilePath);
2667
3478
  addFileToGraph(graph, parsedFile);
@@ -2671,7 +3482,7 @@ async function updateFileInGraph(graph, projectRoot, relativeFilePath) {
2671
3482
  }
2672
3483
 
2673
3484
  // src/health/metrics.ts
2674
- import { dirname as dirname6 } from "path";
3485
+ import { dirname as dirname8 } from "path";
2675
3486
  function scoreToGrade(score) {
2676
3487
  if (score >= 90) return "A";
2677
3488
  if (score >= 80) return "B";
@@ -2704,8 +3515,8 @@ function calculateCouplingScore(graph) {
2704
3515
  totalEdges++;
2705
3516
  fileConnections.set(sourceAttrs.filePath, (fileConnections.get(sourceAttrs.filePath) || 0) + 1);
2706
3517
  fileConnections.set(targetAttrs.filePath, (fileConnections.get(targetAttrs.filePath) || 0) + 1);
2707
- const sourceDir = dirname6(sourceAttrs.filePath).split("/")[0];
2708
- const targetDir = dirname6(targetAttrs.filePath).split("/")[0];
3518
+ const sourceDir = dirname8(sourceAttrs.filePath).split("/")[0];
3519
+ const targetDir = dirname8(targetAttrs.filePath).split("/")[0];
2709
3520
  if (sourceDir !== targetDir) {
2710
3521
  crossDirEdges++;
2711
3522
  }
@@ -2752,8 +3563,8 @@ function calculateCohesionScore(graph) {
2752
3563
  const sourceAttrs = graph.getNodeAttributes(source);
2753
3564
  const targetAttrs = graph.getNodeAttributes(target);
2754
3565
  if (sourceAttrs.filePath !== targetAttrs.filePath) {
2755
- const sourceDir = dirname6(sourceAttrs.filePath);
2756
- const targetDir = dirname6(targetAttrs.filePath);
3566
+ const sourceDir = dirname8(sourceAttrs.filePath);
3567
+ const targetDir = dirname8(targetAttrs.filePath);
2757
3568
  if (!dirEdges.has(sourceDir)) {
2758
3569
  dirEdges.set(sourceDir, { internal: 0, total: 0 });
2759
3570
  }
@@ -3035,8 +3846,8 @@ function calculateDepthScore(graph) {
3035
3846
  }
3036
3847
 
3037
3848
  // src/health/index.ts
3038
- import { readFileSync as readFileSync4, writeFileSync, existsSync as existsSync6, mkdirSync } from "fs";
3039
- import { join as join9, dirname as dirname7 } from "path";
3849
+ import { readFileSync as readFileSync6, writeFileSync, existsSync as existsSync8, mkdirSync } from "fs";
3850
+ import { join as join11, dirname as dirname9 } from "path";
3040
3851
  function calculateHealthScore(graph, projectRoot) {
3041
3852
  const coupling = calculateCouplingScore(graph);
3042
3853
  const cohesion = calculateCohesionScore(graph);
@@ -3135,7 +3946,7 @@ function getHealthTrend(projectRoot, currentScore) {
3135
3946
  }
3136
3947
  }
3137
3948
  function saveHealthHistory(projectRoot, report) {
3138
- const historyFile = join9(projectRoot, ".depwire", "health-history.json");
3949
+ const historyFile = join11(projectRoot, ".depwire", "health-history.json");
3139
3950
  const entry = {
3140
3951
  timestamp: report.timestamp,
3141
3952
  score: report.overall,
@@ -3147,9 +3958,9 @@ function saveHealthHistory(projectRoot, report) {
3147
3958
  }))
3148
3959
  };
3149
3960
  let history = [];
3150
- if (existsSync6(historyFile)) {
3961
+ if (existsSync8(historyFile)) {
3151
3962
  try {
3152
- const content = readFileSync4(historyFile, "utf-8");
3963
+ const content = readFileSync6(historyFile, "utf-8");
3153
3964
  history = JSON.parse(content);
3154
3965
  } catch {
3155
3966
  }
@@ -3158,16 +3969,16 @@ function saveHealthHistory(projectRoot, report) {
3158
3969
  if (history.length > 50) {
3159
3970
  history = history.slice(-50);
3160
3971
  }
3161
- mkdirSync(dirname7(historyFile), { recursive: true });
3972
+ mkdirSync(dirname9(historyFile), { recursive: true });
3162
3973
  writeFileSync(historyFile, JSON.stringify(history, null, 2), "utf-8");
3163
3974
  }
3164
3975
  function loadHealthHistory(projectRoot) {
3165
- const historyFile = join9(projectRoot, ".depwire", "health-history.json");
3166
- if (!existsSync6(historyFile)) {
3976
+ const historyFile = join11(projectRoot, ".depwire", "health-history.json");
3977
+ if (!existsSync8(historyFile)) {
3167
3978
  return [];
3168
3979
  }
3169
3980
  try {
3170
- const content = readFileSync4(historyFile, "utf-8");
3981
+ const content = readFileSync6(historyFile, "utf-8");
3171
3982
  return JSON.parse(content);
3172
3983
  } catch {
3173
3984
  return [];
@@ -3473,11 +4284,11 @@ function filterByConfidence(symbols, minConfidence) {
3473
4284
  }
3474
4285
 
3475
4286
  // src/docs/generator.ts
3476
- import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync9 } from "fs";
3477
- import { join as join12 } from "path";
4287
+ import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync11 } from "fs";
4288
+ import { join as join14 } from "path";
3478
4289
 
3479
4290
  // src/docs/architecture.ts
3480
- import { dirname as dirname8 } from "path";
4291
+ import { dirname as dirname10 } from "path";
3481
4292
 
3482
4293
  // src/docs/templates.ts
3483
4294
  function header(text, level = 1) {
@@ -3628,7 +4439,7 @@ function generateModuleStructure(graph) {
3628
4439
  function getDirectoryStats(graph) {
3629
4440
  const dirMap = /* @__PURE__ */ new Map();
3630
4441
  graph.forEachNode((node, attrs) => {
3631
- const dir = dirname8(attrs.filePath);
4442
+ const dir = dirname10(attrs.filePath);
3632
4443
  if (dir === ".") return;
3633
4444
  if (!dirMap.has(dir)) {
3634
4445
  dirMap.set(dir, {
@@ -3653,7 +4464,7 @@ function getDirectoryStats(graph) {
3653
4464
  });
3654
4465
  const filesPerDir = /* @__PURE__ */ new Map();
3655
4466
  graph.forEachNode((node, attrs) => {
3656
- const dir = dirname8(attrs.filePath);
4467
+ const dir = dirname10(attrs.filePath);
3657
4468
  if (!filesPerDir.has(dir)) {
3658
4469
  filesPerDir.set(dir, /* @__PURE__ */ new Set());
3659
4470
  }
@@ -3668,8 +4479,8 @@ function getDirectoryStats(graph) {
3668
4479
  graph.forEachEdge((edge, attrs, source, target) => {
3669
4480
  const sourceAttrs = graph.getNodeAttributes(source);
3670
4481
  const targetAttrs = graph.getNodeAttributes(target);
3671
- const sourceDir = dirname8(sourceAttrs.filePath);
3672
- const targetDir = dirname8(targetAttrs.filePath);
4482
+ const sourceDir = dirname10(sourceAttrs.filePath);
4483
+ const targetDir = dirname10(targetAttrs.filePath);
3673
4484
  if (sourceDir !== targetDir) {
3674
4485
  if (!dirEdges.has(sourceDir)) {
3675
4486
  dirEdges.set(sourceDir, { in: 0, out: 0 });
@@ -4650,7 +5461,7 @@ function detectCyclesDetailed(graph) {
4650
5461
  }
4651
5462
 
4652
5463
  // src/docs/onboarding.ts
4653
- import { dirname as dirname9 } from "path";
5464
+ import { dirname as dirname11 } from "path";
4654
5465
  function generateOnboarding(graph, projectRoot, version) {
4655
5466
  let output = "";
4656
5467
  const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
@@ -4709,7 +5520,7 @@ function generateQuickOrientation(graph) {
4709
5520
  const primaryLang = Object.entries(languages2).sort((a, b) => b[1] - a[1])[0];
4710
5521
  const dirs = /* @__PURE__ */ new Set();
4711
5522
  graph.forEachNode((node, attrs) => {
4712
- const dir = dirname9(attrs.filePath);
5523
+ const dir = dirname11(attrs.filePath);
4713
5524
  if (dir !== ".") {
4714
5525
  const topLevel = dir.split("/")[0];
4715
5526
  dirs.add(topLevel);
@@ -4813,7 +5624,7 @@ function generateModuleMap(graph) {
4813
5624
  function getDirectoryStats2(graph) {
4814
5625
  const dirMap = /* @__PURE__ */ new Map();
4815
5626
  graph.forEachNode((node, attrs) => {
4816
- const dir = dirname9(attrs.filePath);
5627
+ const dir = dirname11(attrs.filePath);
4817
5628
  if (dir === ".") return;
4818
5629
  if (!dirMap.has(dir)) {
4819
5630
  dirMap.set(dir, {
@@ -4828,7 +5639,7 @@ function getDirectoryStats2(graph) {
4828
5639
  });
4829
5640
  const filesPerDir = /* @__PURE__ */ new Map();
4830
5641
  graph.forEachNode((node, attrs) => {
4831
- const dir = dirname9(attrs.filePath);
5642
+ const dir = dirname11(attrs.filePath);
4832
5643
  if (!filesPerDir.has(dir)) {
4833
5644
  filesPerDir.set(dir, /* @__PURE__ */ new Set());
4834
5645
  }
@@ -4843,8 +5654,8 @@ function getDirectoryStats2(graph) {
4843
5654
  graph.forEachEdge((edge, attrs, source, target) => {
4844
5655
  const sourceAttrs = graph.getNodeAttributes(source);
4845
5656
  const targetAttrs = graph.getNodeAttributes(target);
4846
- const sourceDir = dirname9(sourceAttrs.filePath);
4847
- const targetDir = dirname9(targetAttrs.filePath);
5657
+ const sourceDir = dirname11(sourceAttrs.filePath);
5658
+ const targetDir = dirname11(targetAttrs.filePath);
4848
5659
  if (sourceDir !== targetDir) {
4849
5660
  if (!dirEdges.has(sourceDir)) {
4850
5661
  dirEdges.set(sourceDir, { in: 0, out: 0 });
@@ -4925,7 +5736,7 @@ function detectClusters(graph) {
4925
5736
  const dirFiles = /* @__PURE__ */ new Map();
4926
5737
  const fileEdges = /* @__PURE__ */ new Map();
4927
5738
  graph.forEachNode((node, attrs) => {
4928
- const dir = dirname9(attrs.filePath);
5739
+ const dir = dirname11(attrs.filePath);
4929
5740
  if (!dirFiles.has(dir)) {
4930
5741
  dirFiles.set(dir, /* @__PURE__ */ new Set());
4931
5742
  }
@@ -4979,8 +5790,8 @@ function inferClusterName(files) {
4979
5790
  if (sortedWords.length > 0 && sortedWords[0][1] > 1) {
4980
5791
  return capitalizeFirst2(sortedWords[0][0]);
4981
5792
  }
4982
- const commonDir = dirname9(files[0]);
4983
- if (files.every((f) => dirname9(f) === commonDir)) {
5793
+ const commonDir = dirname11(files[0]);
5794
+ if (files.every((f) => dirname11(f) === commonDir)) {
4984
5795
  return capitalizeFirst2(commonDir.split("/").pop() || "Core");
4985
5796
  }
4986
5797
  return "Core";
@@ -5038,7 +5849,7 @@ function generateDepwireUsage(projectRoot) {
5038
5849
  }
5039
5850
 
5040
5851
  // src/docs/files.ts
5041
- import { dirname as dirname10, basename as basename3 } from "path";
5852
+ import { dirname as dirname12, basename as basename3 } from "path";
5042
5853
  function generateFiles(graph, projectRoot, version) {
5043
5854
  let output = "";
5044
5855
  const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
@@ -5142,7 +5953,7 @@ function generateDirectoryBreakdown(graph) {
5142
5953
  const fileStats = getFileStats2(graph);
5143
5954
  const dirMap = /* @__PURE__ */ new Map();
5144
5955
  for (const file of fileStats) {
5145
- const dir = dirname10(file.filePath);
5956
+ const dir = dirname12(file.filePath);
5146
5957
  const topDir = dir === "." ? "." : dir.split("/")[0];
5147
5958
  if (!dirMap.has(topDir)) {
5148
5959
  dirMap.set(topDir, {
@@ -5785,7 +6596,7 @@ function generateRecommendations(graph) {
5785
6596
  }
5786
6597
 
5787
6598
  // src/docs/tests.ts
5788
- import { basename as basename4, dirname as dirname11 } from "path";
6599
+ import { basename as basename4, dirname as dirname13 } from "path";
5789
6600
  function generateTests(graph, projectRoot, version) {
5790
6601
  let output = "";
5791
6602
  const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
@@ -5814,7 +6625,7 @@ function getFileCount8(graph) {
5814
6625
  }
5815
6626
  function isTestFile3(filePath) {
5816
6627
  const fileName = basename4(filePath).toLowerCase();
5817
- const dirPath = dirname11(filePath).toLowerCase();
6628
+ const dirPath = dirname13(filePath).toLowerCase();
5818
6629
  if (dirPath.includes("test") || dirPath.includes("spec") || dirPath.includes("__tests__")) {
5819
6630
  return true;
5820
6631
  }
@@ -5873,12 +6684,12 @@ function generateTestFileInventory(graph) {
5873
6684
  }
5874
6685
  function matchTestToSource(testFile) {
5875
6686
  const testFileName = basename4(testFile);
5876
- const testDir = dirname11(testFile);
6687
+ const testDir = dirname13(testFile);
5877
6688
  let sourceFileName = testFileName.replace(/\.test\./g, ".").replace(/\.spec\./g, ".").replace(/_test\./g, ".").replace(/_spec\./g, ".");
5878
6689
  const possiblePaths = [];
5879
6690
  possiblePaths.push(testDir + "/" + sourceFileName);
5880
6691
  if (testDir.endsWith("/test") || testDir.endsWith("/tests") || testDir.endsWith("/__tests__")) {
5881
- const parentDir = dirname11(testDir);
6692
+ const parentDir = dirname13(testDir);
5882
6693
  possiblePaths.push(parentDir + "/" + sourceFileName);
5883
6694
  }
5884
6695
  if (testDir.includes("test")) {
@@ -6075,7 +6886,7 @@ function generateTestStatistics(graph) {
6075
6886
  `;
6076
6887
  const dirTestCoverage = /* @__PURE__ */ new Map();
6077
6888
  for (const sourceFile of sourceFiles) {
6078
- const dir = dirname11(sourceFile).split("/")[0];
6889
+ const dir = dirname13(sourceFile).split("/")[0];
6079
6890
  if (!dirTestCoverage.has(dir)) {
6080
6891
  dirTestCoverage.set(dir, { total: 0, tested: 0 });
6081
6892
  }
@@ -6098,7 +6909,7 @@ function generateTestStatistics(graph) {
6098
6909
  }
6099
6910
 
6100
6911
  // src/docs/history.ts
6101
- import { dirname as dirname12 } from "path";
6912
+ import { dirname as dirname14 } from "path";
6102
6913
  import { execSync } from "child_process";
6103
6914
  function generateHistory(graph, projectRoot, version) {
6104
6915
  let output = "";
@@ -6379,7 +7190,7 @@ function generateFeatureClusters(graph) {
6379
7190
  const dirFiles = /* @__PURE__ */ new Map();
6380
7191
  const fileEdges = /* @__PURE__ */ new Map();
6381
7192
  graph.forEachNode((node, attrs) => {
6382
- const dir = dirname12(attrs.filePath);
7193
+ const dir = dirname14(attrs.filePath);
6383
7194
  if (!dirFiles.has(dir)) {
6384
7195
  dirFiles.set(dir, /* @__PURE__ */ new Set());
6385
7196
  }
@@ -6461,7 +7272,7 @@ function capitalizeFirst3(str) {
6461
7272
  }
6462
7273
 
6463
7274
  // src/docs/current.ts
6464
- import { dirname as dirname13 } from "path";
7275
+ import { dirname as dirname15 } from "path";
6465
7276
  function generateCurrent(graph, projectRoot, version) {
6466
7277
  let output = "";
6467
7278
  const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
@@ -6599,7 +7410,7 @@ function generateCompleteFileIndex(graph) {
6599
7410
  fileInfos.sort((a, b) => a.filePath.localeCompare(b.filePath));
6600
7411
  const dirGroups = /* @__PURE__ */ new Map();
6601
7412
  for (const info of fileInfos) {
6602
- const dir = dirname13(info.filePath);
7413
+ const dir = dirname15(info.filePath);
6603
7414
  const topDir = dir === "." ? "root" : dir.split("/")[0];
6604
7415
  if (!dirGroups.has(topDir)) {
6605
7416
  dirGroups.set(topDir, []);
@@ -6810,8 +7621,8 @@ function getTopLevelDir2(filePath) {
6810
7621
  }
6811
7622
 
6812
7623
  // src/docs/status.ts
6813
- import { readFileSync as readFileSync5, existsSync as existsSync7 } from "fs";
6814
- import { join as join10 } from "path";
7624
+ import { readFileSync as readFileSync7, existsSync as existsSync9 } from "fs";
7625
+ import { join as join12 } from "path";
6815
7626
  function generateStatus(graph, projectRoot, version) {
6816
7627
  let output = "";
6817
7628
  const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
@@ -6844,12 +7655,12 @@ function getFileCount11(graph) {
6844
7655
  }
6845
7656
  function extractComments(projectRoot, filePath) {
6846
7657
  const comments = [];
6847
- const fullPath = join10(projectRoot, filePath);
6848
- if (!existsSync7(fullPath)) {
7658
+ const fullPath = join12(projectRoot, filePath);
7659
+ if (!existsSync9(fullPath)) {
6849
7660
  return comments;
6850
7661
  }
6851
7662
  try {
6852
- const content = readFileSync5(fullPath, "utf-8");
7663
+ const content = readFileSync7(fullPath, "utf-8");
6853
7664
  const lines = content.split("\n");
6854
7665
  const patterns = [
6855
7666
  { type: "TODO", regex: /(?:\/\/|#|\/\*)\s*TODO:?\s*(.+)/i },
@@ -7411,15 +8222,15 @@ function generateConfidenceSection(title, description, symbols, projectRoot) {
7411
8222
  }
7412
8223
 
7413
8224
  // src/docs/metadata.ts
7414
- import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync as writeFileSync2 } from "fs";
7415
- import { join as join11 } from "path";
8225
+ import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync2 } from "fs";
8226
+ import { join as join13 } from "path";
7416
8227
  function loadMetadata(outputDir) {
7417
- const metadataPath = join11(outputDir, "metadata.json");
7418
- if (!existsSync8(metadataPath)) {
8228
+ const metadataPath = join13(outputDir, "metadata.json");
8229
+ if (!existsSync10(metadataPath)) {
7419
8230
  return null;
7420
8231
  }
7421
8232
  try {
7422
- const content = readFileSync6(metadataPath, "utf-8");
8233
+ const content = readFileSync8(metadataPath, "utf-8");
7423
8234
  return JSON.parse(content);
7424
8235
  } catch (err) {
7425
8236
  console.error("Failed to load metadata:", err);
@@ -7427,7 +8238,7 @@ function loadMetadata(outputDir) {
7427
8238
  }
7428
8239
  }
7429
8240
  function saveMetadata(outputDir, metadata) {
7430
- const metadataPath = join11(outputDir, "metadata.json");
8241
+ const metadataPath = join13(outputDir, "metadata.json");
7431
8242
  writeFileSync2(metadataPath, JSON.stringify(metadata, null, 2), "utf-8");
7432
8243
  }
7433
8244
  function createMetadata(version, projectPath, fileCount, symbolCount, edgeCount, docTypes) {
@@ -7470,7 +8281,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
7470
8281
  const generated = [];
7471
8282
  const errors = [];
7472
8283
  try {
7473
- if (!existsSync9(options.outputDir)) {
8284
+ if (!existsSync11(options.outputDir)) {
7474
8285
  mkdirSync2(options.outputDir, { recursive: true });
7475
8286
  if (options.verbose) {
7476
8287
  console.log(`Created output directory: ${options.outputDir}`);
@@ -7509,7 +8320,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
7509
8320
  try {
7510
8321
  if (options.verbose) console.log("Generating ARCHITECTURE.md...");
7511
8322
  const content = generateArchitecture(graph, projectRoot, version, parseTime);
7512
- const filePath = join12(options.outputDir, "ARCHITECTURE.md");
8323
+ const filePath = join14(options.outputDir, "ARCHITECTURE.md");
7513
8324
  writeFileSync3(filePath, content, "utf-8");
7514
8325
  generated.push("ARCHITECTURE.md");
7515
8326
  } catch (err) {
@@ -7520,7 +8331,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
7520
8331
  try {
7521
8332
  if (options.verbose) console.log("Generating CONVENTIONS.md...");
7522
8333
  const content = generateConventions(graph, projectRoot, version);
7523
- const filePath = join12(options.outputDir, "CONVENTIONS.md");
8334
+ const filePath = join14(options.outputDir, "CONVENTIONS.md");
7524
8335
  writeFileSync3(filePath, content, "utf-8");
7525
8336
  generated.push("CONVENTIONS.md");
7526
8337
  } catch (err) {
@@ -7531,7 +8342,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
7531
8342
  try {
7532
8343
  if (options.verbose) console.log("Generating DEPENDENCIES.md...");
7533
8344
  const content = generateDependencies(graph, projectRoot, version);
7534
- const filePath = join12(options.outputDir, "DEPENDENCIES.md");
8345
+ const filePath = join14(options.outputDir, "DEPENDENCIES.md");
7535
8346
  writeFileSync3(filePath, content, "utf-8");
7536
8347
  generated.push("DEPENDENCIES.md");
7537
8348
  } catch (err) {
@@ -7542,7 +8353,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
7542
8353
  try {
7543
8354
  if (options.verbose) console.log("Generating ONBOARDING.md...");
7544
8355
  const content = generateOnboarding(graph, projectRoot, version);
7545
- const filePath = join12(options.outputDir, "ONBOARDING.md");
8356
+ const filePath = join14(options.outputDir, "ONBOARDING.md");
7546
8357
  writeFileSync3(filePath, content, "utf-8");
7547
8358
  generated.push("ONBOARDING.md");
7548
8359
  } catch (err) {
@@ -7553,7 +8364,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
7553
8364
  try {
7554
8365
  if (options.verbose) console.log("Generating FILES.md...");
7555
8366
  const content = generateFiles(graph, projectRoot, version);
7556
- const filePath = join12(options.outputDir, "FILES.md");
8367
+ const filePath = join14(options.outputDir, "FILES.md");
7557
8368
  writeFileSync3(filePath, content, "utf-8");
7558
8369
  generated.push("FILES.md");
7559
8370
  } catch (err) {
@@ -7564,7 +8375,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
7564
8375
  try {
7565
8376
  if (options.verbose) console.log("Generating API_SURFACE.md...");
7566
8377
  const content = generateApiSurface(graph, projectRoot, version);
7567
- const filePath = join12(options.outputDir, "API_SURFACE.md");
8378
+ const filePath = join14(options.outputDir, "API_SURFACE.md");
7568
8379
  writeFileSync3(filePath, content, "utf-8");
7569
8380
  generated.push("API_SURFACE.md");
7570
8381
  } catch (err) {
@@ -7575,7 +8386,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
7575
8386
  try {
7576
8387
  if (options.verbose) console.log("Generating ERRORS.md...");
7577
8388
  const content = generateErrors(graph, projectRoot, version);
7578
- const filePath = join12(options.outputDir, "ERRORS.md");
8389
+ const filePath = join14(options.outputDir, "ERRORS.md");
7579
8390
  writeFileSync3(filePath, content, "utf-8");
7580
8391
  generated.push("ERRORS.md");
7581
8392
  } catch (err) {
@@ -7586,7 +8397,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
7586
8397
  try {
7587
8398
  if (options.verbose) console.log("Generating TESTS.md...");
7588
8399
  const content = generateTests(graph, projectRoot, version);
7589
- const filePath = join12(options.outputDir, "TESTS.md");
8400
+ const filePath = join14(options.outputDir, "TESTS.md");
7590
8401
  writeFileSync3(filePath, content, "utf-8");
7591
8402
  generated.push("TESTS.md");
7592
8403
  } catch (err) {
@@ -7597,7 +8408,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
7597
8408
  try {
7598
8409
  if (options.verbose) console.log("Generating HISTORY.md...");
7599
8410
  const content = generateHistory(graph, projectRoot, version);
7600
- const filePath = join12(options.outputDir, "HISTORY.md");
8411
+ const filePath = join14(options.outputDir, "HISTORY.md");
7601
8412
  writeFileSync3(filePath, content, "utf-8");
7602
8413
  generated.push("HISTORY.md");
7603
8414
  } catch (err) {
@@ -7608,7 +8419,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
7608
8419
  try {
7609
8420
  if (options.verbose) console.log("Generating CURRENT.md...");
7610
8421
  const content = generateCurrent(graph, projectRoot, version);
7611
- const filePath = join12(options.outputDir, "CURRENT.md");
8422
+ const filePath = join14(options.outputDir, "CURRENT.md");
7612
8423
  writeFileSync3(filePath, content, "utf-8");
7613
8424
  generated.push("CURRENT.md");
7614
8425
  } catch (err) {
@@ -7619,7 +8430,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
7619
8430
  try {
7620
8431
  if (options.verbose) console.log("Generating STATUS.md...");
7621
8432
  const content = generateStatus(graph, projectRoot, version);
7622
- const filePath = join12(options.outputDir, "STATUS.md");
8433
+ const filePath = join14(options.outputDir, "STATUS.md");
7623
8434
  writeFileSync3(filePath, content, "utf-8");
7624
8435
  generated.push("STATUS.md");
7625
8436
  } catch (err) {
@@ -7630,7 +8441,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
7630
8441
  try {
7631
8442
  if (options.verbose) console.log("Generating HEALTH.md...");
7632
8443
  const content = generateHealth(graph, projectRoot, version);
7633
- const filePath = join12(options.outputDir, "HEALTH.md");
8444
+ const filePath = join14(options.outputDir, "HEALTH.md");
7634
8445
  writeFileSync3(filePath, content, "utf-8");
7635
8446
  generated.push("HEALTH.md");
7636
8447
  } catch (err) {
@@ -7641,7 +8452,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
7641
8452
  try {
7642
8453
  if (options.verbose) console.log("Generating DEAD_CODE.md...");
7643
8454
  const content = generateDeadCode(graph, projectRoot, version);
7644
- const filePath = join12(options.outputDir, "DEAD_CODE.md");
8455
+ const filePath = join14(options.outputDir, "DEAD_CODE.md");
7645
8456
  writeFileSync3(filePath, content, "utf-8");
7646
8457
  generated.push("DEAD_CODE.md");
7647
8458
  } catch (err) {
@@ -7689,13 +8500,13 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
7689
8500
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7690
8501
 
7691
8502
  // src/mcp/tools.ts
7692
- import { dirname as dirname14, join as join15 } from "path";
7693
- import { existsSync as existsSync12, readFileSync as readFileSync8 } from "fs";
8503
+ import { dirname as dirname16, join as join17 } from "path";
8504
+ import { existsSync as existsSync14, readFileSync as readFileSync10 } from "fs";
7694
8505
 
7695
8506
  // src/mcp/connect.ts
7696
8507
  import simpleGit from "simple-git";
7697
- import { existsSync as existsSync10 } from "fs";
7698
- import { join as join13, basename as basename5, resolve as resolve2 } from "path";
8508
+ import { existsSync as existsSync12 } from "fs";
8509
+ import { join as join15, basename as basename5, resolve as resolve2 } from "path";
7699
8510
  import { tmpdir, homedir } from "os";
7700
8511
  function validateProjectPath(source) {
7701
8512
  const resolved = resolve2(source);
@@ -7708,11 +8519,11 @@ function validateProjectPath(source) {
7708
8519
  "/boot",
7709
8520
  "/proc",
7710
8521
  "/sys",
7711
- join13(homedir(), ".ssh"),
7712
- join13(homedir(), ".gnupg"),
7713
- join13(homedir(), ".aws"),
7714
- join13(homedir(), ".config"),
7715
- join13(homedir(), ".env")
8522
+ join15(homedir(), ".ssh"),
8523
+ join15(homedir(), ".gnupg"),
8524
+ join15(homedir(), ".aws"),
8525
+ join15(homedir(), ".config"),
8526
+ join15(homedir(), ".env")
7716
8527
  ];
7717
8528
  for (const blocked of blockedPaths) {
7718
8529
  if (resolved.startsWith(blocked)) {
@@ -7735,11 +8546,11 @@ async function connectToRepo(source, subdirectory, state) {
7735
8546
  };
7736
8547
  }
7737
8548
  projectName = match[1];
7738
- const reposDir = join13(tmpdir(), "depwire-repos");
7739
- const cloneDir = join13(reposDir, projectName);
8549
+ const reposDir = join15(tmpdir(), "depwire-repos");
8550
+ const cloneDir = join15(reposDir, projectName);
7740
8551
  console.error(`Connecting to GitHub repo: ${source}`);
7741
8552
  const git = simpleGit();
7742
- if (existsSync10(cloneDir)) {
8553
+ if (existsSync12(cloneDir)) {
7743
8554
  console.error(`Repo already cloned at ${cloneDir}, pulling latest changes...`);
7744
8555
  try {
7745
8556
  await git.cwd(cloneDir).pull();
@@ -7757,7 +8568,7 @@ async function connectToRepo(source, subdirectory, state) {
7757
8568
  };
7758
8569
  }
7759
8570
  }
7760
- projectRoot = subdirectory ? join13(cloneDir, subdirectory) : cloneDir;
8571
+ projectRoot = subdirectory ? join15(cloneDir, subdirectory) : cloneDir;
7761
8572
  } else {
7762
8573
  const validation2 = validateProjectPath(source);
7763
8574
  if (!validation2.valid) {
@@ -7766,13 +8577,13 @@ async function connectToRepo(source, subdirectory, state) {
7766
8577
  message: validation2.error
7767
8578
  };
7768
8579
  }
7769
- if (!existsSync10(source)) {
8580
+ if (!existsSync12(source)) {
7770
8581
  return {
7771
8582
  error: "Directory not found",
7772
8583
  message: `Directory does not exist: ${source}`
7773
8584
  };
7774
8585
  }
7775
- projectRoot = subdirectory ? join13(source, subdirectory) : source;
8586
+ projectRoot = subdirectory ? join15(source, subdirectory) : source;
7776
8587
  projectName = basename5(projectRoot);
7777
8588
  }
7778
8589
  const validation = validateProjectPath(projectRoot);
@@ -7782,7 +8593,7 @@ async function connectToRepo(source, subdirectory, state) {
7782
8593
  message: validation.error
7783
8594
  };
7784
8595
  }
7785
- if (!existsSync10(projectRoot)) {
8596
+ if (!existsSync12(projectRoot)) {
7786
8597
  return {
7787
8598
  error: "Project root not found",
7788
8599
  message: `Directory does not exist: ${projectRoot}`
@@ -8063,24 +8874,24 @@ function getWeekNumber(date) {
8063
8874
  }
8064
8875
 
8065
8876
  // src/temporal/snapshots.ts
8066
- import { writeFileSync as writeFileSync4, readFileSync as readFileSync7, mkdirSync as mkdirSync3, existsSync as existsSync11, readdirSync as readdirSync3 } from "fs";
8067
- import { join as join14 } from "path";
8877
+ import { writeFileSync as writeFileSync4, readFileSync as readFileSync9, mkdirSync as mkdirSync3, existsSync as existsSync13, readdirSync as readdirSync5 } from "fs";
8878
+ import { join as join16 } from "path";
8068
8879
  function saveSnapshot(snapshot, outputDir) {
8069
- if (!existsSync11(outputDir)) {
8880
+ if (!existsSync13(outputDir)) {
8070
8881
  mkdirSync3(outputDir, { recursive: true });
8071
8882
  }
8072
8883
  const filename = `${snapshot.commitHash.substring(0, 8)}.json`;
8073
- const filepath = join14(outputDir, filename);
8884
+ const filepath = join16(outputDir, filename);
8074
8885
  writeFileSync4(filepath, JSON.stringify(snapshot, null, 2), "utf-8");
8075
8886
  }
8076
8887
  function loadSnapshot(commitHash, outputDir) {
8077
8888
  const shortHash = commitHash.substring(0, 8);
8078
- const filepath = join14(outputDir, `${shortHash}.json`);
8079
- if (!existsSync11(filepath)) {
8889
+ const filepath = join16(outputDir, `${shortHash}.json`);
8890
+ if (!existsSync13(filepath)) {
8080
8891
  return null;
8081
8892
  }
8082
8893
  try {
8083
- const content = readFileSync7(filepath, "utf-8");
8894
+ const content = readFileSync9(filepath, "utf-8");
8084
8895
  return JSON.parse(content);
8085
8896
  } catch {
8086
8897
  return null;
@@ -8767,7 +9578,7 @@ function handleGetArchitectureSummary(graph) {
8767
9578
  const dirMap = /* @__PURE__ */ new Map();
8768
9579
  const languageBreakdown = {};
8769
9580
  fileSummary.forEach((f) => {
8770
- const dir = f.filePath.includes("/") ? dirname14(f.filePath) : ".";
9581
+ const dir = f.filePath.includes("/") ? dirname16(f.filePath) : ".";
8771
9582
  if (!dirMap.has(dir)) {
8772
9583
  dirMap.set(dir, { fileCount: 0, symbolCount: 0 });
8773
9584
  }
@@ -8854,8 +9665,8 @@ The server will keep running until you end the MCP session or press Ctrl+C.`;
8854
9665
  };
8855
9666
  }
8856
9667
  async function handleGetProjectDocs(docType, state) {
8857
- const docsDir = join15(state.projectRoot, ".depwire");
8858
- if (!existsSync12(docsDir)) {
9668
+ const docsDir = join17(state.projectRoot, ".depwire");
9669
+ if (!existsSync14(docsDir)) {
8859
9670
  const errorMessage = `Project documentation has not been generated yet.
8860
9671
 
8861
9672
  Run \`depwire docs ${state.projectRoot}\` to generate codebase documentation.
@@ -8885,12 +9696,12 @@ Available document types:
8885
9696
  missing.push(doc);
8886
9697
  continue;
8887
9698
  }
8888
- const filePath = join15(docsDir, metadata.documents[doc].file);
8889
- if (!existsSync12(filePath)) {
9699
+ const filePath = join17(docsDir, metadata.documents[doc].file);
9700
+ if (!existsSync14(filePath)) {
8890
9701
  missing.push(doc);
8891
9702
  continue;
8892
9703
  }
8893
- const content = readFileSync8(filePath, "utf-8");
9704
+ const content = readFileSync10(filePath, "utf-8");
8894
9705
  if (docsToReturn.length > 1) {
8895
9706
  output += `
8896
9707
 
@@ -8915,16 +9726,16 @@ Available document types:
8915
9726
  }
8916
9727
  async function handleUpdateProjectDocs(docType, state) {
8917
9728
  const startTime = Date.now();
8918
- const docsDir = join15(state.projectRoot, ".depwire");
9729
+ const docsDir = join17(state.projectRoot, ".depwire");
8919
9730
  console.error("Regenerating project documentation...");
8920
9731
  const parsedFiles = await parseProject(state.projectRoot);
8921
9732
  const graph = buildGraph(parsedFiles);
8922
9733
  const parseTime = (Date.now() - startTime) / 1e3;
8923
9734
  state.graph = graph;
8924
- const packageJsonPath = join15(__dirname, "../../package.json");
8925
- const packageJson = JSON.parse(readFileSync8(packageJsonPath, "utf-8"));
9735
+ const packageJsonPath = join17(__dirname, "../../package.json");
9736
+ const packageJson = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
8926
9737
  const docsToGenerate = docType === "all" ? ["architecture", "conventions", "dependencies", "onboarding"] : [docType];
8927
- const docsExist = existsSync12(docsDir);
9738
+ const docsExist = existsSync14(docsDir);
8928
9739
  const result = await generateDocs(graph, state.projectRoot, packageJson.version, parseTime, {
8929
9740
  outputDir: docsDir,
8930
9741
  format: "markdown",
@@ -8983,7 +9794,7 @@ async function handleGetTemporalGraph(state, commits, strategy) {
8983
9794
  }
8984
9795
  const sampledCommits = sampleCommits(allCommits, commits, strategy);
8985
9796
  const snapshots = [];
8986
- const outputDir = join15(projectRoot, ".depwire", "temporal");
9797
+ const outputDir = join17(projectRoot, ".depwire", "temporal");
8987
9798
  for (const commit of sampledCommits) {
8988
9799
  const existing = loadSnapshot(commit.hash, outputDir);
8989
9800
  if (existing) {