Commit Graph
218 Commits
Author SHA1 Message Date
Dorian a0809565f2 feat(09-03): serve the unified AI bot-setup prompt at GET /api/docs/prompt
CI / check (push) Has been cancelled
- New docsRouter.get('/prompt') resolves the shipped container path
  (server/public/docs/BOTFIGHTS.md) then falls back to the dev-checkout
  path (frontend/public/docs/BOTFIGHTS.md), matching app.ts's publicDir
  derivation pattern
- Substitutes {{ARENA_URL}} with PUBLIC_ARENA_URL when set, otherwise the
  request's own origin, so a cloud agent that curls the prompt gets
  working examples pointed back at the arena it fetched from
- Responds as text/markdown so an agent can pipe the response straight
  into its context
- 5 new Vitest cases: 200+content-type, no leftover {{ARENA_URL}} token,
  PUBLIC_ARENA_URL precedence, origin fallback, YOUR_BOT_ID placeholder
  preserved for the in-app substitution flow
2026-07-30 22:23:20 -04:00
DorianandClaude Fable 5 bf240cef9e fix(09-02): sync migrate.ts DDL with schema.ts — fixes 15 pre-existing auth/tournament test failures
CI / check (push) Failing after 6m12s
Deviation (Rule 1 — auto-fix bug), out-of-scope-but-cheap per plan 09-02's
explicit allowance. server/src/db/migrate.ts (the standalone `pnpm migrate`
CLI script) had drifted from server/src/db/schema.ts: it was missing 7
tables (payments, wallet_connections, bets, tournaments, tournament_entries,
analytics, tournament_matches) and several bots/fights columns (sats_won,
sats_wagered, has_wallet, zaps_received, bot_type, mode, pot_sats,
payout_status, current_season). server/src/db/startup.ts's runMigrations()
(the one actually called from index.ts at server boot) already had the
correct, up-to-date DDL — migrate.ts was the stale duplicate. Brought it
back in sync, column-for-column and table-for-table, against schema.ts.

