Commit Graph
300 Commits
Author SHA1 Message Date
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
DorianandClaude Opus 4.6 9c55850b70 test: tier balance analysis — system well-balanced across all tiers
Same-tier: ~50/50 win rates. Adjacent tiers: 70-93% higher-tier wins.
2-tier gap: 87-99% higher wins. K=32 ELO factor appropriate.
Legend vs Platinum: 99% win rate confirms clear skill separation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:54:37 +00:00
DorianandClaude Opus 4.6 929758ed1b test: combo snowball analysis — 60.4% rate, under 70% threshold
Simulated 1000 fights with 80% accuracy and equal speed. First-to-lead
wins 60.4% of decided fights, confirming combo system is balanced.
No decay or comeback mechanics needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:50:52 +00:00
DorianandClaude Opus 4.6 9ad8f1f1eb fix: both-wrong partial credit + tiebreaker
When both bots answer wrong, the one with higher checkAnswer confidence
(closer to correct) gets +1 point advantage. Rewards trying over
timing out. Equally wrong remains a pure draw.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:47:04 +00:00
DorianandClaude Opus 4.6 c6c792dd9e feat: add answer confidence differential as scoring factor
When both bots are correct, the one with higher checkAnswer confidence
(exact match 1.0 vs fuzzy match 0.8) gets up to +1.0 bonus points.
This rewards precise answers over approximate ones, adding another
competitive dimension beyond pure speed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:45:53 +00:00
DorianandClaude Opus 4.6 cb8a45cfb3 fix: lower critical hit threshold from 4 to 3
Both-correct fights could almost never produce critical hits because
max margin at typical speed differences was ~2.2, far below threshold
of 4. Lowering to 3 yields ~15% critical hit rate (target 10-20%),
making speed differences produce more exciting fight dynamics.

Research findings: simulated 1000 fights with both bots answering
correctly. Critical rate went from 0% to 15.3% with new threshold.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:44:29 +00:00
DorianandClaude Opus 4.6 0f8057f6e0 feat: add 10 sophisticated trap_card injection attempts
Multi-turn simulation, authority impersonation, encoding tricks
(Base64, ROT13), fake JSON system prompts, red team framing,
reward manipulation, inverted instruction logic. All difficulty: hard.
Zero audit failures after addition.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:43:01 +00:00
DorianandClaude Opus 4.6 631ace3727 feat: add 15 genuinely hard prompts for trivial challenge types
- speed_blitz: genesis block nonce, embedded headline, first halving
  block height, first pizza transaction value, OP_RETURN payload size
- math_blitz: difficulty adjustment period, sum formula, cross product
  magnitude, log2 calculation, secp256k1 field size
- animal_kingdom: octopus hearts, hummingbird flight, shark bones,
  giraffe blood pressure, cow stomach count
All tagged difficulty: 'hard' for round 5+ difficulty filtering

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:41:47 +00:00
DorianandClaude Opus 4.6 6c6981bea8 test: difficulty distribution audit + roundToDifficulty tests
- Test roundToDifficulty: rounds 1-2 easy, 3-4 medium, 5+ hard
- Test pickChallenge difficulty filtering works with round numbers
- Audit prompt difficulty tags across all 16 challenge types
- 8 types lack hard prompts, 3 lack medium prompts
- 82.7% of prompts are untagged (no difficulty attribute)
- Report written to loop/difficulty-distribution.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:39:33 +00:00
DorianandClaude Opus 4.6 ab1fa6e302 test: scoring competitiveness analysis — speed, accuracy, duration
Simulated 1000+ fights with controlled conditions:
- Speed dominance: faster bot (1.0s) wins 100% vs slower (1.5s)
- Accuracy impact: 90% correct wins 84% vs 70% correct at equal speed
- Both-correct max margin: 4.30 at extreme speed diff, barely crosses
  critical hit threshold (4)
