@claude-flow/cli 3.10.4 → 3.10.5
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/src/benchmarks/gaia-agent-planning.smoke.d.ts +18 -0
- package/dist/src/benchmarks/gaia-agent-planning.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-agent-planning.smoke.js +253 -0
- package/dist/src/benchmarks/gaia-agent-planning.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-agent.d.ts +198 -0
- package/dist/src/benchmarks/gaia-agent.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-agent.js +651 -0
- package/dist/src/benchmarks/gaia-agent.js.map +1 -0
- package/dist/src/benchmarks/gaia-causal-memory.d.ts +133 -0
- package/dist/src/benchmarks/gaia-causal-memory.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-causal-memory.js +281 -0
- package/dist/src/benchmarks/gaia-causal-memory.js.map +1 -0
- package/dist/src/benchmarks/gaia-causal-memory.smoke.d.ts +22 -0
- package/dist/src/benchmarks/gaia-causal-memory.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-causal-memory.smoke.js +300 -0
- package/dist/src/benchmarks/gaia-causal-memory.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-convergence.d.ts +138 -0
- package/dist/src/benchmarks/gaia-convergence.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-convergence.js +260 -0
- package/dist/src/benchmarks/gaia-convergence.js.map +1 -0
- package/dist/src/benchmarks/gaia-convergence.smoke.d.ts +19 -0
- package/dist/src/benchmarks/gaia-convergence.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-convergence.smoke.js +246 -0
- package/dist/src/benchmarks/gaia-convergence.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-critic.d.ts +123 -0
- package/dist/src/benchmarks/gaia-critic.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-critic.js +312 -0
- package/dist/src/benchmarks/gaia-critic.js.map +1 -0
- package/dist/src/benchmarks/gaia-critic.smoke.d.ts +21 -0
- package/dist/src/benchmarks/gaia-critic.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-critic.smoke.js +327 -0
- package/dist/src/benchmarks/gaia-critic.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-decomposer.d.ts +125 -0
- package/dist/src/benchmarks/gaia-decomposer.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-decomposer.js +350 -0
- package/dist/src/benchmarks/gaia-decomposer.js.map +1 -0
- package/dist/src/benchmarks/gaia-decomposer.smoke.d.ts +21 -0
- package/dist/src/benchmarks/gaia-decomposer.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-decomposer.smoke.js +228 -0
- package/dist/src/benchmarks/gaia-decomposer.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-e2e-smoke.d.ts +27 -0
- package/dist/src/benchmarks/gaia-e2e-smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-e2e-smoke.js +136 -0
- package/dist/src/benchmarks/gaia-e2e-smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-extract.smoke.d.ts +45 -0
- package/dist/src/benchmarks/gaia-extract.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-extract.smoke.js +242 -0
- package/dist/src/benchmarks/gaia-extract.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-hardness/features.d.ts +46 -0
- package/dist/src/benchmarks/gaia-hardness/features.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-hardness/features.js +170 -0
- package/dist/src/benchmarks/gaia-hardness/features.js.map +1 -0
- package/dist/src/benchmarks/gaia-hardness/predictor.d.ts +105 -0
- package/dist/src/benchmarks/gaia-hardness/predictor.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-hardness/predictor.js +260 -0
- package/dist/src/benchmarks/gaia-hardness/predictor.js.map +1 -0
- package/dist/src/benchmarks/gaia-hardness/predictor.smoke.d.ts +20 -0
- package/dist/src/benchmarks/gaia-hardness/predictor.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-hardness/predictor.smoke.js +235 -0
- package/dist/src/benchmarks/gaia-hardness/predictor.smoke.js.map +1 -0
- package/dist/src/benchmarks/gaia-hardness/train-data-loader.d.ts +51 -0
- package/dist/src/benchmarks/gaia-hardness/train-data-loader.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-hardness/train-data-loader.js +179 -0
- package/dist/src/benchmarks/gaia-hardness/train-data-loader.js.map +1 -0
- package/dist/src/benchmarks/gaia-judge.d.ts +88 -0
- package/dist/src/benchmarks/gaia-judge.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-judge.js +437 -0
- package/dist/src/benchmarks/gaia-judge.js.map +1 -0
- package/dist/src/benchmarks/gaia-loader.d.ts +87 -0
- package/dist/src/benchmarks/gaia-loader.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-loader.js +326 -0
- package/dist/src/benchmarks/gaia-loader.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/file_read.d.ts +35 -0
- package/dist/src/benchmarks/gaia-tools/file_read.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/file_read.js +403 -0
- package/dist/src/benchmarks/gaia-tools/file_read.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/grounded_query.d.ts +126 -0
- package/dist/src/benchmarks/gaia-tools/grounded_query.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/grounded_query.js +225 -0
- package/dist/src/benchmarks/gaia-tools/grounded_query.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/index.d.ts +32 -0
- package/dist/src/benchmarks/gaia-tools/index.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/index.js +36 -0
- package/dist/src/benchmarks/gaia-tools/index.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/types.d.ts +62 -0
- package/dist/src/benchmarks/gaia-tools/types.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/types.js +12 -0
- package/dist/src/benchmarks/gaia-tools/types.js.map +1 -0
- package/dist/src/benchmarks/gaia-tools/web_search.d.ts +30 -0
- package/dist/src/benchmarks/gaia-tools/web_search.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-tools/web_search.js +210 -0
- package/dist/src/benchmarks/gaia-tools/web_search.js.map +1 -0
- package/dist/src/benchmarks/gaia-voting.d.ts +88 -0
- package/dist/src/benchmarks/gaia-voting.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-voting.js +297 -0
- package/dist/src/benchmarks/gaia-voting.js.map +1 -0
- package/dist/src/benchmarks/gaia-voting.smoke.d.ts +20 -0
- package/dist/src/benchmarks/gaia-voting.smoke.d.ts.map +1 -0
- package/dist/src/benchmarks/gaia-voting.smoke.js +332 -0
- package/dist/src/benchmarks/gaia-voting.smoke.js.map +1 -0
- package/dist/src/commands/gaia-bench.d.ts +40 -0
- package/dist/src/commands/gaia-bench.d.ts.map +1 -0
- package/dist/src/commands/gaia-bench.js +597 -0
- package/dist/src/commands/gaia-bench.js.map +1 -0
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +2 -0
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +41 -4
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/init/executor.d.ts.map +1 -1
- package/dist/src/init/executor.js +25 -6
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/mcp-generator.d.ts.map +1 -1
- package/dist/src/init/mcp-generator.js +9 -4
- package/dist/src/init/mcp-generator.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GAIA Critic Smoke Tests — ADR-135 Track D
|
|
3
|
+
*
|
|
4
|
+
* Tests for the adversarial critic agent in gaia-critic.ts.
|
|
5
|
+
* All tests use mocked responses — NO live API calls.
|
|
6
|
+
*
|
|
7
|
+
* Test coverage:
|
|
8
|
+
* 1. Critic returns "pass" → no retry, immediately returns candidate
|
|
9
|
+
* 2. Critic returns "fail" with suggestedRevision → triggers one retry
|
|
10
|
+
* 3. Critic returns "fail" twice → retries exhausted, returns last candidate
|
|
11
|
+
* 4. Critic returns "uncertain" → treated as "pass", no retry
|
|
12
|
+
* 5. API error in critic → graceful fallback, returns candidate as-is
|
|
13
|
+
* 6. Malformed JSON from critic → fallback parser extracts verdict
|
|
14
|
+
*
|
|
15
|
+
* Usage (no API key required):
|
|
16
|
+
* npx tsx src/benchmarks/gaia-critic.smoke.ts
|
|
17
|
+
*
|
|
18
|
+
* Refs: ADR-135, #2156
|
|
19
|
+
*/
|
|
20
|
+
import { criticReview, runGaiaAgentWithCritic, } from './gaia-critic.js';
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Test helpers
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
let passed = 0;
|
|
25
|
+
let failed = 0;
|
|
26
|
+
function assert(condition, message) {
|
|
27
|
+
if (condition) {
|
|
28
|
+
console.log(` PASS ${message}`);
|
|
29
|
+
passed++;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
console.error(` FAIL ${message}`);
|
|
33
|
+
failed++;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function assertEqual(actual, expected, message) {
|
|
37
|
+
assert(actual === expected, `${message} (expected ${String(expected)}, got ${String(actual)})`);
|
|
38
|
+
}
|
|
39
|
+
/** A minimal GaiaQuestion fixture. */
|
|
40
|
+
const FIXTURE_QUESTION = {
|
|
41
|
+
task_id: 'smoke-001',
|
|
42
|
+
level: 1,
|
|
43
|
+
question: 'What is the capital of France?',
|
|
44
|
+
final_answer: 'Paris',
|
|
45
|
+
file_name: null,
|
|
46
|
+
file_path: null,
|
|
47
|
+
};
|
|
48
|
+
/** Minimal GaiaAgentResult with a given finalAnswer. */
|
|
49
|
+
function makeAgentResult(finalAnswer, turns = 2) {
|
|
50
|
+
return {
|
|
51
|
+
questionId: FIXTURE_QUESTION.task_id,
|
|
52
|
+
finalAnswer,
|
|
53
|
+
turns,
|
|
54
|
+
toolCallsByName: { web_search: 1 },
|
|
55
|
+
totalInputTokens: 100,
|
|
56
|
+
totalOutputTokens: 50,
|
|
57
|
+
wallMs: 1200,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function installFetchMock(responses) {
|
|
61
|
+
let callIndex = 0;
|
|
62
|
+
const original = globalThis.fetch;
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
64
|
+
globalThis.fetch = async (_url, _init) => {
|
|
65
|
+
const resp = responses[Math.min(callIndex, responses.length - 1)];
|
|
66
|
+
callIndex++;
|
|
67
|
+
if (!resp.ok) {
|
|
68
|
+
return {
|
|
69
|
+
ok: false,
|
|
70
|
+
status: resp.status ?? 500,
|
|
71
|
+
text: async () => resp.text ?? 'Internal error',
|
|
72
|
+
json: async () => { throw new Error('not ok'); },
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
ok: true,
|
|
77
|
+
status: 200,
|
|
78
|
+
json: async () => resp.body ?? {},
|
|
79
|
+
text: async () => JSON.stringify(resp.body ?? {}),
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
return () => { globalThis.fetch = original; };
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Build a mock Anthropic response body containing a critic verdict JSON.
|
|
86
|
+
*/
|
|
87
|
+
function mockCriticResponse(verdict, reasoning, suggestedRevision = '') {
|
|
88
|
+
const content = JSON.stringify({ verdict, reasoning, suggestedRevision });
|
|
89
|
+
return {
|
|
90
|
+
content: [{ type: 'text', text: content }],
|
|
91
|
+
usage: { input_tokens: 200, output_tokens: 40 },
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Mock for runGaiaAgent that immediately returns a fixed result.
|
|
96
|
+
* We monkey-patch the module-level import by wrapping runGaiaAgentWithCritic
|
|
97
|
+
* via its options.catalogue approach — but since gaia-agent's runGaiaAgent is
|
|
98
|
+
* imported directly, we mock at the fetch level instead (the agent also calls
|
|
99
|
+
* the Anthropic API, so we intercept there).
|
|
100
|
+
*
|
|
101
|
+
* For the smoke tests we only exercise criticReview directly in Tests 1-6, and
|
|
102
|
+
* use a simplified version of runGaiaAgentWithCritic that pre-supplies a
|
|
103
|
+
* mocked agent result rather than actually calling the API for the agent run.
|
|
104
|
+
*
|
|
105
|
+
* This avoids needing to rewrite the import mechanism just for smoke tests.
|
|
106
|
+
*/
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
// Test 1: critic returns "pass" → no retry
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
async function test1_criticPass() {
|
|
111
|
+
console.log('\nTest 1: critic returns "pass" → no retry');
|
|
112
|
+
const restore = installFetchMock([
|
|
113
|
+
{ ok: true, body: mockCriticResponse('pass', 'Answer is correct.') },
|
|
114
|
+
]);
|
|
115
|
+
try {
|
|
116
|
+
const verdict = await criticReview(FIXTURE_QUESTION, 'Paris', { steps: [{ tool: 'web_search', result: 'Paris is the capital' }], turns: 2 }, { model: 'claude-sonnet-4-6', apiKey: 'test-key' });
|
|
117
|
+
assertEqual(verdict.verdict, 'pass', 'verdict is "pass"');
|
|
118
|
+
assert(verdict.reasoning.length > 0, 'reasoning is non-empty');
|
|
119
|
+
assert(verdict.costUsd >= 0, 'costUsd is non-negative');
|
|
120
|
+
assert(!verdict.error, 'no error flag');
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
restore();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
// Test 2: critic returns "fail" with suggestedRevision
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
async function test2_criticFail() {
|
|
130
|
+
console.log('\nTest 2: critic returns "fail" with suggestedRevision');
|
|
131
|
+
const restore = installFetchMock([
|
|
132
|
+
{
|
|
133
|
+
ok: true,
|
|
134
|
+
body: mockCriticResponse('fail', 'The answer is the wrong city.', 'Paris'),
|
|
135
|
+
},
|
|
136
|
+
]);
|
|
137
|
+
try {
|
|
138
|
+
const verdict = await criticReview(FIXTURE_QUESTION, 'Lyon', { steps: [{ tool: 'web_search', result: 'Lyon is in France' }], turns: 1 }, { model: 'claude-sonnet-4-6', apiKey: 'test-key' });
|
|
139
|
+
assertEqual(verdict.verdict, 'fail', 'verdict is "fail"');
|
|
140
|
+
assert((verdict.suggestedRevision ?? '').length > 0, 'suggestedRevision is non-empty');
|
|
141
|
+
assertEqual(verdict.suggestedRevision, 'Paris', 'suggestedRevision is "Paris"');
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
restore();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// ---------------------------------------------------------------------------
|
|
148
|
+
// Test 3: critic returns "fail" twice → retries exhausted
|
|
149
|
+
// ---------------------------------------------------------------------------
|
|
150
|
+
async function test3_retriesExhausted() {
|
|
151
|
+
console.log('\nTest 3: critic fails twice → retries exhausted, returns last candidate');
|
|
152
|
+
// We test this at the runGaiaAgentWithCritic level.
|
|
153
|
+
// We need to mock BOTH the critic fetch calls AND the agent API calls.
|
|
154
|
+
// Strategy: sequence the mock responses in the order they will be called.
|
|
155
|
+
//
|
|
156
|
+
// Call sequence (with enableCritic=true, maxRetries=1):
|
|
157
|
+
// 1. runGaiaAgent attempt 1 → agent Anthropic API call (returns answer "Lyon")
|
|
158
|
+
// 2. criticReview attempt 1 → critic API call (returns "fail")
|
|
159
|
+
// 3. runGaiaAgent attempt 2 → agent Anthropic API call (returns answer "Marseille")
|
|
160
|
+
// 4. criticReview attempt 2 → critic API call (returns "fail")
|
|
161
|
+
//
|
|
162
|
+
// For simplicity we make the agent calls also return valid Anthropic responses
|
|
163
|
+
// that produce a FINAL_ANSWER (the agent code parses stop_reason=end_turn).
|
|
164
|
+
const agentResponseLyon = {
|
|
165
|
+
id: 'msg_01',
|
|
166
|
+
type: 'message',
|
|
167
|
+
role: 'assistant',
|
|
168
|
+
stop_reason: 'end_turn',
|
|
169
|
+
content: [{ type: 'text', text: 'FINAL_ANSWER: Lyon' }],
|
|
170
|
+
usage: { input_tokens: 150, output_tokens: 20 },
|
|
171
|
+
model: 'claude-haiku-4-5',
|
|
172
|
+
};
|
|
173
|
+
const agentResponseMarseille = {
|
|
174
|
+
id: 'msg_02',
|
|
175
|
+
type: 'message',
|
|
176
|
+
role: 'assistant',
|
|
177
|
+
stop_reason: 'end_turn',
|
|
178
|
+
content: [{ type: 'text', text: 'FINAL_ANSWER: Marseille' }],
|
|
179
|
+
usage: { input_tokens: 150, output_tokens: 20 },
|
|
180
|
+
model: 'claude-haiku-4-5',
|
|
181
|
+
};
|
|
182
|
+
const restore = installFetchMock([
|
|
183
|
+
{ ok: true, body: agentResponseLyon }, // agent call 1
|
|
184
|
+
{ ok: true, body: mockCriticResponse('fail', 'Wrong city.', 'Paris') }, // critic 1
|
|
185
|
+
{ ok: true, body: agentResponseMarseille }, // agent call 2 (retry)
|
|
186
|
+
{ ok: true, body: mockCriticResponse('fail', 'Still wrong.', 'Paris') }, // critic 2
|
|
187
|
+
]);
|
|
188
|
+
try {
|
|
189
|
+
const result = await runGaiaAgentWithCritic(FIXTURE_QUESTION, {
|
|
190
|
+
enableCritic: true,
|
|
191
|
+
apiKey: 'test-key',
|
|
192
|
+
criticOptions: { apiKey: 'test-key', maxRetries: 1 },
|
|
193
|
+
});
|
|
194
|
+
assertEqual(result.retriesAttempted, 1, 'retriesAttempted is 1');
|
|
195
|
+
assertEqual(result.criticVerdicts.length, 2, 'two critic verdicts collected');
|
|
196
|
+
assertEqual(result.criticVerdicts[0].verdict, 'fail', 'first verdict is fail');
|
|
197
|
+
assertEqual(result.criticVerdicts[1].verdict, 'fail', 'second verdict is fail');
|
|
198
|
+
// Last candidate is returned regardless.
|
|
199
|
+
assert(result.finalAnswer !== null, 'finalAnswer is non-null (last candidate returned)');
|
|
200
|
+
}
|
|
201
|
+
finally {
|
|
202
|
+
restore();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// ---------------------------------------------------------------------------
|
|
206
|
+
// Test 4: critic returns "uncertain" → treated as "pass", no retry
|
|
207
|
+
// ---------------------------------------------------------------------------
|
|
208
|
+
async function test4_uncertainAsPass() {
|
|
209
|
+
console.log('\nTest 4: critic returns "uncertain" → treated as pass, no retry');
|
|
210
|
+
const restore = installFetchMock([
|
|
211
|
+
{
|
|
212
|
+
ok: true,
|
|
213
|
+
body: mockCriticResponse('uncertain', 'Cannot verify without more context.'),
|
|
214
|
+
},
|
|
215
|
+
]);
|
|
216
|
+
try {
|
|
217
|
+
const verdict = await criticReview(FIXTURE_QUESTION, 'Paris', { steps: [], turns: 1 }, { model: 'claude-sonnet-4-6', apiKey: 'test-key' });
|
|
218
|
+
assertEqual(verdict.verdict, 'uncertain', 'verdict is "uncertain"');
|
|
219
|
+
// Verify orchestrator treats uncertain as pass (no retry fired).
|
|
220
|
+
// We simulate by checking the logic directly: uncertain !== 'fail', so loop
|
|
221
|
+
// body is skipped. We test it via runGaiaAgentWithCritic with a minimal
|
|
222
|
+
// agent mock that returns a final answer.
|
|
223
|
+
const agentResponseParis = {
|
|
224
|
+
id: 'msg_03',
|
|
225
|
+
type: 'message',
|
|
226
|
+
role: 'assistant',
|
|
227
|
+
stop_reason: 'end_turn',
|
|
228
|
+
content: [{ type: 'text', text: 'FINAL_ANSWER: Paris' }],
|
|
229
|
+
usage: { input_tokens: 100, output_tokens: 15 },
|
|
230
|
+
model: 'claude-haiku-4-5',
|
|
231
|
+
};
|
|
232
|
+
const restore2 = installFetchMock([
|
|
233
|
+
{ ok: true, body: agentResponseParis }, // agent call
|
|
234
|
+
{ ok: true, body: mockCriticResponse('uncertain', 'Cannot verify.') }, // critic
|
|
235
|
+
]);
|
|
236
|
+
try {
|
|
237
|
+
const result = await runGaiaAgentWithCritic(FIXTURE_QUESTION, {
|
|
238
|
+
enableCritic: true,
|
|
239
|
+
apiKey: 'test-key',
|
|
240
|
+
criticOptions: { apiKey: 'test-key', maxRetries: 1 },
|
|
241
|
+
});
|
|
242
|
+
assertEqual(result.retriesAttempted, 0, 'no retries for uncertain verdict');
|
|
243
|
+
assertEqual(result.criticVerdicts.length, 1, 'one critic verdict collected');
|
|
244
|
+
assertEqual(result.criticVerdicts[0].verdict, 'uncertain', 'verdict is uncertain');
|
|
245
|
+
}
|
|
246
|
+
finally {
|
|
247
|
+
restore2();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
finally {
|
|
251
|
+
restore();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// ---------------------------------------------------------------------------
|
|
255
|
+
// Test 5: API error in critic → graceful fallback
|
|
256
|
+
// ---------------------------------------------------------------------------
|
|
257
|
+
async function test5_apiErrorFallback() {
|
|
258
|
+
console.log('\nTest 5: API error in critic → graceful fallback, original candidate returned');
|
|
259
|
+
const restore = installFetchMock([
|
|
260
|
+
{ ok: false, status: 529, text: 'Overloaded' },
|
|
261
|
+
]);
|
|
262
|
+
try {
|
|
263
|
+
const verdict = await criticReview(FIXTURE_QUESTION, 'Paris', { steps: [], turns: 1 }, { model: 'claude-sonnet-4-6', apiKey: 'test-key' });
|
|
264
|
+
// On API error, critic returns uncertain with error flag — does not throw.
|
|
265
|
+
assertEqual(verdict.verdict, 'uncertain', 'verdict is "uncertain" on API error');
|
|
266
|
+
assert(verdict.error === true, 'error flag is set');
|
|
267
|
+
assert(verdict.costUsd === 0, 'costUsd is 0 on error');
|
|
268
|
+
assert(verdict.reasoning.includes('failed'), 'reasoning mentions failure');
|
|
269
|
+
}
|
|
270
|
+
finally {
|
|
271
|
+
restore();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// ---------------------------------------------------------------------------
|
|
275
|
+
// Test 6: malformed JSON from critic → fallback parser
|
|
276
|
+
// ---------------------------------------------------------------------------
|
|
277
|
+
async function test6_malformedJson() {
|
|
278
|
+
console.log('\nTest 6: malformed JSON from critic → fallback parser extracts verdict');
|
|
279
|
+
// Simulate Sonnet returning prose with embedded JSON fragment.
|
|
280
|
+
const malformedBody = {
|
|
281
|
+
content: [{
|
|
282
|
+
type: 'text',
|
|
283
|
+
text: 'After careful review, I believe the answer is wrong. {"verdict":"fail","reasoning":"Incorrect city","suggestedRevision":"Paris"} The agent should try again.',
|
|
284
|
+
}],
|
|
285
|
+
usage: { input_tokens: 180, output_tokens: 60 },
|
|
286
|
+
};
|
|
287
|
+
const restore = installFetchMock([
|
|
288
|
+
{ ok: true, body: malformedBody },
|
|
289
|
+
]);
|
|
290
|
+
try {
|
|
291
|
+
const verdict = await criticReview(FIXTURE_QUESTION, 'Lyon', { steps: [], turns: 1 }, { model: 'claude-sonnet-4-6', apiKey: 'test-key' });
|
|
292
|
+
// Fallback parser should extract "fail" from the embedded JSON.
|
|
293
|
+
assertEqual(verdict.verdict, 'fail', 'fallback parser extracts "fail" verdict');
|
|
294
|
+
assert(!verdict.error, 'no error flag for recoverable parse');
|
|
295
|
+
}
|
|
296
|
+
finally {
|
|
297
|
+
restore();
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
// ---------------------------------------------------------------------------
|
|
301
|
+
// Run all tests
|
|
302
|
+
// ---------------------------------------------------------------------------
|
|
303
|
+
async function main() {
|
|
304
|
+
console.log('=== GAIA Critic Smoke Tests (ADR-135 Track D) ===');
|
|
305
|
+
console.log('All tests use mocked responses — no live API calls.\n');
|
|
306
|
+
try {
|
|
307
|
+
await test1_criticPass();
|
|
308
|
+
await test2_criticFail();
|
|
309
|
+
await test3_retriesExhausted();
|
|
310
|
+
await test4_uncertainAsPass();
|
|
311
|
+
await test5_apiErrorFallback();
|
|
312
|
+
await test6_malformedJson();
|
|
313
|
+
}
|
|
314
|
+
catch (err) {
|
|
315
|
+
console.error('\nUnexpected test runner error:', err);
|
|
316
|
+
process.exit(1);
|
|
317
|
+
}
|
|
318
|
+
console.log(`\n=== Results: ${passed} passed, ${failed} failed ===`);
|
|
319
|
+
if (failed > 0) {
|
|
320
|
+
process.exit(1);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
main().catch(err => {
|
|
324
|
+
console.error(err);
|
|
325
|
+
process.exit(1);
|
|
326
|
+
});
|
|
327
|
+
//# sourceMappingURL=gaia-critic.smoke.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gaia-critic.smoke.js","sourceRoot":"","sources":["../../../src/benchmarks/gaia-critic.smoke.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GAIA Question Decomposer — ADR-135 Track E
|
|
3
|
+
*
|
|
4
|
+
* Decomposes complex GAIA benchmark questions into 1-5 ordered sub-questions
|
|
5
|
+
* that can each be answered with a single tool call, then synthesizes the
|
|
6
|
+
* sub-answers into a final response.
|
|
7
|
+
*
|
|
8
|
+
* Motivation (iter 29 finding): tool quality is the bottleneck on L1 (~20.8%).
|
|
9
|
+
* Bad tools that fail on complex queries may succeed on focused sub-queries.
|
|
10
|
+
* This mimics what humans do at 92% on GAIA (decompose-then-solve).
|
|
11
|
+
* Expected L1 lift: +5-10pp on multi-step questions (~30-40% of L1 set).
|
|
12
|
+
*
|
|
13
|
+
* Design:
|
|
14
|
+
* - NEW standalone file only; NOT wired into gaia-bench.ts to avoid merge
|
|
15
|
+
* conflicts with in-flight iter 29/31/34/35/36 branches.
|
|
16
|
+
* Wiring is a small follow-up PR.
|
|
17
|
+
* - `decomposeQuestion()` — Haiku-cheap classification + decomposition
|
|
18
|
+
* (~$0.0003 per question).
|
|
19
|
+
* - `synthesizeFromSubAnswers()` — Sonnet synthesis from sub-answers
|
|
20
|
+
* (the sub-answers are the hard work; synthesis is just combination).
|
|
21
|
+
* - Atomic questions are returned as-is — no overhead when not needed.
|
|
22
|
+
* - Graceful fallback to atomic on API errors or malformed JSON.
|
|
23
|
+
*
|
|
24
|
+
* Cost discipline:
|
|
25
|
+
* - Decomposition uses claude-haiku-4-5 (~$0.0003/question).
|
|
26
|
+
* - Synthesis uses claude-sonnet-4-6 (~$0.002/question).
|
|
27
|
+
* - Total overhead per question (when decomposed): ~$0.002-0.003.
|
|
28
|
+
*
|
|
29
|
+
* Plugin sync TODO (follow-up PR after gaia-bench wiring):
|
|
30
|
+
* - Update plugins/ruflo-workflows/commands/gaia-run.md with --decompose flag.
|
|
31
|
+
* - Update plugins/ruflo-workflows/skills/gaia-debugging/SKILL.md: add
|
|
32
|
+
* decomposition as a recommended strategy for multi-step failures.
|
|
33
|
+
*
|
|
34
|
+
* Refs: ADR-135, ADR-133, iter 29 finding, #2156
|
|
35
|
+
*/
|
|
36
|
+
export interface DecomposedQuestion {
|
|
37
|
+
/** The original unmodified question text. */
|
|
38
|
+
originalQuestion: string;
|
|
39
|
+
/**
|
|
40
|
+
* Ordered sub-questions in dependency order (1-5).
|
|
41
|
+
* If decomposed=false, contains exactly one entry equal to originalQuestion.
|
|
42
|
+
*/
|
|
43
|
+
subQuestions: string[];
|
|
44
|
+
/**
|
|
45
|
+
* Brief hint for how to combine sub-answers into the final answer.
|
|
46
|
+
* Example: "Multiply the two values found in sub-questions 1 and 2."
|
|
47
|
+
*/
|
|
48
|
+
synthesisHint: string;
|
|
49
|
+
/**
|
|
50
|
+
* true if the question was split into multiple sub-questions;
|
|
51
|
+
* false if it was deemed atomic (single lookup / single computation).
|
|
52
|
+
*/
|
|
53
|
+
decomposed: boolean;
|
|
54
|
+
/** USD spent on the decomposition API call (0 if fallback/atomic). */
|
|
55
|
+
cost: number;
|
|
56
|
+
}
|
|
57
|
+
export interface DecomposerOptions {
|
|
58
|
+
/**
|
|
59
|
+
* Model to use for decomposition classification.
|
|
60
|
+
* Default: 'claude-haiku-4-5' (cheap).
|
|
61
|
+
*/
|
|
62
|
+
model?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Maximum sub-questions to produce when decomposing.
|
|
65
|
+
* Default: 5.
|
|
66
|
+
*/
|
|
67
|
+
maxSubQuestions?: number;
|
|
68
|
+
/** API key override. Falls back to ANTHROPIC_API_KEY env var. */
|
|
69
|
+
apiKey?: string;
|
|
70
|
+
}
|
|
71
|
+
export interface SynthesizerOptions {
|
|
72
|
+
/**
|
|
73
|
+
* Model to use for final-answer synthesis.
|
|
74
|
+
* Default: 'claude-sonnet-4-6'.
|
|
75
|
+
*/
|
|
76
|
+
model?: string;
|
|
77
|
+
/** API key override. Falls back to ANTHROPIC_API_KEY env var. */
|
|
78
|
+
apiKey?: string;
|
|
79
|
+
}
|
|
80
|
+
export interface SynthesisResult {
|
|
81
|
+
/** The synthesized final answer string. */
|
|
82
|
+
finalAnswer: string;
|
|
83
|
+
/** Brief reasoning that led to the final answer. */
|
|
84
|
+
reasoning: string;
|
|
85
|
+
/** USD spent on the synthesis API call. */
|
|
86
|
+
cost: number;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Decomposes a complex question into 1-5 sub-questions in dependency order,
|
|
90
|
+
* OR returns the question as-is if it is already atomic.
|
|
91
|
+
*
|
|
92
|
+
* Uses `claude-haiku-4-5` by default for cheap classification + decomposition
|
|
93
|
+
* (~$0.0003 per question).
|
|
94
|
+
*
|
|
95
|
+
* Heuristics the model uses internally for "should decompose":
|
|
96
|
+
* - Question contains "and", "then", "after", "if X …"
|
|
97
|
+
* - Question contains multiple named entities that must each be looked up
|
|
98
|
+
* - Question asks for a derived/computed answer (X of Y where Y must be found)
|
|
99
|
+
*
|
|
100
|
+
* Graceful degradation: on API errors or malformed JSON, returns the question
|
|
101
|
+
* as atomic so the calling agent can still attempt a direct answer.
|
|
102
|
+
*
|
|
103
|
+
* @param questionText - The full GAIA question text.
|
|
104
|
+
* @param options - Optional overrides (model, maxSubQuestions, apiKey).
|
|
105
|
+
* @returns - DecomposedQuestion with subQuestions and synthesisHint.
|
|
106
|
+
*/
|
|
107
|
+
export declare function decomposeQuestion(questionText: string, options?: DecomposerOptions): Promise<DecomposedQuestion>;
|
|
108
|
+
/**
|
|
109
|
+
* Given a decomposed question and answers to each sub-question, synthesizes
|
|
110
|
+
* a final concise answer.
|
|
111
|
+
*
|
|
112
|
+
* Uses `claude-sonnet-4-6` by default for higher reasoning quality — the
|
|
113
|
+
* sub-answers contain the hard-won information; synthesis is recombination.
|
|
114
|
+
*
|
|
115
|
+
* Graceful degradation: on API errors or malformed JSON, returns the last
|
|
116
|
+
* sub-answer concatenated with reasoning note.
|
|
117
|
+
*
|
|
118
|
+
* @param decomposed - The DecomposedQuestion from `decomposeQuestion()`.
|
|
119
|
+
* @param subAnswers - Array of string answers, one per sub-question.
|
|
120
|
+
* Must be the same length as decomposed.subQuestions.
|
|
121
|
+
* @param options - Optional overrides (model, apiKey).
|
|
122
|
+
* @returns - SynthesisResult with finalAnswer, reasoning, and cost.
|
|
123
|
+
*/
|
|
124
|
+
export declare function synthesizeFromSubAnswers(decomposed: DecomposedQuestion, subAnswers: string[], options?: SynthesizerOptions): Promise<SynthesisResult>;
|
|
125
|
+
//# sourceMappingURL=gaia-decomposer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gaia-decomposer.d.ts","sourceRoot":"","sources":["../../../src/benchmarks/gaia-decomposer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAsCH,MAAM,WAAW,kBAAkB;IACjC,6CAA6C;IAC7C,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,2CAA2C;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;CACd;AA8LD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,kBAAkB,CAAC,CA+D7B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,wBAAwB,CAC5C,UAAU,EAAE,kBAAkB,EAC9B,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,eAAe,CAAC,CAkF1B"}
|