Route-level tests (auth.test.ts, auth-audit.test.ts, auth-edge.test.ts,
tournaments.test.ts) hit the real db/index.ts singleton against the
on-disk, gitignored server/data/botfights.db, which only startup.ts or
this migrate.ts script populate — vitest itself never runs a migration.
Running `pnpm --filter server migrate` against a fresh DB with the fixed
script now creates all tables/columns; full server suite went from
15 failed / 789 passed to 6 failed / 798 passed, with the remaining 6
all pre-existing timing/perf flakes unrelated to auth (answers.test.ts,
lifecycle.test.ts x2, bot-auth.test.ts, docs.test.ts x2 — CPU-contention
sensitive, matches deferred-items.md's documented flake class).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 22:11:29 -04:00
DorianandClaude Fable 5 635ee39373 feat(09-02): GET /api/auth/me — identity from JWT, never a claimed pubkey (BOT-01)
CI / check (push) Has been cancelled
Adds a JWT-gated, read-only session-restore route. Mirrors POST /login's
projection and 200 body shape exactly so normalizeBotData on the client
is unchanged. extractPubkeyFromAuth (already imported later in the file
for /regenerate-secret) covers missing/malformed/forged/expired/
blacklisted tokens via verifyJwt; deduped the now-redundant import at
the /nostr/session section. All 7 auth-me.test.ts cases pass; tsc clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 22:09:11 -04:00
DorianandClaude Fable 5 e824f4ca7f test(09-02): add failing test for GET /api/auth/me (BOT-01)
Covers missing / malformed / forged / blacklisted / unregistered / valid
JWT cases for the JWT-only identity route that replaces the bare-pubkey
auto-restore path. Route does not exist yet — 6/7 fail as expected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 22:03:18 -04:00
DorianandClaude Fable 5 a95cadaf9e test(09-01): verify x-forwarded-for over a real socket, not just presence
CI / check (push) Failing after 6m14s
The prior test drove the proxying app via Hono's in-process app.request()
harness, which has no real Node socket — so it could only assert the header
was non-empty-or-absent, not that the real client IP round-trips. Spin the
proxying app up with @hono/node-server (real loopback socket) and assert the
upstream actually receives 127.0.0.1/::1, exercising the same
remoteAddress lookup arenaProxy uses in production.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 21:34:13 -04:00
DorianandClaude Fable 5 0511b97cb9 feat(09-01): arena-proxy survives SSE, client-IP forwarding, upstream-down
CI / check (push) Has been cancelled
- Forward client IP via x-forwarded-for/x-real-ip so the canonical arena's
  per-IP rate limiting isn't collapsed to one bucket per node.
- 30s AbortSignal.timeout on non-stream requests; SSE fight streams
  (/api/fights/:id/stream) are exempt (long-lived by design).
- On upstream fetch failure, log and return 502 {error} instead of a
  buffered hang or a 500 stack trace.
- fights.ts: set X-Accel-Buffering: no on the SSE stream response so an
  nginx-fronted arena (nginx-proxy-manager) doesn't buffer live fight events.
- docker-compose.yml: document ARENA_UPSTREAM_URL / TRUSTED_PROXY (commented,
  no active value set here — the canonical arena gets its own compose file
  in a later plan).

TDD: added the SSE/XFF/502 tests, confirmed the 502 test failed against the
prior implementation, then implemented to green (9/9 arena-proxy tests,
17/17 combined with rate-limit.test.ts).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 21:32:57 -04:00
DorianandClaude Fable 5 143ca808e8 feat(09-01): arena-proxy middleware — REST forwarding to canonical arena
CI / check (push) Has been cancelled
Hono middleware that forwards /api/* to ARENA_UPSTREAM_URL when set, with
standalone mode (env unset) and /api/health untouched. Verified end-to-end
against a real second HTTP server: register a bot upstream, read it back
through the proxy, method/query/JSON body forwarded unchanged, inbound Host
header dropped, response content-encoding/content-length stripped.

TDD: 6 tests written first and confirmed failing (module didn't exist),
then implemented to green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 21:30:24 -04:00
Dorian 32e6c19f72 stuff 2026-04-11 19:46:37 +01:00
DorianandClaude Opus 4.6 18e4b05399 fix: practice fights send challenges to polling/webhook bots instead of forcing human mode
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 23:23:37 +00:00
DorianandClaude Opus 4.6 8076d860c7 fix: creator auto-creates as bot (poll mode), auto-upgrade existing human records
The creator was being registered with webhookUrl='http://human.local/' and
isHuman=true. Now uses poll.local and isHuman=false. The auto-upgrade logic
on login also converts any existing creator record from human to bot mode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 22:28:43 +00:00
DorianandClaude Opus 4.6 2e7a039b8b fix: serve /docs/*.md as static files, not SPA fallback
- Add /docs/* route to serve markdown setup guides
- Add md to MIME map and SPA catch-all exclusion
- Normalize BOTFIGHTS.md placeholders to YOUR_BOT_ID/YOUR_BOT_SECRET

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 16:16:44 +00:00
DorianandClaude Opus 4.6 60dd6893be fix: replace download with inline copy-paste setup guide, fix CSP for WASM + Nostr relays
- Replace file download with collapsible inline guide + COPY ALL button
- Guide content has bot_id/secret pre-filled from credentials
- JoinBoutPage: "COPY GUIDE + CREDENTIALS" eagerly loads guide content
- BotProfilePage: webhook/polling guide selector with copy after secret regen
- CSP: add wasm-unsafe-eval to scriptSrc (fixes Kokoro TTS WASM)
- CSP: add wss://relay.damus.io, wss://relay.nostr.band, wss://nos.lol to connectSrc

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 14:06:34 +00:00
DorianandClaude Opus 4.6 cef9f4188f feat: fix setup guide download with embedded credentials + profile page regenerate secret
- downloadSetupGuide() now triggers a real file download with bot_id/secret injected
- Add POST /api/auth/regenerate-secret endpoint (JWT auth, 3/hour rate limit)
- Add "Download Setup Guide" section to BotProfilePage with secret regeneration flow
- Old secret immediately invalidated on regeneration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:35:48 +00:00
DorianandClaude Opus 4.6 2f5fe4f350 test: add regression tests for BUG-4, BUG-6, BUG-7, BUG-F2
Source pattern verification tests:
- BUG-6: webhook calls wrapped in Promise.all (parallel, not sequential)
- BUG-7: SSE maps (spectatorCounts, fightReactions, ssePerIp) cleaned on disconnect
- BUG-4: no raw setTimeout in game code (all use trackedTimeout)
- BUG-F2: no silent .catch(() => {}) in frontend source
43 regression tests total, all passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:35:48 +00:00
DorianandClaude Opus 4.6 a358374d71 test: verify all E2E specs pass, fix flaky tests and creative scoring
- Fix E2E Playwright config: correct port 5173→9101, increase webServer timeout
- Fix signup-bot and signup-human specs: add missing nsec backup step
- Implement scoreCreativeAnswer() heuristic for creative round scoring
- Pass DB ELO to generateMockBotResponse for non-MOCK_BOTS integration tests
- Update challenges tests: all 16 types are now factual (no creative types)
- Fix lifecycle test flakiness: widen ELO correlation tolerance, add timeout
- All 11 E2E specs pass, 770 unit/integration tests pass

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:28:39 +00:00
DorianandClaude Opus 4.6 42d79487a1 test: add odds calculation and retro-moves coverage — 50 tests
Odds: eloProbability, calculateOdds, fractional/American display,
payout calculation, bet validation (30 tests).
Retro moves: RETRO_MOVES data, lookupMove, scoreRetroResponse,
generateRetroChallenge, mock response generation (20 tests).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:46:03 +00:00
DorianandClaude Opus 4.6 2c83858115 fix: correct challenge audit test assertions — actual distribution and crit rates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:38:26 +00:00
DorianandClaude Opus 4.6 cae8f0b83e test: add comprehensive auth audit — 28 tests verify endpoint protection
Covers all 7 admin endpoints (403 without creator pubkey), polling
endpoints (bot auth required), tournament mutations (creator-only),
ranked queue (pubkey ownership), NIP-98 session (signature required),
and 10 public endpoint accessibility checks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:37:46 +00:00
DorianandClaude Opus 4.6 18b92fbbdf test: API auth audit — 18 tests verify auth, rate limiting, validation, error sanitization
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:34:08 +00:00
DorianandClaude Opus 4.6 eac8539825 fix: update hono 4.7.6→4.12.6, @hono/node-server 1.14.1→1.19.10, override tar/serialize-javascript
Resolves 6 high audit vulnerabilities (Hono auth bypass, serveStatic, JWK confusion,
node-tar symlink traversal, serialize-javascript RCE).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:30:56 +00:00
DorianandClaude Opus 4.6 321ccdec7b test: add 39 regression tests covering BUG-1 through BUG-S9
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:25:07 +00:00
DorianandClaude Opus 4.6 6a00cfe324 test: add soak and stress tests — 1000 fights, 50 concurrent queue joins
Soak: 1000 random fights verify zero crashes, ELO bell curve around
1200, and bounded heap growth. Stress: 50 concurrent queue joins
verify no races, no duplicates, correct rejoin behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:20:50 +00:00
DorianandClaude Opus 4.6 27b3b89424 test: add payment/betting edge cases — concurrent bets, draw refunds, validation
17 tests covering: simultaneous bet placement, draw refund mechanics,
bet validation bounds, extreme ELO odds, Cashu token rejection, and
escrow lifecycle leak prevention.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:17:55 +00:00
DorianandClaude Opus 4.6 f15504b400 test: add auth registration edge cases — concurrent names, expired JWT, NIP-98 tampering
Tests concurrent same-name registration (exactly one succeeds),
case-insensitive name collisions, expired JWT rejection, NIP-98
pubkey mismatch, and duplicate pubkey prevention.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:15:13 +00:00
DorianandClaude Opus 4.6 5799ff60d3 test: auth & registration edge cases — unicode names, shared URLs
8 new tests: unicode/emoji/diacritics in bot names rejected, special
chars rejected, same webhook URL allowed, pubkey hex validation,
missing required fields rejected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:11:12 +00:00
DorianandClaude Opus 4.6 2dd09fb954 test: add simultaneous KO and negative ELO edge cases
Adds tests for both-bots-at-0-HP tiebreaker asymmetry (botA penalized
first) and verifies ELO can go negative when 0-rated bot loses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:10:49 +00:00
DorianandClaude Opus 4.6 ffad432e5b test: 10-round double timeout simulation — draw, equal HP, no loops
Simulates both bots timing out every round for 10 rounds. Verifies
zero damage per round, HP unchanged at 200, draw outcome.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:10:15 +00:00
DorianandClaude Opus 4.6 9346b6b260 test: add ELO extremes and challenge rotation edge cases
ELO: 0v0, 9999v1 upset, 9999v1 expected, NaN/Infinity check.
Challenge rotation: 16 unique types, reset after exhaustion,
filter exclusion works. Total: 24 edge case tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:09:36 +00:00
DorianandClaude Opus 4.6 135bf644fa test: add 17 fight engine edge case tests
Covers: identical answers (speed tiebreaker), 2000-char answers,
null/empty/whitespace answers, unicode/emoji, HTTP errors, double
timeout/error, both-wrong draws, correct-beats-wrong regardless of
speed, speed advantage margin, arena modifier damage, combo stacks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:07:20 +00:00
DorianandClaude Opus 4.6 3c5c6c6b95 fix: improve graceful shutdown — stop loop, drain fights, clear all state
Shutdown now: stops background fight loop, waits up to 15s for active
fights to drain (polling every 500ms), clears human + poll pending
challenges, clears bet escrow. Added clearEscrow() to betting.ts and
5 tests verifying cleanup functions and correct shutdown order.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:54:10 +00:00
DorianandClaude Opus 4.6 4134a27ea6 feat: improve graceful shutdown — stop bg loop, drain fights, clear state
Shutdown now: 1) stops background fight loop, 2) waits up to 15s for
active fights to finish, 3) cancels pending human + poll challenges,
4) clears bet escrow. Added clearEscrow() to betting.ts. Tests verify
each cleanup function and shutdown sequence ordering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:53:39 +00:00
DorianandClaude Opus 4.6 023a1a58a9 test: verify orphaned fight cleanup cancels stale live fights
Add 3 tests for cleanupOrphanedFights: verifies db.update sets
status='cancelled' with endedAt on stale live fights, returns 0
on success, and propagates DB errors correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:49:27 +00:00
DorianandClaude Opus 4.6 9b0d251d1c fix: sanitize error responses to prevent internal detail leakage
Add sanitizeError() helper that strips file paths, stack traces, SQLite
errors, and system errors from messages before returning them to clients.
Applied to all route-level catch blocks in payments, queue, fights, and
admin routes. Includes 12 tests for the sanitizer and static analysis
test verifying no route files leak raw err.message.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:46:38 +00:00
DorianandClaude Opus 4.6 1b1f9eb2d7 chore: add composite (is_active, elo_rating) index for leaderboard queries
All individual indexes from plan already existed. Added missing composite
index that covers WHERE is_active=1 ORDER BY elo_rating DESC pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:41:30 +00:00
DorianandClaude Opus 4.6 d3bb00c5c8 feat: add per-phase timing instrumentation to fight orchestration
Log timing for each round phase: webhook calls, scoring, DB operations,
and total round time. Also log finalize transaction time. Uses logger
with 'perf' category for easy filtering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:35:42 +00:00
DorianandClaude Opus 4.6 dc9884e27e test: verify wallet disconnect wipes connection data from DB
Add test confirming disconnect-wallet deletes walletConnections rows
and sets hasWallet=false on the bot record.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:33:50 +00:00
DorianandClaude Opus 4.6 b1e86843a7 test: audit AES-256-GCM crypto with 7 test cases
Verify random IV (same plaintext encrypts differently), ciphertext
format (iv:authTag:encrypted), auth tag tamper detection, encrypted
data tamper detection, empty string handling, and unicode support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:33:08 +00:00
DorianandClaude Opus 4.6 c5744f5984 test: pentest payment edge cases with 10 attack vector tests
Cover amount=0, over-max (999999999), zap non-winner, zap unfinished
fight, invalid wallet method, empty cashu token, claim nonexistent
payment, confirm already-confirmed, confirm outbound payment, claim
payment with no token.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:32:19 +00:00
DorianandClaude Opus 4.6 2fea2bf8c9 test: verify error responses never leak stack traces or file paths
Add tests confirming production error handler sanitizes all internal
errors (ENOENT, stack traces, file paths). Add static analysis test
verifying no route file passes err.stack to c.json() responses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:30:55 +00:00
DorianandClaude Opus 4.6 21bb46c1b0 test: verify admin endpoints require creator pubkey on all routes
Test all 7 admin endpoints (stats, bots, deactivate, activate,
reset-elo, fights, backup) reject non-creator pubkeys and missing
pubkeys with 403. Verifies global middleware guard works correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:29:08 +00:00
DorianandClaude Opus 4.6 d4c51f0aac fix: tighten auth rate limits to 10/min and add rate limit tests
Reduce login and nostr/session rate limits from 30 to 10 requests per
minute per IP to prevent brute-force attacks. Add tests verifying 429
response after exceeding the limit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:28:38 +00:00
DorianandClaude Opus 4.6 9de47fd760 test: add timing attack tests for bot-auth and use timingSafeEqual
Replace manual XOR loop with Node's native crypto.timingSafeEqual for
constant-time secret comparison. Add tests verifying identical error
messages for wrong secrets and <1ms response time variance across 100
requests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:26:39 +00:00
DorianandClaude Opus 4.6 5bf557ba6a fix: only trust proxy headers in rate-limit when TRUSTED_PROXY is set
X-Forwarded-For, X-Real-IP, and CF-Connecting-IP headers were
blindly trusted, allowing attackers to bypass rate limiting by
spoofing different IPs. Now only trusted when TRUSTED_PROXY env
var is configured. Falls back to Node.js socket remoteAddress.

Add tests verifying proxy headers are ignored without TRUSTED_PROXY
and respected when it is set.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:23:10 +00:00
DorianandClaude Opus 4.6 0131949643 fix: harden SSRF protection and add comprehensive tests
Fix gaps in isAllowedWebhookUrl: IPv6 bracket stripping for [::1],
[fe80::], [::ffff:7f00:1]; block 0.0.0.0 and [::] (IPv6 all-zeros);
handle URL-parser normalized ::ffff:7fxx IPv6-mapped localhost.

Add 20 SSRF test cases covering: file://, gopher://, data: schemes,
localhost, 127.0.0.1, 10.x, 172.16-31.x, 192.168.x, IPv6 ::1,
fe80::, fc00::/fd00::, octal/decimal IP bypass, metadata IP
169.254.169.254, .localhost TLD, overly long URLs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:21:16 +00:00
DorianandClaude Opus 4.6 2051a95e13 refactor: add centralized Zod validators for all API inputs
Create server/src/lib/validators.ts with reusable schemas for all API
inputs (auth, fights, bets, payments, tournaments, queue, docs).
Import and use in all route handlers, replacing inline validation.
Add formatZodError helper for user-friendly error messages.
77 test cases in validators.test.ts cover valid, invalid, boundary,
and attack inputs (SQL injection, XSS, prototype pollution).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:16:04 +00:00
DorianandClaude Opus 4.6 55d0f84251 chore: pin all dependency versions for reproducible builds
Remove ^ prefix from all 33 dependencies across root, server, and
frontend package.json files. Lockfile regenerated and verified with
pnpm install --frozen-lockfile.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 06:21:16 +00:00
DorianandClaude Opus 4.6 e2dc2bbd70 feat: add eslint-plugin-security rules for static analysis
Adds 12 security-focused ESLint rules (unsafe-regex, eval, timing
attacks, child-process, bidi-characters, etc). One legitimate
non-literal RegExp in answers.ts suppressed with inline comment.
CI already runs pnpm lint + pnpm audit for SAST coverage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 05:26:10 +00:00
DorianandClaude Opus 4.6 5e40221a2f test: SSE, polling, human, and concurrent fight integration tests
14 integration tests covering full fight lifecycle with real in-memory
DB: SSE event ordering, polling bot challenge/response flow, human
player response submission, and 3 concurrent fights without interference.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 05:10:27 +00:00
DorianandClaude Opus 4.6 41c66d7732 test: full fight flow integration test with real in-memory DB
8 tests covering: complete fight lifecycle, HP progression, ELO
updates, concurrent fight prevention, round data validity, ELO
conservation, status transitions, and win streak tracking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 05:00:25 +00:00
DorianandClaude Opus 4.6 fc00490d61 test: speed meta analysis — 50ms gap wins 95.4% when both correct
Critical finding: when all bots answer correctly, even a 50ms speed
advantage wins 95.4% of fights. At 100ms+ gap it's 100% deterministic.
ELO separation reaches 450+ after just 50 fights. Speed completely
dominates the "all correct" meta.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:56:01 +00:00