claude-flow 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.
Files changed (58) hide show
  1. package/package.json +1 -1
  2. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-agent-planning.smoke.d.ts +18 -0
  3. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-agent-planning.smoke.js +253 -0
  4. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-agent.d.ts +198 -0
  5. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-agent.js +651 -0
  6. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-causal-memory.d.ts +133 -0
  7. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-causal-memory.js +281 -0
  8. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-causal-memory.smoke.d.ts +22 -0
  9. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-causal-memory.smoke.js +300 -0
  10. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-convergence.d.ts +138 -0
  11. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-convergence.js +260 -0
  12. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-convergence.smoke.d.ts +19 -0
  13. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-convergence.smoke.js +246 -0
  14. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-critic.d.ts +123 -0
  15. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-critic.js +312 -0
  16. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-critic.smoke.d.ts +21 -0
  17. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-critic.smoke.js +327 -0
  18. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-decomposer.d.ts +125 -0
  19. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-decomposer.js +350 -0
  20. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-decomposer.smoke.d.ts +21 -0
  21. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-decomposer.smoke.js +228 -0
  22. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-e2e-smoke.d.ts +27 -0
  23. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-e2e-smoke.js +136 -0
  24. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-extract.smoke.d.ts +45 -0
  25. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-extract.smoke.js +242 -0
  26. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-hardness/features.d.ts +46 -0
  27. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-hardness/features.js +170 -0
  28. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-hardness/predictor.d.ts +105 -0
  29. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-hardness/predictor.js +260 -0
  30. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-hardness/predictor.smoke.d.ts +20 -0
  31. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-hardness/predictor.smoke.js +235 -0
  32. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-hardness/train-data-loader.d.ts +51 -0
  33. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-hardness/train-data-loader.js +179 -0
  34. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-judge.d.ts +88 -0
  35. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-judge.js +437 -0
  36. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-loader.d.ts +87 -0
  37. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-loader.js +326 -0
  38. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/file_read.d.ts +35 -0
  39. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/file_read.js +403 -0
  40. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/grounded_query.d.ts +126 -0
  41. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/grounded_query.js +225 -0
  42. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/index.d.ts +32 -0
  43. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/index.js +36 -0
  44. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/types.d.ts +62 -0
  45. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/types.js +12 -0
  46. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/web_search.d.ts +30 -0
  47. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-tools/web_search.js +210 -0
  48. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-voting.d.ts +88 -0
  49. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-voting.js +297 -0
  50. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-voting.smoke.d.ts +20 -0
  51. package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-voting.smoke.js +332 -0
  52. package/v3/@claude-flow/cli/dist/src/commands/gaia-bench.d.ts +40 -0
  53. package/v3/@claude-flow/cli/dist/src/commands/gaia-bench.js +597 -0
  54. package/v3/@claude-flow/cli/dist/src/commands/index.js +2 -0
  55. package/v3/@claude-flow/cli/dist/src/commands/init.js +41 -4
  56. package/v3/@claude-flow/cli/dist/src/init/executor.js +25 -6
  57. package/v3/@claude-flow/cli/dist/src/init/mcp-generator.js +9 -4
  58. package/v3/@claude-flow/cli/package.json +1 -1
