@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
@@ -0,0 +1,323 @@
1
+ import { buildUnityScanContext, buildUnityScanContextFromSeed } from '../../core/unity/scan-context.js';
2
+ import { resolveUnityBindings } from '../../core/unity/resolver.js';
3
+ import { formatLazyHydrationBudgetDiagnostic, } from './unity-enrichment.js';
4
+ import { resolveUnityLazyConfig } from './unity-lazy-config.js';
5
+ import { hydrateLazyBindings } from './unity-lazy-hydrator.js';
6
+ import { readUnityOverlayBindings, upsertUnityOverlayBindings } from './unity-lazy-overlay.js';
7
+ import { readUnityParityCache, upsertUnityParityCache } from './unity-parity-cache.js';
8
+ import { createParityWarmupQueue } from './unity-parity-warmup-queue.js';
9
+ import { loadUnityParitySeed } from './unity-parity-seed-loader.js';
10
+ const inFlightParityHydration = new Map();
11
+ const parityWarmupQueue = createParityWarmupQueue({
12
+ maxParallel: resolveParityWarmupMaxParallel(process.env),
13
+ });
14
+ function resolveParityWarmupMaxParallel(env) {
15
+ const raw = String(env.GITNEXUS_UNITY_PARITY_WARMUP_MAX_PARALLEL || '').trim();
16
+ const parsed = Number.parseInt(raw, 10);
17
+ if (Number.isFinite(parsed) && parsed > 0) {
18
+ return parsed;
19
+ }
20
+ return 2;
21
+ }
22
+ function normalizePath(filePath) {
23
+ return String(filePath || '').replace(/\\/g, '/');
24
+ }
25
+ function bindingIdentity(binding) {
26
+ return [
27
+ normalizePath(binding.resourcePath),
28
+ binding.bindingKind,
29
+ binding.componentObjectId,
30
+ ].join('|');
31
+ }
32
+ export function mergeUnityBindings(baseBindings, resolvedByPath) {
33
+ const merged = [];
34
+ const expandedPaths = new Set();
35
+ for (const binding of baseBindings) {
36
+ const resourcePath = normalizePath(binding.resourcePath);
37
+ if (!binding.lightweight) {
38
+ merged.push(binding);
39
+ continue;
40
+ }
41
+ const expanded = resolvedByPath.get(resourcePath);
42
+ if (expanded && expanded.length > 0) {
43
+ if (!expandedPaths.has(resourcePath)) {
44
+ merged.push(...expanded.map((row) => ({ ...row, lightweight: false })));
45
+ expandedPaths.add(resourcePath);
46
+ }
47
+ continue;
48
+ }
49
+ merged.push(binding);
50
+ }
51
+ return merged;
52
+ }
53
+ export function mergeParityUnityBindings(baseNonLightweightBindings, resolvedBindings) {
54
+ const merged = [];
55
+ const seen = new Set();
56
+ for (const row of [...baseNonLightweightBindings, ...resolvedBindings]) {
57
+ const key = bindingIdentity(row);
58
+ if (seen.has(key))
59
+ continue;
60
+ seen.add(key);
61
+ merged.push({ ...row, lightweight: false });
62
+ }
63
+ return merged;
64
+ }
65
+ export function attachUnityHydrationMeta(payload, input) {
66
+ const { hasExpandableBindings, ...metaInput } = input;
67
+ const reasons = [];
68
+ if (metaInput.effectiveMode === 'compact' && hasExpandableBindings) {
69
+ reasons.push('mode_compact');
70
+ }
71
+ if (metaInput.fallbackToCompact) {
72
+ reasons.push('fallback_to_compact');
73
+ }
74
+ if (hasExpandableBindings) {
75
+ reasons.push('lightweight_bindings_remaining');
76
+ }
77
+ if ((payload.unityDiagnostics || []).some((diag) => /budget exceeded/i.test(String(diag || '')))) {
78
+ reasons.push('budget_exceeded');
79
+ }
80
+ const isComplete = reasons.length === 0;
81
+ const needsParityRetry = !isComplete && metaInput.effectiveMode === 'compact';
82
+ return {
83
+ ...payload,
84
+ hydrationMeta: {
85
+ ...metaInput,
86
+ resourceBindingCount: payload.resourceBindings.length,
87
+ unityDiagnosticsCount: payload.unityDiagnostics.length,
88
+ isComplete,
89
+ completenessReason: reasons,
90
+ needsParityRetry,
91
+ ...(needsParityRetry ? { retryHint: 'rerun_with_unity_hydration=parity' } : {}),
92
+ },
93
+ };
94
+ }
95
+ export async function hydrateUnityForSymbol(input) {
96
+ const runtime = resolveRuntime(input.runtime);
97
+ const startedAt = runtime.now();
98
+ if (input.mode === 'compact') {
99
+ const compactPayload = await runCompactHydration(input, runtime);
100
+ const withMeta = attachUnityHydrationMeta(compactPayload, {
101
+ requestedMode: 'compact',
102
+ effectiveMode: 'compact',
103
+ elapsedMs: runtime.now() - startedAt,
104
+ fallbackToCompact: false,
105
+ hasExpandableBindings: hasExpandableBindings(compactPayload),
106
+ });
107
+ if (withMeta.hydrationMeta?.needsParityRetry) {
108
+ scheduleParityWarmup(input, runtime);
109
+ }
110
+ return withMeta;
111
+ }
112
+ const parityResult = await runParityHydrationWithFallback(input, runtime);
113
+ return attachUnityHydrationMeta(parityResult.payload, {
114
+ requestedMode: 'parity',
115
+ effectiveMode: parityResult.effectiveMode,
116
+ elapsedMs: runtime.now() - startedAt,
117
+ fallbackToCompact: parityResult.fallbackToCompact,
118
+ hasExpandableBindings: hasExpandableBindings(parityResult.payload),
119
+ });
120
+ }
121
+ function resolveRuntime(overrides) {
122
+ return {
123
+ now: () => Date.now(),
124
+ queue: parityWarmupQueue,
125
+ resolveLazyConfig: resolveUnityLazyConfig,
126
+ hydrateLazyBindings,
127
+ readOverlayBindings: readUnityOverlayBindings,
128
+ upsertOverlayBindings: upsertUnityOverlayBindings,
129
+ readParityCache: readUnityParityCache,
130
+ upsertParityCache: upsertUnityParityCache,
131
+ loadParitySeed: loadUnityParitySeed,
132
+ buildScanContext: buildUnityScanContext,
133
+ buildScanContextFromSeed: buildUnityScanContextFromSeed,
134
+ resolveBindings: resolveUnityBindings,
135
+ shouldEnableWarmup,
136
+ ...overrides,
137
+ };
138
+ }
139
+ function hasExpandableBindings(payload) {
140
+ return payload.resourceBindings.some((binding) => binding.lightweight || binding.componentObjectId === 'summary');
141
+ }
142
+ function buildParityWarmupKey(input) {
143
+ return `${input.deps.storagePath}::${input.deps.indexedCommit}::${input.symbol.uid}`;
144
+ }
145
+ function scheduleParityWarmup(input, runtime) {
146
+ if (!runtime.shouldEnableWarmup(process.env)) {
147
+ return;
148
+ }
149
+ if (!input.symbol.uid || !input.symbol.name || !input.symbol.filePath) {
150
+ return;
151
+ }
152
+ void runtime.queue.run(() => getOrRunParityHydration(input, runtime))
153
+ .then(() => undefined)
154
+ .catch(() => undefined);
155
+ }
156
+ function shouldEnableWarmup(env) {
157
+ const raw = String(env.GITNEXUS_UNITY_PARITY_WARMUP || '').trim().toLowerCase();
158
+ return raw === '1' || raw === 'true' || raw === 'on';
159
+ }
160
+ async function getOrRunParityHydration(input, runtime) {
161
+ const key = buildParityWarmupKey(input);
162
+ const existing = inFlightParityHydration.get(key);
163
+ if (existing) {
164
+ return existing;
165
+ }
166
+ const pending = (async () => {
167
+ const cached = await runtime.readParityCache(input.deps.storagePath, input.deps.indexedCommit, input.symbol.uid);
168
+ if (cached) {
169
+ return cached;
170
+ }
171
+ const payload = await computeParityPayload(input, runtime);
172
+ await runtime.upsertParityCache(input.deps.storagePath, input.deps.indexedCommit, input.symbol.uid, payload);
173
+ return payload;
174
+ })().finally(() => {
175
+ inFlightParityHydration.delete(key);
176
+ });
177
+ inFlightParityHydration.set(key, pending);
178
+ return pending;
179
+ }
180
+ async function computeParityPayload(input, runtime) {
181
+ const symbolDeclarations = [{ symbol: input.symbol.name, scriptPath: input.symbol.filePath }];
182
+ const paritySeed = await runtime.loadParitySeed(input.deps.storagePath, {
183
+ indexedCommit: input.deps.indexedCommit,
184
+ });
185
+ const seededScanContext = paritySeed
186
+ ? runtime.buildScanContextFromSeed({ seed: paritySeed, symbolDeclarations })
187
+ : null;
188
+ let resolved = await runtime.resolveBindings({
189
+ repoRoot: input.deps.repoPath,
190
+ symbol: input.symbol.name,
191
+ scanContext: seededScanContext || await runtime.buildScanContext({
192
+ repoRoot: input.deps.repoPath,
193
+ symbolDeclarations,
194
+ }),
195
+ deepParseLargeResources: true,
196
+ });
197
+ if (seededScanContext && resolved.resourceBindings.length === 0 && input.basePayload.resourceBindings.length > 0) {
198
+ const fallbackScanContext = await runtime.buildScanContext({
199
+ repoRoot: input.deps.repoPath,
200
+ symbolDeclarations,
201
+ });
202
+ resolved = await runtime.resolveBindings({
203
+ repoRoot: input.deps.repoPath,
204
+ symbol: input.symbol.name,
205
+ scanContext: fallbackScanContext,
206
+ deepParseLargeResources: true,
207
+ });
208
+ }
209
+ if (resolved.resourceBindings.length === 0 && input.basePayload.resourceBindings.length > 0) {
210
+ throw new Error('parity-expand returned zero bindings');
211
+ }
212
+ const baseNonLightweight = input.basePayload.resourceBindings.filter((binding) => !binding.lightweight && binding.componentObjectId !== 'summary');
213
+ const mergedBindings = mergeParityUnityBindings(baseNonLightweight, resolved.resourceBindings);
214
+ return toUnityContextPayload(mergedBindings, [
215
+ ...input.basePayload.unityDiagnostics,
216
+ ...resolved.unityDiagnostics,
217
+ ]);
218
+ }
219
+ async function runParityHydrationWithFallback(input, runtime) {
220
+ try {
221
+ return {
222
+ payload: await getOrRunParityHydration(input, runtime),
223
+ effectiveMode: 'parity',
224
+ fallbackToCompact: false,
225
+ };
226
+ }
227
+ catch (error) {
228
+ const compactFallback = await runCompactHydration(input, runtime);
229
+ const message = String(error instanceof Error ? error.message : error);
230
+ return {
231
+ payload: {
232
+ ...compactFallback,
233
+ unityDiagnostics: [
234
+ ...compactFallback.unityDiagnostics,
235
+ /parity-expand returned zero bindings/i.test(message)
236
+ ? 'parity-expand returned zero bindings; fell back to compact hydration'
237
+ : `parity-expand failed: ${message}`,
238
+ ],
239
+ },
240
+ effectiveMode: 'compact',
241
+ fallbackToCompact: true,
242
+ };
243
+ }
244
+ }
245
+ async function runCompactHydration(input, runtime) {
246
+ const lightweightPaths = [...new Set(input.basePayload.resourceBindings
247
+ .filter((binding) => binding.lightweight || binding.componentObjectId === 'summary')
248
+ .map((binding) => normalizePath(binding.resourcePath))
249
+ .filter((value) => value.length > 0))];
250
+ if (lightweightPaths.length === 0) {
251
+ return input.basePayload;
252
+ }
253
+ const overlayHits = await runtime.readOverlayBindings(input.deps.storagePath, input.deps.indexedCommit, input.symbol.uid, lightweightPaths);
254
+ const pendingPaths = lightweightPaths.filter((resourcePath) => !overlayHits.has(resourcePath));
255
+ const resolvedByPath = new Map(overlayHits);
256
+ const unityDiagnostics = [...input.basePayload.unityDiagnostics];
257
+ if (pendingPaths.length > 0) {
258
+ try {
259
+ const cfg = runtime.resolveLazyConfig(process.env);
260
+ const hydration = await runtime.hydrateLazyBindings({
261
+ pendingPaths,
262
+ config: cfg,
263
+ dedupeKey: `${input.symbol.uid}::${pendingPaths.slice().sort().join('|')}`,
264
+ resolveBatch: async (resourcePaths) => {
265
+ const scopedPaths = [
266
+ input.symbol.filePath,
267
+ `${input.symbol.filePath}.meta`,
268
+ ...resourcePaths,
269
+ ...resourcePaths.map((resourcePath) => `${resourcePath}.meta`),
270
+ ].map(normalizePath);
271
+ const scanContext = await runtime.buildScanContext({
272
+ repoRoot: input.deps.repoPath,
273
+ scopedPaths,
274
+ symbolDeclarations: [{ symbol: input.symbol.name, scriptPath: input.symbol.filePath }],
275
+ });
276
+ const resolved = await runtime.resolveBindings({
277
+ repoRoot: input.deps.repoPath,
278
+ symbol: input.symbol.name,
279
+ scanContext,
280
+ resourcePathAllowlist: resourcePaths,
281
+ deepParseLargeResources: true,
282
+ });
283
+ unityDiagnostics.push(...resolved.unityDiagnostics);
284
+ const byPath = new Map();
285
+ for (const resourcePath of resourcePaths) {
286
+ byPath.set(resourcePath, resolved.resourceBindings.filter((binding) => normalizePath(binding.resourcePath) === normalizePath(resourcePath)));
287
+ }
288
+ return byPath;
289
+ },
290
+ });
291
+ const freshByPath = hydration.resolvedByPath;
292
+ if (hydration.timedOut) {
293
+ unityDiagnostics.push(formatLazyHydrationBudgetDiagnostic(hydration.elapsedMs));
294
+ }
295
+ const hydrationExtras = hydration.diagnostics.filter((diag) => !/budget exceeded/i.test(diag));
296
+ if (hydrationExtras.length > 0) {
297
+ unityDiagnostics.push(...hydrationExtras);
298
+ }
299
+ await runtime.upsertOverlayBindings(input.deps.storagePath, input.deps.indexedCommit, input.symbol.uid, freshByPath);
300
+ for (const [resourcePath, bindings] of freshByPath.entries()) {
301
+ resolvedByPath.set(resourcePath, bindings);
302
+ }
303
+ }
304
+ catch (error) {
305
+ unityDiagnostics.push(`lazy-expand failed: ${error instanceof Error ? error.message : String(error)}`);
306
+ }
307
+ }
308
+ const mergedBindings = mergeUnityBindings(input.basePayload.resourceBindings, resolvedByPath);
309
+ return toUnityContextPayload(mergedBindings, unityDiagnostics);
310
+ }
311
+ function toUnityContextPayload(resourceBindings, unityDiagnostics) {
312
+ return {
313
+ resourceBindings,
314
+ serializedFields: {
315
+ scalarFields: resourceBindings.flatMap((binding) => binding.serializedFields.scalarFields),
316
+ referenceFields: resourceBindings.flatMap((binding) => binding.serializedFields.referenceFields),
317
+ },
318
+ unityDiagnostics,
319
+ };
320
+ }
321
+ export function __resetUnityRuntimeHydrationStateForTest() {
322
+ inFlightParityHydration.clear();
323
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,108 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { hydrateUnityForSymbol } from './unity-runtime-hydration.js';
4
+ test('hydrateUnityForSymbol(compact) marks needsParityRetry when lightweight bindings remain', async () => {
5
+ const out = await hydrateUnityForSymbol({
6
+ mode: 'compact',
7
+ basePayload: {
8
+ resourceBindings: [
9
+ {
10
+ resourcePath: 'Assets/A.prefab',
11
+ resourceType: 'prefab',
12
+ bindingKind: 'direct',
13
+ componentObjectId: 'summary',
14
+ lightweight: true,
15
+ evidence: { line: 0, lineText: '' },
16
+ serializedFields: { scalarFields: [], referenceFields: [] },
17
+ resolvedReferences: [],
18
+ assetRefPaths: [],
19
+ },
20
+ ],
21
+ serializedFields: { scalarFields: [], referenceFields: [] },
22
+ unityDiagnostics: [],
23
+ },
24
+ deps: {
25
+ executeQuery: async () => [],
26
+ repoPath: '/tmp/repo',
27
+ storagePath: '/tmp/storage',
28
+ indexedCommit: 'abc123',
29
+ },
30
+ symbol: {
31
+ uid: 'Class:Assets/Scripts/A.cs:A',
32
+ name: 'A',
33
+ filePath: 'Assets/Scripts/A.cs',
34
+ },
35
+ runtime: {
36
+ shouldEnableWarmup: () => false,
37
+ resolveLazyConfig: () => ({ maxPendingPathsPerRequest: 10, batchSize: 10, maxHydrationMs: 5000 }),
38
+ hydrateLazyBindings: async () => ({
39
+ resolvedByPath: new Map(),
40
+ timedOut: false,
41
+ elapsedMs: 1,
42
+ diagnostics: [],
43
+ }),
44
+ readOverlayBindings: async () => new Map(),
45
+ upsertOverlayBindings: async () => undefined,
46
+ },
47
+ });
48
+ assert.equal(out.hydrationMeta?.effectiveMode, 'compact');
49
+ assert.equal(out.hydrationMeta?.needsParityRetry, true);
50
+ });
51
+ test('hydrateUnityForSymbol(parity) sets isComplete=true on parity success', async () => {
52
+ const out = await hydrateUnityForSymbol({
53
+ mode: 'parity',
54
+ basePayload: {
55
+ resourceBindings: [
56
+ {
57
+ resourcePath: 'Assets/A.prefab',
58
+ resourceType: 'prefab',
59
+ bindingKind: 'direct',
60
+ componentObjectId: 'summary',
61
+ lightweight: true,
62
+ evidence: { line: 0, lineText: '' },
63
+ serializedFields: { scalarFields: [], referenceFields: [] },
64
+ resolvedReferences: [],
65
+ assetRefPaths: [],
66
+ },
67
+ ],
68
+ serializedFields: { scalarFields: [], referenceFields: [] },
69
+ unityDiagnostics: [],
70
+ },
71
+ deps: {
72
+ executeQuery: async () => [],
73
+ repoPath: '/tmp/repo',
74
+ storagePath: '/tmp/storage',
75
+ indexedCommit: 'abc123',
76
+ },
77
+ symbol: {
78
+ uid: 'Class:Assets/Scripts/A.cs:A',
79
+ name: 'A',
80
+ filePath: 'Assets/Scripts/A.cs',
81
+ },
82
+ runtime: {
83
+ shouldEnableWarmup: () => false,
84
+ readParityCache: async () => null,
85
+ upsertParityCache: async () => undefined,
86
+ loadParitySeed: async () => null,
87
+ buildScanContext: async () => ({}),
88
+ resolveBindings: async () => ({
89
+ resourceBindings: [
90
+ {
91
+ resourcePath: 'Assets/A.prefab',
92
+ resourceType: 'prefab',
93
+ bindingKind: 'direct',
94
+ componentObjectId: '114',
95
+ lightweight: false,
96
+ evidence: { line: 1, lineText: 'stub' },
97
+ serializedFields: { scalarFields: [], referenceFields: [] },
98
+ resolvedReferences: [],
99
+ assetRefPaths: [],
100
+ },
101
+ ],
102
+ unityDiagnostics: [],
103
+ }),
104
+ },
105
+ });
106
+ assert.equal(out.hydrationMeta?.effectiveMode, 'parity');
107
+ assert.equal(out.hydrationMeta?.isComplete, true);
108
+ });
@@ -64,7 +64,7 @@ export function getResourceTemplates() {
64
64
  {
65
65
  uriTemplate: 'gitnexus://repo/{name}/process/{processName}',
66
66
  name: 'Process Trace',
67
- description: 'Step-by-step execution trace',
67
+ description: 'Step-by-step execution trace with lifecycle subtype and step evidence when available',
68
68
  mimeType: 'text/yaml',
69
69
  },
70
70
  ];
@@ -250,6 +250,12 @@ async function getProcessesResource(backend, repoName) {
250
250
  lines.push(` - name: "${label}"`);
251
251
  lines.push(` type: ${proc.processType || 'unknown'}`);
252
252
  lines.push(` steps: ${proc.stepCount || 0}`);
253
+ if (proc.processSubtype) {
254
+ lines.push(` subtype: ${proc.processSubtype}`);
255
+ }
256
+ if (proc.runtimeChainConfidence) {
257
+ lines.push(` runtime_chain_confidence: ${proc.runtimeChainConfidence}`);
258
+ }
253
259
  }
254
260
  if (result.processes.length > displayLimit) {
255
261
  lines.push(`\n# Showing top ${displayLimit} of ${result.processes.length} processes. Use gitnexus_query for deeper search.`);
@@ -358,13 +364,17 @@ async function getProcessDetailResource(name, backend, repoName) {
358
364
  const lines = [
359
365
  `name: "${proc.heuristicLabel || proc.label || proc.id}"`,
360
366
  `type: ${proc.processType || 'unknown'}`,
367
+ `subtype: ${proc.processSubtype || 'static_calls'}`,
368
+ `runtime_chain_confidence: ${proc.runtimeChainConfidence || 'high'}`,
361
369
  `step_count: ${proc.stepCount || steps.length}`,
362
370
  ];
363
371
  if (steps.length > 0) {
364
372
  lines.push('');
365
373
  lines.push('trace:');
366
374
  for (const step of steps) {
367
- lines.push(` ${step.step}: ${step.name} (${step.filePath})`);
375
+ const reason = step.reason ? ` reason=${step.reason}` : '';
376
+ const confidence = step.confidence !== undefined ? ` confidence=${step.confidence}` : '';
377
+ lines.push(` ${step.step}: ${step.name} (${step.filePath})${reason}${confidence}`);
368
378
  }
369
379
  }
370
380
  return lines.join('\n');
package/dist/mcp/tools.js CHANGED
@@ -34,6 +34,18 @@ Returns results grouped by process (execution flow):
34
34
  - processes: ranked execution flows with relevance priority
35
35
  - process_symbols: all symbols in those flows with file locations and module (functional area)
36
36
  - definitions: standalone types/interfaces not in any process
37
+ - processes[].evidence_mode: direct_step | method_projected | resource_heuristic
38
+ - processes[].confidence: high | medium | low
39
+ - processes[].process_subtype: unity_lifecycle | static_calls (when persisted metadata exists)
40
+ - processes[].runtime_chain_confidence: high | medium | low (when GITNEXUS_UNITY_PROCESS_CONFIDENCE_FIELDS=on)
41
+ - processes[].runtime_chain_evidence_level: none | clue | verified_segment | verified_chain (when GITNEXUS_UNITY_PROCESS_CONFIDENCE_FIELDS=on)
42
+ - processes[].verification_hint: { action, target, next_command } (required when confidence=low and confidence fields flag is on)
43
+ - process_symbols[].process_evidence_mode: direct_step | method_projected | resource_heuristic
44
+ - process_symbols[].process_confidence: high | medium | low
45
+ - process_symbols[].process_subtype: unity_lifecycle | static_calls (when persisted metadata exists)
46
+ - process_symbols[].runtime_chain_confidence: high | medium | low (when GITNEXUS_UNITY_PROCESS_CONFIDENCE_FIELDS=on)
47
+ - process_symbols[].runtime_chain_evidence_level: none | clue | verified_segment | verified_chain (when GITNEXUS_UNITY_PROCESS_CONFIDENCE_FIELDS=on)
48
+ - process_symbols[].verification_hint: { action, target, next_command } (when confidence fields flag is on)
37
49
 
38
50
  Hybrid ranking: BM25 keyword + semantic vector search, ranked by Reciprocal Rank Fusion.
39
51
  Supports optional scope controls for noisy codebases:
@@ -70,6 +82,12 @@ Includes optional Unity retrieval contract:
70
82
  description: 'Unity hydration mode when unity_resources is enabled (default: compact)',
71
83
  default: 'compact',
72
84
  },
85
+ runtime_chain_verify: {
86
+ type: 'string',
87
+ enum: ['off', 'on-demand'],
88
+ description: 'Explicit runtime chain verification mode (default: off)',
89
+ default: 'off',
90
+ },
73
91
  repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
74
92
  },
75
93
  required: ['query'],
@@ -134,6 +152,14 @@ AFTER THIS: Use impact() if planning changes, or READ gitnexus://repo/{name}/pro
134
152
 
135
153
  Handles disambiguation: if multiple symbols share the same name, returns candidates for you to pick from. Use uid param for zero-ambiguity lookup from prior results.
136
154
 
155
+ Process participation metadata:
156
+ - processes[].evidence_mode: direct_step | method_projected | resource_heuristic
157
+ - processes[].confidence: high | medium | low
158
+ - processes[].process_subtype: unity_lifecycle | static_calls (when persisted metadata exists)
159
+ - processes[].runtime_chain_confidence: high | medium | low (when GITNEXUS_UNITY_PROCESS_CONFIDENCE_FIELDS=on)
160
+ - processes[].runtime_chain_evidence_level: none | clue | verified_segment | verified_chain (when GITNEXUS_UNITY_PROCESS_CONFIDENCE_FIELDS=on)
161
+ - processes[].verification_hint: { action, target, next_command } (required when confidence=low and confidence fields flag is on)
162
+
137
163
  Unity retrieval contract:
138
164
  - Set unity_resources=on|auto to include Unity resource evidence.
139
165
  - Default unity_hydration_mode=compact (fast path).
@@ -157,6 +183,12 @@ Unity retrieval contract:
157
183
  description: 'Unity hydration mode when unity_resources is enabled (default: compact)',
158
184
  default: 'compact',
159
185
  },
