@veewo/gitnexus 1.4.10-rc → 1.4.11-rc.2

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.
Files changed (84) hide show
  1. package/dist/benchmark/u2-e2e/live-evidence-validator.d.ts +19 -0
  2. package/dist/benchmark/u2-e2e/live-evidence-validator.js +87 -0
  3. package/dist/benchmark/u2-e2e/live-evidence-validator.test.d.ts +1 -0
  4. package/dist/benchmark/u2-e2e/live-evidence-validator.test.js +33 -0
  5. package/dist/benchmark/u2-e2e/neonspark-full-e2e.js +23 -4
  6. package/dist/benchmark/u2-e2e/reload-v1-acceptance-runner.d.ts +38 -0
  7. package/dist/benchmark/u2-e2e/reload-v1-acceptance-runner.js +206 -0
  8. package/dist/benchmark/u2-e2e/reload-v1-acceptance-runner.test.d.ts +1 -0
  9. package/dist/benchmark/u2-e2e/reload-v1-acceptance-runner.test.js +72 -0
  10. package/dist/benchmark/u2-e2e/report.d.ts +1 -0
  11. package/dist/benchmark/u2-e2e/report.js +2 -0
  12. package/dist/benchmark/u2-e2e/retrieval-runner.d.ts +34 -0
  13. package/dist/benchmark/u2-e2e/retrieval-runner.js +95 -5
  14. package/dist/benchmark/u2-e2e/retrieval-runner.test.js +161 -2
  15. package/dist/cli/ai-context.js +25 -1
  16. package/dist/cli/ai-context.test.js +8 -0
  17. package/dist/cli/analyze-summary.d.ts +1 -0
  18. package/dist/cli/analyze-summary.js +21 -0
  19. package/dist/cli/analyze-summary.test.js +7 -1
  20. package/dist/cli/analyze.js +3 -10
  21. package/dist/cli/eval-server.js +1 -1
  22. package/dist/cli/index.js +2 -0
  23. package/dist/cli/setup.js +9 -0
  24. package/dist/cli/setup.test.js +2 -0
  25. package/dist/cli/tool.d.ts +2 -0
  26. package/dist/cli/tool.js +2 -0
  27. package/dist/core/ingestion/pipeline.js +24 -3
  28. package/dist/core/ingestion/process-processor.d.ts +6 -0
  29. package/dist/core/ingestion/process-processor.js +188 -7
  30. package/dist/core/ingestion/unity-lifecycle-config.d.ts +5 -0
  31. package/dist/core/ingestion/unity-lifecycle-config.js +25 -0
  32. package/dist/core/ingestion/unity-lifecycle-synthetic-calls.d.ts +26 -0
  33. package/dist/core/ingestion/unity-lifecycle-synthetic-calls.js +384 -0
  34. package/dist/core/ingestion/unity-lifecycle-synthetic-calls.test.d.ts +1 -0
  35. package/dist/core/ingestion/unity-lifecycle-synthetic-calls.test.js +541 -0
  36. package/dist/core/ingestion/unity-resource-processor.test.js +81 -0
  37. package/dist/core/lbug/csv-generator.js +11 -1
  38. package/dist/core/lbug/fallback-relationship-replay.d.ts +21 -0
  39. package/dist/core/lbug/fallback-relationship-replay.js +39 -0
  40. package/dist/core/lbug/fallback-relationship-replay.test.d.ts +1 -0
  41. package/dist/core/lbug/fallback-relationship-replay.test.js +25 -0
  42. package/dist/core/lbug/lbug-adapter.d.ts +5 -0
  43. package/dist/core/lbug/lbug-adapter.js +22 -23
  44. package/dist/core/lbug/schema.d.ts +2 -2
  45. package/dist/core/lbug/schema.js +9 -0
  46. package/dist/core/lbug/schema.test.js +1 -0
  47. package/dist/mcp/local/local-backend.d.ts +1 -1
  48. package/dist/mcp/local/local-backend.js +339 -50
  49. package/dist/mcp/local/local-backend.unity-merge.test.js +1 -1
  50. package/dist/mcp/local/process-confidence.d.ts +19 -0
  51. package/dist/mcp/local/process-confidence.js +29 -0
  52. package/dist/mcp/local/process-confidence.test.d.ts +1 -0
  53. package/dist/mcp/local/process-confidence.test.js +36 -0
  54. package/dist/mcp/local/process-evidence.d.ts +28 -0
  55. package/dist/mcp/local/process-evidence.js +65 -0
  56. package/dist/mcp/local/process-evidence.test.d.ts +1 -0
  57. package/dist/mcp/local/process-evidence.test.js +56 -0
  58. package/dist/mcp/local/runtime-chain-evidence.d.ts +7 -0
  59. package/dist/mcp/local/runtime-chain-evidence.js +13 -0
  60. package/dist/mcp/local/runtime-chain-evidence.test.d.ts +1 -0
  61. package/dist/mcp/local/runtime-chain-evidence.test.js +24 -0
  62. package/dist/mcp/local/runtime-chain-verify.d.ts +37 -0
  63. package/dist/mcp/local/runtime-chain-verify.js +221 -0
  64. package/dist/mcp/local/runtime-chain-verify.test.d.ts +1 -0
  65. package/dist/mcp/local/runtime-chain-verify.test.js +56 -0
  66. package/dist/mcp/local/unity-process-confidence-config.d.ts +1 -0
  67. package/dist/mcp/local/unity-process-confidence-config.js +4 -0
  68. package/dist/mcp/local/unity-runtime-chain-verify-config.d.ts +1 -0
  69. package/dist/mcp/local/unity-runtime-chain-verify-config.js +10 -0
  70. package/dist/mcp/local/unity-runtime-hydration.d.ts +50 -0
  71. package/dist/mcp/local/unity-runtime-hydration.js +323 -0
  72. package/dist/mcp/local/unity-runtime-hydration.test.d.ts +1 -0
  73. package/dist/mcp/local/unity-runtime-hydration.test.js +108 -0
  74. package/dist/mcp/resources.js +12 -2
  75. package/dist/mcp/tools.js +32 -0
  76. package/package.json +1 -1
  77. package/skills/_shared/unity-runtime-process-contract.md +38 -0
  78. package/skills/gitnexus-cli.md +16 -0
  79. package/skills/gitnexus-debugging.md +6 -0
  80. package/skills/gitnexus-exploring.md +6 -0
  81. package/skills/gitnexus-guide.md +4 -0
  82. package/skills/gitnexus-impact-analysis.md +6 -0
  83. package/skills/gitnexus-pr-review.md +5 -0
  84. package/skills/gitnexus-refactoring.md +4 -0
