@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.
- package/dist/benchmark/agent-context/runner.js +3 -0
- package/dist/benchmark/agent-context/runner.test.js +22 -0
- package/dist/benchmark/agent-context/tool-runner.d.ts +7 -6
- package/dist/benchmark/agent-safe-query-context/io.d.ts +2 -0
- package/dist/benchmark/agent-safe-query-context/io.js +86 -0
- package/dist/benchmark/agent-safe-query-context/io.test.d.ts +1 -0
- package/dist/benchmark/agent-safe-query-context/io.test.js +13 -0
- package/dist/benchmark/agent-safe-query-context/report.d.ts +57 -0
- package/dist/benchmark/agent-safe-query-context/report.js +159 -0
- package/dist/benchmark/agent-safe-query-context/report.test.d.ts +1 -0
- package/dist/benchmark/agent-safe-query-context/report.test.js +362 -0
- package/dist/benchmark/agent-safe-query-context/runner.d.ts +44 -0
- package/dist/benchmark/agent-safe-query-context/runner.js +406 -0
- package/dist/benchmark/agent-safe-query-context/runner.test.d.ts +1 -0
- package/dist/benchmark/agent-safe-query-context/runner.test.js +290 -0
- package/dist/benchmark/agent-safe-query-context/semantic-tuple.d.ts +20 -0
- package/dist/benchmark/agent-safe-query-context/semantic-tuple.js +225 -0
- package/dist/benchmark/agent-safe-query-context/semantic-tuple.test.d.ts +1 -0
- package/dist/benchmark/agent-safe-query-context/semantic-tuple.test.js +122 -0
- package/dist/benchmark/agent-safe-query-context/subagent-live.d.ts +47 -0
- package/dist/benchmark/agent-safe-query-context/subagent-live.js +128 -0
- package/dist/benchmark/agent-safe-query-context/subagent-live.test.d.ts +1 -0
- package/dist/benchmark/agent-safe-query-context/subagent-live.test.js +155 -0
- package/dist/benchmark/agent-safe-query-context/telemetry-tool.d.ts +9 -0
- package/dist/benchmark/agent-safe-query-context/telemetry-tool.js +77 -0
- package/dist/benchmark/agent-safe-query-context/types.d.ts +61 -0
- package/dist/benchmark/agent-safe-query-context/types.js +8 -0
- package/dist/benchmark/runtime-poc/provenance-artifact.d.ts +47 -0
- package/dist/benchmark/runtime-poc/provenance-artifact.js +89 -0
- package/dist/benchmark/runtime-poc/runner.d.ts +31 -0
- package/dist/benchmark/runtime-poc/runner.js +163 -0
- package/dist/benchmark/u2-e2e/hydration-policy-repeatability-runner.d.ts +8 -0
- package/dist/benchmark/u2-e2e/hydration-policy-repeatability-runner.js +21 -0
- package/dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.d.ts +0 -1
- package/dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.js +53 -51
- package/dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.test.js +0 -1
- package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.d.ts +1 -1
- package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.js +82 -18
- package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.test.js +1 -2
- package/dist/benchmark/u2-e2e/retrieval-runner.js +15 -7
- package/dist/benchmark/u2-e2e/retrieval-runner.test.js +46 -0
- package/dist/cli/ai-context.js +2 -12
- package/dist/cli/ai-context.test.js +8 -0
- package/dist/cli/analyze-runtime-summary.js +1 -0
- package/dist/cli/analyze-runtime-summary.test.js +2 -0
- package/dist/cli/analyze-summary.d.ts +2 -0
- package/dist/cli/analyze-summary.js +24 -0
- package/dist/cli/analyze-summary.test.js +65 -1
- package/dist/cli/analyze.js +5 -1
- package/dist/cli/benchmark-agent-safe-query-context.d.ts +20 -0
- package/dist/cli/benchmark-agent-safe-query-context.js +39 -0
- package/dist/cli/benchmark-agent-safe-query-context.test.d.ts +1 -0
- package/dist/cli/benchmark-agent-safe-query-context.test.js +271 -0
- package/dist/cli/benchmark.d.ts +29 -0
- package/dist/cli/benchmark.js +55 -0
- package/dist/cli/index.js +23 -0
- package/dist/cli/rule-lab.d.ts +3 -7
- package/dist/cli/rule-lab.js +13 -22
- package/dist/cli/rule-lab.test.js +23 -3
- package/dist/cli/tool.d.ts +2 -0
- package/dist/cli/tool.js +2 -0
- package/dist/core/config/unity-config.d.ts +0 -1
- package/dist/core/config/unity-config.js +0 -1
- package/dist/core/ingestion/pipeline.js +35 -6
- package/dist/core/ingestion/unity-lifecycle-synthetic-calls.test.js +18 -20
- package/dist/core/ingestion/unity-parity-seed.d.ts +2 -1
- package/dist/core/ingestion/unity-parity-seed.js +8 -0
- package/dist/core/ingestion/unity-resource-processor.d.ts +11 -0
- package/dist/core/ingestion/unity-resource-processor.js +102 -0
- package/dist/core/ingestion/unity-resource-processor.test.js +449 -0
- package/dist/core/ingestion/unity-runtime-binding-rules.d.ts +15 -0
- package/dist/core/ingestion/unity-runtime-binding-rules.js +178 -30
- package/dist/core/lbug/csv-generator.test.js +2 -2
- package/dist/core/unity/doc-contract.test.d.ts +1 -0
- package/dist/core/unity/doc-contract.test.js +30 -0
- package/dist/core/unity/prefab-source-scan.d.ts +25 -0
- package/dist/core/unity/prefab-source-scan.js +152 -0
- package/dist/core/unity/prefab-source-scan.test.d.ts +1 -0
- package/dist/core/unity/prefab-source-scan.test.js +70 -0
- package/dist/core/unity/scan-context.d.ts +12 -0
- package/dist/core/unity/scan-context.js +50 -2
- package/dist/core/unity/scan-context.test.js +74 -0
- package/dist/mcp/local/agent-safe-response.d.ts +10 -0
- package/dist/mcp/local/agent-safe-response.js +639 -0
- package/dist/mcp/local/derived-process-reader.js +1 -1
- package/dist/mcp/local/local-backend.d.ts +18 -1
- package/dist/mcp/local/local-backend.js +319 -125
- package/dist/mcp/local/process-confidence.d.ts +1 -2
- package/dist/mcp/local/process-confidence.js +0 -3
- package/dist/mcp/local/process-confidence.test.js +4 -2
- package/dist/mcp/local/process-evidence.d.ts +1 -8
- package/dist/mcp/local/process-evidence.js +1 -23
- package/dist/mcp/local/process-evidence.test.js +2 -16
- package/dist/mcp/local/process-ref.d.ts +1 -1
- package/dist/mcp/local/runtime-chain-closure-evaluator.d.ts +33 -0
- package/dist/mcp/local/runtime-chain-closure-evaluator.js +273 -0
- package/dist/mcp/local/runtime-chain-graph-candidates.d.ts +23 -0
- package/dist/mcp/local/runtime-chain-graph-candidates.js +131 -0
- package/dist/mcp/local/runtime-chain-verify.d.ts +1 -1
- package/dist/mcp/local/runtime-chain-verify.js +149 -138
- package/dist/mcp/local/runtime-chain-verify.test.js +126 -68
- package/dist/mcp/local/runtime-claim-rule-registry.d.ts +4 -0
- package/dist/mcp/local/runtime-claim-rule-registry.js +4 -0
- package/dist/mcp/local/runtime-claim-rule-registry.test.js +37 -4
- package/dist/mcp/local/runtime-claim.d.ts +11 -0
- package/dist/mcp/local/runtime-claim.js +28 -0
- package/dist/mcp/local/unity-evidence-view.d.ts +1 -1
- package/dist/mcp/local/unity-evidence-view.js +1 -1
- package/dist/mcp/local/unity-evidence-view.test.js +22 -0
- package/dist/mcp/tools.js +51 -21
- package/dist/rule-lab/analyze.d.ts +2 -1
- package/dist/rule-lab/analyze.js +94 -59
- package/dist/rule-lab/analyze.test.js +238 -20
- package/dist/rule-lab/curate.d.ts +2 -1
- package/dist/rule-lab/curate.js +24 -3
- package/dist/rule-lab/curate.test.js +65 -0
- package/dist/rule-lab/curation-input-builder.d.ts +45 -0
- package/dist/rule-lab/curation-input-builder.js +133 -0
- package/dist/rule-lab/promote.js +80 -7
- package/dist/rule-lab/promote.test.js +150 -0
- package/dist/rule-lab/review-pack.d.ts +3 -0
- package/dist/rule-lab/review-pack.js +41 -1
- package/dist/rule-lab/review-pack.test.js +67 -0
- package/dist/rule-lab/types.d.ts +29 -0
- package/dist/types/pipeline.d.ts +3 -0
- package/package.json +3 -2
- package/scripts/run-node-tests.mjs +61 -0
- package/skills/_shared/unity-rule-authoring-contract.md +64 -0
- package/skills/_shared/unity-runtime-process-contract.md +16 -0
- package/skills/gitnexus-cli.md +8 -0
- package/skills/gitnexus-debugging.md +9 -0
- package/skills/gitnexus-exploring.md +66 -18
- package/skills/gitnexus-guide.md +42 -3
- package/skills/gitnexus-impact-analysis.md +8 -0
- package/skills/gitnexus-pr-review.md +8 -0
- package/skills/gitnexus-refactoring.md +8 -0
- 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:
|
|
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;
|