@veewo/gitnexus 1.5.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/dist/benchmark/agent-context/runner.js +3 -0
  2. package/dist/benchmark/agent-context/runner.test.js +22 -0
  3. package/dist/benchmark/agent-context/tool-runner.d.ts +7 -6
  4. package/dist/benchmark/agent-safe-query-context/io.d.ts +2 -0
  5. package/dist/benchmark/agent-safe-query-context/io.js +86 -0
  6. package/dist/benchmark/agent-safe-query-context/io.test.d.ts +1 -0
  7. package/dist/benchmark/agent-safe-query-context/io.test.js +13 -0
  8. package/dist/benchmark/agent-safe-query-context/report.d.ts +57 -0
  9. package/dist/benchmark/agent-safe-query-context/report.js +159 -0
  10. package/dist/benchmark/agent-safe-query-context/report.test.d.ts +1 -0
  11. package/dist/benchmark/agent-safe-query-context/report.test.js +362 -0
  12. package/dist/benchmark/agent-safe-query-context/runner.d.ts +44 -0
  13. package/dist/benchmark/agent-safe-query-context/runner.js +406 -0
  14. package/dist/benchmark/agent-safe-query-context/runner.test.d.ts +1 -0
  15. package/dist/benchmark/agent-safe-query-context/runner.test.js +290 -0
  16. package/dist/benchmark/agent-safe-query-context/semantic-tuple.d.ts +20 -0
  17. package/dist/benchmark/agent-safe-query-context/semantic-tuple.js +225 -0
  18. package/dist/benchmark/agent-safe-query-context/semantic-tuple.test.d.ts +1 -0
  19. package/dist/benchmark/agent-safe-query-context/semantic-tuple.test.js +122 -0
  20. package/dist/benchmark/agent-safe-query-context/subagent-live.d.ts +47 -0
  21. package/dist/benchmark/agent-safe-query-context/subagent-live.js +128 -0
  22. package/dist/benchmark/agent-safe-query-context/subagent-live.test.d.ts +1 -0
  23. package/dist/benchmark/agent-safe-query-context/subagent-live.test.js +155 -0
  24. package/dist/benchmark/agent-safe-query-context/telemetry-tool.d.ts +9 -0
  25. package/dist/benchmark/agent-safe-query-context/telemetry-tool.js +77 -0
  26. package/dist/benchmark/agent-safe-query-context/types.d.ts +61 -0
  27. package/dist/benchmark/agent-safe-query-context/types.js +8 -0
  28. package/dist/benchmark/runtime-poc/provenance-artifact.d.ts +47 -0
  29. package/dist/benchmark/runtime-poc/provenance-artifact.js +89 -0
  30. package/dist/benchmark/runtime-poc/runner.d.ts +31 -0
  31. package/dist/benchmark/runtime-poc/runner.js +163 -0
  32. package/dist/benchmark/u2-e2e/hydration-policy-repeatability-runner.d.ts +8 -0
  33. package/dist/benchmark/u2-e2e/hydration-policy-repeatability-runner.js +21 -0
  34. package/dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.d.ts +0 -1
  35. package/dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.js +53 -51
  36. package/dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.test.js +0 -1
  37. package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.d.ts +1 -1
  38. package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.js +82 -18
  39. package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.test.js +1 -2
  40. package/dist/benchmark/u2-e2e/retrieval-runner.js +15 -7
  41. package/dist/benchmark/u2-e2e/retrieval-runner.test.js +46 -0
  42. package/dist/cli/ai-context.js +2 -12
  43. package/dist/cli/ai-context.test.js +8 -0
  44. package/dist/cli/analyze-runtime-summary.js +1 -0
  45. package/dist/cli/analyze-runtime-summary.test.js +2 -0
  46. package/dist/cli/analyze-summary.d.ts +2 -0
  47. package/dist/cli/analyze-summary.js +24 -0
  48. package/dist/cli/analyze-summary.test.js +65 -1
  49. package/dist/cli/analyze.js +5 -1
  50. package/dist/cli/benchmark-agent-safe-query-context.d.ts +20 -0
  51. package/dist/cli/benchmark-agent-safe-query-context.js +39 -0
  52. package/dist/cli/benchmark-agent-safe-query-context.test.d.ts +1 -0
  53. package/dist/cli/benchmark-agent-safe-query-context.test.js +271 -0
  54. package/dist/cli/benchmark.d.ts +29 -0
  55. package/dist/cli/benchmark.js +55 -0
  56. package/dist/cli/index.js +23 -0
  57. package/dist/cli/rule-lab.d.ts +3 -7
  58. package/dist/cli/rule-lab.js +13 -22
  59. package/dist/cli/rule-lab.test.js +23 -3
  60. package/dist/cli/tool.d.ts +2 -0
  61. package/dist/cli/tool.js +2 -0
  62. package/dist/core/config/unity-config.d.ts +0 -1
  63. package/dist/core/config/unity-config.js +0 -1
  64. package/dist/core/ingestion/pipeline.js +35 -6
  65. package/dist/core/ingestion/unity-lifecycle-synthetic-calls.test.js +18 -20
  66. package/dist/core/ingestion/unity-parity-seed.d.ts +2 -1
  67. package/dist/core/ingestion/unity-parity-seed.js +8 -0
  68. package/dist/core/ingestion/unity-resource-processor.d.ts +11 -0
  69. package/dist/core/ingestion/unity-resource-processor.js +102 -0
  70. package/dist/core/ingestion/unity-resource-processor.test.js +449 -0
  71. package/dist/core/ingestion/unity-runtime-binding-rules.d.ts +15 -0
  72. package/dist/core/ingestion/unity-runtime-binding-rules.js +178 -30
  73. package/dist/core/lbug/csv-generator.test.js +2 -2
  74. package/dist/core/unity/doc-contract.test.d.ts +1 -0
  75. package/dist/core/unity/doc-contract.test.js +30 -0
  76. package/dist/core/unity/prefab-source-scan.d.ts +25 -0
  77. package/dist/core/unity/prefab-source-scan.js +152 -0
  78. package/dist/core/unity/prefab-source-scan.test.d.ts +1 -0
  79. package/dist/core/unity/prefab-source-scan.test.js +70 -0
  80. package/dist/core/unity/scan-context.d.ts +12 -0
  81. package/dist/core/unity/scan-context.js +50 -2
  82. package/dist/core/unity/scan-context.test.js +74 -0
  83. package/dist/mcp/local/agent-safe-response.d.ts +10 -0
  84. package/dist/mcp/local/agent-safe-response.js +639 -0
  85. package/dist/mcp/local/derived-process-reader.js +1 -1
  86. package/dist/mcp/local/local-backend.d.ts +18 -1
  87. package/dist/mcp/local/local-backend.js +319 -125
  88. package/dist/mcp/local/process-confidence.d.ts +1 -2
  89. package/dist/mcp/local/process-confidence.js +0 -3
  90. package/dist/mcp/local/process-confidence.test.js +4 -2
  91. package/dist/mcp/local/process-evidence.d.ts +1 -8
  92. package/dist/mcp/local/process-evidence.js +1 -23
  93. package/dist/mcp/local/process-evidence.test.js +2 -16
  94. package/dist/mcp/local/process-ref.d.ts +1 -1
  95. package/dist/mcp/local/runtime-chain-closure-evaluator.d.ts +33 -0
  96. package/dist/mcp/local/runtime-chain-closure-evaluator.js +273 -0
  97. package/dist/mcp/local/runtime-chain-graph-candidates.d.ts +23 -0
  98. package/dist/mcp/local/runtime-chain-graph-candidates.js +131 -0
  99. package/dist/mcp/local/runtime-chain-verify.d.ts +1 -1
  100. package/dist/mcp/local/runtime-chain-verify.js +149 -138
  101. package/dist/mcp/local/runtime-chain-verify.test.js +126 -68
  102. package/dist/mcp/local/runtime-claim-rule-registry.d.ts +4 -0
  103. package/dist/mcp/local/runtime-claim-rule-registry.js +4 -0
  104. package/dist/mcp/local/runtime-claim-rule-registry.test.js +37 -4
  105. package/dist/mcp/local/runtime-claim.d.ts +11 -0
  106. package/dist/mcp/local/runtime-claim.js +28 -0
  107. package/dist/mcp/local/unity-evidence-view.d.ts +1 -1
  108. package/dist/mcp/local/unity-evidence-view.js +1 -1
  109. package/dist/mcp/local/unity-evidence-view.test.js +22 -0
  110. package/dist/mcp/tools.js +51 -21
  111. package/dist/rule-lab/analyze.d.ts +2 -1
  112. package/dist/rule-lab/analyze.js +94 -59
  113. package/dist/rule-lab/analyze.test.js +238 -20
  114. package/dist/rule-lab/curate.d.ts +2 -1
  115. package/dist/rule-lab/curate.js +24 -3
  116. package/dist/rule-lab/curate.test.js +65 -0
  117. package/dist/rule-lab/curation-input-builder.d.ts +45 -0
  118. package/dist/rule-lab/curation-input-builder.js +133 -0
  119. package/dist/rule-lab/promote.js +80 -7
  120. package/dist/rule-lab/promote.test.js +150 -0
  121. package/dist/rule-lab/review-pack.d.ts +3 -0
  122. package/dist/rule-lab/review-pack.js +41 -1
  123. package/dist/rule-lab/review-pack.test.js +67 -0
  124. package/dist/rule-lab/types.d.ts +29 -0
  125. package/dist/types/pipeline.d.ts +3 -0
  126. package/package.json +3 -2
  127. package/scripts/run-node-tests.mjs +61 -0
  128. package/skills/_shared/unity-rule-authoring-contract.md +64 -0
  129. package/skills/_shared/unity-runtime-process-contract.md +16 -0
  130. package/skills/gitnexus-cli.md +8 -0
  131. package/skills/gitnexus-debugging.md +9 -0
  132. package/skills/gitnexus-exploring.md +66 -18
  133. package/skills/gitnexus-guide.md +42 -3
  134. package/skills/gitnexus-impact-analysis.md +8 -0
  135. package/skills/gitnexus-pr-review.md +8 -0
  136. package/skills/gitnexus-refactoring.md +8 -0
  137. package/skills/gitnexus-unity-rule-gen.md +66 -312