@@ -0,0 +1,88 @@
1
+ /**
2
+ * GAIA Voting — ADR-135 Track A
3
+ *
4
+ * Multi-attempt self-consistency voting wrapper around `runGaiaAgent`.
5
+ *
6
+ * Algorithm:
7
+ * 1. Spawn N parallel `runGaiaAgent` calls, each with a distinct system-prompt
8
+ * seed (web-first / code-first / cautious) and varied temperature (0.3/0.5/0.7).
9
+ * 2. Collect all N final answers; filter out nulls.
10
+ * 3. Normalize each answer: lowercase, trim, strip punctuation, normalize numbers.
11
+ * 4. Count by normalized value; the highest-count non-null wins (majority vote).
12
+ * 5. Tie-break: pick the attempt whose normalized answer won and has the lowest
13
+ * error count (null/timed-out attempts score worst).
14
+ * 6. All-disagree: pick the attempt with the lowest error/timeout count.
15
+ * 7. All null: return null answer.
16
+ *
17
+ * Diversification system-prompt seeds (one per attempt, cycling if N > 3):
18
+ * - "web-first" — prefer web_search before reasoning
19
+ * - "code-first" — prefer code_exec/calculator before web
20
+ * - "cautious" — step-by-step, verify each sub-claim before answering
21
+ *
22
+ * Temperature schedule (cycling if N > 3):
23
+ * - attempt 0: 0.3 (conservative)
24
+ * - attempt 1: 0.5 (balanced)
25
+ * - attempt 2: 0.7 (exploratory)
26
+ *
27
+ * Expected L1 lift per ADR-135: +5-10pp.
28
+ * Cost: N× per question (default N=3 → ~3× per question).
29
+ *
30
+ * Refs: ADR-135, ADR-133, #2156
31
+ */
32
+ import { type GaiaAgentResult } from './gaia-agent.js';
33
+ import type { GaiaQuestion } from './gaia-loader.js';
34
+ export interface VotingResult extends GaiaAgentResult {
35
+ /** All individual attempt results (includes failed/null attempts). */
36
+ attempts: GaiaAgentResult[];
37
+ /**
38
+ * How the winner was decided:
39
+ * - 'majority' — at least 2 attempts agreed on the winning answer
40
+ * - 'highest-confidence' — all attempts disagreed; winner had fewest errors/timeouts
41
+ * - 'all-disagree-retry' — all non-null attempts gave different answers (same as highest-confidence)
42
+ * - 'sole-survivor' — only one non-null attempt; used directly
43
+ */
44
+ votingMethod: 'majority' | 'highest-confidence' | 'all-disagree-retry' | 'sole-survivor';
45
+ /** How many attempts produced the winning (normalized) answer. */
46
+ agreementCount: number;
47
+ }
48
+ export interface VotingOptions {
49
+ /** Number of parallel attempts (default: 3). */
50
+ attempts?: number;
51
+ /**
52
+ * Optional custom system-prompt seed overrides per attempt (index-aligned).
53
+ * Defaults to cycling through STRATEGY_SEEDS.
54
+ */
55
+ diversityPromptSeeds?: string[];
56
+ /**
57
+ * Number of attempts to run in parallel (default: attempts — full parallel).
58
+ * Values < attempts cause sequential batches (useful for rate-limit avoidance).
59
+ */
60
+ parallelism?: number;
61
+ /** Model ID (default: 'claude-haiku-4-5'). */
62
+ model?: string;
63
+ /** Max agent turns per attempt (default: 8). */
64
+ maxTurns?: number;
65
+ /** Anthropic API key (resolved automatically if omitted). */
66
+ apiKey?: string;
67
+ }
68
+ /**
69
+ * Normalize a raw answer string for voting comparison.
70
+ *
71
+ * Steps:
72
+ * 1. Lowercase + trim.
73
+ * 2. Collapse internal whitespace.
74
+ * 3. Strip leading/trailing punctuation (commas, periods, quotes, etc.).
75
+ * 4. Normalize numeric representations: "1,234" → "1234", "1.0" → "1",
76
+ * "1.50" → "1.5".
77
+ */
78
+ export declare function normalizeAnswer(raw: string): string;
79
+ /**
80
+ * Run a GAIA question N times in parallel with diversified strategies,
81
+ * then majority-vote on the answer.
82
+ *
83
+ * @param question The GAIA question to answer.
84
+ * @param options Voting + agent options.
85
+ * @returns VotingResult containing the winning answer and all attempt traces.
86
+ */
87
+ export declare function runGaiaAgentWithVoting(question: GaiaQuestion, options?: VotingOptions): Promise<VotingResult>;
88
+ //# sourceMappingURL=gaia-voting.d.ts.map
@@ -0,0 +1,297 @@
1
+ /**
2
+ * GAIA Voting — ADR-135 Track A
3
+ *
4
+ * Multi-attempt self-consistency voting wrapper around `runGaiaAgent`.
5
+ *
6
+ * Algorithm:
7
+ * 1. Spawn N parallel `runGaiaAgent` calls, each with a distinct system-prompt
8
+ * seed (web-first / code-first / cautious) and varied temperature (0.3/0.5/0.7).
9
+ * 2. Collect all N final answers; filter out nulls.
10
+ * 3. Normalize each answer: lowercase, trim, strip punctuation, normalize numbers.
11
+ * 4. Count by normalized value; the highest-count non-null wins (majority vote).
12
+ * 5. Tie-break: pick the attempt whose normalized answer won and has the lowest
13
+ * error count (null/timed-out attempts score worst).
14
+ * 6. All-disagree: pick the attempt with the lowest error/timeout count.
15
+ * 7. All null: return null answer.
16
+ *
17
+ * Diversification system-prompt seeds (one per attempt, cycling if N > 3):
18
+ * - "web-first" — prefer web_search before reasoning
19
+ * - "code-first" — prefer code_exec/calculator before web
20
+ * - "cautious" — step-by-step, verify each sub-claim before answering
21
+ *
22
+ * Temperature schedule (cycling if N > 3):
23
+ * - attempt 0: 0.3 (conservative)
24
+ * - attempt 1: 0.5 (balanced)
25
+ * - attempt 2: 0.7 (exploratory)
26
+ *
27
+ * Expected L1 lift per ADR-135: +5-10pp.
28
+ * Cost: N× per question (default N=3 → ~3× per question).
29
+ *
30
+ * Refs: ADR-135, ADR-133, #2156
31
+ */
32
+ import { runGaiaAgent, } from './gaia-agent.js';
33
+ import { createDefaultToolCatalogue } from './gaia-tools/index.js';
34
+ // ---------------------------------------------------------------------------
35
+ // Constants
36
+ // ---------------------------------------------------------------------------
37
+ /** System-prompt seeds injected per attempt to diversify exploration strategy. */
38
+ const STRATEGY_SEEDS = [
39
+ 'web-first',
40
+ 'code-first',
41
+ 'cautious',
42
+ ];
43
+ /** Temperature schedule (cycling if N > 3). */
44
+ const TEMP_SCHEDULE = [0.3, 0.5, 0.7];
45
+ // ---------------------------------------------------------------------------
46
+ // Answer normalization
47
+ // ---------------------------------------------------------------------------
48
+ /**
49
+ * Normalize a raw answer string for voting comparison.
50
+ *
51
+ * Steps:
52
+ * 1. Lowercase + trim.
53
+ * 2. Collapse internal whitespace.
54
+ * 3. Strip leading/trailing punctuation (commas, periods, quotes, etc.).
55
+ * 4. Normalize numeric representations: "1,234" → "1234", "1.0" → "1",
56
+ * "1.50" → "1.5".
57
+ */
58
+ export function normalizeAnswer(raw) {
59
+ if (!raw)
60
+ return '';
61
+ let s = raw.trim().toLowerCase();
62
+ // Collapse internal whitespace
63
+ s = s.replace(/\s+/g, ' ');
64
+ // Strip surrounding quotes
65
+ s = s.replace(/^["'`]+|["'`]+$/g, '');
66
+ // Strip leading/trailing punctuation (but not internal hyphens or dots)
67
+ s = s.replace(/^[.,;:!?]+|[.,;:!?]+$/g, '');
68
+ // Normalize thousands-separated numbers: "1,234" → "1234"
69
+ s = s.replace(/(\d),(\d)/g, '$1$2');
70
+ // Normalize trailing zeros after decimal: "1.50" → "1.5", "2.0" → "2"
71
+ s = s.replace(/(\.\d*?)0+$/, '$1').replace(/\.$/, '');
72
+ return s.trim();
73
+ }
74
+ // ---------------------------------------------------------------------------
75
+ // Build per-attempt system prompt
76
+ // ---------------------------------------------------------------------------
77
+ /**
78
+ * Returns a diversified system prompt for the given attempt index.
79
+ *
80
+ * The base prompt (from gaia-agent.ts) is supplemented with a strategy hint
81
+ * so each attempt explores the problem from a different angle.
82
+ */
83
+ function buildDiversifiedSystemPrompt(seed) {
84
+ const strategyHints = {
85
+ 'web-first': [
86
+ 'STRATEGY: Prefer web_search as your first tool call.',
87
+ 'Search for relevant facts before attempting to reason from memory.',
88
+ 'Verify key claims via search before finalising your answer.',
89
+ ].join(' '),
90
+ 'code-first': [
91
+ 'STRATEGY: Prefer code_exec or calculator tools for numerical or logical steps.',
92
+ 'Write and run code to derive answers whenever possible rather than estimating.',
93
+ 'Fall back to web_search only if computation is insufficient.',
94
+ ].join(' '),
95
+ 'cautious': [
96
+ 'STRATEGY: Work step-by-step and verify each sub-claim before proceeding.',
97
+ 'If unsure about an intermediate fact, use a tool to confirm it.',
98
+ 'Only output FINAL_ANSWER when you have high confidence in every step.',
99
+ ].join(' '),
100
+ };
101
+ return strategyHints[seed] ?? strategyHints['cautious'];
102
+ }
103
+ // ---------------------------------------------------------------------------
104
+ // Single attempt runner with strategy injection
105
+ // ---------------------------------------------------------------------------
106
+ /**
107
+ * Run a single GAIA agent attempt with a specific strategy seed and temperature.
108
+ *
109
+ * NOTE: The current `runGaiaAgent` API does not expose a `temperature` or
110
+ * `systemPromptSuffix` parameter. We achieve diversification by:
111
+ * 1. Injecting a strategy hint via `GaiaAgentOptions.catalogue` wrapping
112
+ * (future work — catalogue is a no-op here until gaia-agent supports suffix).
113
+ * 2. Appending the hint to the question text as a prefixed instruction when
114
+ * the strategy is non-default. This is the simplest approach that does
115
+ * not require modifying gaia-agent.ts.
116
+ *
117
+ * Temperature diversification is logged for audit but cannot be passed through
118
+ * the current API. Track B (prompt engineering) will extend the API signature.
119
+ */
120
+ async function runAttempt(question, attemptIndex, seed, temperature, options) {
121
+ // Inject strategy hint into the question text (cheapest injection point
122
+ // that avoids API changes). The model sees this as part of the user turn.
123
+ const strategyHint = buildDiversifiedSystemPrompt(seed);
124
+ const augmentedQuestion = {
125
+ ...question,
126
+ // Prefix with a strategy instruction block the model will read first.
127
+ question: `[Strategy: ${strategyHint}]\n\n${question.question}`,
128
+ // Keep task_id unique per attempt for trace attribution.
129
+ task_id: `${question.task_id}__attempt${attemptIndex}`,
130
+ };
131
+ // temperature and seed are logged for diagnostics but not yet wired into
132
+ // the underlying fetch call (gaia-agent.ts does not expose temperature).
133
+ // When gaia-agent.ts gains a `temperature` option this is where we pass it.
134
+ void temperature; // intentional no-op until API extended
135
+ return runGaiaAgent(augmentedQuestion, {
136
+ model: options.model,
137
+ maxTurns: options.maxTurns,
138
+ apiKey: options.apiKey,
139
+ // Use a fresh catalogue per attempt to avoid state cross-contamination.
140
+ catalogue: createDefaultToolCatalogue(),
141
+ });
142
+ }
143
+ // ---------------------------------------------------------------------------
144
+ // Core voting function
145
+ // ---------------------------------------------------------------------------
146
+ /**
147
+ * Run a GAIA question N times in parallel with diversified strategies,
148
+ * then majority-vote on the answer.
149
+ *
150
+ * @param question The GAIA question to answer.
151
+ * @param options Voting + agent options.
152
+ * @returns VotingResult containing the winning answer and all attempt traces.
153
+ */
154
+ export async function runGaiaAgentWithVoting(question, options = {}) {
155
+ const { attempts: numAttempts = 3, diversityPromptSeeds, parallelism, model, maxTurns, apiKey, } = options;
156
+ const effectiveParallelism = parallelism ?? numAttempts;
157
+ const wallStart = Date.now();
158
+ // Build per-attempt seeds and temperatures
159
+ const seeds = Array.from({ length: numAttempts }, (_, i) => diversityPromptSeeds?.[i] ?? STRATEGY_SEEDS[i % STRATEGY_SEEDS.length]);
160
+ const temps = Array.from({ length: numAttempts }, (_, i) => TEMP_SCHEDULE[i % TEMP_SCHEDULE.length]);
161
+ // Run attempts in batches of `effectiveParallelism`
162
+ const allAttempts = [];
163
+ for (let batchStart = 0; batchStart < numAttempts; batchStart += effectiveParallelism) {
164
+ const batchEnd = Math.min(batchStart + effectiveParallelism, numAttempts);
165
+ const batchIndices = Array.from({ length: batchEnd - batchStart }, (_, i) => batchStart + i);
166
+ const batchResults = await Promise.all(batchIndices.map((i) => runAttempt(question, i, seeds[i], temps[i], { model, maxTurns, apiKey })));
167
+ allAttempts.push(...batchResults);
168
+ }
169
+ // -------------------------------------------------------------------------
170
+ // Voting
171
+ // -------------------------------------------------------------------------
172
+ // Normalize answers; map each attempt to its normalized form (or null).
173
+ const normalized = allAttempts.map((a) => a.finalAnswer !== null ? normalizeAnswer(a.finalAnswer) : null);
174
+ // Count votes for each non-null normalized answer.
175
+ const voteCounts = new Map();
176
+ for (const n of normalized) {
177
+ if (n !== null && n !== '') {
178
+ voteCounts.set(n, (voteCounts.get(n) ?? 0) + 1);
179
+ }
180
+ }
181
+ // Aggregate token totals across all attempts.
182
+ const totalInputTokens = allAttempts.reduce((s, a) => s + a.totalInputTokens, 0);
183
+ const totalOutputTokens = allAttempts.reduce((s, a) => s + a.totalOutputTokens, 0);
184
+ const totalTurns = allAttempts.reduce((s, a) => s + a.turns, 0);
185
+ // Base result fields (shared across all voting paths).
186
+ const baseResult = {
187
+ questionId: question.task_id,
188
+ turns: totalTurns,
189
+ toolCallsByName: mergeToolCallCounts(allAttempts),
190
+ totalInputTokens,
191
+ totalOutputTokens,
192
+ wallMs: Date.now() - wallStart,
193
+ attempts: allAttempts,
194
+ };
195
+ // Case 1: All answers are null/empty.
196
+ if (voteCounts.size === 0) {
197
+ return {
198
+ ...baseResult,
199
+ finalAnswer: null,
200
+ votingMethod: 'majority',
201
+ agreementCount: 0,
202
+ };
203
+ }
204
+ // Find the maximum vote count.
205
+ let maxVotes = 0;
206
+ for (const count of voteCounts.values()) {
207
+ if (count > maxVotes)
208
+ maxVotes = count;
209
+ }
210
+ // Collect all answers that achieved the maximum vote count.
211
+ const winners = [];
212
+ for (const [answer, count] of voteCounts.entries()) {
213
+ if (count === maxVotes)
214
+ winners.push(answer);
215
+ }
216
+ // Case 2: Clear majority (or all agree).
217
+ if (maxVotes > 1) {
218
+ // Pick the first winner; if multiple tie, pick lexicographically smallest for determinism.
219
+ const winnerNorm = winners.sort()[0];
220
+ const winningAttemptIndex = normalized.findIndex((n) => n === winnerNorm);
221
+ const winningAttempt = allAttempts[winningAttemptIndex];
222
+ return {
223
+ ...baseResult,
224
+ finalAnswer: winningAttempt.finalAnswer,
225
+ votingMethod: 'majority',
226
+ agreementCount: maxVotes,
227
+ };
228
+ }
229
+ // Case 3: All non-null attempts disagree (maxVotes === 1, voteCounts.size > 1).
230
+ // Pick the attempt with the best quality signal: fewest errors + not timed-out.
231
+ if (voteCounts.size === 1) {
232
+ // Only one unique answer exists — sole survivor or unanimous.
233
+ const soleSurvivor = winners[0];
234
+ const survivorIndex = normalized.findIndex((n) => n === soleSurvivor);
235
+ const survivorAttempt = allAttempts[survivorIndex];
236
+ return {
237
+ ...baseResult,
238
+ finalAnswer: survivorAttempt.finalAnswer,
239
+ votingMethod: 'sole-survivor',
240
+ agreementCount: 1,
241
+ };
242
+ }
243
+ // All disagree: pick highest-confidence attempt.
244
+ const bestAttempt = pickHighestConfidence(allAttempts, normalized);
245
+ const votingMethod = numAttempts >= 3 ? 'all-disagree-retry' : 'highest-confidence';
246
+ return {
247
+ ...baseResult,
248
+ finalAnswer: bestAttempt.finalAnswer,
249
+ votingMethod,
250
+ agreementCount: 1,
251
+ };
252
+ }
253
+ // ---------------------------------------------------------------------------
254
+ // Helpers
255
+ // ---------------------------------------------------------------------------
256
+ /**
257
+ * Pick the "highest-confidence" attempt from a set of all-disagreeing results.
258
+ *
259
+ * Confidence heuristic (lower score = better):
260
+ * - Timed-out attempt: +1000
261
+ * - Error present: +100
262
+ * - null finalAnswer: +500
263
+ * - turns used: +turns (fewer turns = more direct answer)
264
+ */
265
+ function pickHighestConfidence(attempts, normalized) {
266
+ let bestScore = Infinity;
267
+ let bestIndex = 0;
268
+ for (let i = 0; i < attempts.length; i++) {
269
+ const a = attempts[i];
270
+ let score = 0;
271
+ if (a.timedOut)
272
+ score += 1000;
273
+ if (a.error)
274
+ score += 100;
275
+ if (normalized[i] === null || normalized[i] === '')
276
+ score += 500;
277
+ score += a.turns;
278
+ if (score < bestScore) {
279
+ bestScore = score;
280
+ bestIndex = i;
281
+ }
282
+ }
283
+ return attempts[bestIndex];
284
+ }
285
+ /**
286
+ * Merge per-tool call counts across all attempts.
287
+ */
288
+ function mergeToolCallCounts(attempts) {
289
+ const merged = {};
290
+ for (const a of attempts) {
291
+ for (const [tool, count] of Object.entries(a.toolCallsByName)) {
292
+ merged[tool] = (merged[tool] ?? 0) + count;
293
+ }
294
+ }
295
+ return merged;
296
+ }
297
+ //# sourceMappingURL=gaia-voting.js.map
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Smoke tests for gaia-voting.ts — ADR-135 Track A
3
+ *
4
+ * All tests are mock-based (no live API calls, no HF token, $0 cost).
5
+ *
6
+ * Test matrix:
7
+ * 1. Clear majority — { "Paris", "Paris", "London" } → "Paris", agreementCount=2, method="majority"
8
+ * 2. All disagree — { "A", "B", "C" } → best-confidence pick, method="all-disagree-retry"
9
+ * 3. All null — { null, null, null } → finalAnswer=null, agreementCount=0
10
+ * 4. Sole survivor — { null, null, "Berlin" } → "Berlin", method="sole-survivor"
11
+ * 5. Normalization — " Paris. " vs "paris" → same normalized key
12
+ * 6. Numeric normalization — "1,234" vs "1234" → same key
13
+ * 7. Diversification — confirm seeds/temps vary per attempt
14
+ * 8. Unanimous 3-way — { "Rome", "Rome", "Rome" } → "Rome", agreementCount=3
15
+ *
16
+ * Refs: ADR-135, ADR-133
17
+ */
18
+ declare function runSmoke(): Promise<void>;
19
+ export { runSmoke };
20
+ //# sourceMappingURL=gaia-voting.smoke.d.ts.map