@optave/codegraph 3.11.2 → 3.13.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.
- package/README.md +73 -37
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +2 -1
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/batch.d.ts.map +1 -1
- package/dist/cli/commands/batch.js +1 -0
- package/dist/cli/commands/batch.js.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +6 -1
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/config.d.ts +3 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +272 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/triage.js +1 -1
- package/dist/cli/commands/triage.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +10 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/shared/options.d.ts +2 -1
- package/dist/cli/shared/options.d.ts.map +1 -1
- package/dist/cli/shared/options.js +11 -1
- package/dist/cli/shared/options.js.map +1 -1
- package/dist/cli/types.d.ts +2 -0
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +8 -1
- package/dist/db/migrations.js.map +1 -1
- package/dist/domain/analysis/module-map.d.ts +2 -0
- package/dist/domain/analysis/module-map.d.ts.map +1 -1
- package/dist/domain/analysis/module-map.js +24 -2
- package/dist/domain/analysis/module-map.js.map +1 -1
- package/dist/domain/graph/builder/call-resolver.d.ts +16 -10
- package/dist/domain/graph/builder/call-resolver.d.ts.map +1 -1
- package/dist/domain/graph/builder/call-resolver.js +251 -34
- package/dist/domain/graph/builder/call-resolver.js.map +1 -1
- package/dist/domain/graph/builder/cha.d.ts +69 -0
- package/dist/domain/graph/builder/cha.d.ts.map +1 -0
- package/dist/domain/graph/builder/cha.js +158 -0
- package/dist/domain/graph/builder/cha.js.map +1 -0
- package/dist/domain/graph/builder/context.d.ts +3 -0
- package/dist/domain/graph/builder/context.d.ts.map +1 -1
- package/dist/domain/graph/builder/context.js +2 -0
- package/dist/domain/graph/builder/context.js.map +1 -1
- package/dist/domain/graph/builder/helpers.d.ts +25 -1
- package/dist/domain/graph/builder/helpers.d.ts.map +1 -1
- package/dist/domain/graph/builder/helpers.js +178 -5
- package/dist/domain/graph/builder/helpers.js.map +1 -1
- package/dist/domain/graph/builder/incremental.d.ts.map +1 -1
- package/dist/domain/graph/builder/incremental.js +74 -2
- package/dist/domain/graph/builder/incremental.js.map +1 -1
- package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
- package/dist/domain/graph/builder/pipeline.js +37 -2
- package/dist/domain/graph/builder/pipeline.js.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.js +704 -34
- package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.js +3 -2
- package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.js +4 -0
- package/dist/domain/graph/builder/stages/finalize.js.map +1 -1
- package/dist/domain/graph/builder/stages/native-orchestrator.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/native-orchestrator.js +783 -37
- package/dist/domain/graph/builder/stages/native-orchestrator.js.map +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.d.ts +1 -0
- package/dist/domain/graph/builder/stages/resolve-imports.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.js +10 -1
- package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -1
- package/dist/domain/graph/journal.js +1 -1
- package/dist/domain/graph/journal.js.map +1 -1
- package/dist/domain/graph/resolver/points-to.d.ts +53 -0
- package/dist/domain/graph/resolver/points-to.d.ts.map +1 -0
- package/dist/domain/graph/resolver/points-to.js +213 -0
- package/dist/domain/graph/resolver/points-to.js.map +1 -0
- package/dist/domain/graph/resolver/ts-resolver.d.ts +9 -0
- package/dist/domain/graph/resolver/ts-resolver.d.ts.map +1 -0
- package/dist/domain/graph/resolver/ts-resolver.js +476 -0
- package/dist/domain/graph/resolver/ts-resolver.js.map +1 -0
- package/dist/domain/parser.d.ts +12 -4
- package/dist/domain/parser.d.ts.map +1 -1
- package/dist/domain/parser.js +83 -20
- package/dist/domain/parser.js.map +1 -1
- package/dist/domain/wasm-worker-entry.js +35 -2
- package/dist/domain/wasm-worker-entry.js.map +1 -1
- package/dist/domain/wasm-worker-pool.d.ts.map +1 -1
- package/dist/domain/wasm-worker-pool.js +34 -0
- package/dist/domain/wasm-worker-pool.js.map +1 -1
- package/dist/domain/wasm-worker-protocol.d.ts +15 -1
- package/dist/domain/wasm-worker-protocol.d.ts.map +1 -1
- package/dist/extractors/c.js +3 -3
- package/dist/extractors/c.js.map +1 -1
- package/dist/extractors/clojure.js +1 -1
- package/dist/extractors/clojure.js.map +1 -1
- package/dist/extractors/cpp.d.ts.map +1 -1
- package/dist/extractors/cpp.js +45 -4
- package/dist/extractors/cpp.js.map +1 -1
- package/dist/extractors/csharp.d.ts.map +1 -1
- package/dist/extractors/csharp.js +37 -8
- package/dist/extractors/csharp.js.map +1 -1
- package/dist/extractors/cuda.d.ts.map +1 -1
- package/dist/extractors/cuda.js +45 -4
- package/dist/extractors/cuda.js.map +1 -1
- package/dist/extractors/elixir.js +6 -6
- package/dist/extractors/elixir.js.map +1 -1
- package/dist/extractors/fsharp.js +1 -1
- package/dist/extractors/fsharp.js.map +1 -1
- package/dist/extractors/go.js +5 -5
- package/dist/extractors/go.js.map +1 -1
- package/dist/extractors/haskell.js +1 -1
- package/dist/extractors/haskell.js.map +1 -1
- package/dist/extractors/helpers.d.ts +11 -0
- package/dist/extractors/helpers.d.ts.map +1 -1
- package/dist/extractors/helpers.js +40 -0
- package/dist/extractors/helpers.js.map +1 -1
- package/dist/extractors/java.d.ts.map +1 -1
- package/dist/extractors/java.js +10 -9
- package/dist/extractors/java.js.map +1 -1
- package/dist/extractors/javascript.d.ts +2 -0
- package/dist/extractors/javascript.d.ts.map +1 -1
- package/dist/extractors/javascript.js +1812 -71
- package/dist/extractors/javascript.js.map +1 -1
- package/dist/extractors/kotlin.js +5 -5
- package/dist/extractors/kotlin.js.map +1 -1
- package/dist/extractors/lua.js +1 -1
- package/dist/extractors/lua.js.map +1 -1
- package/dist/extractors/objc.js +3 -3
- package/dist/extractors/objc.js.map +1 -1
- package/dist/extractors/ocaml.js +1 -1
- package/dist/extractors/ocaml.js.map +1 -1
- package/dist/extractors/php.js +2 -2
- package/dist/extractors/php.js.map +1 -1
- package/dist/extractors/python.js +7 -7
- package/dist/extractors/python.js.map +1 -1
- package/dist/extractors/ruby.js +2 -2
- package/dist/extractors/ruby.js.map +1 -1
- package/dist/extractors/scala.js +1 -1
- package/dist/extractors/scala.js.map +1 -1
- package/dist/extractors/solidity.js +1 -1
- package/dist/extractors/solidity.js.map +1 -1
- package/dist/extractors/swift.js +4 -4
- package/dist/extractors/swift.js.map +1 -1
- package/dist/extractors/zig.js +4 -4
- package/dist/extractors/zig.js.map +1 -1
- package/dist/features/structure-query.d.ts +1 -1
- package/dist/features/structure-query.d.ts.map +1 -1
- package/dist/features/structure-query.js +6 -6
- package/dist/features/structure-query.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/config.d.ts +85 -2
- package/dist/infrastructure/config.d.ts.map +1 -1
- package/dist/infrastructure/config.js +408 -19
- package/dist/infrastructure/config.js.map +1 -1
- package/dist/infrastructure/native.d.ts +11 -0
- package/dist/infrastructure/native.d.ts.map +1 -1
- package/dist/infrastructure/native.js +78 -5
- package/dist/infrastructure/native.js.map +1 -1
- package/dist/infrastructure/registry.d.ts +27 -0
- package/dist/infrastructure/registry.d.ts.map +1 -1
- package/dist/infrastructure/registry.js +59 -1
- package/dist/infrastructure/registry.js.map +1 -1
- package/dist/presentation/queries-cli/overview.d.ts.map +1 -1
- package/dist/presentation/queries-cli/overview.js +5 -0
- package/dist/presentation/queries-cli/overview.js.map +1 -1
- package/dist/presentation/structure.d.ts +1 -1
- package/dist/presentation/structure.d.ts.map +1 -1
- package/dist/presentation/structure.js +2 -2
- package/dist/presentation/structure.js.map +1 -1
- package/dist/types.d.ts +221 -0
- package/dist/types.d.ts.map +1 -1
- package/grammars/tree-sitter-gleam.wasm +0 -0
- package/package.json +7 -8
- package/src/cli/commands/audit.ts +2 -1
- package/src/cli/commands/batch.ts +1 -0
- package/src/cli/commands/build.ts +6 -1
- package/src/cli/commands/config.ts +353 -0
- package/src/cli/commands/triage.ts +1 -1
- package/src/cli/index.ts +10 -0
- package/src/cli/shared/options.ts +11 -1
- package/src/cli/types.ts +2 -0
- package/src/db/migrations.ts +8 -1
- package/src/domain/analysis/module-map.ts +29 -1
- package/src/domain/graph/builder/call-resolver.ts +263 -35
- package/src/domain/graph/builder/cha.ts +192 -0
- package/src/domain/graph/builder/context.ts +3 -0
- package/src/domain/graph/builder/helpers.ts +195 -5
- package/src/domain/graph/builder/incremental.ts +80 -1
- package/src/domain/graph/builder/pipeline.ts +49 -2
- package/src/domain/graph/builder/stages/build-edges.ts +867 -32
- package/src/domain/graph/builder/stages/detect-changes.ts +4 -2
- package/src/domain/graph/builder/stages/finalize.ts +4 -0
- package/src/domain/graph/builder/stages/native-orchestrator.ts +910 -43
- package/src/domain/graph/builder/stages/resolve-imports.ts +15 -1
- package/src/domain/graph/journal.ts +1 -1
- package/src/domain/graph/resolver/points-to.ts +254 -0
- package/src/domain/graph/resolver/ts-resolver.ts +536 -0
- package/src/domain/parser.ts +86 -17
- package/src/domain/wasm-worker-entry.ts +35 -2
- package/src/domain/wasm-worker-pool.ts +22 -0
- package/src/domain/wasm-worker-protocol.ts +15 -0
- package/src/extractors/c.ts +3 -3
- package/src/extractors/clojure.ts +1 -1
- package/src/extractors/cpp.ts +47 -4
- package/src/extractors/csharp.ts +33 -9
- package/src/extractors/cuda.ts +47 -4
- package/src/extractors/elixir.ts +6 -6
- package/src/extractors/fsharp.ts +1 -1
- package/src/extractors/go.ts +5 -5
- package/src/extractors/haskell.ts +1 -1
- package/src/extractors/helpers.ts +43 -0
- package/src/extractors/java.ts +10 -9
- package/src/extractors/javascript.ts +1929 -72
- package/src/extractors/kotlin.ts +5 -5
- package/src/extractors/lua.ts +1 -1
- package/src/extractors/objc.ts +3 -3
- package/src/extractors/ocaml.ts +1 -1
- package/src/extractors/php.ts +2 -2
- package/src/extractors/python.ts +7 -7
- package/src/extractors/ruby.ts +2 -2
- package/src/extractors/scala.ts +1 -1
- package/src/extractors/solidity.ts +1 -1
- package/src/extractors/swift.ts +4 -4
- package/src/extractors/zig.ts +4 -4
- package/src/features/structure-query.ts +7 -7
- package/src/index.ts +5 -1
- package/src/infrastructure/config.ts +494 -20
- package/src/infrastructure/native.ts +87 -5
- package/src/infrastructure/registry.ts +82 -1
- package/src/presentation/queries-cli/overview.ts +15 -1
- package/src/presentation/structure.ts +3 -3
- package/src/types.ts +235 -0
- package/grammars/tree-sitter-erlang.wasm +0 -0
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
* to the existing WASM pipeline.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { existsSync } from 'node:fs';
|
|
9
10
|
import { createRequire } from 'node:module';
|
|
10
11
|
import os from 'node:os';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
11
13
|
import { EngineError, toErrorMessage } from '../shared/errors.js';
|
|
12
14
|
import type { NativeAddon } from '../types.js';
|
|
13
|
-
import { debug } from './logger.js';
|
|
15
|
+
import { debug, warn } from './logger.js';
|
|
14
16
|
|
|
15
17
|
let _cached: NativeAddon | null | undefined; // undefined = not yet tried, null = failed, NativeAddon = module
|
|
16
18
|
let _loadError: Error | null = null;
|
|
@@ -44,31 +46,107 @@ const PLATFORM_PACKAGES: Record<string, string> = {
|
|
|
44
46
|
'win32-x64': '@optave/codegraph-win32-x64-msvc',
|
|
45
47
|
};
|
|
46
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Map of (platform-arch[-libc]) → locally compiled binary filename.
|
|
51
|
+
* Checked before the npm package so that locally compiled Rust changes
|
|
52
|
+
* are picked up immediately in development without publishing a new release.
|
|
53
|
+
*/
|
|
54
|
+
const PLATFORM_LOCAL_BINARIES: Record<string, string> = {
|
|
55
|
+
'linux-x64-gnu': 'codegraph-core.linux-x64-gnu.node',
|
|
56
|
+
'linux-x64-musl': 'codegraph-core.linux-x64-musl.node',
|
|
57
|
+
'linux-arm64-gnu': 'codegraph-core.linux-arm64-gnu.node',
|
|
58
|
+
'linux-arm64-musl': 'codegraph-core.linux-arm64-musl.node',
|
|
59
|
+
'darwin-arm64': 'codegraph-core.darwin-arm64.node',
|
|
60
|
+
'darwin-x64': 'codegraph-core.darwin-x64.node',
|
|
61
|
+
'win32-x64': 'codegraph-core.win32-x64-msvc.node',
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/** Compute the platform key used to index PLATFORM_PACKAGES / PLATFORM_LOCAL_BINARIES. */
|
|
65
|
+
function resolvePlatformKey(): string {
|
|
66
|
+
const platform = os.platform();
|
|
67
|
+
const arch = os.arch();
|
|
68
|
+
return platform === 'linux' ? `${platform}-${arch}-${detectLibc()}` : `${platform}-${arch}`;
|
|
69
|
+
}
|
|
70
|
+
|
|
47
71
|
/**
|
|
48
72
|
* Resolve the platform-specific npm package name for the native addon.
|
|
49
73
|
* Returns null if the current platform is not supported.
|
|
50
74
|
*/
|
|
51
75
|
function resolvePlatformPackage(): string | null {
|
|
52
|
-
|
|
53
|
-
const arch = os.arch();
|
|
54
|
-
const key = platform === 'linux' ? `${platform}-${arch}-${detectLibc()}` : `${platform}-${arch}`;
|
|
55
|
-
return PLATFORM_PACKAGES[key] || null;
|
|
76
|
+
return PLATFORM_PACKAGES[resolvePlatformKey()] ?? null;
|
|
56
77
|
}
|
|
57
78
|
|
|
58
79
|
/**
|
|
59
80
|
* Try to load the native napi addon.
|
|
60
81
|
* Returns the module on success, null on failure.
|
|
82
|
+
*
|
|
83
|
+
* Load order:
|
|
84
|
+
* 1. NAPI_RS_NATIVE_LIBRARY_PATH env var (explicit override)
|
|
85
|
+
* 2. locally compiled binary in crates/codegraph-core/ (dev mode — preferred
|
|
86
|
+
* over the npm package so that Rust changes are picked up immediately
|
|
87
|
+
* without publishing a new release)
|
|
88
|
+
* 3. npm platform package (production path)
|
|
61
89
|
*/
|
|
62
90
|
export function loadNative(): NativeAddon | null {
|
|
63
91
|
if (_cached !== undefined) return _cached;
|
|
64
92
|
|
|
93
|
+
const platformKey = resolvePlatformKey();
|
|
94
|
+
|
|
95
|
+
// 1. Explicit path override — highest priority. Failure is fatal: if the
|
|
96
|
+
// operator set this variable, silently loading a different binary would
|
|
97
|
+
// be harder to diagnose than an explicit error.
|
|
98
|
+
const envPath = process.env.NAPI_RS_NATIVE_LIBRARY_PATH;
|
|
99
|
+
if (envPath) {
|
|
100
|
+
try {
|
|
101
|
+
_cached = _require(envPath) as NativeAddon;
|
|
102
|
+
debug(`loadNative: loaded from NAPI_RS_NATIVE_LIBRARY_PATH: ${envPath}`);
|
|
103
|
+
return _cached;
|
|
104
|
+
} catch (err) {
|
|
105
|
+
_loadError = err as Error;
|
|
106
|
+
warn(
|
|
107
|
+
`loadNative: NAPI_RS_NATIVE_LIBRARY_PATH is set but failed to load "${envPath}": ${toErrorMessage(err as Error)}`,
|
|
108
|
+
);
|
|
109
|
+
_cached = null;
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// 2. Locally compiled dev binary — preferred over npm package so that Rust
|
|
115
|
+
// changes are visible without publishing. Only used when the file exists.
|
|
116
|
+
// If the file exists but fails to load (e.g. stale ABI), we warn and halt
|
|
117
|
+
// rather than silently falling through to the npm package — that would
|
|
118
|
+
// defeat the purpose of this priority order.
|
|
119
|
+
const localFile = PLATFORM_LOCAL_BINARIES[platformKey];
|
|
120
|
+
if (localFile) {
|
|
121
|
+
const localPath = fileURLToPath(
|
|
122
|
+
new URL(`../../crates/codegraph-core/${localFile}`, import.meta.url),
|
|
123
|
+
);
|
|
124
|
+
if (existsSync(localPath)) {
|
|
125
|
+
try {
|
|
126
|
+
_cached = _require(localPath) as NativeAddon;
|
|
127
|
+
debug(`loadNative: loaded local dev binary: ${localPath}`);
|
|
128
|
+
return _cached;
|
|
129
|
+
} catch (err) {
|
|
130
|
+
_loadError = err as Error;
|
|
131
|
+
warn(
|
|
132
|
+
`loadNative: local dev binary exists but failed to load "${localPath}": ${toErrorMessage(err as Error)}`,
|
|
133
|
+
);
|
|
134
|
+
_cached = null;
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// 3. Published npm platform package — production path.
|
|
65
141
|
const pkg = resolvePlatformPackage();
|
|
66
142
|
if (pkg) {
|
|
67
143
|
try {
|
|
68
144
|
_cached = _require(pkg) as NativeAddon;
|
|
145
|
+
debug(`loadNative: loaded npm package: ${pkg}`);
|
|
69
146
|
return _cached;
|
|
70
147
|
} catch (err) {
|
|
71
148
|
_loadError = err as Error;
|
|
149
|
+
debug(`loadNative: npm package ${pkg} not available: ${toErrorMessage(err as Error)}`);
|
|
72
150
|
}
|
|
73
151
|
} else {
|
|
74
152
|
_loadError = new Error(`Unsupported platform: ${os.platform()}-${os.arch()}`);
|
|
@@ -88,6 +166,10 @@ export function isNativeAvailable(): boolean {
|
|
|
88
166
|
/**
|
|
89
167
|
* Read the version from the platform-specific npm package.json.
|
|
90
168
|
* Returns null if the package is not installed or has no version.
|
|
169
|
+
*
|
|
170
|
+
* Note: always reports the npm package version. When the local dev binary or
|
|
171
|
+
* NAPI_RS_NATIVE_LIBRARY_PATH is loaded instead, this version may not match
|
|
172
|
+
* the running binary.
|
|
91
173
|
*/
|
|
92
174
|
export function getNativePackageVersion(): string | null {
|
|
93
175
|
const pkg = resolvePlatformPackage();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import type { ConsentDecision } from '../types.js';
|
|
4
5
|
import { debug, warn } from './logger.js';
|
|
5
6
|
|
|
6
7
|
export const REGISTRY_PATH: string =
|
|
@@ -16,8 +17,15 @@ interface RegistryEntry {
|
|
|
16
17
|
lastAccessedAt?: string;
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
interface UserConfigSection {
|
|
21
|
+
/** Per-repo consent decisions keyed by absolute repo path. */
|
|
22
|
+
consent: Record<string, ConsentDecision>;
|
|
23
|
+
}
|
|
24
|
+
|
|
19
25
|
interface Registry {
|
|
20
26
|
repos: Record<string, RegistryEntry>;
|
|
27
|
+
/** User-level global config consent store — separate from MCP repo listings. */
|
|
28
|
+
userConfig?: UserConfigSection;
|
|
21
29
|
}
|
|
22
30
|
|
|
23
31
|
/**
|
|
@@ -160,6 +168,67 @@ export function resolveRepoDbPath(
|
|
|
160
168
|
return entry.dbPath;
|
|
161
169
|
}
|
|
162
170
|
|
|
171
|
+
// ── User-config consent ────────────────────────────────────────────────
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Read the per-repo consent decision for the global user config.
|
|
175
|
+
* Returns `undefined` when the repo is undecided (no recorded decision).
|
|
176
|
+
*/
|
|
177
|
+
export function getUserConfigConsent(
|
|
178
|
+
rootDir: string,
|
|
179
|
+
registryPath: string = REGISTRY_PATH,
|
|
180
|
+
): ConsentDecision | undefined {
|
|
181
|
+
const registry = loadRegistry(registryPath);
|
|
182
|
+
const absRoot = path.resolve(rootDir);
|
|
183
|
+
return registry.userConfig?.consent?.[absRoot];
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Persist a per-repo consent decision. Atomic write via temp+rename.
|
|
188
|
+
*/
|
|
189
|
+
export function setUserConfigConsent(
|
|
190
|
+
rootDir: string,
|
|
191
|
+
decision: ConsentDecision,
|
|
192
|
+
registryPath: string = REGISTRY_PATH,
|
|
193
|
+
): void {
|
|
194
|
+
const registry = loadRegistry(registryPath);
|
|
195
|
+
const absRoot = path.resolve(rootDir);
|
|
196
|
+
if (!registry.userConfig) registry.userConfig = { consent: {} };
|
|
197
|
+
if (!registry.userConfig.consent) registry.userConfig.consent = {};
|
|
198
|
+
registry.userConfig.consent[absRoot] = decision;
|
|
199
|
+
saveRegistry(registry, registryPath);
|
|
200
|
+
debug(`User-config consent for "${absRoot}" set to "${decision}"`);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* List every repo with a recorded consent decision, sorted by path.
|
|
205
|
+
*/
|
|
206
|
+
export function listUserConfigConsent(
|
|
207
|
+
registryPath: string = REGISTRY_PATH,
|
|
208
|
+
): Array<{ path: string; decision: ConsentDecision }> {
|
|
209
|
+
const registry = loadRegistry(registryPath);
|
|
210
|
+
const consent = registry.userConfig?.consent ?? {};
|
|
211
|
+
return Object.entries(consent)
|
|
212
|
+
.map(([p, decision]) => ({ path: p, decision }))
|
|
213
|
+
.sort((a, b) => a.path.localeCompare(b.path));
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Revert a repo to undecided state. Returns true if a decision was removed.
|
|
218
|
+
*/
|
|
219
|
+
export function clearUserConfigConsent(
|
|
220
|
+
rootDir: string,
|
|
221
|
+
registryPath: string = REGISTRY_PATH,
|
|
222
|
+
): boolean {
|
|
223
|
+
const registry = loadRegistry(registryPath);
|
|
224
|
+
const absRoot = path.resolve(rootDir);
|
|
225
|
+
const consent = registry.userConfig?.consent;
|
|
226
|
+
if (!consent || !(absRoot in consent)) return false;
|
|
227
|
+
delete consent[absRoot];
|
|
228
|
+
saveRegistry(registry, registryPath);
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
|
|
163
232
|
interface PrunedEntry {
|
|
164
233
|
name: string;
|
|
165
234
|
path: string;
|
|
@@ -200,7 +269,19 @@ export function pruneRegistry(
|
|
|
200
269
|
}
|
|
201
270
|
}
|
|
202
271
|
|
|
203
|
-
|
|
272
|
+
// Prune consent entries whose repo paths no longer exist on disk.
|
|
273
|
+
// Consent entries are TTL-exempt — only the missing-path rule applies.
|
|
274
|
+
let consentChanged = false;
|
|
275
|
+
if (!dryRun && registry.userConfig?.consent) {
|
|
276
|
+
for (const p of Object.keys(registry.userConfig.consent)) {
|
|
277
|
+
if (!fs.existsSync(p)) {
|
|
278
|
+
delete registry.userConfig.consent[p];
|
|
279
|
+
consentChanged = true;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (!dryRun && (pruned.length > 0 || consentChanged)) {
|
|
204
285
|
saveRegistry(registry, registryPath);
|
|
205
286
|
}
|
|
206
287
|
|
|
@@ -54,7 +54,13 @@ interface EmbeddingsInfo {
|
|
|
54
54
|
|
|
55
55
|
interface QualityInfo {
|
|
56
56
|
score: number;
|
|
57
|
-
callerCoverage: {
|
|
57
|
+
callerCoverage: {
|
|
58
|
+
ratio: number;
|
|
59
|
+
percentage: number;
|
|
60
|
+
covered: number;
|
|
61
|
+
total: number;
|
|
62
|
+
byTechnique?: Record<string, number>;
|
|
63
|
+
};
|
|
58
64
|
callConfidence: { ratio: number; highConf: number; total: number };
|
|
59
65
|
falsePositiveWarnings: { name: string; callerCount: number; file: string; line: number }[];
|
|
60
66
|
}
|
|
@@ -189,6 +195,14 @@ function printQuality(data: StatsData): void {
|
|
|
189
195
|
console.log(
|
|
190
196
|
` Caller coverage: ${(cc.ratio * 100).toFixed(1)}% (${cc.covered}/${cc.total} functions have >=1 caller)`,
|
|
191
197
|
);
|
|
198
|
+
if (cc.byTechnique && Object.keys(cc.byTechnique).length > 0) {
|
|
199
|
+
const entries = Object.entries(cc.byTechnique).sort((a, b) => b[1] - a[1]) as [
|
|
200
|
+
string,
|
|
201
|
+
number,
|
|
202
|
+
][];
|
|
203
|
+
const parts = entries.map(([k, v]) => `${k} ${v}`).join(' ');
|
|
204
|
+
console.log(` by technique: ${parts}`);
|
|
205
|
+
}
|
|
192
206
|
console.log(
|
|
193
207
|
` Call confidence: ${(cf.ratio * 100).toFixed(1)}% (${cf.highConf}/${cf.total} call edges are high-confidence)`,
|
|
194
208
|
);
|
|
@@ -53,15 +53,15 @@ interface HotspotsResult {
|
|
|
53
53
|
metric: string;
|
|
54
54
|
level: string;
|
|
55
55
|
limit: number;
|
|
56
|
-
|
|
56
|
+
items: any[];
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
export function formatHotspots(data: HotspotsResult): string {
|
|
60
|
-
if (data.
|
|
60
|
+
if (data.items.length === 0) return 'No hotspots found. Run "codegraph build" first.';
|
|
61
61
|
|
|
62
62
|
const lines = [`\nHotspots by ${data.metric} (${data.level}-level, top ${data.limit}):\n`];
|
|
63
63
|
let rank = 1;
|
|
64
|
-
for (const h of data.
|
|
64
|
+
for (const h of data.items) {
|
|
65
65
|
const extra =
|
|
66
66
|
h.kind === 'directory'
|
|
67
67
|
? `${h.fileCount} files, cohesion=${h.cohesion !== null ? h.cohesion!.toFixed(2) : 'n/a'}`
|
package/src/types.ts
CHANGED
|
@@ -523,6 +523,125 @@ export interface TypeMapEntry {
|
|
|
523
523
|
confidence: number;
|
|
524
524
|
}
|
|
525
525
|
|
|
526
|
+
/**
|
|
527
|
+
* A variable assignment from a call expression, recorded during extraction for
|
|
528
|
+
* cross-file return-type propagation (Phase 8.2).
|
|
529
|
+
*/
|
|
530
|
+
export interface CallAssignment {
|
|
531
|
+
/** Variable being assigned to. */
|
|
532
|
+
varName: string;
|
|
533
|
+
/** Name of the function or method being called. */
|
|
534
|
+
calleeName: string;
|
|
535
|
+
/** Resolved receiver type, if the call is a method call (e.g. service.getRepo()). */
|
|
536
|
+
receiverTypeName?: string;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* A function-reference binding recorded during extraction for points-to analysis (Phase 8.3).
|
|
541
|
+
* Captures `const fn = handler` or `const fn = obj.method` patterns where the right-hand
|
|
542
|
+
* side is a named function reference (not a call expression or literal).
|
|
543
|
+
*/
|
|
544
|
+
export interface FnRefBinding {
|
|
545
|
+
/** Variable being assigned (the left-hand side identifier). */
|
|
546
|
+
lhs: string;
|
|
547
|
+
/** Named function/property on the right-hand side. */
|
|
548
|
+
rhs: string;
|
|
549
|
+
/** If rhs is a member expression (obj.method), the receiver object name. */
|
|
550
|
+
rhsReceiver?: string;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* An argument-to-parameter binding at a call site, recorded for parameter-flow
|
|
555
|
+
* points-to analysis (Phase 8.3c). Captures `f(x)` where `x` is an identifier
|
|
556
|
+
* that may carry a function reference into `f`'s parameter.
|
|
557
|
+
*/
|
|
558
|
+
export interface ParamBinding {
|
|
559
|
+
/** The function being called at the call site. */
|
|
560
|
+
callee: string;
|
|
561
|
+
/** Zero-based index of the argument. */
|
|
562
|
+
argIndex: number;
|
|
563
|
+
/** Identifier name of the argument being passed. */
|
|
564
|
+
argName: string;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* A this-context binding recorded when `fn.call(namedCtx, ...)` or
|
|
569
|
+
* `fn.apply(namedCtx, ...)` is seen. Seeds `fn::this → namedCtx` in the
|
|
570
|
+
* points-to map so that `this()` calls inside `fn` resolve to `namedCtx`.
|
|
571
|
+
*/
|
|
572
|
+
export interface ThisCallBinding {
|
|
573
|
+
/** The function being invoked via .call() or .apply(). */
|
|
574
|
+
callee: string;
|
|
575
|
+
/** The identifier passed as the `this` context (first argument). */
|
|
576
|
+
thisArg: string;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* An array-element binding: `const arr = [fn1, fn2]` records each named function
|
|
581
|
+
* stored at a specific index. Phase 8.3e: array-element pts tracking.
|
|
582
|
+
*/
|
|
583
|
+
export interface ArrayElemBinding {
|
|
584
|
+
arrayName: string;
|
|
585
|
+
index: number;
|
|
586
|
+
elemName: string;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* A spread-argument binding: `f(...arr)` records that `arr` is spread into `f`'s
|
|
591
|
+
* parameter list starting at `startIndex`. Phase 8.3e.
|
|
592
|
+
*/
|
|
593
|
+
export interface SpreadArgBinding {
|
|
594
|
+
callee: string;
|
|
595
|
+
arrayName: string;
|
|
596
|
+
startIndex: number;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* A for-of iteration binding: `for (const x of arr)` records that `x` receives
|
|
601
|
+
* each element of `arr` within `enclosingFunc`. Phase 8.3e.
|
|
602
|
+
*/
|
|
603
|
+
export interface ForOfBinding {
|
|
604
|
+
varName: string;
|
|
605
|
+
sourceName: string;
|
|
606
|
+
enclosingFunc: string;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* An array-callback binding: `Array.from(arr, cb)` records that `cb`'s first
|
|
611
|
+
* parameter receives each element of `arr`. Phase 8.3e.
|
|
612
|
+
*/
|
|
613
|
+
export interface ArrayCallbackBinding {
|
|
614
|
+
sourceName: string;
|
|
615
|
+
calleeName: string;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* An object-rest parameter binding: `function f({ a, ...rest })` records that
|
|
620
|
+
* `rest` is the rest of the object passed as argument `argIndex` to `f`.
|
|
621
|
+
* Phase 8.3f: object destructuring rest dispatch.
|
|
622
|
+
*/
|
|
623
|
+
export interface ObjectRestParamBinding {
|
|
624
|
+
/** Function that owns this rest parameter, e.g. "f3" */
|
|
625
|
+
callee: string;
|
|
626
|
+
/** Name of the rest binding, e.g. "eerest" */
|
|
627
|
+
restName: string;
|
|
628
|
+
/** Zero-based index of the argument whose rest is bound, e.g. 0 */
|
|
629
|
+
argIndex: number;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* An object-property binding: `const obj = { e4 }` or `const obj = { e4: fn }` records
|
|
634
|
+
* that `obj.e4` points to the named function `fn`. Phase 8.3f.
|
|
635
|
+
*/
|
|
636
|
+
export interface ObjectPropBinding {
|
|
637
|
+
/** Variable holding the object, e.g. "obj" */
|
|
638
|
+
objectName: string;
|
|
639
|
+
/** Property name, e.g. "e4" */
|
|
640
|
+
propName: string;
|
|
641
|
+
/** Named function value, e.g. "e4" or "fn" */
|
|
642
|
+
valueName: string;
|
|
643
|
+
}
|
|
644
|
+
|
|
526
645
|
/** The normalized output shape returned by every language extractor. */
|
|
527
646
|
export interface ExtractorOutput {
|
|
528
647
|
definitions: Definition[];
|
|
@@ -531,6 +650,63 @@ export interface ExtractorOutput {
|
|
|
531
650
|
classes: ClassRelation[];
|
|
532
651
|
exports: Export[];
|
|
533
652
|
typeMap: Map<string, TypeMapEntry>;
|
|
653
|
+
/**
|
|
654
|
+
* Maps function/method names to their declared or inferred return types.
|
|
655
|
+
* Keys: plain name (e.g. "createUser") or qualified name (e.g. "UserService.getUser").
|
|
656
|
+
* Populated by JS/TS extractor; used for inter-procedural type propagation (Phase 8.2).
|
|
657
|
+
*/
|
|
658
|
+
returnTypeMap?: Map<string, TypeMapEntry>;
|
|
659
|
+
/**
|
|
660
|
+
* Variable assignments from call expressions that could not be resolved from the
|
|
661
|
+
* per-file returnTypeMap. Consumed by build-edges.ts to propagate cross-file return types.
|
|
662
|
+
*/
|
|
663
|
+
callAssignments?: CallAssignment[];
|
|
664
|
+
/**
|
|
665
|
+
* Function-reference bindings for points-to analysis (Phase 8.3).
|
|
666
|
+
* Records `const fn = handler` and `const fn = obj.method` patterns so the
|
|
667
|
+
* edge builder can follow aliases when a call target has no direct definition.
|
|
668
|
+
*/
|
|
669
|
+
fnRefBindings?: FnRefBinding[];
|
|
670
|
+
/**
|
|
671
|
+
* Argument-to-parameter bindings for parameter-flow points-to analysis (Phase 8.3c).
|
|
672
|
+
* Records `f(x)` call sites where `x` is an identifier, enabling the pts solver
|
|
673
|
+
* to propagate function references through function parameters.
|
|
674
|
+
*/
|
|
675
|
+
paramBindings?: ParamBinding[];
|
|
676
|
+
/** Phase 8.3e: array-element bindings from `const arr = [fn1, fn2]` patterns. */
|
|
677
|
+
arrayElemBindings?: ArrayElemBinding[];
|
|
678
|
+
/** Phase 8.3e: spread-argument bindings from `f(...arr)` call sites. */
|
|
679
|
+
spreadArgBindings?: SpreadArgBinding[];
|
|
680
|
+
/** Phase 8.3e: for-of iteration variable bindings. */
|
|
681
|
+
forOfBindings?: ForOfBinding[];
|
|
682
|
+
/** Phase 8.3e: array callback bindings from Array.from/forEach/etc. */
|
|
683
|
+
arrayCallbackBindings?: ArrayCallbackBinding[];
|
|
684
|
+
/** Phase 8.3f: object-rest parameter bindings from `function f({ ...rest })` patterns. */
|
|
685
|
+
objectRestParamBindings?: ObjectRestParamBinding[];
|
|
686
|
+
/** Phase 8.3f: object-property bindings from `const obj = { fn }` patterns. */
|
|
687
|
+
objectPropBindings?: ObjectPropBinding[];
|
|
688
|
+
/**
|
|
689
|
+
* This-context bindings from `fn.call(namedCtx, ...)` / `fn.apply(namedCtx, ...)`.
|
|
690
|
+
* Seeds `fn::this → namedCtx` in the points-to map so that `this()` calls inside
|
|
691
|
+
* `fn` resolve to `namedCtx` when `fn` is invoked via `.call()`/`.apply()`.
|
|
692
|
+
*/
|
|
693
|
+
thisCallBindings?: ThisCallBinding[];
|
|
694
|
+
/**
|
|
695
|
+
* Phase 8.5 (RTA): constructor names from all `new X()` expressions in the file,
|
|
696
|
+
* including unassigned ones (e.g. `doSomething(new Foo())`). Used to build the
|
|
697
|
+
* project-wide instantiated-types set for Rapid Type Analysis filtering.
|
|
698
|
+
*/
|
|
699
|
+
newExpressions?: readonly string[];
|
|
700
|
+
/**
|
|
701
|
+
* Object.defineProperty receiver bindings: maps function name → target object name.
|
|
702
|
+
* Records `Object.defineProperty(obj, "bar", { get: getter })` so the edge builder
|
|
703
|
+
* can resolve `this.X()` calls inside `getter` as `obj.X()` (this === obj when the
|
|
704
|
+
* accessor is invoked through the property).
|
|
705
|
+
*
|
|
706
|
+
* Example: `Object.defineProperty(obj, "bar", { get: getter })` emits
|
|
707
|
+
* `definePropertyReceivers.set("getter", "obj")`.
|
|
708
|
+
*/
|
|
709
|
+
definePropertyReceivers?: Map<string, string>;
|
|
534
710
|
/** WASM tree retained for downstream analysis (complexity, CFG, dataflow). */
|
|
535
711
|
_tree?: TreeSitterTree;
|
|
536
712
|
/** Language identifier. */
|
|
@@ -1078,6 +1254,20 @@ export interface BuildGraphOpts {
|
|
|
1078
1254
|
* `findDbPath` for every other DB-scoped command.
|
|
1079
1255
|
*/
|
|
1080
1256
|
dbPath?: string;
|
|
1257
|
+
/**
|
|
1258
|
+
* User-config override for this build (from --user-config / --no-user-config).
|
|
1259
|
+
* - false → --no-user-config: skip global layer for this run
|
|
1260
|
+
* - string → --user-config <path>: apply the given file
|
|
1261
|
+
* - true → --user-config (bare): apply the default global file
|
|
1262
|
+
* - undefined → honour per-repo consent from the registry (normal)
|
|
1263
|
+
*/
|
|
1264
|
+
userConfig?: string | boolean;
|
|
1265
|
+
/**
|
|
1266
|
+
* When true, an interactive consent prompt may fire on first build for
|
|
1267
|
+
* repos whose global-config consent is undecided. Only set by the CLI
|
|
1268
|
+
* build command when stdin/stdout are TTYs and CI is not set.
|
|
1269
|
+
*/
|
|
1270
|
+
promptForConsent?: boolean;
|
|
1081
1271
|
}
|
|
1082
1272
|
|
|
1083
1273
|
/** Build timing result from buildGraph. */
|
|
@@ -1092,6 +1282,16 @@ export interface BuildResult {
|
|
|
1092
1282
|
edgesMs: number;
|
|
1093
1283
|
structureMs: number;
|
|
1094
1284
|
rolesMs: number;
|
|
1285
|
+
/** Wall-clock time for the CHA expansion post-pass (native path only). */
|
|
1286
|
+
chaMs?: number;
|
|
1287
|
+
/** Wall-clock time for the this/super dispatch WASM post-pass (native path only). */
|
|
1288
|
+
thisDispatchMs?: number;
|
|
1289
|
+
/** Wall-clock time for the dropped-language gap detection + backfill (native path only). */
|
|
1290
|
+
gapDetectMs?: number;
|
|
1291
|
+
/** Wall-clock time for role re-classification after JS edge-writing post-passes (native path only). */
|
|
1292
|
+
reclassifyMs?: number;
|
|
1293
|
+
/** Wall-clock time for the technique-column backfill on native-written edges (native path only). */
|
|
1294
|
+
techniqueBackfillMs?: number;
|
|
1095
1295
|
astMs: number;
|
|
1096
1296
|
complexityMs: number;
|
|
1097
1297
|
cfgMs: number;
|
|
@@ -1119,6 +1319,14 @@ export interface CodegraphConfig {
|
|
|
1119
1319
|
dbPath: string;
|
|
1120
1320
|
driftThreshold: number;
|
|
1121
1321
|
smallFilesThreshold: number;
|
|
1322
|
+
/**
|
|
1323
|
+
* Use the TypeScript compiler API to enrich typeMap for .ts/.tsx files.
|
|
1324
|
+
* Improves method-call edge accuracy for patterns like `const svc = container.get<MyService>()`.
|
|
1325
|
+
* Disabled by default because `ts.createProgram` adds ~1s overhead per build;
|
|
1326
|
+
* enable in `.codegraphrc.json` when you need accurate type-resolved call edges.
|
|
1327
|
+
* Default: false.
|
|
1328
|
+
*/
|
|
1329
|
+
typescriptResolver: boolean;
|
|
1122
1330
|
};
|
|
1123
1331
|
|
|
1124
1332
|
query: {
|
|
@@ -1189,6 +1397,14 @@ export interface CodegraphConfig {
|
|
|
1189
1397
|
briefImporterDepth: number;
|
|
1190
1398
|
briefHighRiskCallers: number;
|
|
1191
1399
|
briefMediumRiskCallers: number;
|
|
1400
|
+
/** Maximum chain depth for inter-procedural return-type propagation (Phase 8.2). */
|
|
1401
|
+
typePropagationDepth: number;
|
|
1402
|
+
/**
|
|
1403
|
+
* Maximum fixed-point iterations for the Phase 8.3 points-to solver.
|
|
1404
|
+
* @reserved — currently not wired to either solver; both use a hardcoded
|
|
1405
|
+
* constant of 50. See TODO in `src/infrastructure/config.ts`.
|
|
1406
|
+
*/
|
|
1407
|
+
pointsToMaxIterations: number;
|
|
1192
1408
|
};
|
|
1193
1409
|
|
|
1194
1410
|
community: {
|
|
@@ -1275,6 +1491,25 @@ export interface McpDefaults {
|
|
|
1275
1491
|
interfaces: number;
|
|
1276
1492
|
}
|
|
1277
1493
|
|
|
1494
|
+
/** Per-repo consent decision for the user-level global config. */
|
|
1495
|
+
export type ConsentDecision = 'enabled' | 'disabled';
|
|
1496
|
+
|
|
1497
|
+
/** Which layer contributed a resolved config value. */
|
|
1498
|
+
export type ConfigSource = 'default' | 'user' | 'project' | 'env';
|
|
1499
|
+
|
|
1500
|
+
/** Maps config key paths (dot notation) to the layer that supplied the value. */
|
|
1501
|
+
export type ConfigProvenance = Record<string, ConfigSource>;
|
|
1502
|
+
|
|
1503
|
+
/** Result of loadConfigWithProvenance. */
|
|
1504
|
+
export interface ConfigWithProvenance {
|
|
1505
|
+
config: CodegraphConfig;
|
|
1506
|
+
provenance: ConfigProvenance;
|
|
1507
|
+
/** Absolute path of the applied global file, or null if none was applied. */
|
|
1508
|
+
appliedGlobalPath: string | null;
|
|
1509
|
+
/** This repo's recorded consent decision (may be undefined if undecided). */
|
|
1510
|
+
consentDecision: ConsentDecision | undefined;
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1278
1513
|
// ════════════════════════════════════════════════════════════════════════
|
|
1279
1514
|
// §12 Pagination
|
|
1280
1515
|
// ════════════════════════════════════════════════════════════════════════
|
|
Binary file
|