186
+ runtime_chain_verify: {
187
+ type: 'string',
188
+ enum: ['off', 'on-demand'],
189
+ description: 'Explicit runtime chain verification mode (default: off)',
190
+ default: 'off',
191
+ },
160
192
  repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
161
193
  },
162
194
  required: [],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veewo/gitnexus",
3
- "version": "1.4.10-rc",
3
+ "version": "1.4.11-rc.2",
4
4
  "description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
5
5
  "author": "Abhigyan Patwari",
6
6
  "license": "PolyForm-Noncommercial-1.0.0",
@@ -0,0 +1,38 @@
1
+ # Unity Runtime Process Contract
2
+
3
+ Use this contract when analysis touches Unity runtime process semantics (runtime chain, lifecycle/loader stitching, or confidence-based closure).
4
+
5
+ ## Trigger Conditions
6
+
7
+ Load this contract when any of the following is true:
8
+
9
+ - Query/debug/impact/refactor task requires Unity runtime process closure.
10
+ - Result contains Unity process evidence with `confidence` interpretation.
11
+ - Result has empty `processes` but Unity resource evidence is present.
12
+ - User asks for runtime-chain verification quality or closure certainty.
13
+
14
+ ## Required Workflow
15
+
16
+ 1. Run `query/context` with `unity_resources: "on"` and `unity_hydration_mode: "compact"` first.
17
+ 2. If `hydrationMeta.needsParityRetry === true`, rerun with `unity_hydration_mode: "parity"` before conclusions.
18
+ 3. Do not conclude "no runtime chain" from empty `processes` alone.
19
+ 4. If Unity evidence exists, continue stitching:
20
+ - `processes`
21
+ - `resourceBindings`
22
+ - asset/meta mapping anchors
23
+ - runtime candidate symbols
24
+ 5. Treat low-confidence rows as unresolved unless `verification_hint` includes:
25
+ - `action`
26
+ - `target`
27
+ - `next_command`
28
+ 6. Semantic closure requires hop anchors/evidence anchors for each stitched step.
29
+
30
+ ## Optional Strong Verification
31
+
32
+ For Reload-focused confirmation, request on-demand verification:
33
+
34
+ - pass `runtime_chain_verify: "on-demand"` in MCP tools, or
35
+ - use CLI `--runtime-chain-verify on-demand`.
36
+
37
+ When on-demand verification is used, report `runtime_chain.status`, `evidence_level`, `hops`, and `gaps` before final risk/closure statements.
38
+
@@ -113,6 +113,22 @@ Rules:
113
113
  - If response `hydrationMeta.needsParityRetry=true`, rerun with `--unity-hydration parity`.