@@ -12,6 +12,8 @@
12
12
  import { calculateEntryPointScore, isTestFile } from './entry-point-scoring.js';
13
13
  import { SupportedLanguages } from '../../config/supported-languages.js';
14
14
  const isDev = process.env.NODE_ENV === 'development';
15
+ const SYNTHETIC_RUNTIME_ROOT_MARKER = 'unity-runtime-root';
16
+ const SYNTHETIC_RUNTIME_ROOT_TRACE_LIMIT = 8;
15
17
  const DEFAULT_CONFIG = {
16
18
  maxTraceDepth: 10,
17
19
  maxBranching: 4,
@@ -33,6 +35,7 @@ export const processProcesses = async (knowledgeGraph, memberships, onProgress,
33
35
  const membershipMap = new Map();
34
36
  memberships.forEach(m => membershipMap.set(m.nodeId, m.communityId));
35
37
  const callsEdges = buildCallsGraph(knowledgeGraph);
38
+ const callsEvidenceMap = buildCallsEvidenceMap(knowledgeGraph);
36
39
  const reverseCallsEdges = buildReverseCallsGraph(knowledgeGraph);
37
40
  const nodeMap = new Map();
38
41
  for (const n of knowledgeGraph.iterNodes())
@@ -57,11 +60,23 @@ export const processProcesses = async (knowledgeGraph, memberships, onProgress,
57
60
  const uniqueTraces = deduplicateTraces(allTraces);
58
61
  // Step 3b: Deduplicate by entry+terminal pair (keep longest path per pair)
59
62
  const endpointDeduped = deduplicateByEndpoints(uniqueTraces);
60
- onProgress?.(`Deduped ${uniqueTraces.length} ${endpointDeduped.length} unique endpoint pairs`, 70);
63
+ const syntheticRootBounded = capSyntheticRuntimeRootTraces(endpointDeduped);
64
+ onProgress?.(`Deduped ${uniqueTraces.length} → ${syntheticRootBounded.length} unique endpoint pairs`, 70);
61
65
  // Step 4: Limit to max processes (prioritize longer traces)
62
- const limitedTraces = endpointDeduped
63
- .sort((a, b) => b.length - a.length)
64
- .slice(0, cfg.maxProcesses);
66
+ const sortedTraces = syntheticRootBounded.sort((a, b) => {
67
+ const runtimeScore = scoreSyntheticRuntimeTrace(b) - scoreSyntheticRuntimeTrace(a);
68
+ if (runtimeScore !== 0)
69
+ return runtimeScore;
70
+ return b.length - a.length;
71
+ });
72
+ const prioritizedRuntimeTraces = sortedTraces
73
+ .filter(isSyntheticRuntimeRootTrace)
74
+ .slice(0, SYNTHETIC_RUNTIME_ROOT_TRACE_LIMIT);
75
+ const prioritizedRuntimeKeys = new Set(prioritizedRuntimeTraces.map((trace) => trace.join('->')));
76
+ const limitedTraces = [
77
+ ...prioritizedRuntimeTraces,
78
+ ...sortedTraces.filter((trace) => !prioritizedRuntimeKeys.has(trace.join('->'))),
79
+ ].slice(0, cfg.maxProcesses);
65
80
  onProgress?.(`Creating ${limitedTraces.length} process nodes...`, 80);
66
81
  // Step 5: Create process nodes
67
82
  const processes = [];
@@ -69,6 +84,7 @@ export const processProcesses = async (knowledgeGraph, memberships, onProgress,
69
84
  limitedTraces.forEach((trace, idx) => {
70
85
  const entryPointId = trace[0];
71
86
  const terminalId = trace[trace.length - 1];
87
+ const traceEvidence = collectTraceEvidence(trace, callsEvidenceMap);
72
88
  // Get communities touched
73
89
  const communitiesSet = new Set();
74
90
  trace.forEach(nodeId => {
@@ -79,6 +95,14 @@ export const processProcesses = async (knowledgeGraph, memberships, onProgress,
79
95
  const communities = Array.from(communitiesSet);
80
96
  // Determine process type
81
97
  const processType = communities.length > 1 ? 'cross_community' : 'intra_community';
98
+ const processSubtype = isSyntheticRuntimeRootTrace(trace) ? 'unity_lifecycle' : 'static_calls';
99
+ const sourceReasons = Array.from(new Set(traceEvidence
100
+ .map((edge) => edge.reason?.trim())
101
+ .filter((reason) => Boolean(reason) && !/TODO|TBD|placeholder/i.test(reason))));
102
+ const sourceConfidences = Array.from(new Set(traceEvidence
103
+ .map((edge) => edge.confidence)
104
+ .filter((confidence) => Number.isFinite(confidence))));
105
+ const runtimeChainConfidence = sourceReasons.some(isSyntheticLifecycleReason) ? 'medium' : 'high';
82
106
  // Generate label
83
107
  const entryNode = nodeMap.get(entryPointId);
84
108
  const terminalNode = nodeMap.get(terminalId);
@@ -91,6 +115,10 @@ export const processProcesses = async (knowledgeGraph, memberships, onProgress,
91
115
  label: heuristicLabel,
92
116
  heuristicLabel,
93
117
  processType,
118
+ processSubtype,
119
+ runtimeChainConfidence,
120
+ sourceReasons,
121
+ sourceConfidences,
94
122
  stepCount: trace.length,
95
123
  communities,
96
124
  entryPointId,
@@ -99,10 +127,13 @@ export const processProcesses = async (knowledgeGraph, memberships, onProgress,
99
127
  });
100
128
  // Create step relationships
101
129
  trace.forEach((nodeId, stepIdx) => {
130
+ const edgeEvidence = resolveStepEvidence(trace, stepIdx, callsEvidenceMap);
102
131
  steps.push({
103
132
  nodeId,
104
133
  processId,
105
134
  step: stepIdx + 1, // 1-indexed
135
+ reason: edgeEvidence?.reason,
136
+ confidence: edgeEvidence?.confidence,
106
137
  });
107
138
  });
108
139
  });
@@ -153,6 +184,45 @@ const buildReverseCallsGraph = (graph) => {
153
184
  }
154
185
  return adj;
155
186
  };
187
+ const buildCallsEvidenceMap = (graph) => {
188
+ const evidenceMap = new Map();
189
+ for (const rel of graph.iterRelationships()) {
190
+ if (rel.type !== 'CALLS' || rel.confidence < MIN_TRACE_CONFIDENCE)
191
+ continue;
192
+ const key = `${rel.sourceId}->${rel.targetId}`;
193
+ const existing = evidenceMap.get(key);
194
+ if (!existing || rel.confidence >= existing.confidence) {
195
+ evidenceMap.set(key, {
196
+ reason: rel.reason,
197
+ confidence: rel.confidence,
198
+ });
199
+ }
200
+ }
201
+ return evidenceMap;
202
+ };
203
+ const collectTraceEvidence = (trace, callsEvidenceMap) => {
204
+ const evidence = [];
205
+ for (let i = 0; i < trace.length - 1; i++) {
206
+ const edge = callsEvidenceMap.get(`${trace[i]}->${trace[i + 1]}`);
207
+ if (edge)
208
+ evidence.push(edge);
209
+ }
210
+ return evidence;
211
+ };
212
+ const resolveStepEvidence = (trace, stepIdx, callsEvidenceMap) => {
213
+ const current = trace[stepIdx];
214
+ const next = trace[stepIdx + 1];
215
+ if (next) {
216
+ const outgoing = callsEvidenceMap.get(`${current}->${next}`);
217
+ if (outgoing)
218
+ return outgoing;
219
+ }
220
+ const prev = trace[stepIdx - 1];
221
+ if (!prev)
222
+ return undefined;
223
+ return callsEvidenceMap.get(`${prev}->${current}`);
224
+ };
225
+ const isSyntheticLifecycleReason = (reason) => reason.includes('unity-lifecycle-synthetic') || reason.includes('unity-runtime-loader-synthetic');
156
226
  /**
157
227
  * Find functions/methods that are good entry points for tracing.
158
228
  *
@@ -178,6 +248,14 @@ const findEntryPoints = (graph, reverseCallsEdges, callsEdges) => {
178
248
  // Must have at least 1 outgoing call to trace forward
179
249
  if (callees.length === 0)
180
250
  continue;
251
+ if (node.id.includes(SYNTHETIC_RUNTIME_ROOT_MARKER) || String(node.properties.name || '').includes(SYNTHETIC_RUNTIME_ROOT_MARKER)) {
252
+ entryPointCandidates.push({
253
+ id: node.id,
254
+ score: 10_000 + callees.length,
255
+ reasons: ['synthetic-runtime-root'],
256
+ });
257
+ continue;
258
+ }
181
259
  // Calculate entry point score using new scoring system
182
260
  const { score: baseScore, reasons } = calculateEntryPointScore(node.properties.name, node.properties.language ?? SupportedLanguages.JavaScript, node.properties.isExported ?? false, callers.length, callees.length, filePath // Pass filePath for framework detection
183
261
  );
@@ -217,10 +295,12 @@ const findEntryPoints = (graph, reverseCallsEdges, callsEdges) => {
217
295
  */
218
296
  const traceFromEntryPoint = (entryId, callsEdges, config) => {
219
297
  const traces = [];
298
+ const isRuntimeRootEntry = entryId.includes(SYNTHETIC_RUNTIME_ROOT_MARKER);
299
+ const maxTraceCount = isRuntimeRootEntry ? SYNTHETIC_RUNTIME_ROOT_TRACE_LIMIT * 6 : config.maxBranching * 3;
220
300
  // BFS with path tracking
221
301
  // Each queue item: [currentNodeId, pathSoFar]
222
302
  const queue = [[entryId, [entryId]]];
223
- while (queue.length > 0 && traces.length < config.maxBranching * 3) {
303
+ while (queue.length > 0 && traces.length < maxTraceCount) {
224
304
  const [currentId, path] = queue.shift();
225
305
  // Get outgoing calls
226
306
  const callees = callsEdges.get(currentId) || [];
@@ -238,7 +318,13 @@ const traceFromEntryPoint = (entryId, callsEdges, config) => {
238
318
  }
239
319
  else {
240
320
  // Continue tracing - limit branching
241
- const limitedCallees = callees.slice(0, config.maxBranching);
321
+ const branchingLimit = path.length === 1 && currentId.includes(SYNTHETIC_RUNTIME_ROOT_MARKER)
322
+ ? Math.min(callees.length, Math.max(config.maxBranching * 8, SYNTHETIC_RUNTIME_ROOT_TRACE_LIMIT * 4))
323
+ : config.maxBranching;
324
+ const orderedCallees = isRuntimeRootEntry
325
+ ? [...callees].sort((left, right) => scoreRuntimeTraceTarget(right) - scoreRuntimeTraceTarget(left))
326
+ : callees;
327
+ const limitedCallees = orderedCallees.slice(0, branchingLimit);
242
328
  let addedBranch = false;
243
329
  for (const calleeId of limitedCallees) {
244
330
  // Avoid cycles
@@ -295,13 +381,108 @@ const deduplicateByEndpoints = (traces) => {
295
381
  // Sort longest first so the first seen per key is the longest
296
382
  const sorted = [...traces].sort((a, b) => b.length - a.length);
297
383
  for (const trace of sorted) {
298
- const key = `${trace[0]}::${trace[trace.length - 1]}`;
384
+ const key = isSyntheticRuntimeRootTrace(trace)
385
+ ? `${trace[0]}::${trace[1] ?? ''}::${trace[trace.length - 1]}`
386
+ : `${trace[0]}::${trace[trace.length - 1]}`;
299
387
  if (!byEndpoints.has(key)) {
300
388
  byEndpoints.set(key, trace);
301
389
  }
302
390
  }
303
391
  return Array.from(byEndpoints.values());
304
392
  };
393
+ /**
394
+ * Keep synthetic runtime-root traces useful but bounded.
395
+ * Preserve a small set of distinct lifecycle/runtime traces instead of collapsing to one.
396
+ */
397
+ const capSyntheticRuntimeRootTraces = (traces) => {
398
+ if (traces.length === 0)
399
+ return [];
400
+ const runtimeRootTraces = traces
401
+ .filter(isSyntheticRuntimeRootTrace)
402
+ .sort((a, b) => scoreSyntheticRuntimeTrace(b) - scoreSyntheticRuntimeTrace(a));
403
+ if (runtimeRootTraces.length <= SYNTHETIC_RUNTIME_ROOT_TRACE_LIMIT)
404
+ return traces;
405
+ const keep = runtimeRootTraces.slice(0, SYNTHETIC_RUNTIME_ROOT_TRACE_LIMIT);
406
+ const filtered = traces.filter((trace) => !isSyntheticRuntimeRootTrace(trace));
407
+ filtered.push(...keep);
408
+ return filtered;
409
+ };
410
+ const isSyntheticRuntimeRootTrace = (trace) => Boolean(trace[0]?.includes(SYNTHETIC_RUNTIME_ROOT_MARKER));
411
+ const scoreSyntheticRuntimeTrace = (trace) => {
412
+ let score = trace.length * 100;
413
+ const joined = trace.join(' ');
414
+ if (joined.includes('RegisterGraphEvents'))
415
+ score += 80;
416
+ if (joined.includes('RegisterEvents'))
417
+ score += 60;
418
+ if (joined.includes('StartRoutineWithEvents'))
419
+ score += 60;
420
+ if (joined.includes('GetValue'))
421
+ score += 70;
422
+ if (joined.includes('CheckReload'))
423
+ score += 60;
424
+ if (joined.includes('ReloadRoutine'))
425
+ score += 60;
426
+ if (joined.includes('EquipWithEvent'))
427
+ score += 40;
428
+ if (joined.includes('Equip'))
429
+ score += 30;
430
+ return score;
431
+ };
432
+ const scoreRuntimeRootTarget = (nodeId) => {
433
+ let score = 0;
434
+ const text = String(nodeId || '');
435
+ if (text.includes('GunGraphMB'))
436
+ score += 200;
437
+ if (text.includes('MeleeGraphMB'))
438
+ score += 120;
439
+ if (text.includes('/Reload'))
440
+ score += 180;
441
+ if (text.includes('/Graph/'))
442
+ score += 100;
443
+ if (text.includes('/PowerUps/'))
444
+ score += 70;
445
+ if (text.includes('/Core/'))
446
+ score += 40;
447
+ if (text.includes(':OnEnable'))
448
+ score += 30;
449
+ if (text.includes(':Awake'))
450
+ score += 20;
451
+ if (text.includes(':Start'))
452
+ score += 10;
453
+ return score;
454
+ };
455
+ const scoreRuntimeTraceTarget = (nodeId) => {
456
+ const text = String(nodeId || '');
457
+ let score = scoreRuntimeRootTarget(text);
458
+ if (text.includes('RegisterGraphEvents'))
459
+ score += 220;
460
+ if (text.includes('RegisterEvents'))
461
+ score += 180;
462
+ if (text.includes('StartRoutineWithEvents'))
463
+ score += 260;
464
+ if (text.includes('GetValue'))
465
+ score += 200;
466
+ if (text.includes('CheckReload'))
467
+ score += 180;
468
+ if (text.includes('ReloadRoutine'))
469
+ score += 170;
470
+ if (text.includes('AttackRoutineWithEvents'))
471
+ score -= 80;
472
+ if (text.includes('IGraphEvent.cs:Register'))
473
+ score -= 140;
474
+ if (text.includes('WaitForHelper.cs:EndOfFrame'))
475
+ score -= 160;
476
+ if (text.includes('/Graph/Graphs/GunGraph.cs'))
477
+ score += 120;
478
+ if (text.includes('/Graph/Nodes/Reloads/ReloadBase.cs'))
479
+ score += 220;
480
+ if (text.includes('/Graph/Nodes/Reloads/Reload.cs'))
481
+ score += 180;
482
+ if (text.includes('/Graph/Nodes/Reloads/'))
483
+ score += 120;
484
+ return score;
485
+ };
305
486
  // ============================================================================
306
487
  // HELPER: String utilities
307
488
  // ============================================================================
@@ -0,0 +1,5 @@
1
+ import { type UnityLifecycleSyntheticConfig } from './unity-lifecycle-synthetic-calls.js';
2
+ export interface UnityLifecycleConfig extends UnityLifecycleSyntheticConfig {
3
+ persistLifecycleProcessMetadata: boolean;
4
+ }
5
+ export declare const resolveUnityLifecycleConfig: (env: NodeJS.ProcessEnv) => UnityLifecycleConfig;
@@ -0,0 +1,25 @@
1
+ import { DEFAULT_UNITY_LIFECYCLE_SYNTHETIC_CONFIG, } from './unity-lifecycle-synthetic-calls.js';
2
+ const TRUE_VALUES = new Set(['1', 'true', 'on', 'yes']);
3
+ const parsePositiveInt = (raw, fallback) => {
4
+ const value = Number.parseInt(String(raw || '').trim(), 10);
5
+ if (!Number.isFinite(value) || value <= 0)
6
+ return fallback;
7
+ return value;
8
+ };
9
+ const parseBool = (raw) => {
10
+ const normalized = String(raw || '').trim().toLowerCase();
11
+ return TRUE_VALUES.has(normalized);
12
+ };
13
+ export const resolveUnityLifecycleConfig = (env) => {
14
+ const enabled = parseBool(env.GITNEXUS_UNITY_LIFECYCLE_SYNTHETIC_CALLS);
15
+ const persistLifecycleProcessMetadata = parseBool(env.GITNEXUS_UNITY_LIFECYCLE_PROCESS_PERSIST);
16
+ const maxSyntheticEdgesPerClass = parsePositiveInt(env.GITNEXUS_UNITY_LIFECYCLE_SYNTHETIC_MAX_PER_CLASS, DEFAULT_UNITY_LIFECYCLE_SYNTHETIC_CONFIG.maxSyntheticEdgesPerClass);
17
+ const maxSyntheticEdgesTotal = parsePositiveInt(env.GITNEXUS_UNITY_LIFECYCLE_SYNTHETIC_MAX_TOTAL, DEFAULT_UNITY_LIFECYCLE_SYNTHETIC_CONFIG.maxSyntheticEdgesTotal);
18
+ return {
19
+ ...DEFAULT_UNITY_LIFECYCLE_SYNTHETIC_CONFIG,
20
+ enabled,
21
+ persistLifecycleProcessMetadata,
22
+ maxSyntheticEdgesPerClass,
23
+ maxSyntheticEdgesTotal,
24
+ };
25
+ };
@@ -0,0 +1,26 @@
1
+ import type { GraphNode, KnowledgeGraph } from '../graph/types.js';
2
+ export interface UnityLifecycleSyntheticConfig {
3
+ enabled: boolean;
4
+ maxSyntheticEdgesPerClass: number;
5
+ maxSyntheticEdgesTotal: number;
6
+ lifecycleEdgeConfidence: number;
7
+ loaderEdgeConfidence: number;
8
+ }
9
+ export declare const DEFAULT_UNITY_LIFECYCLE_SYNTHETIC_CONFIG: UnityLifecycleSyntheticConfig;
10
+ export interface UnityLifecycleHost {
11
+ classNode: GraphNode;
12
+ baseType: 'MonoBehaviour' | 'ScriptableObject';
13
+ lifecycleCallbacks: GraphNode[];
14
+ loaderAnchors: GraphNode[];
15
+ methods: GraphNode[];
16
+ }
17
+ export interface UnityLifecycleSyntheticResult {
18
+ syntheticEdgeCount: number;
19
+ lifecycleEdgeCount: number;
20
+ loaderEdgeCount: number;
21
+ hostCount: number;
22
+ rejectedHostCount: number;
23
+ runtimeRootNodeId?: string;
24
+ }
25
+ export declare const detectUnityLifecycleHosts: (graph: KnowledgeGraph) => UnityLifecycleHost[];
26
+ export declare const applyUnityLifecycleSyntheticCalls: (graph: KnowledgeGraph, config?: Partial<UnityLifecycleSyntheticConfig>) => UnityLifecycleSyntheticResult;