@probelabs/visor 0.1.148 → 0.1.149
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/defaults/assistant.yaml +2141 -0
- package/defaults/code-talk.yaml +1250 -0
- package/defaults/intent-router.yaml +478 -0
- package/dist/defaults/assistant.yaml +2141 -0
- package/dist/defaults/code-talk.yaml +1250 -0
- package/dist/defaults/intent-router.yaml +478 -0
- package/dist/index.js +17 -4
- package/dist/output/traces/{run-2026-03-02T18-32-11-359Z.ndjson → run-2026-03-03T07-19-07-543Z.ndjson} +84 -84
- package/dist/{traces/run-2026-03-02T18-32-55-702Z.ndjson → output/traces/run-2026-03-03T07-19-50-933Z.ndjson} +1866 -1187
- package/dist/sdk/{check-provider-registry-35BPTY4W.mjs → check-provider-registry-IYSUDKPB.mjs} +7 -7
- package/dist/sdk/{check-provider-registry-DVQDGTOE.mjs → check-provider-registry-LVLC4EPF.mjs} +4 -4
- package/dist/sdk/{check-provider-registry-KHPY6LB4.mjs → check-provider-registry-X4OZJWPK.mjs} +4 -4
- package/dist/sdk/{chunk-6N6JRWCW.mjs → chunk-6EXCUX7Y.mjs} +10 -10
- package/dist/sdk/{chunk-S2YO4ZE3.mjs → chunk-BR7DYA3S.mjs} +2 -2
- package/dist/sdk/{chunk-DIND4ZCV.mjs → chunk-DNDS7R3N.mjs} +11 -1
- package/dist/sdk/{chunk-DIND4ZCV.mjs.map → chunk-DNDS7R3N.mjs.map} +1 -1
- package/dist/sdk/{chunk-IF2UD2KS.mjs → chunk-GFNXX64M.mjs} +18 -18
- package/dist/sdk/{chunk-AYQE4JCU.mjs → chunk-Q6EPAJ6Z.mjs} +3 -3
- package/dist/sdk/{chunk-H4AYMOAT.mjs → chunk-V6GI4U2M.mjs} +10 -10
- package/dist/sdk/{chunk-EGUHXVWS.mjs → chunk-VLUGLWLA.mjs} +2 -2
- package/dist/sdk/{chunk-EGUHXVWS.mjs.map → chunk-VLUGLWLA.mjs.map} +1 -1
- package/dist/sdk/{chunk-XNTBSV6M.mjs → chunk-YYZAN5NK.mjs} +3 -3
- package/dist/sdk/{config-G5UU4WXT.mjs → config-KQH254CA.mjs} +2 -2
- package/dist/sdk/{failure-condition-evaluator-I6QWFKV3.mjs → failure-condition-evaluator-LZ2AG5PY.mjs} +3 -3
- package/dist/sdk/{github-frontend-2MC77L7F.mjs → github-frontend-S523EEJB.mjs} +3 -3
- package/dist/sdk/{host-4F6I3ZXN.mjs → host-7YKRMOUJ.mjs} +2 -2
- package/dist/sdk/{routing-UT3BXBXH.mjs → routing-ZMBKWMVI.mjs} +4 -4
- package/dist/sdk/{schedule-tool-K3GQXCBN.mjs → schedule-tool-CDVUSZEG.mjs} +7 -7
- package/dist/sdk/{schedule-tool-SBXAEBDD.mjs → schedule-tool-EOMZFICZ.mjs} +4 -4
- package/dist/sdk/{schedule-tool-CONR4VW3.mjs → schedule-tool-NX75VKGA.mjs} +4 -4
- package/dist/sdk/{schedule-tool-handler-GFQCJAVZ.mjs → schedule-tool-handler-3FJHDIPG.mjs} +7 -7
- package/dist/sdk/{schedule-tool-handler-R7PG3VMR.mjs → schedule-tool-handler-KKN7XJYT.mjs} +4 -4
- package/dist/sdk/{schedule-tool-handler-YUC6CAXX.mjs → schedule-tool-handler-QNZG55DX.mjs} +4 -4
- package/dist/sdk/sdk.js +11 -1
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +6 -6
- package/dist/sdk/{trace-helpers-J463EU4B.mjs → trace-helpers-EJUIOP6L.mjs} +2 -2
- package/dist/sdk/{workflow-check-provider-GJNGTS3F.mjs → workflow-check-provider-6ERNNCNA.mjs} +7 -7
- package/dist/sdk/{workflow-check-provider-DYSO3PML.mjs → workflow-check-provider-AGZ5JY2I.mjs} +4 -4
- package/dist/sdk/{workflow-check-provider-FIFFQDQU.mjs → workflow-check-provider-PTNUWM5W.mjs} +4 -4
- package/dist/sdk/{workflow-registry-AAD37XKZ.mjs → workflow-registry-MHUSKSD6.mjs} +2 -2
- package/dist/traces/{run-2026-03-02T18-32-11-359Z.ndjson → run-2026-03-03T07-19-07-543Z.ndjson} +84 -84
- package/dist/{output/traces/run-2026-03-02T18-32-55-702Z.ndjson → traces/run-2026-03-03T07-19-50-933Z.ndjson} +1866 -1187
- package/dist/workflow-registry.d.ts.map +1 -1
- package/package.json +1 -1
- /package/dist/sdk/{check-provider-registry-35BPTY4W.mjs.map → check-provider-registry-IYSUDKPB.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-DVQDGTOE.mjs.map → check-provider-registry-LVLC4EPF.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-KHPY6LB4.mjs.map → check-provider-registry-X4OZJWPK.mjs.map} +0 -0
- /package/dist/sdk/{chunk-6N6JRWCW.mjs.map → chunk-6EXCUX7Y.mjs.map} +0 -0
- /package/dist/sdk/{chunk-S2YO4ZE3.mjs.map → chunk-BR7DYA3S.mjs.map} +0 -0
- /package/dist/sdk/{chunk-IF2UD2KS.mjs.map → chunk-GFNXX64M.mjs.map} +0 -0
- /package/dist/sdk/{chunk-AYQE4JCU.mjs.map → chunk-Q6EPAJ6Z.mjs.map} +0 -0
- /package/dist/sdk/{chunk-H4AYMOAT.mjs.map → chunk-V6GI4U2M.mjs.map} +0 -0
- /package/dist/sdk/{chunk-XNTBSV6M.mjs.map → chunk-YYZAN5NK.mjs.map} +0 -0
- /package/dist/sdk/{config-G5UU4WXT.mjs.map → config-KQH254CA.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-I6QWFKV3.mjs.map → failure-condition-evaluator-LZ2AG5PY.mjs.map} +0 -0
- /package/dist/sdk/{github-frontend-2MC77L7F.mjs.map → github-frontend-S523EEJB.mjs.map} +0 -0
- /package/dist/sdk/{host-4F6I3ZXN.mjs.map → host-7YKRMOUJ.mjs.map} +0 -0
- /package/dist/sdk/{routing-UT3BXBXH.mjs.map → routing-ZMBKWMVI.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-CONR4VW3.mjs.map → schedule-tool-CDVUSZEG.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-K3GQXCBN.mjs.map → schedule-tool-EOMZFICZ.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-SBXAEBDD.mjs.map → schedule-tool-NX75VKGA.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-GFQCJAVZ.mjs.map → schedule-tool-handler-3FJHDIPG.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-R7PG3VMR.mjs.map → schedule-tool-handler-KKN7XJYT.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-YUC6CAXX.mjs.map → schedule-tool-handler-QNZG55DX.mjs.map} +0 -0
- /package/dist/sdk/{trace-helpers-J463EU4B.mjs.map → trace-helpers-EJUIOP6L.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-DYSO3PML.mjs.map → workflow-check-provider-6ERNNCNA.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-FIFFQDQU.mjs.map → workflow-check-provider-AGZ5JY2I.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-GJNGTS3F.mjs.map → workflow-check-provider-PTNUWM5W.mjs.map} +0 -0
- /package/dist/sdk/{workflow-registry-AAD37XKZ.mjs.map → workflow-registry-MHUSKSD6.mjs.map} +0 -0
|
@@ -0,0 +1,1250 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# code-talk: Reusable workflow for AI-powered code exploration
|
|
3
|
+
# =============================================================================
|
|
4
|
+
#
|
|
5
|
+
# A battle-tested workflow for answering code questions across multiple
|
|
6
|
+
# repositories with architecture-aware routing.
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# imports:
|
|
10
|
+
# - ./code-talk.yaml
|
|
11
|
+
#
|
|
12
|
+
# checks:
|
|
13
|
+
# code-help:
|
|
14
|
+
# type: workflow
|
|
15
|
+
# workflow: code-talk
|
|
16
|
+
# args:
|
|
17
|
+
# question: "How does authentication work?"
|
|
18
|
+
# architecture: ./ARCHITECTURE.md
|
|
19
|
+
# docs_repo: my-org/docs
|
|
20
|
+
# projects:
|
|
21
|
+
# - id: backend
|
|
22
|
+
# repo: my-org/backend
|
|
23
|
+
# description: Backend API services
|
|
24
|
+
#
|
|
25
|
+
# =============================================================================
|
|
26
|
+
|
|
27
|
+
id: code-talk
|
|
28
|
+
name: Code Talk
|
|
29
|
+
description: AI-powered code exploration across multiple repositories with confidence scoring
|
|
30
|
+
version: "1.0.0"
|
|
31
|
+
|
|
32
|
+
inputs:
|
|
33
|
+
- name: question
|
|
34
|
+
required: true
|
|
35
|
+
description: The code question to answer
|
|
36
|
+
schema:
|
|
37
|
+
type: string
|
|
38
|
+
|
|
39
|
+
- name: architecture
|
|
40
|
+
required: true
|
|
41
|
+
description: |
|
|
42
|
+
Architecture model - file path or inline markdown describing
|
|
43
|
+
project topology and routing rules
|
|
44
|
+
schema:
|
|
45
|
+
type: string
|
|
46
|
+
|
|
47
|
+
- name: docs_repo
|
|
48
|
+
required: true
|
|
49
|
+
description: Documentation repository (owner/name format)
|
|
50
|
+
schema:
|
|
51
|
+
type: string
|
|
52
|
+
|
|
53
|
+
- name: projects
|
|
54
|
+
required: true
|
|
55
|
+
description: |
|
|
56
|
+
Array of available code projects for AI routing:
|
|
57
|
+
- id: unique identifier for routing
|
|
58
|
+
- repo: GitHub repository (owner/name)
|
|
59
|
+
- description: used by AI for routing decisions
|
|
60
|
+
schema:
|
|
61
|
+
type: array
|
|
62
|
+
items:
|
|
63
|
+
type: object
|
|
64
|
+
properties:
|
|
65
|
+
id: { type: string }
|
|
66
|
+
repo: { type: string }
|
|
67
|
+
description: { type: string }
|
|
68
|
+
required: [id, repo, description]
|
|
69
|
+
|
|
70
|
+
- name: max_projects
|
|
71
|
+
default: 3
|
|
72
|
+
description: Maximum code projects to checkout (excludes docs)
|
|
73
|
+
schema:
|
|
74
|
+
type: number
|
|
75
|
+
|
|
76
|
+
- name: docs_ref
|
|
77
|
+
default: main
|
|
78
|
+
description: Git ref for docs repository
|
|
79
|
+
schema:
|
|
80
|
+
type: string
|
|
81
|
+
|
|
82
|
+
- name: routing_prompt
|
|
83
|
+
required: false
|
|
84
|
+
description: Additional routing instructions (appended to built-in)
|
|
85
|
+
schema:
|
|
86
|
+
type: string
|
|
87
|
+
|
|
88
|
+
- name: exploration_prompt
|
|
89
|
+
required: false
|
|
90
|
+
description: Additional exploration instructions (appended to built-in)
|
|
91
|
+
schema:
|
|
92
|
+
type: string
|
|
93
|
+
|
|
94
|
+
- name: ai_model
|
|
95
|
+
required: false
|
|
96
|
+
description: Override AI model for exploration step
|
|
97
|
+
schema:
|
|
98
|
+
type: string
|
|
99
|
+
|
|
100
|
+
outputs:
|
|
101
|
+
- name: answer
|
|
102
|
+
description: The answer object with text
|
|
103
|
+
value_js: |
|
|
104
|
+
const result = outputs?.['explore-code'];
|
|
105
|
+
if (result?.answer) return result.answer;
|
|
106
|
+
const routeOutput = outputs?.['route-projects'];
|
|
107
|
+
// Handle proper notes field
|
|
108
|
+
const routeNotes = routeOutput?.notes;
|
|
109
|
+
if (typeof routeNotes === 'string' && routeNotes.trim().length > 0) {
|
|
110
|
+
return { text: routeNotes };
|
|
111
|
+
}
|
|
112
|
+
// Fallback: if AI returned {text: "..."} instead of proper schema
|
|
113
|
+
const routeText = routeOutput?.text;
|
|
114
|
+
if (typeof routeText === 'string' && routeText.trim().length > 0) {
|
|
115
|
+
return { text: routeText };
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
|
|
119
|
+
- name: references
|
|
120
|
+
description: Code/doc references from exploration
|
|
121
|
+
value_js: |
|
|
122
|
+
const result = outputs?.['explore-code'];
|
|
123
|
+
return result?.references ?? [];
|
|
124
|
+
|
|
125
|
+
- name: confidence
|
|
126
|
+
description: |
|
|
127
|
+
Confidence in the final answer ("high", "medium", or "low").
|
|
128
|
+
Treat non-high confidence as a signal to verify before acting.
|
|
129
|
+
value_js: |
|
|
130
|
+
const result = outputs?.['explore-code'];
|
|
131
|
+
if (result?.confidence) return result.confidence;
|
|
132
|
+
const routeNotes = outputs?.['route-projects']?.notes;
|
|
133
|
+
if (typeof routeNotes === 'string' && routeNotes.trim().length > 0) return 'low';
|
|
134
|
+
return 'low';
|
|
135
|
+
|
|
136
|
+
- name: confidence_reason
|
|
137
|
+
description: |
|
|
138
|
+
Why confidence is not high. Should explain missing evidence,
|
|
139
|
+
ambiguity, or investigation gaps. May be empty only when confidence is high.
|
|
140
|
+
value_js: |
|
|
141
|
+
const result = outputs?.['explore-code'];
|
|
142
|
+
const confidence = result?.confidence;
|
|
143
|
+
const reason = result?.confidence_reason;
|
|
144
|
+
if (typeof reason === 'string') return reason;
|
|
145
|
+
if (confidence === 'high') return '';
|
|
146
|
+
const routeNotes = outputs?.['route-projects']?.notes;
|
|
147
|
+
if (typeof routeNotes === 'string' && routeNotes.trim().length > 0) return routeNotes;
|
|
148
|
+
return 'No confidence explanation was provided by explore-code.';
|
|
149
|
+
|
|
150
|
+
- name: projects_explored
|
|
151
|
+
description: Which project IDs were checked out
|
|
152
|
+
value_js: |
|
|
153
|
+
// Try to get from history first
|
|
154
|
+
const historyItems = outputs?.history?.['project-items'];
|
|
155
|
+
const lastItems = Array.isArray(historyItems) ? historyItems[historyItems.length - 1] : historyItems;
|
|
156
|
+
if (Array.isArray(lastItems)) {
|
|
157
|
+
return lastItems
|
|
158
|
+
.map(function (p) { return p?.project_id; })
|
|
159
|
+
.filter(function (p) { return p; });
|
|
160
|
+
}
|
|
161
|
+
// Fallback: try to get from direct output
|
|
162
|
+
const projectItems = outputs?.['project-items'];
|
|
163
|
+
if (Array.isArray(projectItems)) {
|
|
164
|
+
return projectItems
|
|
165
|
+
.map(function (p) { return p?.project_id; })
|
|
166
|
+
.filter(function (p) { return p; });
|
|
167
|
+
}
|
|
168
|
+
return [];
|
|
169
|
+
|
|
170
|
+
- name: projects_explored_details
|
|
171
|
+
description: Project details for routed projects (id, repo, description, reason)
|
|
172
|
+
value_js: |
|
|
173
|
+
const normalizeFromItems = function (items) {
|
|
174
|
+
const result = [];
|
|
175
|
+
if (!Array.isArray(items)) return result;
|
|
176
|
+
for (let i = 0; i < items.length; i++) {
|
|
177
|
+
const item = items[i];
|
|
178
|
+
if (!item) continue;
|
|
179
|
+
const id = item.project_id ?? item.id;
|
|
180
|
+
const repo = item.repository ?? item.repo;
|
|
181
|
+
if (!id || !repo) continue;
|
|
182
|
+
result.push({
|
|
183
|
+
id,
|
|
184
|
+
repo,
|
|
185
|
+
description: item.description ?? '',
|
|
186
|
+
reason: item.reason ?? ''
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
return result;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// Prefer detailed project-items output (includes repo/description/reason)
|
|
193
|
+
const historyItems = outputs?.history?.['project-items'];
|
|
194
|
+
const lastHistory = Array.isArray(historyItems) ? historyItems[historyItems.length - 1] : historyItems;
|
|
195
|
+
const normalized = normalizeFromItems(lastHistory);
|
|
196
|
+
if (normalized.length > 0) return normalized;
|
|
197
|
+
|
|
198
|
+
const directItems = normalizeFromItems(outputs?.['project-items']);
|
|
199
|
+
if (directItems.length > 0) return directItems;
|
|
200
|
+
|
|
201
|
+
// Fallback: map project IDs to inputs.projects
|
|
202
|
+
let ids = [];
|
|
203
|
+
if (Array.isArray(lastHistory)) {
|
|
204
|
+
ids = lastHistory
|
|
205
|
+
.map(function (p) { return p?.project_id; })
|
|
206
|
+
.filter(function (p) { return p; });
|
|
207
|
+
}
|
|
208
|
+
if (ids.length === 0) {
|
|
209
|
+
const projectItems = outputs?.['project-items'];
|
|
210
|
+
if (Array.isArray(projectItems)) {
|
|
211
|
+
ids = projectItems
|
|
212
|
+
.map(function (p) { return p?.project_id; })
|
|
213
|
+
.filter(function (p) { return p; });
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const inputProjects = Array.isArray(inputs?.projects) ? inputs.projects : [];
|
|
218
|
+
const byId = {};
|
|
219
|
+
for (let j = 0; j < inputProjects.length; j++) {
|
|
220
|
+
const p = inputProjects[j];
|
|
221
|
+
if (p?.id) {
|
|
222
|
+
byId[p.id] = p;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const mapped = [];
|
|
227
|
+
for (let k = 0; k < ids.length; k++) {
|
|
228
|
+
const pid = ids[k];
|
|
229
|
+
const info = byId[pid];
|
|
230
|
+
if (!info?.repo) continue;
|
|
231
|
+
mapped.push({
|
|
232
|
+
id: pid,
|
|
233
|
+
repo: info.repo,
|
|
234
|
+
description: info.description ?? '',
|
|
235
|
+
reason: ''
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
return mapped;
|
|
239
|
+
|
|
240
|
+
- name: checkout_projects
|
|
241
|
+
description: Checked-out project paths aligned with routed projects
|
|
242
|
+
value_js: |
|
|
243
|
+
const historyItems = outputs?.history?.['project-items'];
|
|
244
|
+
const lastHistory = Array.isArray(historyItems) ? historyItems[historyItems.length - 1] : historyItems;
|
|
245
|
+
const items = Array.isArray(outputs?.['project-items'])
|
|
246
|
+
? outputs['project-items']
|
|
247
|
+
: Array.isArray(lastHistory)
|
|
248
|
+
? lastHistory
|
|
249
|
+
: [];
|
|
250
|
+
|
|
251
|
+
const checkoutOutput = outputs?.['checkout-projects'];
|
|
252
|
+
const checkouts = Array.isArray(checkoutOutput?.forEachItems)
|
|
253
|
+
? checkoutOutput.forEachItems
|
|
254
|
+
: Array.isArray(checkoutOutput)
|
|
255
|
+
? checkoutOutput
|
|
256
|
+
: [];
|
|
257
|
+
|
|
258
|
+
const result = [];
|
|
259
|
+
if (!Array.isArray(items) || !Array.isArray(checkouts)) return result;
|
|
260
|
+
|
|
261
|
+
for (let i = 0; i < items.length; i++) {
|
|
262
|
+
const item = items[i];
|
|
263
|
+
if (!item?.project_id) continue;
|
|
264
|
+
const checkout = checkouts[i] ?? {};
|
|
265
|
+
result.push({
|
|
266
|
+
project_id: item.project_id,
|
|
267
|
+
repository: item.repository ?? item.repo ?? '',
|
|
268
|
+
description: item.description ?? '',
|
|
269
|
+
path: checkout.path ?? checkout.workspace_path ?? ''
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
return result;
|
|
273
|
+
|
|
274
|
+
steps:
|
|
275
|
+
# ===========================================================================
|
|
276
|
+
# Step 1: Checkout documentation (always first)
|
|
277
|
+
# ===========================================================================
|
|
278
|
+
checkout-docs:
|
|
279
|
+
type: git-checkout
|
|
280
|
+
criticality: internal
|
|
281
|
+
assume:
|
|
282
|
+
- "true"
|
|
283
|
+
repository: "{{ inputs.docs_repo }}"
|
|
284
|
+
ref: "{{ inputs.docs_ref }}"
|
|
285
|
+
fetch_depth: 1
|
|
286
|
+
description: "Documentation"
|
|
287
|
+
|
|
288
|
+
# ===========================================================================
|
|
289
|
+
# Step 2: Route to relevant projects (AI-based)
|
|
290
|
+
# ===========================================================================
|
|
291
|
+
route-projects:
|
|
292
|
+
type: ai
|
|
293
|
+
criticality: internal
|
|
294
|
+
depends_on: [checkout-docs]
|
|
295
|
+
assume:
|
|
296
|
+
- "true"
|
|
297
|
+
guarantee: "(output?.projects?.length ?? 0) > 0 || (output?.notes?.length ?? 0) > 0"
|
|
298
|
+
fail_if: "(output?.projects?.length ?? 0) === 0 && !(output?.notes?.length > 0)"
|
|
299
|
+
ai:
|
|
300
|
+
skip_code_context: true
|
|
301
|
+
prompt_type: general
|
|
302
|
+
system_prompt: |
|
|
303
|
+
<role>
|
|
304
|
+
You are a project routing planner. Given a question, you decide which
|
|
305
|
+
code repositories need to be queried. You do NOT answer questions
|
|
306
|
+
directly - you only plan which projects to consult.
|
|
307
|
+
</role>
|
|
308
|
+
|
|
309
|
+
<context_handling>
|
|
310
|
+
The full conversation context (e.g., Slack thread) may be available in
|
|
311
|
+
<slack_context>. Use it to understand the real question. If the latest
|
|
312
|
+
message is a correction, reconstruct the original question from earlier
|
|
313
|
+
messages. Questions may include appended ticket/page context.
|
|
314
|
+
</context_handling>
|
|
315
|
+
|
|
316
|
+
<architecture>
|
|
317
|
+
{{ inputs.architecture }}
|
|
318
|
+
</architecture>
|
|
319
|
+
|
|
320
|
+
<docs_context>
|
|
321
|
+
The documentation has been checked out and is available for reference.
|
|
322
|
+
Use it to understand feature behavior, configuration options, and
|
|
323
|
+
cross-component interactions before deciding which code projects to query.
|
|
324
|
+
Path: {{ outputs['checkout-docs'].path }}
|
|
325
|
+
</docs_context>
|
|
326
|
+
|
|
327
|
+
<available_projects>
|
|
328
|
+
{% for p in inputs.projects %}
|
|
329
|
+
- id: {{ p.id }}
|
|
330
|
+
repo: {{ p.repo }}
|
|
331
|
+
description: {{ p.description }}
|
|
332
|
+
{% endfor %}
|
|
333
|
+
</available_projects>
|
|
334
|
+
schema: |
|
|
335
|
+
{
|
|
336
|
+
"type": "object",
|
|
337
|
+
"additionalProperties": false,
|
|
338
|
+
"properties": {
|
|
339
|
+
"projects": {
|
|
340
|
+
"type": "array",
|
|
341
|
+
"description": "Projects to query for this question",
|
|
342
|
+
"items": {
|
|
343
|
+
"type": "object",
|
|
344
|
+
"additionalProperties": false,
|
|
345
|
+
"properties": {
|
|
346
|
+
"project_id": {
|
|
347
|
+
"type": "string",
|
|
348
|
+
"description": "One of the available project IDs",
|
|
349
|
+
"enum": [{% for p in inputs.projects %}"{{ p.id }}"{% unless forloop.last %}, {% endunless %}{% endfor %}]
|
|
350
|
+
},
|
|
351
|
+
"reason": {
|
|
352
|
+
"type": "string",
|
|
353
|
+
"description": "Brief explanation of why this project is relevant"
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
"required": ["project_id"]
|
|
357
|
+
}
|
|
358
|
+
},
|
|
359
|
+
"notes": {
|
|
360
|
+
"type": "string",
|
|
361
|
+
"description": "Optional planner notes"
|
|
362
|
+
}
|
|
363
|
+
},
|
|
364
|
+
"required": ["projects"]
|
|
365
|
+
}
|
|
366
|
+
prompt: |
|
|
367
|
+
<question>{{ inputs.question }}</question>
|
|
368
|
+
|
|
369
|
+
<task>
|
|
370
|
+
Determine which projects are needed to answer this question.
|
|
371
|
+
Consider all parts of the stack that the functionality touches, then
|
|
372
|
+
select the smallest set that covers the behavior.
|
|
373
|
+
|
|
374
|
+
Return a "projects" array with:
|
|
375
|
+
- "project_id": from the available project IDs listed above
|
|
376
|
+
- "reason" (optional): brief explanation of relevance
|
|
377
|
+
- If you cannot determine the relevant projects from the context,
|
|
378
|
+
return an empty "projects" array and include a "notes" string
|
|
379
|
+
asking for the missing details you need.
|
|
380
|
+
|
|
381
|
+
Routing guidelines:
|
|
382
|
+
- When functionality spans multiple components, include ALL affected projects
|
|
383
|
+
- It's better to include a small superset than to miss a relevant project
|
|
384
|
+
- Typical plans contain 1-3 projects, but include more when necessary
|
|
385
|
+
- Consider how data/config flows between services
|
|
386
|
+
- Maximum projects: {{ inputs.max_projects }}
|
|
387
|
+
</task>
|
|
388
|
+
|
|
389
|
+
{% if inputs.routing_prompt %}
|
|
390
|
+
<additional_routing_rules>
|
|
391
|
+
{{ inputs.routing_prompt }}
|
|
392
|
+
</additional_routing_rules>
|
|
393
|
+
{% endif %}
|
|
394
|
+
|
|
395
|
+
# ===========================================================================
|
|
396
|
+
# Step 3: Map routed projects to checkout descriptors
|
|
397
|
+
# ===========================================================================
|
|
398
|
+
project-items:
|
|
399
|
+
type: script
|
|
400
|
+
criticality: internal
|
|
401
|
+
depends_on: [route-projects]
|
|
402
|
+
assume:
|
|
403
|
+
- "Array.isArray(outputs['route-projects']?.projects)"
|
|
404
|
+
guarantee: "Array.isArray(output)"
|
|
405
|
+
schema:
|
|
406
|
+
type: array
|
|
407
|
+
content: |
|
|
408
|
+
// Build a map of project ID -> project info from inputs
|
|
409
|
+
const projectMap = {};
|
|
410
|
+
const inputProjects = Array.isArray(inputs?.projects) ? inputs.projects : [];
|
|
411
|
+
for (let i = 0; i < inputProjects.length; i++) {
|
|
412
|
+
const p = inputProjects[i];
|
|
413
|
+
if (p?.id) {
|
|
414
|
+
projectMap[p.id] = {
|
|
415
|
+
repo: p.repo,
|
|
416
|
+
description: p.description ?? p.id
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Get routed projects from AI
|
|
422
|
+
const routeOutput = outputs?.['route-projects'];
|
|
423
|
+
const routedProjects = Array.isArray(routeOutput?.projects) ? routeOutput.projects : [];
|
|
424
|
+
|
|
425
|
+
// Map to checkout descriptors
|
|
426
|
+
const result = [];
|
|
427
|
+
const maxProjects = inputs?.max_projects ?? 3;
|
|
428
|
+
|
|
429
|
+
for (let j = 0; j < routedProjects.length && result.length < maxProjects; j++) {
|
|
430
|
+
const routed = routedProjects[j];
|
|
431
|
+
if (!routed?.project_id) continue;
|
|
432
|
+
|
|
433
|
+
const info = projectMap[routed.project_id];
|
|
434
|
+
// Skip unknown project IDs (not in inputs.projects)
|
|
435
|
+
if (!info?.repo) continue;
|
|
436
|
+
|
|
437
|
+
result.push({
|
|
438
|
+
project_id: routed.project_id,
|
|
439
|
+
reason: routed.reason ?? '',
|
|
440
|
+
repository: info.repo,
|
|
441
|
+
description: info.description
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return result;
|
|
446
|
+
forEach: true
|
|
447
|
+
|
|
448
|
+
# ===========================================================================
|
|
449
|
+
# Step 4: Checkout each selected project
|
|
450
|
+
# ===========================================================================
|
|
451
|
+
checkout-projects:
|
|
452
|
+
type: git-checkout
|
|
453
|
+
criticality: internal
|
|
454
|
+
depends_on: [project-items]
|
|
455
|
+
assume:
|
|
456
|
+
- "output != null"
|
|
457
|
+
repository: "{{ outputs['project-items'].repository }}"
|
|
458
|
+
ref: main
|
|
459
|
+
fetch_depth: 1
|
|
460
|
+
description: "{{ outputs['project-items'].description }}"
|
|
461
|
+
|
|
462
|
+
# ===========================================================================
|
|
463
|
+
# Step 5: Explore code across all projects (main AI call)
|
|
464
|
+
# ===========================================================================
|
|
465
|
+
explore-code:
|
|
466
|
+
type: ai
|
|
467
|
+
criticality: internal
|
|
468
|
+
depends_on: [route-projects, project-items, checkout-projects]
|
|
469
|
+
fanout: reduce
|
|
470
|
+
assume:
|
|
471
|
+
- "outputs['route-projects']?.projects?.length > 0"
|
|
472
|
+
ai:
|
|
473
|
+
skip_code_context: true
|
|
474
|
+
enableDelegate: true
|
|
475
|
+
enableExecutePlan: true
|
|
476
|
+
max_iterations: 40
|
|
477
|
+
prompt_type: code-explorer
|
|
478
|
+
allowBash: true
|
|
479
|
+
bashConfig:
|
|
480
|
+
allow:
|
|
481
|
+
# Git read-only commands only (no commit, push, reset, rebase, merge, etc.)
|
|
482
|
+
- "git:diff:*"
|
|
483
|
+
- "git:log:*"
|
|
484
|
+
- "git:show:*"
|
|
485
|
+
- "git:blame:*"
|
|
486
|
+
- "git:checkout:*"
|
|
487
|
+
- "git:branch:*"
|
|
488
|
+
- "git:tag:*"
|
|
489
|
+
- "git:fetch:*"
|
|
490
|
+
- "git:status:*"
|
|
491
|
+
- "git:rev-parse:*"
|
|
492
|
+
- "git:ls-files:*"
|
|
493
|
+
- "git:ls-tree:*"
|
|
494
|
+
# File operations
|
|
495
|
+
- "ls:*"
|
|
496
|
+
- "find:*"
|
|
497
|
+
- "cat:*"
|
|
498
|
+
- "head:*"
|
|
499
|
+
- "tail:*"
|
|
500
|
+
- "wc:*"
|
|
501
|
+
- "grep:*"
|
|
502
|
+
# GitHub CLI read-only operations
|
|
503
|
+
- "gh:run:*"
|
|
504
|
+
- "gh:run:list:*"
|
|
505
|
+
- "gh:run:view:*"
|
|
506
|
+
- "gh:run:watch:*"
|
|
507
|
+
- "gh:workflow:*"
|
|
508
|
+
- "gh:workflow:list:*"
|
|
509
|
+
- "gh:workflow:view:*"
|
|
510
|
+
- "gh:pr:*"
|
|
511
|
+
- "gh:pr:list:*"
|
|
512
|
+
- "gh:pr:view:*"
|
|
513
|
+
- "gh:pr:checks:*"
|
|
514
|
+
- "gh:pr:diff:*"
|
|
515
|
+
- "gh:issue:*"
|
|
516
|
+
- "gh:issue:list:*"
|
|
517
|
+
- "gh:issue:view:*"
|
|
518
|
+
- "gh:repo:view:*"
|
|
519
|
+
- "gh:repo:list:*"
|
|
520
|
+
- "gh:api:*"
|
|
521
|
+
- "gh:release:list:*"
|
|
522
|
+
- "gh:release:view:*"
|
|
523
|
+
# Curl for API calls (read-only)
|
|
524
|
+
- "curl:-s:*"
|
|
525
|
+
- "curl:*"
|
|
526
|
+
timeout: 60000
|
|
527
|
+
completion_prompt: |
|
|
528
|
+
Before finalizing your answer, triple-check everything:
|
|
529
|
+
|
|
530
|
+
Challenge assumptions:
|
|
531
|
+
1. Did you INDEPENDENTLY verify the user's claims, or just search for confirmation?
|
|
532
|
+
2. If the user assumed a root cause, did you verify it's actually correct?
|
|
533
|
+
3. Could the real issue be something completely different from what was suggested?
|
|
534
|
+
|
|
535
|
+
Investigation completeness:
|
|
536
|
+
4. Did you consider MULTIPLE possible explanations, not just the first one?
|
|
537
|
+
5. If there were alternative theories, did you investigate each one?
|
|
538
|
+
6. Have you ruled out other possibilities with evidence, not assumptions?
|
|
539
|
+
|
|
540
|
+
Cross-project verification:
|
|
541
|
+
4. Are there dependencies or interactions between projects you examined?
|
|
542
|
+
5. Did you verify how data/config flows between components?
|
|
543
|
+
6. Did you check both the happy path AND error handling paths?
|
|
544
|
+
|
|
545
|
+
Reference accuracy:
|
|
546
|
+
7. Are all code references accurate (file paths, function names, line numbers)?
|
|
547
|
+
8. Do the docs match what the code actually does?
|
|
548
|
+
|
|
549
|
+
CRITICAL: When you identify a configuration variable, you MUST then perform
|
|
550
|
+
a second search to find the code that consumes that variable. You cannot draw
|
|
551
|
+
conclusions from a variable's name alone. You must confirm its purpose by
|
|
552
|
+
analyzing how it is used in the application logic.
|
|
553
|
+
|
|
554
|
+
If you found any ambiguity, gaps in your investigation, or unexplored
|
|
555
|
+
hypotheses - use delegate tool to investigate further before concluding.
|
|
556
|
+
|
|
557
|
+
When you finish, ensure your answer includes:
|
|
558
|
+
- All relevant details grounded in code
|
|
559
|
+
- If multiple theories were considered, explain which one is correct and WHY
|
|
560
|
+
(with evidence ruling out alternatives)
|
|
561
|
+
- A confidence score ("high", "medium", or "low")
|
|
562
|
+
- If confidence is "medium" or "low", include a clear confidence_reason
|
|
563
|
+
explaining what evidence is missing or ambiguous
|
|
564
|
+
- At the END of your answer.text, append a "## References" section with a
|
|
565
|
+
bulleted list of all code/doc references in this format:
|
|
566
|
+
- [file.go:42-50](https://github.com/org/repo/blob/main/path/file.go#L42-L50) - brief description
|
|
567
|
+
- Also populate the references array with structured data for each reference
|
|
568
|
+
schema:
|
|
569
|
+
type: object
|
|
570
|
+
additionalProperties: false
|
|
571
|
+
properties:
|
|
572
|
+
answer:
|
|
573
|
+
type: object
|
|
574
|
+
additionalProperties: false
|
|
575
|
+
properties:
|
|
576
|
+
text:
|
|
577
|
+
type: string
|
|
578
|
+
description: |
|
|
579
|
+
The complete answer with explanations. MUST end with a
|
|
580
|
+
"## References" section containing clickable GitHub links.
|
|
581
|
+
summary:
|
|
582
|
+
type: string
|
|
583
|
+
description: One-line summary (optional)
|
|
584
|
+
required: [text]
|
|
585
|
+
references:
|
|
586
|
+
type: array
|
|
587
|
+
description: Code and documentation references (must not be empty)
|
|
588
|
+
items:
|
|
589
|
+
type: object
|
|
590
|
+
properties:
|
|
591
|
+
project:
|
|
592
|
+
type: string
|
|
593
|
+
description: Project ID (e.g., "tyk", "tyk-analytics")
|
|
594
|
+
file:
|
|
595
|
+
type: string
|
|
596
|
+
description: File path relative to repo root
|
|
597
|
+
lines:
|
|
598
|
+
type: array
|
|
599
|
+
description: Line numbers (start and end if range)
|
|
600
|
+
items: { type: number }
|
|
601
|
+
url:
|
|
602
|
+
type: string
|
|
603
|
+
description: Full GitHub URL with line numbers (e.g., https://github.com/org/repo/blob/main/file.go#L42-L50)
|
|
604
|
+
snippet:
|
|
605
|
+
type: string
|
|
606
|
+
description: Brief description of what this reference shows
|
|
607
|
+
required: [project, file, url]
|
|
608
|
+
confidence:
|
|
609
|
+
type: string
|
|
610
|
+
enum: [high, medium, low]
|
|
611
|
+
description: |
|
|
612
|
+
Confidence in the answer based on evidence quality and investigation coverage.
|
|
613
|
+
Use "high" only when claims are directly backed by code/doc evidence.
|
|
614
|
+
confidence_reason:
|
|
615
|
+
type: string
|
|
616
|
+
description: |
|
|
617
|
+
Why confidence is not high (required to be meaningful for medium/low confidence).
|
|
618
|
+
Leave empty string only when confidence is high.
|
|
619
|
+
required: [answer, references, confidence, confidence_reason]
|
|
620
|
+
prompt: |
|
|
621
|
+
<instructions>
|
|
622
|
+
You are a code/documentation explorer. Your goal is to answer a code-level
|
|
623
|
+
question that can span multiple projects, using:
|
|
624
|
+
- the checked-out code repositories
|
|
625
|
+
- the checked-out documentation repository
|
|
626
|
+
- code-explorer tools (search, extract, query, listFiles, searchFiles)
|
|
627
|
+
- delegate sub-agents when you need to dive deeply into a project
|
|
628
|
+
- ensure that delegate sub-agents return detailed references with files and line numbers
|
|
629
|
+
|
|
630
|
+
IMPORTANT - Handling ambiguity:
|
|
631
|
+
If the question is ambiguous, unclear, or you need more details to provide
|
|
632
|
+
a useful answer, DO NOT guess or make assumptions. Instead:
|
|
633
|
+
- Clearly state what information is missing or unclear
|
|
634
|
+
- Ask specific clarifying questions
|
|
635
|
+
- Explain what you could investigate with more context
|
|
636
|
+
|
|
637
|
+
Examples of when to ask for clarification:
|
|
638
|
+
- "Which version/branch are you asking about?"
|
|
639
|
+
- "Are you asking about the gateway or dashboard implementation?"
|
|
640
|
+
- "Could you provide the specific error message or log output?"
|
|
641
|
+
- "Which repository or component is this related to?"
|
|
642
|
+
|
|
643
|
+
It's better to ask for clarification than to provide an incorrect or
|
|
644
|
+
irrelevant answer based on assumptions.
|
|
645
|
+
|
|
646
|
+
Git bash commands:
|
|
647
|
+
You can use git commands for deeper code investigation:
|
|
648
|
+
- `git diff` to compare branches or commits
|
|
649
|
+
- `git log` to see commit history and understand changes over time
|
|
650
|
+
- `git show` to inspect specific commits
|
|
651
|
+
- `git blame` to understand who changed what and when
|
|
652
|
+
- `git checkout` to switch branches when comparing implementations
|
|
653
|
+
- `git branch -a` to list ALL branches (local and remote)
|
|
654
|
+
- `git fetch --tags` to fetch all tags from remote
|
|
655
|
+
- `git tag -l` to list all available tags
|
|
656
|
+
|
|
657
|
+
IMPORTANT - Fetching remote branches:
|
|
658
|
+
Repositories are checked out with shallow clone (fetch_depth: 1), so remote
|
|
659
|
+
branches are NOT available locally by default. Before checking out a branch:
|
|
660
|
+
1. First fetch the specific branch: `git fetch origin <branch-name>`
|
|
661
|
+
2. Then checkout: `git checkout <branch-name>` or `git checkout origin/<branch-name>`
|
|
662
|
+
|
|
663
|
+
Example for checking out release-5.3:
|
|
664
|
+
- First: `git fetch origin release-5.3`
|
|
665
|
+
- Then: `git checkout release-5.3`
|
|
666
|
+
|
|
667
|
+
If the branch doesn't exist, try listing available branches:
|
|
668
|
+
- `git branch -r` to see remote branches
|
|
669
|
+
- `git ls-remote --heads origin` to list all remote branches
|
|
670
|
+
|
|
671
|
+
Use these when you need to understand how code evolved, compare different
|
|
672
|
+
versions, or investigate recent changes related to the question.
|
|
673
|
+
|
|
674
|
+
GitHub CLI (gh) for PR review and GitHub data:
|
|
675
|
+
You have access to the `gh` CLI tool for GitHub operations:
|
|
676
|
+
- `gh pr view <number> --repo owner/repo` - View PR details, description, status
|
|
677
|
+
- `gh pr diff <number> --repo owner/repo` - Get the full diff of a PR
|
|
678
|
+
- `gh pr checks <number> --repo owner/repo` - View CI/CD check status
|
|
679
|
+
- `gh pr list --repo owner/repo` - List open PRs
|
|
680
|
+
- `gh issue view <number> --repo owner/repo` - View issue details
|
|
681
|
+
- `gh api repos/owner/repo/pulls/<number>/files` - Get list of changed files
|
|
682
|
+
- `gh api repos/owner/repo/pulls/<number>/comments` - Get PR review comments
|
|
683
|
+
- `gh run list --repo owner/repo` - List workflow runs
|
|
684
|
+
- `gh run view <run-id> --repo owner/repo --log` - View workflow run logs
|
|
685
|
+
|
|
686
|
+
IMPORTANT - Checking out PR branches for review:
|
|
687
|
+
When asked to review a PR or investigate PR code, you need to checkout the PR branch:
|
|
688
|
+
1. GitHub maintains special refs for PRs: `refs/pull/<PR_NUMBER>/head`
|
|
689
|
+
2. To fetch and checkout a PR:
|
|
690
|
+
- `git fetch origin pull/<PR_NUMBER>/head:pr-<PR_NUMBER>` - fetch PR to local branch
|
|
691
|
+
- `git checkout pr-<PR_NUMBER>` - checkout the PR branch
|
|
692
|
+
3. Example for PR #123:
|
|
693
|
+
- `git fetch origin pull/123/head:pr-123`
|
|
694
|
+
- `git checkout pr-123`
|
|
695
|
+
4. To see what changed vs main/master:
|
|
696
|
+
- `git diff main...pr-123` or `git diff origin/main...HEAD`
|
|
697
|
+
|
|
698
|
+
IMPORTANT bash tool usage rules:
|
|
699
|
+
- Do NOT use shell operators like && or || or | (pipes)
|
|
700
|
+
- Do NOT use `cd dir && command`
|
|
701
|
+
- INSTEAD, use the workingDirectory parameter to specify where to run commands
|
|
702
|
+
- Each bash call should be a single simple command with workingDirectory set
|
|
703
|
+
|
|
704
|
+
Version-specific queries:
|
|
705
|
+
- When asked about a specific version (e.g., "5.8", "v5.8.3"):
|
|
706
|
+
1. First run `git fetch --tags` (with workingDirectory set)
|
|
707
|
+
2. Then run `git tag -l "v5.8*"` to find matching tags
|
|
708
|
+
3. Checkout to the relevant tag: `git checkout v5.8.10`
|
|
709
|
+
- Always verify you're on the correct version/branch before investigating code
|
|
710
|
+
|
|
711
|
+
Path rules: Always use relative paths (e.g., "gateway/mw_jwt.go"), never absolute
|
|
712
|
+
paths with /tmp/ or workspace UUIDs.
|
|
713
|
+
|
|
714
|
+
High-level behavior:
|
|
715
|
+
- Use documentation to understand intended behavior, configuration, and
|
|
716
|
+
cross-component interactions for the feature in question
|
|
717
|
+
- For each selected project, read the code and relevant docs to answer
|
|
718
|
+
the question as concretely as possible
|
|
719
|
+
- When multiple projects are involved, deliberately follow data and control
|
|
720
|
+
flow across them and explain the connections
|
|
721
|
+
- Always ground your answer in actual code/docs, not speculation
|
|
722
|
+
- When you see a dependency - prove it by code
|
|
723
|
+
|
|
724
|
+
Critical thinking - DO NOT blindly trust user assumptions:
|
|
725
|
+
- Users often report real problems but with INCORRECT root cause analysis
|
|
726
|
+
- The symptom may be real, but the explanation in the question may be wrong
|
|
727
|
+
- Verify every claim independently - don't just search for what the user expects
|
|
728
|
+
- If a bug report says "X causes Y", verify BOTH that Y happens AND that X is the cause
|
|
729
|
+
- Look at the bigger picture - the real issue might be elsewhere entirely
|
|
730
|
+
- Be unbiased: don't anchor on the user's theory, form your own based on evidence
|
|
731
|
+
|
|
732
|
+
Investigation methodology - IMPORTANT:
|
|
733
|
+
1. Before diving deep, form multiple hypotheses about the answer:
|
|
734
|
+
- What are the possible explanations or root causes?
|
|
735
|
+
- Could the behavior be in component A, B, or both?
|
|
736
|
+
- Is this a configuration issue, code bug, or expected behavior?
|
|
737
|
+
- Is the user's assumption about the cause actually correct?
|
|
738
|
+
2. Investigate each hypothesis systematically:
|
|
739
|
+
- Don't assume your first theory OR the user's theory is correct
|
|
740
|
+
- If evidence contradicts a hypothesis, note it and move on
|
|
741
|
+
- Look for edge cases and alternative code paths
|
|
742
|
+
3. When investigating complex issues:
|
|
743
|
+
- Check error handling paths, not just happy paths
|
|
744
|
+
- Look at configuration options that might affect behavior
|
|
745
|
+
- Consider version differences if relevant
|
|
746
|
+
4. Cross-reference your findings:
|
|
747
|
+
- Do the docs match what the code actually does?
|
|
748
|
+
- Are there any TODOs, FIXMEs, or known issues?
|
|
749
|
+
- Check git blame/log for recent changes if behavior seems unexpected
|
|
750
|
+
|
|
751
|
+
Using delegate tool effectively:
|
|
752
|
+
- Use delegate when you need DEEP investigation into a specific component
|
|
753
|
+
- Each delegate call should focus on ONE specific question or hypothesis
|
|
754
|
+
- Good delegate uses:
|
|
755
|
+
- "Investigate how JWT validation handles expired tokens in gateway"
|
|
756
|
+
- "Find all places where rate limit counters are incremented"
|
|
757
|
+
- "Trace the request flow from API entry to database query"
|
|
758
|
+
- Bad delegate uses:
|
|
759
|
+
- "Look at the code" (too vague)
|
|
760
|
+
- "Find everything about auth" (too broad)
|
|
761
|
+
- Run multiple delegates in PARALLEL when investigating different hypotheses
|
|
762
|
+
or different components - don't wait for one to finish before starting another
|
|
763
|
+
- Always ask delegates to return specific file paths and line numbers
|
|
764
|
+
|
|
765
|
+
CRITICAL - Preserve detailed output from tools and delegates:
|
|
766
|
+
When tools or delegates return detailed data (customer insights, code analysis, etc.):
|
|
767
|
+
- DO NOT summarize or compress the output
|
|
768
|
+
- RELAY THE FULL DATA including all names, specifics, and details
|
|
769
|
+
- If a tool returns 10 items with details, include ALL 10 in your answer
|
|
770
|
+
- Never say "based on the analysis" without presenting the actual data
|
|
771
|
+
- Tools already synthesize data - your job is to present it completely
|
|
772
|
+
|
|
773
|
+
CRITICAL: Always use `attempt_completion` tool to submit your final answer.
|
|
774
|
+
This enables validation of your investigation before the response is finalized.
|
|
775
|
+
</instructions>
|
|
776
|
+
|
|
777
|
+
{% if inputs.exploration_prompt %}
|
|
778
|
+
<additional_instructions>
|
|
779
|
+
{{ inputs.exploration_prompt }}
|
|
780
|
+
</additional_instructions>
|
|
781
|
+
{% endif %}
|
|
782
|
+
|
|
783
|
+
<context>
|
|
784
|
+
<question>
|
|
785
|
+
{{ inputs.question }}
|
|
786
|
+
</question>
|
|
787
|
+
|
|
788
|
+
<architecture>
|
|
789
|
+
The following architecture document describes the project topology, routing rules,
|
|
790
|
+
and important guidelines for working with this codebase. Use it to understand
|
|
791
|
+
project relationships, debugging procedures, and special instructions.
|
|
792
|
+
|
|
793
|
+
{{ inputs.architecture }}
|
|
794
|
+
</architecture>
|
|
795
|
+
|
|
796
|
+
<routing_decision>
|
|
797
|
+
{{ outputs['route-projects'] | json }}
|
|
798
|
+
</routing_decision>
|
|
799
|
+
|
|
800
|
+
<docs_checkout>
|
|
801
|
+
<repo>{{ inputs.docs_repo }}</repo>
|
|
802
|
+
<ref>{{ inputs.docs_ref }}</ref>
|
|
803
|
+
<path>{{ outputs['checkout-docs'].path }}</path>
|
|
804
|
+
</docs_checkout>
|
|
805
|
+
|
|
806
|
+
{% assign items = outputs.history['project-items'] | last %}
|
|
807
|
+
{% assign checkouts = outputs.history['checkout-projects'] %}
|
|
808
|
+
{% if checkouts == nil or checkouts == empty %}
|
|
809
|
+
{% assign checkouts = outputs['checkout-projects'].forEachItems %}
|
|
810
|
+
{% endif %}
|
|
811
|
+
<projects>
|
|
812
|
+
{% if items and checkouts %}
|
|
813
|
+
{% for p in items %}
|
|
814
|
+
{% assign co = checkouts[forloop.index0] %}
|
|
815
|
+
<project>
|
|
816
|
+
<id>{{ p.project_id }}</id>
|
|
817
|
+
<repo>{{ p.repository }}</repo>
|
|
818
|
+
<path>{{ co.path }}</path>
|
|
819
|
+
<reason>{{ p.reason | default: 'not provided' }}</reason>
|
|
820
|
+
</project>
|
|
821
|
+
{% endfor %}
|
|
822
|
+
{% endif %}
|
|
823
|
+
</projects>
|
|
824
|
+
</context>
|
|
825
|
+
|
|
826
|
+
<task>
|
|
827
|
+
For each project listed in <projects>:
|
|
828
|
+
- Use code-explorer tools to:
|
|
829
|
+
- listFiles/searchFiles to understand the structure and find relevant
|
|
830
|
+
directories and files
|
|
831
|
+
- search/query/extract to locate and read the core implementation
|
|
832
|
+
- consult documentation to confirm semantics, configuration options,
|
|
833
|
+
and cross-project responsibilities
|
|
834
|
+
- When multiple projects are involved, pay attention to:
|
|
835
|
+
- how configuration flows between components
|
|
836
|
+
- how identity, auth, or data flows between services
|
|
837
|
+
- any shared libraries used by more than one project
|
|
838
|
+
- Use delegate tools per project when a deeper, focused investigation
|
|
839
|
+
is needed
|
|
840
|
+
|
|
841
|
+
Finally, synthesize everything into a single answer that explains the
|
|
842
|
+
behavior to an engineer:
|
|
843
|
+
- Be concrete and code/doc-grounded (mention key components, files, and
|
|
844
|
+
configuration options when helpful)
|
|
845
|
+
- Keep the explanation focused and coherent
|
|
846
|
+
- IMPORTANT: At the END of your answer, include a "## References" section
|
|
847
|
+
with clickable GitHub links pointing to specific lines
|
|
848
|
+
|
|
849
|
+
Return your answer in the schema format with:
|
|
850
|
+
- answer.text: your complete explanation, ending with a "## References" section like:
|
|
851
|
+
```
|
|
852
|
+
## References
|
|
853
|
+
- [mw_jwt.go:142-180](https://github.com/TykTechnologies/tyk/blob/master/gateway/mw_jwt.go#L142-L180) - JWT validation middleware
|
|
854
|
+
- [jwt.md](https://github.com/TykTechnologies/tyk-docs/blob/main/tyk-docs/content/basic-config-and-security/security/authentication-authorization/jwt.md) - JWT documentation
|
|
855
|
+
```
|
|
856
|
+
- answer.summary: one-line summary (optional)
|
|
857
|
+
- references: array with structured data for each reference (project, file, url, snippet)
|
|
858
|
+
- confidence: "high" | "medium" | "low"
|
|
859
|
+
- confidence_reason: required explanation when confidence is "medium" or "low";
|
|
860
|
+
use empty string only when confidence is "high"
|
|
861
|
+
</task>
|
|
862
|
+
|
|
863
|
+
# =============================================================================
|
|
864
|
+
# Tests
|
|
865
|
+
# =============================================================================
|
|
866
|
+
tests:
|
|
867
|
+
defaults:
|
|
868
|
+
strict: true
|
|
869
|
+
ai_provider: mock
|
|
870
|
+
|
|
871
|
+
cases:
|
|
872
|
+
- name: basic-code-question
|
|
873
|
+
event: manual
|
|
874
|
+
fixture: local.minimal
|
|
875
|
+
workflow_input:
|
|
876
|
+
question: "How does authentication work?"
|
|
877
|
+
architecture: |
|
|
878
|
+
# Architecture
|
|
879
|
+
## Projects
|
|
880
|
+
- gateway: API Gateway
|
|
881
|
+
- backend: Backend services
|
|
882
|
+
docs_repo: org/docs
|
|
883
|
+
projects:
|
|
884
|
+
- id: gateway
|
|
885
|
+
repo: org/gateway
|
|
886
|
+
description: API Gateway
|
|
887
|
+
- id: backend
|
|
888
|
+
repo: org/backend
|
|
889
|
+
description: Backend services
|
|
890
|
+
mocks:
|
|
891
|
+
checkout-docs:
|
|
892
|
+
path: "/tmp/visor/docs"
|
|
893
|
+
repository: "org/docs"
|
|
894
|
+
ref: "main"
|
|
895
|
+
checkout-projects:
|
|
896
|
+
path: "/tmp/visor/project"
|
|
897
|
+
repository: "org/gateway"
|
|
898
|
+
ref: "main"
|
|
899
|
+
route-projects:
|
|
900
|
+
projects:
|
|
901
|
+
- project_id: "gateway"
|
|
902
|
+
reason: "Gateway handles authentication"
|
|
903
|
+
explore-code:
|
|
904
|
+
answer:
|
|
905
|
+
text: "Authentication is handled in the gateway via JWT middleware."
|
|
906
|
+
summary: "JWT auth in gateway"
|
|
907
|
+
references:
|
|
908
|
+
- project: gateway
|
|
909
|
+
file: src/auth/jwt.go
|
|
910
|
+
url: https://github.com/org/gateway/blob/main/src/auth/jwt.go#L42
|
|
911
|
+
confidence: high
|
|
912
|
+
confidence_reason: ""
|
|
913
|
+
expect:
|
|
914
|
+
calls:
|
|
915
|
+
- step: checkout-docs
|
|
916
|
+
exactly: 1
|
|
917
|
+
- step: route-projects
|
|
918
|
+
exactly: 1
|
|
919
|
+
- step: project-items
|
|
920
|
+
exactly: 1
|
|
921
|
+
- step: checkout-projects
|
|
922
|
+
exactly: 1
|
|
923
|
+
- step: explore-code
|
|
924
|
+
exactly: 1
|
|
925
|
+
# Verify workflow inputs are rendered in the route-projects prompt
|
|
926
|
+
# Note: prompts assertion captures the user prompt only, not system_prompt.
|
|
927
|
+
# The user prompt contains question; system_prompt contains architecture and projects.
|
|
928
|
+
prompts:
|
|
929
|
+
- step: route-projects
|
|
930
|
+
contains:
|
|
931
|
+
# Verify question input is rendered (from inputs.question)
|
|
932
|
+
- "How does authentication work?"
|
|
933
|
+
# Verify max_projects default is rendered
|
|
934
|
+
- "Maximum projects:"
|
|
935
|
+
workflow_output:
|
|
936
|
+
- path: answer.text
|
|
937
|
+
equals: "Authentication is handled in the gateway via JWT middleware."
|
|
938
|
+
- path: confidence
|
|
939
|
+
equals: "high"
|
|
940
|
+
|
|
941
|
+
- name: multi-project-question
|
|
942
|
+
event: manual
|
|
943
|
+
fixture: local.minimal
|
|
944
|
+
workflow_input:
|
|
945
|
+
question: "How does data flow from gateway to backend?"
|
|
946
|
+
architecture: "# Arch"
|
|
947
|
+
docs_repo: org/docs
|
|
948
|
+
projects:
|
|
949
|
+
- id: gateway
|
|
950
|
+
repo: org/gateway
|
|
951
|
+
description: API Gateway
|
|
952
|
+
- id: backend
|
|
953
|
+
repo: org/backend
|
|
954
|
+
description: Backend services
|
|
955
|
+
mocks:
|
|
956
|
+
checkout-docs:
|
|
957
|
+
path: "/tmp/visor/docs"
|
|
958
|
+
repository: "org/docs"
|
|
959
|
+
ref: "main"
|
|
960
|
+
checkout-projects:
|
|
961
|
+
path: "/tmp/visor/project"
|
|
962
|
+
repository: "org/example"
|
|
963
|
+
ref: "main"
|
|
964
|
+
route-projects:
|
|
965
|
+
projects:
|
|
966
|
+
- project_id: "gateway"
|
|
967
|
+
reason: "Handles incoming requests"
|
|
968
|
+
- project_id: "backend"
|
|
969
|
+
reason: "Processes data"
|
|
970
|
+
explore-code:
|
|
971
|
+
answer:
|
|
972
|
+
text: "Data flows via gRPC from gateway to backend."
|
|
973
|
+
references: []
|
|
974
|
+
confidence: medium
|
|
975
|
+
confidence_reason: "References are incomplete for full cross-project verification."
|
|
976
|
+
expect:
|
|
977
|
+
calls:
|
|
978
|
+
- step: checkout-docs
|
|
979
|
+
exactly: 1
|
|
980
|
+
- step: route-projects
|
|
981
|
+
exactly: 1
|
|
982
|
+
- step: project-items
|
|
983
|
+
exactly: 1
|
|
984
|
+
- step: checkout-projects
|
|
985
|
+
exactly: 2
|
|
986
|
+
- step: explore-code
|
|
987
|
+
exactly: 1
|
|
988
|
+
|
|
989
|
+
- name: empty-routing-returns-notes
|
|
990
|
+
strict: false
|
|
991
|
+
event: manual
|
|
992
|
+
fixture: local.minimal
|
|
993
|
+
workflow_input:
|
|
994
|
+
question: "Vague question"
|
|
995
|
+
architecture: "# Arch"
|
|
996
|
+
docs_repo: org/docs
|
|
997
|
+
projects:
|
|
998
|
+
- id: main
|
|
999
|
+
repo: org/main
|
|
1000
|
+
description: Main app
|
|
1001
|
+
mocks:
|
|
1002
|
+
checkout-docs:
|
|
1003
|
+
path: "/tmp/visor/docs"
|
|
1004
|
+
repository: "org/docs"
|
|
1005
|
+
ref: "main"
|
|
1006
|
+
route-projects:
|
|
1007
|
+
projects: []
|
|
1008
|
+
notes: "I need more context to route this question."
|
|
1009
|
+
expect:
|
|
1010
|
+
calls:
|
|
1011
|
+
- step: route-projects
|
|
1012
|
+
exactly: 1
|
|
1013
|
+
workflow_output:
|
|
1014
|
+
- path: answer.text
|
|
1015
|
+
equals: "I need more context to route this question."
|
|
1016
|
+
|
|
1017
|
+
# =========================================================================
|
|
1018
|
+
# Edge Case: Checkout failure stops downstream checks
|
|
1019
|
+
# When checkout fails (success: false), dependent checks don't run.
|
|
1020
|
+
# =========================================================================
|
|
1021
|
+
- name: checkout-failure-stops-exploration
|
|
1022
|
+
strict: false
|
|
1023
|
+
event: manual
|
|
1024
|
+
fixture: local.minimal
|
|
1025
|
+
workflow_input:
|
|
1026
|
+
question: "How does auth work?"
|
|
1027
|
+
architecture: "# Arch"
|
|
1028
|
+
docs_repo: org/docs
|
|
1029
|
+
projects:
|
|
1030
|
+
- id: backend
|
|
1031
|
+
repo: org/backend
|
|
1032
|
+
description: Backend services
|
|
1033
|
+
mocks:
|
|
1034
|
+
checkout-docs:
|
|
1035
|
+
path: "/tmp/visor/docs"
|
|
1036
|
+
repository: "org/docs"
|
|
1037
|
+
ref: "main"
|
|
1038
|
+
route-projects:
|
|
1039
|
+
projects:
|
|
1040
|
+
- project_id: "backend"
|
|
1041
|
+
reason: "Auth is in backend"
|
|
1042
|
+
checkout-projects:
|
|
1043
|
+
# Failure stops downstream checks
|
|
1044
|
+
success: false
|
|
1045
|
+
error: "Repository not found: org/backend"
|
|
1046
|
+
expect:
|
|
1047
|
+
calls:
|
|
1048
|
+
- step: checkout-docs
|
|
1049
|
+
exactly: 1
|
|
1050
|
+
- step: route-projects
|
|
1051
|
+
exactly: 1
|
|
1052
|
+
- step: project-items
|
|
1053
|
+
exactly: 1
|
|
1054
|
+
- step: checkout-projects
|
|
1055
|
+
exactly: 1
|
|
1056
|
+
# explore-code does NOT run because checkout failed
|
|
1057
|
+
- step: explore-code
|
|
1058
|
+
exactly: 0
|
|
1059
|
+
|
|
1060
|
+
# =========================================================================
|
|
1061
|
+
# Edge Case: Malformed AI response (missing required fields)
|
|
1062
|
+
# =========================================================================
|
|
1063
|
+
- name: malformed-routing-response
|
|
1064
|
+
strict: false
|
|
1065
|
+
event: manual
|
|
1066
|
+
fixture: local.minimal
|
|
1067
|
+
workflow_input:
|
|
1068
|
+
question: "What is X?"
|
|
1069
|
+
architecture: "# Arch"
|
|
1070
|
+
docs_repo: org/docs
|
|
1071
|
+
projects:
|
|
1072
|
+
- id: app
|
|
1073
|
+
repo: org/app
|
|
1074
|
+
description: Main app
|
|
1075
|
+
mocks:
|
|
1076
|
+
checkout-docs:
|
|
1077
|
+
path: "/tmp/visor/docs"
|
|
1078
|
+
repository: "org/docs"
|
|
1079
|
+
ref: "main"
|
|
1080
|
+
route-projects:
|
|
1081
|
+
# Missing 'projects' field entirely - malformed response
|
|
1082
|
+
notes: "I couldn't determine the projects"
|
|
1083
|
+
expect:
|
|
1084
|
+
calls:
|
|
1085
|
+
- step: route-projects
|
|
1086
|
+
exactly: 1
|
|
1087
|
+
# Should fail because projects array is missing/empty
|
|
1088
|
+
|
|
1089
|
+
# =========================================================================
|
|
1090
|
+
# Edge Case: Unknown project ID in routing (not in input projects)
|
|
1091
|
+
# The script filters out unknown IDs and only processes valid ones.
|
|
1092
|
+
# =========================================================================
|
|
1093
|
+
- name: unknown-project-id-filtered
|
|
1094
|
+
event: manual
|
|
1095
|
+
fixture: local.minimal
|
|
1096
|
+
workflow_input:
|
|
1097
|
+
question: "How does caching work?"
|
|
1098
|
+
architecture: "# Arch"
|
|
1099
|
+
docs_repo: org/docs
|
|
1100
|
+
projects:
|
|
1101
|
+
- id: backend
|
|
1102
|
+
repo: org/backend
|
|
1103
|
+
description: Backend services
|
|
1104
|
+
mocks:
|
|
1105
|
+
checkout-docs:
|
|
1106
|
+
path: "/tmp/visor/docs"
|
|
1107
|
+
repository: "org/docs"
|
|
1108
|
+
ref: "main"
|
|
1109
|
+
checkout-projects:
|
|
1110
|
+
path: "/tmp/visor/project"
|
|
1111
|
+
repository: "org/backend"
|
|
1112
|
+
ref: "main"
|
|
1113
|
+
route-projects:
|
|
1114
|
+
projects:
|
|
1115
|
+
# AI returns a project ID that doesn't exist in inputs
|
|
1116
|
+
- project_id: "nonexistent-service"
|
|
1117
|
+
reason: "This doesn't exist"
|
|
1118
|
+
# Plus a valid one
|
|
1119
|
+
- project_id: "backend"
|
|
1120
|
+
reason: "Caching logic"
|
|
1121
|
+
explore-code:
|
|
1122
|
+
answer:
|
|
1123
|
+
text: "Caching is implemented in the backend."
|
|
1124
|
+
references: []
|
|
1125
|
+
confidence: medium
|
|
1126
|
+
confidence_reason: "One routed project was invalid and filtered before exploration."
|
|
1127
|
+
expect:
|
|
1128
|
+
calls:
|
|
1129
|
+
- step: checkout-docs
|
|
1130
|
+
exactly: 1
|
|
1131
|
+
- step: route-projects
|
|
1132
|
+
exactly: 1
|
|
1133
|
+
- step: project-items
|
|
1134
|
+
exactly: 1
|
|
1135
|
+
# Only 1 checkout because nonexistent-service is filtered out
|
|
1136
|
+
- step: checkout-projects
|
|
1137
|
+
exactly: 1
|
|
1138
|
+
- step: explore-code
|
|
1139
|
+
exactly: 1
|
|
1140
|
+
workflow_output:
|
|
1141
|
+
- path: answer.text
|
|
1142
|
+
equals: "Caching is implemented in the backend."
|
|
1143
|
+
|
|
1144
|
+
# =========================================================================
|
|
1145
|
+
# Edge Case: max_projects limit respected
|
|
1146
|
+
# =========================================================================
|
|
1147
|
+
- name: max-projects-limit
|
|
1148
|
+
event: manual
|
|
1149
|
+
fixture: local.minimal
|
|
1150
|
+
workflow_input:
|
|
1151
|
+
question: "How does the full stack work?"
|
|
1152
|
+
architecture: "# Arch"
|
|
1153
|
+
docs_repo: org/docs
|
|
1154
|
+
max_projects: 2
|
|
1155
|
+
projects:
|
|
1156
|
+
- id: frontend
|
|
1157
|
+
repo: org/frontend
|
|
1158
|
+
description: Frontend app
|
|
1159
|
+
- id: backend
|
|
1160
|
+
repo: org/backend
|
|
1161
|
+
description: Backend services
|
|
1162
|
+
- id: database
|
|
1163
|
+
repo: org/database
|
|
1164
|
+
description: Database layer
|
|
1165
|
+
- id: cache
|
|
1166
|
+
repo: org/cache
|
|
1167
|
+
description: Cache layer
|
|
1168
|
+
mocks:
|
|
1169
|
+
checkout-docs:
|
|
1170
|
+
path: "/tmp/visor/docs"
|
|
1171
|
+
repository: "org/docs"
|
|
1172
|
+
ref: "main"
|
|
1173
|
+
checkout-projects:
|
|
1174
|
+
path: "/tmp/visor/project"
|
|
1175
|
+
repository: "org/example"
|
|
1176
|
+
ref: "main"
|
|
1177
|
+
route-projects:
|
|
1178
|
+
projects:
|
|
1179
|
+
- project_id: "frontend"
|
|
1180
|
+
- project_id: "backend"
|
|
1181
|
+
- project_id: "database"
|
|
1182
|
+
- project_id: "cache"
|
|
1183
|
+
explore-code:
|
|
1184
|
+
answer:
|
|
1185
|
+
text: "The stack flows from frontend through backend."
|
|
1186
|
+
references: []
|
|
1187
|
+
confidence: medium
|
|
1188
|
+
confidence_reason: "Exploration scope was reduced by max_projects limit."
|
|
1189
|
+
expect:
|
|
1190
|
+
calls:
|
|
1191
|
+
- step: checkout-docs
|
|
1192
|
+
exactly: 1
|
|
1193
|
+
- step: route-projects
|
|
1194
|
+
exactly: 1
|
|
1195
|
+
- step: project-items
|
|
1196
|
+
exactly: 1
|
|
1197
|
+
# Only 2 checkouts due to max_projects: 2
|
|
1198
|
+
- step: checkout-projects
|
|
1199
|
+
exactly: 2
|
|
1200
|
+
- step: explore-code
|
|
1201
|
+
exactly: 1
|
|
1202
|
+
|
|
1203
|
+
# =========================================================================
|
|
1204
|
+
# Edge Case: Empty explore-code response handled gracefully
|
|
1205
|
+
# =========================================================================
|
|
1206
|
+
- name: empty-exploration-response
|
|
1207
|
+
event: manual
|
|
1208
|
+
fixture: local.minimal
|
|
1209
|
+
workflow_input:
|
|
1210
|
+
question: "What is feature X?"
|
|
1211
|
+
architecture: "# Arch"
|
|
1212
|
+
docs_repo: org/docs
|
|
1213
|
+
projects:
|
|
1214
|
+
- id: main
|
|
1215
|
+
repo: org/main
|
|
1216
|
+
description: Main app
|
|
1217
|
+
mocks:
|
|
1218
|
+
checkout-docs:
|
|
1219
|
+
path: "/tmp/visor/docs"
|
|
1220
|
+
repository: "org/docs"
|
|
1221
|
+
ref: "main"
|
|
1222
|
+
checkout-projects:
|
|
1223
|
+
path: "/tmp/visor/project"
|
|
1224
|
+
repository: "org/main"
|
|
1225
|
+
ref: "main"
|
|
1226
|
+
route-projects:
|
|
1227
|
+
projects:
|
|
1228
|
+
- project_id: "main"
|
|
1229
|
+
explore-code:
|
|
1230
|
+
# Minimal valid response with empty text
|
|
1231
|
+
answer:
|
|
1232
|
+
text: ""
|
|
1233
|
+
references: []
|
|
1234
|
+
confidence: low
|
|
1235
|
+
confidence_reason: "The final answer text is empty."
|
|
1236
|
+
expect:
|
|
1237
|
+
calls:
|
|
1238
|
+
- step: checkout-docs
|
|
1239
|
+
exactly: 1
|
|
1240
|
+
- step: route-projects
|
|
1241
|
+
exactly: 1
|
|
1242
|
+
- step: project-items
|
|
1243
|
+
exactly: 1
|
|
1244
|
+
- step: checkout-projects
|
|
1245
|
+
exactly: 1
|
|
1246
|
+
- step: explore-code
|
|
1247
|
+
exactly: 1
|
|
1248
|
+
workflow_output:
|
|
1249
|
+
- path: answer.text
|
|
1250
|
+
equals: ""
|