gitnexus 1.6.12-rc.24 → 1.6.12-rc.25
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.
|
@@ -15,6 +15,7 @@ import { createRequire } from 'node:module';
|
|
|
15
15
|
import { fileURLToPath } from 'node:url';
|
|
16
16
|
import { dirname, resolve } from 'node:path';
|
|
17
17
|
import { Worker } from 'node:worker_threads';
|
|
18
|
+
import { isHeuristicEdgeReason } from '../graph/edge-reasons.js';
|
|
18
19
|
const __filename = fileURLToPath(import.meta.url);
|
|
19
20
|
const __dirname = dirname(__filename);
|
|
20
21
|
// Navigate to package root (works from both src/ and dist/)
|
|
@@ -49,6 +50,16 @@ const DEFAULT_COMMUNITY_ENGINE = 'graphology';
|
|
|
49
50
|
const LEIDEN_TIMEOUT_MS = 60_000;
|
|
50
51
|
const ICEBUG_TIMEOUT_MS = 60_000;
|
|
51
52
|
const MIN_CONFIDENCE_LARGE = 0.5;
|
|
53
|
+
/**
|
|
54
|
+
* Whether a large graph's projection may include this edge.
|
|
55
|
+
*
|
|
56
|
+
* The confidence floor alone lets every global-name-fallback edge through — it
|
|
57
|
+
* is emitted at exactly `MIN_CONFIDENCE_LARGE`, so `confidence <` never
|
|
58
|
+
* excludes it. Clustering on unique-name guesses fuses unrelated areas into one
|
|
59
|
+
* community, which is precisely the noise the large-graph floor exists to
|
|
60
|
+
* remove, so the reason is checked too — see `graph/edge-reasons.ts`.
|
|
61
|
+
*/
|
|
62
|
+
const isLargeGraphEligible = (confidence, reason) => confidence >= MIN_CONFIDENCE_LARGE && !isHeuristicEdgeReason(reason);
|
|
52
63
|
export const resolveCommunityDetectionEngine = (raw = process.env[COMMUNITY_ENGINE_ENV]) => {
|
|
53
64
|
if (raw === undefined || raw.trim() === '')
|
|
54
65
|
return DEFAULT_COMMUNITY_ENGINE;
|
|
@@ -153,12 +164,18 @@ export const buildCommunityProjection = (knowledgeGraph) => {
|
|
|
153
164
|
const isLarge = symbolCount > 10_000;
|
|
154
165
|
const connectedNodes = new Set();
|
|
155
166
|
const nodeDegree = new Map();
|
|
156
|
-
// Field-wise scan (#2680): this walks every edge and reads only these
|
|
167
|
+
// Field-wise scan (#2680): this walks every edge and reads only these five,
|
|
157
168
|
// so taking objects would allocate one per edge for nothing.
|
|
158
|
-
knowledgeGraph.forEachRelationshipFields((sourceId, targetId, type, confidence) => {
|
|
169
|
+
knowledgeGraph.forEachRelationshipFields((sourceId, targetId, type, confidence, reason) => {
|
|
159
170
|
if (!isClusteringRelationship(type) || sourceId === targetId)
|
|
160
171
|
return;
|
|
161
|
-
|
|
172
|
+
// A name-guessed edge must not join two nodes into a community at ANY graph
|
|
173
|
+
// size — the rationale in `graph/edge-reasons.ts` is about what the edge
|
|
174
|
+
// claims, not about how many symbols surround it. Process tracing applies
|
|
175
|
+
// the same reason gate unconditionally (`process-processor.ts`).
|
|
176
|
+
if (isHeuristicEdgeReason(reason))
|
|
177
|
+
return;
|
|
178
|
+
if (isLarge && !isLargeGraphEligible(confidence, reason))
|
|
162
179
|
return;
|
|
163
180
|
connectedNodes.add(sourceId);
|
|
164
181
|
connectedNodes.add(targetId);
|
|
@@ -189,10 +206,12 @@ export const buildCommunityProjection = (knowledgeGraph) => {
|
|
|
189
206
|
}
|
|
190
207
|
const seenEdges = new Set();
|
|
191
208
|
const edges = [];
|
|
192
|
-
knowledgeGraph.forEachRelationshipFields((sourceId, targetId, type, confidence) => {
|
|
209
|
+
knowledgeGraph.forEachRelationshipFields((sourceId, targetId, type, confidence, reason) => {
|
|
193
210
|
if (!isClusteringRelationship(type) || sourceId === targetId)
|
|
194
211
|
return;
|
|
195
|
-
if (
|
|
212
|
+
if (isHeuristicEdgeReason(reason))
|
|
213
|
+
return;
|
|
214
|
+
if (isLarge && !isLargeGraphEligible(confidence, reason))
|
|
196
215
|
return;
|
|
197
216
|
const sourceIndex = nodeIndexById.get(sourceId);
|
|
198
217
|
const targetIndex = nodeIndexById.get(targetId);
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* Processes help agents understand how features work through the codebase.
|
|
11
11
|
*/
|
|
12
|
+
import { isHeuristicEdgeReason } from '../graph/edge-reasons.js';
|
|
12
13
|
import { calculateEntryPointScore, isTestFile } from './entry-point-scoring.js';
|
|
13
14
|
import { SupportedLanguages } from '../../_shared/index.js';
|
|
14
15
|
import { isDev } from './utils/env.js';
|
|
@@ -289,11 +290,21 @@ outwardActionSites = []) => {
|
|
|
289
290
|
* traces to jump across unrelated code areas.
|
|
290
291
|
*/
|
|
291
292
|
const MIN_TRACE_CONFIDENCE = 0.5;
|
|
293
|
+
/**
|
|
294
|
+
* True when an edge may seed or extend a traced flow.
|
|
295
|
+
*
|
|
296
|
+
* The confidence floor alone is not sufficient: the global-name fallback emits
|
|
297
|
+
* at exactly `MIN_TRACE_CONFIDENCE`, so a `<` comparison admits every one of
|
|
298
|
+
* its guesses. A flow assembled from name guesses reads as a real execution
|
|
299
|
+
* path through code that may never call each other, so the reason is checked
|
|
300
|
+
* too — see `graph/edge-reasons.ts`.
|
|
301
|
+
*/
|
|
302
|
+
const isTraceableCallsEdge = (type, confidence, reason) => type === 'CALLS' && confidence >= MIN_TRACE_CONFIDENCE && !isHeuristicEdgeReason(reason);
|
|
292
303
|
const buildCallsGraph = (graph) => {
|
|
293
304
|
const adj = new Map();
|
|
294
|
-
// Field-wise scan (#2680) — whole-graph walk,
|
|
295
|
-
graph.forEachRelationshipFields((sourceId, targetId, type, confidence) => {
|
|
296
|
-
if (type
|
|
305
|
+
// Field-wise scan (#2680) — whole-graph walk, five fields, no object needed.
|
|
306
|
+
graph.forEachRelationshipFields((sourceId, targetId, type, confidence, reason) => {
|
|
307
|
+
if (!isTraceableCallsEdge(type, confidence, reason))
|
|
297
308
|
return;
|
|
298
309
|
const existing = adj.get(sourceId);
|
|
299
310
|
if (existing === undefined)
|
|
@@ -305,8 +316,8 @@ const buildCallsGraph = (graph) => {
|
|
|
305
316
|
};
|
|
306
317
|
const buildReverseCallsGraph = (graph) => {
|
|
307
318
|
const adj = new Map();
|
|
308
|
-
graph.forEachRelationshipFields((sourceId, targetId, type, confidence) => {
|
|
309
|
-
if (type
|
|
319
|
+
graph.forEachRelationshipFields((sourceId, targetId, type, confidence, reason) => {
|
|
320
|
+
if (!isTraceableCallsEdge(type, confidence, reason))
|
|
310
321
|
return;
|
|
311
322
|
const existing = adj.get(targetId);
|
|
312
323
|
if (existing === undefined)
|
package/package.json
CHANGED