- Replace null with Option in GameResultStreamListener, PairingRepository,
ParticipantRepository, TournamentService
- Replace isInstanceOf checks with pattern matching in GameResultStreamListener
- Wrap var in SwissPairingService resolveConflicts with scalafix:off
- Apply spotlessScalaApply formatting across tournament and official-bots modules
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add token field to OfficialBotAccount and generate a non-expiring bot
JWT on creation so official bots can authenticate
- Expose token in POST /api/account/official-bots response and open the
endpoint to any authenticated user
- Bridge TournamentService to Redis: publish gameStart events to
nowchess:bot:<name>:events after each pairing so OfficialBotService
picks up games automatically
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements the full tournament lifecycle: create, join, withdraw, start,
round progression, and finish with Buchholz tiebreak standings.
- REST resource covering all 11 endpoints from the OpenAPI spec
- Swiss pairing algorithm with bye support
- Per-bot NDJSON stream with targeted gameStart events (color field)
- Game result ingestion via Redis writeback stream
- H2-backed integration tests for resource and pairing service
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace synchronous account→core game-creation HTTP call and plain
pub/sub bot game-start events with Redis Streams using consumer groups,
XACK, retry, and a Dead Letter Queue for at-least-once delivery and
observability.
- account: GameCreationStreamClient publishes game-creation requests and
correlates responses via a per-instance consumer group (NCS-91)
- core: GameCreationStreamListener consumes requests, calls
GameCreationService, publishes response events, retries, and routes
exhausted/unparseable events to the DLQ (NCS-91, NCS-93, NCS-94)
- official-bots: bot game-start events migrated from pub/sub to Streams
with consumer group, XACK, retry, and DLQ (NCS-92)
- account EventPublisher dual-writes to the stream and legacy pub/sub
channel for backward compatibility
- all flows use the typed EventEnvelope (eventId/type/payload/timestamp/
correlationId) with DLQ error context (eventType, error, attempt)
- register new DTOs and EventEnvelope/EventType for native reflection
Closes NCS-91, NCS-92, NCS-93, NCS-94
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Janis Eccarius <eccariusjanis@gmail.com>
Reviewed-on: #62
- Add EventEnvelope case class (eventId, type, payload, timestamp, correlationId)
- Add EventType enum with all known event types
- Update account EventPublisher to use EventEnvelope instead of raw string interpolation
- Add EventEnvelope/EventType to account NativeReflectionConfig
- Add Jackson Scala and JSR310 modules to api dependencies
- Add api module dependency to account module
- Add NativeReflectionConfig rule to CLAUDE.md
Closes NCS-90
https://knockoutwhist.youtrack.cloud/issue/NCS-90
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #61
Add Step 5b to fix-defect and implement-feature commands: after applying
review comments, rerun compile, test, spotlessScalaApply, and lint, then
re-spawn reviewer to confirm findings are resolved.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pass discard_changes: true so cleanup succeeds after branch is pushed.
Add .claude/worktrees/ to .gitignore.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Run spotlessScalaApply then lint synchronously (never background) in
fix-defect and implement-feature workflows. Hard gate: do not proceed
to review/commit until lint exits 0.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two bugs in move notation causing PGN import failures in LiChess:
1. Disambiguation: when two pieces of same type can reach same square,
SAN requires file/rank/full-square prefix (e.g. "Ndf3" not "Nf3").
Added disambiguate() in PgnExporter and disambiguatePiece() in
GameEngine, both querying allLegalMoves to find competing pieces.
2. Check/checkmate suffix: "+" and "#" were never appended.
PgnExporter now threads ctxAfter through moveToAlgebraic and
calls DefaultRules.isCheck/isCheckmate. GameEngine passes
PostMoveStatus to translateMoveToNotation for the same result.
Also removes dead notation code in executeMoveBody (result was never
used — not passed to MoveExecutedEvent).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Janis Eccarius <eccariusjanis@gmail.com>
Reviewed-on: #56
Adds x86-64-v2 microarchitecture as a second build target alongside
default. Images tagged with -x86_v2 suffix; GHA cache scoped per arch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Default Agroal pool (max-size=20) exhausted under concurrent logins due to
bcrypt latency per request. Fixes NCS-87.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>