@@ -0,0 +1,639 @@
1
+ import path from 'node:path';
2
+ export function resolveResponseProfile(value) {
3
+ return String(value || '').trim().toLowerCase() === 'full' ? 'full' : 'slim';
4
+ }
5
+ export function buildSlimQueryResult(full, input) {
6
+ const strictAnchorMode = Boolean(full?.decision_context?.strict_anchor_mode);
7
+ const strictAnchorResourcePath = String(full?.decision_context?.anchor_resource_path || '').trim();
8
+ const candidates = buildCandidates(full, {
9
+ queryText: input.queryText,
10
+ });
11
+ const processHints = buildProcessHints(full.processes);
12
+ const resourceHints = buildResourceHints(full.next_hops);
13
+ const resourceChains = buildResourceChains(full.resource_chains);
14
+ const runtimePreview = buildRuntimePreview(full.runtime_claim);
15
+ const suggestedContextTargets = buildSuggestedContextTargets({
16
+ candidates,
17
+ processHints,
18
+ });
19
+ const upgradeHints = buildUpgradeHints({
20
+ mode: 'query',
21
+ nextHops: full.next_hops,
22
+ repoName: input.repoName,
23
+ subject: input.queryText,
24
+ suggestedContextTargets,
25
+ });
26
+ const missingProofTargets = buildMissingProofTargets({
27
+ resourceHints,
28
+ processHints,
29
+ runtimeClaim: full.runtime_claim,
30
+ });
31
+ const facts = {
32
+ candidates,
33
+ process_hints: processHints,
34
+ };
35
+ const closure = {
36
+ runtime_preview: runtimePreview,
37
+ missing_proof_targets: missingProofTargets,
38
+ resource_chains: resourceChains,
39
+ };
40
+ const clues = {
41
+ process_hints: [],
42
+ resource_hints: resourceHints,
43
+ };
44
+ const summary = chooseTopSummary({
45
+ candidates,
46
+ processHints,
47
+ runtimePreview,
48
+ fallback: String(candidates[0]?.name || 'no_match'),
49
+ strictAnchorMode,
50
+ });
51
+ const summarySource = inferSummarySource({
52
+ summary,
53
+ facts,
54
+ closure,
55
+ clues,
56
+ });
57
+ const semanticOrderPass = validateTierSemanticOrder({
58
+ summarySource,
59
+ facts,
60
+ });
61
+ return {
62
+ summary,
63
+ candidates,
64
+ process_hints: processHints,
65
+ resource_hints: resourceHints,
66
+ resource_chains: resourceChains,
67
+ facts,
68
+ closure,
69
+ clues,
70
+ tier_envelope: {
71
+ facts_present: true,
72
+ closure_present: true,
73
+ clues_present: true,
74
+ summary_source: summarySource,
75
+ semantic_order_pass: semanticOrderPass,
76
+ },
77
+ decision: {
78
+ primary_candidate: candidates[0]?.name || null,
79
+ recommended_follow_up: chooseRecommendedFollowUp({
80
+ upgradeHints,
81
+ strictAnchorMode,
82
+ strictAnchorResourcePath,
83
+ }),
84
+ response_profile: 'slim',
85
+ },
86
+ missing_proof_targets: missingProofTargets,
87
+ suggested_context_targets: suggestedContextTargets,
88
+ fallback_candidates: candidates.slice(1, 4),
89
+ upgrade_hints: upgradeHints,
90
+ runtime_preview: runtimePreview,
91
+ };
92
+ }
93
+ export function buildSlimContextResult(full, input) {
94
+ const strictAnchorMode = Boolean(full?.decision_context?.strict_anchor_mode);
95
+ const processHints = buildProcessHints(full.processes);
96
+ const resourceHints = buildResourceHints(full.next_hops);
97
+ const resourceChains = buildResourceChains(full.resource_chains);
98
+ const runtimePreview = buildRuntimePreview(full.runtime_claim);
99
+ const suggestedContextTargets = buildSuggestedContextTargets({
100
+ processHints,
101
+ symbolName: input.symbolName,
102
+ symbol: full.symbol,
103
+ });
104
+ const upgradeHints = buildUpgradeHints({
105
+ mode: 'context',
106
+ nextHops: full.next_hops,
107
+ repoName: input.repoName,
108
+ subject: input.symbolName,
109
+ suggestedContextTargets,
110
+ });
111
+ const missingProofTargets = buildMissingProofTargets({
112
+ resourceHints,
113
+ processHints,
114
+ runtimeClaim: full.runtime_claim,
115
+ });
116
+ const facts = {
117
+ symbol: full.symbol,
118
+ incoming: trimRelationBuckets(full.incoming),
119
+ outgoing: trimRelationBuckets(full.outgoing),
120
+ process_hints: processHints,
121
+ };
122
+ const closure = {
123
+ runtime_preview: runtimePreview,
124
+ missing_proof_targets: missingProofTargets,
125
+ resource_chains: resourceChains,
126
+ verification_hint: Array.isArray(full.processes)
127
+ ? full.processes.find((row) => row?.verification_hint)?.verification_hint
128
+ : undefined,
129
+ };
130
+ const clues = {
131
+ process_hints: [],
132
+ resource_hints: resourceHints,
133
+ };
134
+ const summary = chooseTopSummary({
135
+ processHints,
136
+ runtimePreview,
137
+ fallback: String(full?.symbol?.name || input.symbolName || 'no_match'),
138
+ strictAnchorMode,
139
+ });
140
+ const summarySource = inferSummarySource({
141
+ summary,
142
+ facts,
143
+ closure,
144
+ clues,
145
+ });
146
+ const semanticOrderPass = validateTierSemanticOrder({
147
+ summarySource,
148
+ facts,
149
+ });
150
+ return {
151
+ summary,
152
+ status: full.status,
153
+ symbol: full.symbol,
154
+ incoming: facts.incoming,
155
+ outgoing: facts.outgoing,
156
+ processes: processHints,
157
+ resource_hints: resourceHints,
158
+ resource_chains: resourceChains,
159
+ facts,
160
+ closure,
161
+ clues,
162
+ tier_envelope: {
163
+ facts_present: true,
164
+ closure_present: true,
165
+ clues_present: true,
166
+ summary_source: summarySource,
167
+ semantic_order_pass: semanticOrderPass,
168
+ },
169
+ missing_proof_targets: missingProofTargets,
170
+ suggested_context_targets: suggestedContextTargets,
171
+ verification_hint: closure.verification_hint,
172
+ upgrade_hints: upgradeHints,
173
+ runtime_preview: runtimePreview,
174
+ };
175
+ }
176
+ function inferSummarySource(input) {
177
+ const summary = String(input.summary || '').trim();
178
+ if (!summary)
179
+ return 'fallback';
180
+ const factCandidates = Array.isArray(input.facts.candidates) ? input.facts.candidates : [];
181
+ const factProcessHints = Array.isArray(input.facts.process_hints) ? input.facts.process_hints : [];
182
+ const clueProcessHints = Array.isArray(input.clues.process_hints) ? input.clues.process_hints : [];
183
+ const runtimePreview = input.closure.runtime_preview;
184
+ const runtimeStatus = String(runtimePreview?.status || '').trim();
185
+ if (factCandidates.some((row) => String(row?.name || '').trim() === summary)) {
186
+ return 'facts';
187
+ }
188
+ if (factProcessHints.some((row) => String(row?.summary || '').trim() === summary)) {
189
+ return 'facts';
190
+ }
191
+ if (runtimeStatus && runtimeStatus === summary) {
192
+ return 'closure';
193
+ }
194
+ if (clueProcessHints.some((row) => String(row?.summary || '').trim() === summary)) {
195
+ return 'clues';
196
+ }
197
+ return 'fallback';
198
+ }
199
+ function validateTierSemanticOrder(input) {
200
+ if (input.summarySource !== 'clues')
201
+ return true;
202
+ const factCandidates = Array.isArray(input.facts.candidates) ? input.facts.candidates : [];
203
+ if (factCandidates.length > 0)
204
+ return false;
205
+ const factProcessHints = Array.isArray(input.facts.process_hints) ? input.facts.process_hints : [];
206
+ if (factProcessHints.length === 0)
207
+ return true;
208
+ return !factProcessHints.some((row) => {
209
+ const confidence = String(row?.confidence || '').trim().toLowerCase();
210
+ return confidence === 'high' || confidence === 'medium';
211
+ });
212
+ }
213
+ function buildCandidates(full, input) {
214
+ const rows = [
215
+ ...(Array.isArray(full.process_symbols) ? full.process_symbols : []),
216
+ ...(Array.isArray(full.definitions) ? full.definitions : []),
217
+ ];
218
+ const preferredResourceTargets = extractPreferredResourceTargets(full.next_hops);
219
+ const seen = new Set();
220
+ const out = [];
221
+ for (const [index, row] of rows.entries()) {
222
+ const key = String(row?.id || `${row?.name}:${row?.filePath || ''}`);
223
+ if (!key || seen.has(key))
224
+ continue;
225
+ seen.add(key);
226
+ out.push({
227
+ score: scoreCandidateRow(row, {
228
+ queryText: input.queryText,
229
+ preferredResourceTargets,
230
+ }),
231
+ index,
232
+ candidate: {
233
+ id: row?.id,
234
+ name: row?.name,
235
+ kind: resolveCandidateKind(row),
236
+ filePath: row?.filePath,
237
+ module: row?.module,
238
+ },
239
+ });
240
+ }
241
+ return out
242
+ .sort((a, b) => (b.score - a.score) || (a.index - b.index))
243
+ .slice(0, 5)
244
+ .map((entry) => entry.candidate);
245
+ }
246
+ function scoreCandidateRow(row, input) {
247
+ const name = String(row?.name || '').trim();
248
+ const filePath = String(row?.filePath || '').trim();
249
+ const nameLower = name.toLowerCase();
250
+ const queryLower = String(input.queryText || '').trim().toLowerCase();
251
+ const fileBase = path.basename(filePath, path.extname(filePath)).toLowerCase();
252
+ const kind = resolveCandidateKind(row);
253
+ const exactLexicalMatch = Boolean(nameLower && queryLower.includes(nameLower));
254
+ const fileBaseMatch = Boolean(fileBase && fileBase === nameLower);
255
+ const kindBonus = (kind === 'Class' || kind === 'Interface' || kind === 'Struct') ? 8 : 0;
256
+ const classAnchorBonus = (kind === 'Class' && exactLexicalMatch) ? 18 : 0;
257
+ const lexicalBonus = exactLexicalMatch ? 80 : 0;
258
+ const fileAffinityBonus = (exactLexicalMatch && fileBaseMatch) ? 14 : 0;
259
+ const evidenceBonus = scoreEvidenceMode(String(row?.process_evidence_mode || ''));
260
+ const confidenceBonus = scoreConfidence(String(row?.process_confidence || ''));
261
+ const resourceAffinityBonus = hasPreferredResourceAffinity(row, input.preferredResourceTargets) ? 35 : 0;
262
+ return lexicalBonus
263
+ + fileAffinityBonus
264
+ + kindBonus
265
+ + classAnchorBonus
266
+ + resourceAffinityBonus
267
+ + evidenceBonus
268
+ + confidenceBonus;
269
+ }
270
+ function extractPreferredResourceTargets(nextHops) {
271
+ if (!Array.isArray(nextHops))
272
+ return [];
273
+ const targets = new Set();
274
+ for (const hop of nextHops) {
275
+ if (!hop || typeof hop !== 'object')
276
+ continue;
277
+ const kind = String(hop?.kind || '').trim();
278
+ if (kind !== 'resource' && kind !== 'verify')
279
+ continue;
280
+ const target = String(hop?.target || '').trim();
281
+ if (target)
282
+ targets.add(target);
283
+ }
284
+ return [...targets];
285
+ }
286
+ function hasPreferredResourceAffinity(row, preferredResourceTargets) {
287
+ if (preferredResourceTargets.length === 0)
288
+ return false;
289
+ const bindings = Array.isArray(row?.resourceBindings) ? row.resourceBindings : [];
290
+ const bindingSet = new Set(bindings
291
+ .map((binding) => String(binding?.resourcePath || '').trim())
292
+ .filter(Boolean));
293
+ return preferredResourceTargets.some((target) => bindingSet.has(target));
294
+ }
295
+ function scoreEvidenceMode(value) {
296
+ const normalized = String(value || '').trim();
297
+ if (normalized === 'direct_step')
298
+ return 18;
299
+ if (normalized === 'method_projected')
300
+ return 10;
301
+ return 0;
302
+ }
303
+ function scoreConfidence(value) {
304
+ const normalized = String(value || '').trim();
305
+ if (normalized === 'high')
306
+ return 18;
307
+ if (normalized === 'medium')
308
+ return 8;
309
+ if (normalized === 'low')
310
+ return -8;
311
+ return 0;
312
+ }
313
+ function resolveCandidateKind(row) {
314
+ const explicit = String(row?.type || row?.kind || '').trim();
315
+ if (explicit)
316
+ return explicit;
317
+ const id = String(row?.id || '').trim();
318
+ if (!id.includes(':'))
319
+ return undefined;
320
+ return id.split(':', 1)[0] || undefined;
321
+ }
322
+ function buildProcessHints(processes) {
323
+ if (!Array.isArray(processes))
324
+ return [];
325
+ const scored = processes.map((row, index) => {
326
+ const hint = {
327
+ id: row?.id,
328
+ summary: row?.summary || row?.name,
329
+ confidence: row?.confidence || row?.process_confidence,
330
+ process_subtype: row?.process_subtype,
331
+ evidence_mode: row?.evidence_mode || row?.process_evidence_mode,
332
+ verification_hint: row?.verification_hint,
333
+ };
334
+ return {
335
+ hint,
336
+ index,
337
+ score: scoreProcessHint(hint),
338
+ };
339
+ });
340
+ return scored
341
+ .sort((a, b) => (b.score - a.score) || (a.index - b.index))
342
+ .slice(0, 5)
343
+ .map((entry) => entry.hint);
344
+ }
345
+ function scoreProcessHint(hint) {
346
+ if (!hint)
347
+ return Number.NEGATIVE_INFINITY;
348
+ const evidenceMode = String(hint?.evidence_mode || '').trim();
349
+ const confidence = String(hint?.confidence || '').trim();
350
+ let score = 0;
351
+ if (evidenceMode === 'direct_step')
352
+ score += 60;
353
+ else if (evidenceMode === 'method_projected')
354
+ score += 40;
355
+ else
356
+ score += 20;
357
+ if (confidence === 'high')
358
+ score += 20;
359
+ else if (confidence === 'medium')
360
+ score += 10;
361
+ else if (confidence === 'low')
362
+ score -= 10;
363
+ return score;
364
+ }
365
+ function chooseTopSummary(input) {
366
+ const processHints = Array.isArray(input.processHints) ? input.processHints : [];
367
+ const topProcess = processHints[0];
368
+ const topProcessSummary = String(topProcess?.summary || '').trim();
369
+ const topProcessScore = scoreProcessHint(topProcess);
370
+ const candidateName = String(input.candidates?.[0]?.name || '').trim();
371
+ const candidateScore = candidateName ? 45 : Number.NEGATIVE_INFINITY;
372
+ if (topProcessSummary && topProcessScore >= candidateScore) {
373
+ return topProcessSummary;
374
+ }
375
+ if (candidateName && candidateScore > topProcessScore) {
376
+ return candidateName;
377
+ }
378
+ if (topProcessSummary) {
379
+ return topProcessSummary;
380
+ }
381
+ const runtimeStatus = String(input.runtimePreview?.status || '').trim();
382
+ if (runtimeStatus) {
383
+ return runtimeStatus;
384
+ }
385
+ return input.fallback;
386
+ }
387
+ function buildResourceHints(nextHops) {
388
+ if (!Array.isArray(nextHops))
389
+ return [];
390
+ return nextHops
391
+ .filter((hop) => hop?.kind === 'resource' || hop?.kind === 'verify')
392
+ .slice(0, 5)
393
+ .map((hop) => ({
394
+ kind: hop.kind,
395
+ target: hop.target,
396
+ why: hop.why,
397
+ next_command: hop.next_command,
398
+ }));
399
+ }
400
+ function buildResourceChains(resourceChains) {
401
+ if (!Array.isArray(resourceChains))
402
+ return [];
403
+ return resourceChains
404
+ .slice(0, 5)
405
+ .map((chain) => ({
406
+ sourceResourcePath: chain?.sourceResourcePath,
407
+ relationType: chain?.relationType,
408
+ intermediateResourcePath: chain?.intermediateResourcePath,
409
+ nextRelationType: chain?.nextRelationType,
410
+ targetSymbol: chain?.targetSymbol && typeof chain.targetSymbol === 'object'
411
+ ? {
412
+ uid: chain.targetSymbol.uid,
413
+ name: chain.targetSymbol.name,
414
+ kind: chain.targetSymbol.kind,
415
+ filePath: chain.targetSymbol.filePath,
416
+ }
417
+ : undefined,
418
+ }))
419
+ .filter((chain) => Boolean(chain.sourceResourcePath && chain.intermediateResourcePath && chain.targetSymbol));
420
+ }
421
+ function buildUpgradeHints(input) {
422
+ const repoArg = input.repoName ? ` --repo "${input.repoName}"` : '';
423
+ const subject = String(input.subject || '').trim();
424
+ const fullCommand = input.mode === 'query'
425
+ ? `gitnexus query${repoArg} --response-profile full "${subject}"`
426
+ : `gitnexus context${repoArg} --response-profile full "${subject}"`;
427
+ const hints = [];
428
+ if (Array.isArray(input.nextHops)) {
429
+ for (const hop of input.nextHops.slice(0, 4)) {
430
+ const paramDelta = inferParamDelta(hop);
431
+ hints.push({
432
+ kind: hop.kind,
433
+ target: hop.target,
434
+ why: hop.why,
435
+ param_delta: paramDelta,
436
+ next_command: resolveNarrowNextCommand({
437
+ mode: input.mode,
438
+ repoArg,
439
+ subject,
440
+ hop,
441
+ paramDelta,
442
+ }),
443
+ });
444
+ }
445
+ }
446
+ if (Array.isArray(input.suggestedContextTargets)) {
447
+ for (const target of input.suggestedContextTargets.slice(0, 3)) {
448
+ const uid = String(target?.uid || '').trim();
449
+ if (!uid)
450
+ continue;
451
+ const filePath = String(target?.filePath || '').trim();
452
+ hints.push({
453
+ kind: 'symbol',
454
+ target: target?.name,
455
+ why: target?.why || 'Use the exact symbol UID to avoid same-name ambiguity.',
456
+ param_delta: `uid=${uid}`,
457
+ next_command: `gitnexus context${repoArg} --uid "${uid}"${filePath ? ` --file "${filePath}"` : ''}`,
458
+ });
459
+ }
460
+ }
461
+ hints.push({
462
+ kind: 'full',
463
+ target: input.mode,
464
+ why: 'Expand back to the legacy heavy payload when deeper evidence is required.',
465
+ param_delta: 'response_profile=full',
466
+ next_command: fullCommand,
467
+ });
468
+ return hints;
469
+ }
470
+ function inferParamDelta(hop) {
471
+ if (hop?.kind === 'resource' && hop?.target) {
472
+ return `resource_path_prefix=${hop.target}`;
473
+ }
474
+ if (hop?.kind === 'symbol' && hop?.target) {
475
+ return `name=${hop.target}`;
476
+ }
477
+ return 'follow_next_hop';
478
+ }
479
+ function resolveNarrowNextCommand(input) {
480
+ if (input.paramDelta.startsWith('resource_path_prefix=')) {
481
+ const target = String(input.hop?.target || '').trim();
482
+ if (!target)
483
+ return input.hop?.next_command || null;
484
+ return `gitnexus query${input.repoArg} "${input.subject}" # resource_path_prefix=${target}`;
485
+ }
486
+ if (input.paramDelta.startsWith('name=')) {
487
+ const target = String(input.hop?.target || '').trim();
488
+ if (!target)
489
+ return input.hop?.next_command || null;
490
+ return `gitnexus context${input.repoArg} "${target}"`;
491
+ }
492
+ return input.hop?.next_command || null;
493
+ }
494
+ function chooseRecommendedFollowUp(input) {
495
+ const strictAnchorMode = Boolean(input.strictAnchorMode);
496
+ const strictAnchorResourcePath = String(input.strictAnchorResourcePath || '').trim();
497
+ if (strictAnchorMode && strictAnchorResourcePath) {
498
+ return `resource_path_prefix=${strictAnchorResourcePath}`;
499
+ }
500
+ const upgradeHints = input.upgradeHints;
501
+ if (!Array.isArray(upgradeHints) || upgradeHints.length === 0) {
502
+ return null;
503
+ }
504
+ const ranked = upgradeHints
505
+ .filter((hint) => hint?.kind !== 'full')
506
+ .map((hint, index) => ({
507
+ hint,
508
+ index,
509
+ score: scoreRecommendedFollowUpHint({
510
+ hint,
511
+ strictAnchorMode,
512
+ }),
513
+ }))
514
+ .filter((entry) => entry.score > Number.NEGATIVE_INFINITY)
515
+ .sort((a, b) => (b.score - a.score) || (a.index - b.index));
516
+ const selected = ranked[0]?.hint;
517
+ if (selected) {
518
+ return String(selected.param_delta || selected.next_command || '') || null;
519
+ }
520
+ return String(upgradeHints[0]?.next_command || upgradeHints[0]?.param_delta || '') || null;
521
+ }
522
+ function scoreRecommendedFollowUpHint(input) {
523
+ const hint = input.hint;
524
+ const paramDelta = String(hint?.param_delta || '').trim();
525
+ const nextCommand = String(hint?.next_command || '').trim();
526
+ if (input.strictAnchorMode && paramDelta === 'follow_next_hop')
527
+ return Number.NEGATIVE_INFINITY;
528
+ if (paramDelta.startsWith('resource_path_prefix='))
529
+ return 40;
530
+ if (paramDelta.startsWith('uid='))
531
+ return 30;
532
+ if (paramDelta.startsWith('name='))
533
+ return 20;
534
+ if (paramDelta === 'follow_next_hop')
535
+ return Number.NEGATIVE_INFINITY;
536
+ if (nextCommand)
537
+ return 5;
538
+ return Number.NEGATIVE_INFINITY;
539
+ }
540
+ function buildMissingProofTargets(input) {
541
+ const targets = new Set();
542
+ for (const hint of input.resourceHints) {
543
+ if (typeof hint.target === 'string' && hint.target.trim()) {
544
+ targets.add(`resource:${hint.target.trim()}`);
545
+ }
546
+ }
547
+ for (const process of input.processHints) {
548
+ const verification = process?.verification_hint;
549
+ const target = typeof verification?.target === 'string' ? verification.target.trim() : '';
550
+ if (target) {
551
+ targets.add(`symbol:${target}`);
552
+ }
553
+ }
554
+ const runtimeReason = String(input.runtimeClaim?.reason || '');
555
+ if (runtimeReason.includes('evidence_missing')) {
556
+ targets.add('telemetry:evidence_rows');
557
+ }
558
+ return [...targets].slice(0, 5);
559
+ }
560
+ function buildSuggestedContextTargets(input) {
561
+ const targets = new Map();
562
+ const addTarget = (target) => {
563
+ const name = String(target.name || '').trim();
564
+ if (!name)
565
+ return;
566
+ const uid = String(target.uid || '').trim();
567
+ const filePath = String(target.filePath || '').trim();
568
+ const key = uid || `${name}:${filePath}`;
569
+ if (!key || targets.has(key))
570
+ return;
571
+ targets.set(key, {
572
+ name,
573
+ ...(uid ? { uid } : {}),
574
+ ...(filePath ? { filePath } : {}),
575
+ why: target.why,
576
+ });
577
+ };
578
+ if (Array.isArray(input.candidates)) {
579
+ for (const candidate of input.candidates) {
580
+ addTarget({
581
+ name: candidate?.name,
582
+ uid: candidate?.id,
583
+ filePath: candidate?.filePath,
584
+ why: 'Query returned this ranked symbol candidate for direct context disambiguation.',
585
+ });
586
+ }
587
+ }
588
+ if (input.symbol && typeof input.symbol === 'object') {
589
+ addTarget({
590
+ name: input.symbol.name,
591
+ uid: input.symbol.uid,
592
+ filePath: input.symbol.filePath,
593
+ why: 'Current context symbol can be revisited via exact UID to avoid same-name ambiguity.',
594
+ });
595
+ }
596
+ for (const process of input.processHints) {
597
+ const verification = process?.verification_hint;
598
+ const target = typeof verification?.target === 'string' ? verification.target.trim() : '';
599
+ if (target) {
600
+ addTarget({
601
+ name: target,
602
+ why: 'Verification guidance references this symbol as the next disambiguation target.',
603
+ });
604
+ }
605
+ }
606
+ if (input.symbolName?.trim()) {
607
+ addTarget({
608
+ name: input.symbolName.trim(),
609
+ why: 'Current symbol name remains available as a fallback context target.',
610
+ });
611
+ }
612
+ return [...targets.values()].slice(0, 5);
613
+ }
614
+ function buildRuntimePreview(runtimeClaim) {
615
+ if (!runtimeClaim || typeof runtimeClaim !== 'object')
616
+ return undefined;
617
+ return {
618
+ status: runtimeClaim.status,
619
+ evidence_level: runtimeClaim.evidence_level,
620
+ reason: runtimeClaim.reason,
621
+ next_action: runtimeClaim.next_action,
622
+ };
623
+ }
624
+ function trimRelationBuckets(buckets) {
625
+ if (!buckets || typeof buckets !== 'object')
626
+ return {};
627
+ const out = {};
628
+ for (const [key, rows] of Object.entries(buckets)) {
629
+ if (!Array.isArray(rows))
630
+ continue;
631
+ out[key] = rows.slice(0, 10).map((row) => ({
632
+ uid: row?.uid,
633
+ name: row?.name,
634
+ filePath: row?.filePath,
635
+ kind: row?.kind,
636
+ }));
637
+ }
638
+ return out;
639
+ }
@@ -6,7 +6,7 @@ export async function getDerivedProcessDetailResource(id, _backend, repoName) {
6
6
  const lines = [
7
7
  `id: "${normalizedId}"`,
8
8
  'kind: derived',
9
- 'origin: resource_heuristic',
9
+ 'origin: method_projected',
10
10
  `reader_uri: "gitnexus://repo/${encodeURIComponent(String(repoName || ''))}/derived-process/${encodeURIComponent(normalizedId)}"`,
11
11
  'readable: true',
12
12
  'note: "Derived process references are synthesized at query/context runtime from symbol + evidence fingerprints."',
@@ -25,6 +25,16 @@ export interface ExpandedSymbolCandidate {
25
25
  }
26
26
  export declare function parseResourceSeedMode(raw: unknown): ResourceSeedMode;
27
27
  export declare function extractUnityResourcePaths(text: string): string[];
28
+ export declare function computeVerifierMinimumEvidenceSatisfied(input: {
29
+ evidenceMetaRows: Array<{
30
+ verifier_minimum_evidence_satisfied?: boolean;
31
+ minimum_evidence_satisfied?: boolean;
32
+ truncated?: boolean;
33
+ filter_exhausted?: boolean;
34
+ }>;
35
+ truncated: boolean;
36
+ filterExhausted: boolean;
37
+ }): boolean;
28
38
  export declare function resolveSeedPath(input: {
29
39
  queryText?: string;
30
40
  resourcePathPrefix?: string;
@@ -48,6 +58,14 @@ export declare function pickVerificationTarget(input: {
48
58
  resourceBindings: ResolvedUnityBinding[];
49
59
  fallback: string;
50
60
  }): string;
61
+ export declare function pickVerifierSymbolAnchor(input: {
62
+ queryText?: string;
63
+ processSymbols: any[];
64
+ definitions: any[];
65
+ }): {
66
+ symbolName?: string;
67
+ symbolFilePath?: string;
68
+ };
51
69
  export declare function buildNextHops(input: {
52
70
  seedPath?: string;
53
71
  mappedSeedTargets: string[];
@@ -160,7 +178,6 @@ export declare class LocalBackend {
160
178
  }>>;
161
179
  callTool(method: string, params: any): Promise<any>;
162
180
  private unityUiTrace;
163
- private ruleLabDiscover;
164
181
  private ruleLabAnalyze;
165
182
  private ruleLabReviewPack;
166
183
  private ruleLabCurate;