114
114
  - `--unity-hydration parity` is completeness-first mode for advanced verification.
115
115
 
116
+ ### Unity runtime process contract trigger
117
+
118
+ When CLI analysis targets Unity runtime process semantics (runtime chain closure/confidence), load:
119
+
120
+ - `_shared/unity-runtime-process-contract.md`
121
+
122
+ Runtime-process verification examples:
123
+
124
+ ```bash
125
+ $GN query "Reload NEON.Game.Graph.Nodes.Reloads" --repo neonspark --unity-resources on --unity-hydration parity --runtime-chain-verify on-demand
126
+ ```
127
+
128
+ ```bash
129
+ $GN context ReloadNode --repo neonspark --unity-resources on --unity-hydration compact --runtime-chain-verify on-demand
130
+ ```
131
+
116
132
  ### unity-ui-trace — Unity UI evidence tracing workflow
117
133
 
118
134
  ```bash
@@ -39,6 +39,12 @@ description: "Use when the user is debugging a bug, tracing an error, or asking
39
39
  - [ ] Read source files to confirm root cause
40
40
  ```
41
41
 
42
+ ## Unity Runtime Process Trigger
43
+
44
+ When debugging involves Unity runtime process semantics (runtime chain confidence, process closure certainty, lifecycle/loader stitching), load and follow:
45
+
46
+ - `_shared/unity-runtime-process-contract.md`
47
+
42
48
  ## Debugging Patterns