- Fight duration: avg 11.2 rounds equal speed, 7.4 when speed diff

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:38:31 +00:00
DorianandClaude Opus 4.6 4d6e50d988 fix: checkAnswer best-match + decimal preservation + prompt data fixes
- checkAnswer now returns highest score across all accepted answers
  instead of first match, fixing 95 false-low-confidence results
- Skip string containment for purely numeric strings to prevent
  false positives like "1000" matching inside "10000"
- Preserve decimal points in normalize() (42.0 no longer becomes 420)
- Use word-boundary regex for number matching in responses
- Fix 47 wrong choices scoring too high (comma-formatted numbers,
  verbose choices matching terse answers)
- Fix 17 prompts where no choice matched any accepted answer
- Challenge audit now reports zero failures across all 1472 prompts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:35:54 +00:00
DorianandClaude Opus 4.6 6314861513 test: challenge difficulty + ambiguous prompts audits
Run heuristic LLM difficulty classification on all 1472 prompts:
- 43.6% TRIVIAL, 27.9% MODERATE, 21.4% HARD, 7.1% TRICK
- Hypothesis "80%+ TRIVIAL" rejected — distribution more varied

Ambiguous prompts audit found 517 issues:
- 22 rejected alternatives (single-char answers fail with prefixes)
- 368 substring conflicts between accepted answers
- 127 first-match-not-best scoring issues

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:07:29 +00:00
DorianandClaude Opus 4.6 b8acc1c95b test: comprehensive challenge audit — 1472 prompts, 176 issues found
Audit covers all factual prompts through checkAnswer. Findings:
- 95 low-confidence correct answers (substring collision at 0.8)
- 64 false-positive wrong choices (normalization strips commas)
- 17 choices missing correct answer (paraphrasing mismatch)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 00:16:49 +00:00
DorianandClaude Opus 4.6 39b8504157 test: add checkAnswer edge case tests with findings (15 cases)
Documents: unicode accent stripping not supported, 3-char reverse
containment false positives, first-match-not-best-match ordering,
yes/true equivalence in boolean checks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 00:12:49 +00:00
DorianandClaude Opus 4.6 8b72bef22e fix: query all 3 Nostr relays in parallel, pick latest profile (BUG-F8)
fetchNostrProfile now uses Promise.allSettled to query all relays
concurrently. Aggregates results with latest-created_at-wins strategy
instead of stopping at the first relay that responds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 00:10:11 +00:00
DorianandClaude Opus 4.6 c288b23c13 fix: persist autoRestoreRan on globalThis to survive Vite HMR (BUG-F7)
Module re-evaluation during HMR reset autoRestoreRan to false, causing
duplicate auth-restore API calls. Now persists flag on globalThis.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 00:09:20 +00:00
DorianandClaude Opus 4.6 1c296c6f1c test: add frontend composable tests and remaining test files
useNostr (9), useFightCache (5), useOnlineStatus (4) composable tests.
Added fake-indexeddb dev dependency for IDB tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 00:08:01 +00:00
DorianandClaude Opus 4.6 806163c6c5 test: add frontend composable tests — useNostr (9), useFightCache (5), useOnlineStatus (4)
Tests cover login state, logout, signer detection, key persistence, IndexedDB
caching/eviction, online/offline detection, and singleton pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 00:07:50 +00:00
DorianandClaude Opus 4.6 11a76cc249 fix: selective leaderboard cache invalidation instead of full clear (BUG-S10)
Only invalidates __alltime__ and current season cache keys on fight completion,
preserving historical season caches. Test verifies selective behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 00:03:16 +00:00
DorianandClaude Opus 4.6 c224776c90 test: add payments.test.ts (12 cases) and expand bets.test.ts (30 cases)
Covers wallet connection, invoice creation, payment confirmation, zap validation,
odds calculation, escrow settlement, bet validation, and display conversion.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 00:01:17 +00:00
DorianandClaude Opus 4.6 2576221e24 fix: replace sort-based rate-limit eviction with Map insertion-order iteration (BUG-S9)
O(k) oldest-first eviction instead of O(n log n) sort. Added 10k benchmark test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:56:41 +00:00
DorianandClaude Opus 4.6 f18b04ba20 test: verify global error handler returns 500 without stack traces (BUG-S7)
Global app.onError handler already in app.ts catches all unhandled route
exceptions. Production mode returns "Internal server error" only.
Tests verify no stack traces or file paths leak in responses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:51:12 +00:00
DorianandClaude Opus 4.6 14dbb29377 test: add timeout draw and perfect victory ELO tests to lifecycle suite
- Both bots timing out every round: verified draw with zero damage
- Perfect victory (10-0): verified correct ELO calculation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:49:34 +00:00
DorianandClaude Opus 4.6 e6c3894443 test: add orchestrator test suite — utility functions and SSRF protection (9 tests)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:48:12 +00:00
DorianandClaude Opus 4.6 a96e8922b6 feat: add JWT blacklist for logout with TTL cleanup
blacklistJwt() adds token to in-memory blacklist until its natural expiry.
verifyJwt() checks blacklist before signature verification.
Cleanup interval removes expired entries every 10 minutes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:45:57 +00:00
DorianandClaude Opus 4.6 ca9f5f36e6 test: add NIP-98 edge cases — replay, future clock drift, URL path mismatch
Documents finding: no replay protection in NIP-98 verification.
Token replay within 120s window succeeds (mitigated by JWT issuance being idempotent).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:44:56 +00:00
DorianandClaude Opus 4.6 34a83fb0fc test: add auth routes test suite with 13 cases
Tests check-name validation, login pubkey validation, register name/pubkey
validation, register-human validation, NIP-98 session (valid + expired).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:43:57 +00:00
DorianandClaude Opus 4.6 6144fa7910 test: add queue test suite with 8 cases (cooldown, join, leave, snapshot)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:42:11 +00:00
DorianandClaude Opus 4.6 21f9650585 test: add poll-responses, NIP-98, and bot-auth test suites
- poll-responses.test.ts: 10 tests covering lifecycle, timeout, duplicate rejection
- nip98.test.ts: 7 tests covering valid token, expiry, method, signature, tags
- bot-auth.test.ts: 5 tests covering header auth, query params, invalid credentials

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:40:24 +00:00
DorianandClaude Opus 4.6 a49cc124fe test: expand human-responses tests to 11 cases (isHumanPlayer, getPendingAnswers, numericDistractors)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:37:21 +00:00
DorianandClaude Opus 4.6 5f732d139c fix: remove duplicate JWT_SECRET production check (BUG-S5)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:34:20 +00:00
DorianandClaude Opus 4.6 2e2a6f18cb test: verify /poll endpoint rate limiting returns 429 (BUG-S3)
Tests the actual rateLimit middleware with production mode via dynamic import.
Covers: under-limit allows, over-limit returns 429, window reset, per-IP
isolation, and poll endpoint config (30 req/1s window).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:33:32 +00:00
DorianandClaude Opus 4.6 5e0bc1dc00 test: verify correct/incorrect feedback in respond endpoint (BUG-1)
Tests confirm checkAnswer integration: correct answer returns
correct: true, wrong answer returns correct: false.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:17:16 +00:00
DorianandClaude Opus 4.6 004413457d fix: use 'invoiced' status on NWC fallback instead of invalid 'pending'
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:15:49 +00:00
DorianandClaude Opus 4.6 e7d3cab85a feat: add ErrorBoundary component with onErrorCaptured (BUG-F5)
Catches runtime errors in child components, displays user-friendly
error message with reload button. Wired into App.vue wrapping
router-view. Tests verify error capture and button rendering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:15:28 +00:00
DorianandClaude Opus 4.6 74cb5cc728 fix: NWC payment timeout/error now rejects properly (BUG-F4)
- Timeout and WebSocket errors reject with proper Error objects
- Caller catches and falls through to poll-based confirmation
- Preimage undefined check prevents calling confirm with no preimage

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:10:50 +00:00
DorianandClaude Opus 4.6 acecc79d04 test: verify HumanFightPage timer cleanup on unmount (BUG-F3)
feedbackTimer, timerHandle, and pollHandle are all cleared in
onUnmounted. Test confirms cleanup pattern works correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:07:47 +00:00
DorianandClaude Opus 4.6 b4900cb66f fix: replace all silent .catch(() => {}) with console.warn (BUG-F2)
13 silent catch handlers replaced with descriptive console.warn logging
across 6 frontend files. No silent error swallowing remains.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:06:22 +00:00
DorianandClaude Opus 4.6 e5ed856df9 fix: SSE reconnection with exponential backoff (BUG-F1)
SSE now always attempts reconnection when fight isn't finished,
regardless of isLive.value. Uses exponential backoff (1s, 2s, 4s,
max 8s). Moved sseRetries to outer scope to persist across reconnects.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:02:10 +00:00
DorianandClaude Opus 4.6 370d8643b7 fix: add Zod enum validation for challenge types in webhook tester (BUG-S6)
Validates challenge type against the full CHALLENGE_TYPES enum before
processing. Invalid types now return 400 instead of silently falling
back to speed_blitz.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:56:26 +00:00
DorianandClaude Opus 4.6 b82c2755aa fix: throw if JWT_SECRET missing in production (BUG-S5)
Production now requires JWT_SECRET env var. Added comprehensive JWT
tests: creation, verification, expiry, tampered payload, tampered
signature, and malformed token rejection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:48:30 +00:00
DorianandClaude Opus 4.6 e4a7f47e0f fix: validate Cashu token format before placing bets (BUG-S4)
Added getDecodedToken validation that rejects malformed tokens with
400 before any DB lookups. Tests cover empty, non-base64, truncated,
and random base64 tokens.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:46:24 +00:00
DorianandClaude Opus 4.6 c6a54d63c4 fix: add rate limiting to /poll endpoint + fix test type errors (BUG-S3)
- Add rateLimit(1_000, 30) middleware to GET /poll endpoint
- Fix Challenge type errors in human-responses test files (missing baseDamage)
- Add rate-limit unit test verifying 429 after exceeding limit

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:41:59 +00:00
DorianandClaude Opus 4.6 48847d879c test: add human-responses unit tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:36:32 +00:00
DorianandClaude Opus 4.6 e48a984d96 test: verify human challenge race condition fix ordering (BUG-S2)
waitForHumanResponse synchronously stores pending challenge before
returning, ensuring SSE emit happens after storage. Tests verify
ordering, choice consistency, promise resolution, and cleanup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:36:04 +00:00
DorianandClaude Opus 4.6 8468c89352 test: verify tournaments .get() is sync + add route tests
better-sqlite3 driver is synchronous — .get() does NOT need await.
Added tests for unknown pubkey (404) and missing pubkey (400) on join.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:32:37 +00:00
DorianandClaude Opus 4.6 d9e32123fe test: add test infrastructure for frontend and server
- Frontend: vitest.config.ts with vue plugin + jsdom, dummy component test
- Server: in-memory SQLite test DB factory + Hono testClient helper + smoke test
- CI: add pnpm audit and server coverage threshold steps
- Root: vitest workspace config for multi-project test discovery

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:30:43 +00:00
DorianandClaude Opus 4.6 6f0eb92ebb fix: both-wrong draws + double TTS entrance fix
Scoring: both-wrong is now a DRAW — equal scores (3/3), no winner,
symmetric minimal damage. Garbage answers no longer beat reasonable
ones just by being faster. Both-wrong narrations reflect the draw.

Entrance: removed duplicate announceDeepIntro() call from FightViewer
(was already called inside playEntrance). Removed _resetPositions()
after entrance (entrance already places fighters at home positions,
the extra reset caused a visible snap/reset).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 20:09:11 +00:00