43
49
 
44
50
  | Symptom | GitNexus Approach |
@@ -39,6 +39,12 @@ description: "Use when the user asks how code works, wants to understand archite
39
39
  - [ ] Read source files for implementation details
40
40
  ```
41
41
 
42
+ ## Unity Runtime Process Trigger
43
+
44
+ When exploration touches Unity runtime process semantics (runtime chain closure, lifecycle/loader stitching, confidence-based closure), load and follow:
45
+
46
+ - `_shared/unity-runtime-process-contract.md`
47
+
42
48
  ## Resources
43
49
 
44
50
  | Resource | What you get |
@@ -56,6 +56,10 @@ Recommended default workflow:
56
56
  - `isComplete: true` → keep compact result
57
57
  3. Treat parity as the completeness path for advanced verification.
58
58
 
59
+ When task scope includes Unity runtime process semantics, load and follow:
60
+
61
+ - `_shared/unity-runtime-process-contract.md`
62
+
59
63
  ### Unity UI Trace Contract (`unity_ui_trace` / `gitnexus unity-ui-trace`)
60
64
 
61
65
  Input:
@@ -38,6 +38,12 @@ description: "Use when the user wants to know what will break if they change som
38
38
  - [ ] Assess risk level and report to user
39
39
  ```
40
40
 
41
+ ## Unity Runtime Process Trigger
42
+
43
+ When impact analysis depends on Unity runtime process closure or confidence interpretation, load and follow:
44
+
45
+ - `_shared/unity-runtime-process-contract.md`
46
+
41
47
  ## Understanding Output
42
48
 
43
49
  | Depth | Risk Level | Meaning |
@@ -28,6 +28,11 @@ description: "Use when the user wants to review a pull request, understand what
28
28
 
29
29
  > If "Index is stale" → run `gitnexus analyze` when local CLI exists; otherwise resolve the pinned npx package spec from `~/.gitnexus/config.json` and run `npx -y <resolved-cli-spec> analyze` before reviewing.
30
30
 
31
+ Conditional triggers:
32
+ - If analysis touches Unity serialized/binding-state interpretation, apply `_shared/unity-resource-binding-contract.md`.
33
+ - If analysis touches UIToolkit visual semantics, apply `_shared/unity-ui-trace-contract.md`.
34
+ - If analysis touches Unity runtime process semantics (runtime chain closure/confidence), apply `_shared/unity-runtime-process-contract.md`.
35
+
31
36
  ## Checklist
32
37
 
33
38
  ```