Commit graph

33 commits

Author SHA1 Message Date
jedarden
70c51d5df2 feat(api): add GET /api/status/{bot_id} endpoint per plan §8.2
Adds lightweight bot status endpoint that returns status and last_active.
Public endpoint for checking bot health without full profile fetch.

Closes: bf-5p43

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 16:53:03 -04:00
jedarden
ea04f4debb style: apply gofmt alignment fixes across codebase
Tab/space alignment consistency from running gofmt on all packages.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 10:40:33 -04:00
jedarden
6bfd3e6679 feat(api): implement POST /api/request-enrichment endpoint
Per plan §13.3, implements user-requested AI replay commentary with:
- HMAC bot authentication via shared_secret
- Rate limiting: 5 requests/day per bot
- Match validation (exists and completed)
- Idempotency via enrichment_requested_at column
- Enqueues to Valkey for acb-enrichment service
- Returns 202 Accepted with estimated wait time

Also adds:
- AllowN() method to ratelimit package for multi-token checks
- enrichment_requested_at column to matches table (idempotency)
- enrichLtr rate limiter (5/day per bot)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 02:58:11 -04:00
jedarden
9972cb8c84 feat(matchmaker): add best-of-5 weekly featured and best-of-7 championship series scheduling
- Add 'featured' boolean column to series table for weekly featured series
- Add tickFeaturedSeries ticker that runs Friday 20:00 UTC to create bo5 featured series
- Featured series: query top 20 bots by rating, select 4 rivalry pairs by ELO proximity
- Best-of-7 championship bracket already implemented via createChampionshipBracket
- Add FeaturedSchedSecs config (default: 3600s check interval)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 02:34:47 -04:00
jedarden
6dd69f596d feat(api): add spam/word filter for feedback submission
Per plan §13.6, implement a configurable spam filter for the
handleCreateFeedback endpoint that:

- Validates minimum content length (default 10 chars, configurable
  via ACB_SPAM_MIN_LENGTH env var)
- Normalizes case and strips common unicode substitutions
  (leetspeak: 0→o, 1→i, 3→e, 4→a, 5→s, 7→t, @→a, $→s, etc.)
- Checks content against a block-list of banned terms with word-boundary
  matching
- Returns HTTP 422 (Unprocessable Entity) on filter rejection

Configuration:
- ACB_SPAM_BLOCK_LIST: comma-separated custom blocked terms (optional,
  defaults to embedded list of common spam/offensive words)
- ACB_SPAM_MIN_LENGTH: minimum feedback content length (default: 10)

The embedded default block-list includes:
- Profanity and offensive language
- Common spam patterns (buy now, click here, free money, etc.)
- Scam patterns (bitcoin giveaway, urgent, act now, etc.)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 01:26:32 -04:00
jedarden
4937f94afd feat(combat): rank matches by enemy-kill combat turns
Adds combat_turns metric (distinct turns where ≥1 bot died from enemy
focus-fire, excluding self-collisions). Worker computes it after each
match; index builder sorts matches/index.json and the new most-combat
playlist descending by it, and bumps interest score for combat-heavy
matches so they surface in highlights.

Also switches homepage featured replay default view from influence to
standard so the actual bot-on-bot combat is visible.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 18:32:08 -04:00
jedarden
e5dc3bc543 fix: accept base64-encoded AES keys (OpenBao stores keys as base64, not hex)
The encryption key stored in OpenBao/K8s secrets is base64-encoded but
the API and worker crypto functions expected hex. Add parseAESKey() that
accepts both formats (tries hex first, falls back to base64).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 23:04:29 -04:00
jedarden
b13f98416b fix(api): add missing replay_feedback FK migration
The replay_feedback table was missing its foreign key constraint to
matches(match_id). This happened because CREATE TABLE IF NOT EXISTS
doesn't add FKs to existing tables.

Added an idempotent migration that checks for the constraint's existence
before adding it, ensuring it's safe to run on both fresh installs and
existing databases.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-28 23:36:02 -04:00
jedarden
b7990ad475 fix(docker): add COPY ratelimit/ to acb-api Dockerfile
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 18:09:53 -04:00
jedarden
d0087a3241 fix(docker): add COPY metrics/ to all service Dockerfiles
The metrics package is a local module dependency imported by all services
but was missing from every Dockerfile's build context.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 18:00:16 -04:00
jedarden
0813e36297 fix(evolver): wire Nash mixture and meta weaknesses into LLM prompts, fix 4-D diversity
- Add NashMixture and MetaWeaknesses fields to meta.Description and
  compute them from island population proportions (§10.2 PSRO)
- Update behaviorDistance to support N-D vectors for 4-D MAP-Elites
  grid (aggression, economy, exploration, formation)
- Wire NashMixture/MetaWeaknesses through FromMetaDescription converter
  so they actually reach the LLM prompt (was dead code before)
- Align LLM prompt with plan §15.1/§15.5: correct combat rules
  (focus-fire), fog of war, HTTP protocol section, Nash mixture target
- Fix diversity normalization from sqrt(2) (2-D) to 2.0 (4-D max)
- Rename handleUIFeedback to handleCreateFeedback (§13.6 naming)
- Update tests for new fields and corrected prompt text

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-23 01:22:19 -04:00
jedarden
88bd70640a fix(types): add missing ReplayPlayer import and type annotation for transcript feature
- Add ReplayPlayer to type imports in replay-viewer.ts
- Add explicit type annotation for entry parameter in replay.ts transcript map
- Fixes TypeScript compilation errors for §15.3 screen reader transcript feature
2026-04-22 18:20:56 -04:00
jedarden
6c1f031071 feat(config): add season_id + rules_version to Config per §4.2
- SeasonID and RulesVersion already present in engine/types.go Config struct
- Worker already populates from active season row via DB join
- Config embedded in VisibleState sent to bots each turn (including turn 0)
- All starter kits (go, python, rust, java, csharp) already expose and log fields
- Add season_id/rules_version logging to JavaScript starter on turn 0
- TypeScript Config interface already includes season_id and rules_version

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 18:09:26 -04:00
jedarden
35c705fa66 fix(api): remove unused time import from rotatekey_test.go
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 17:40:06 -04:00
jedarden
7df2fad568 feat(api): wire voteLtr rate limiter for upvote endpoint (§13.6)
Add dedicated 10/hour-per-IP rate limiter for POST /api/feedback/{id}/upvote,
separate from the 20/hour feedback submission limiter. Wired in main.go init,
server_test.go helper, and RegisterRoutes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 17:37:34 -04:00
jedarden
477a54c548 feat(matchmaker): implement §6.1 Pareto skill-proximity + LRU pairing algorithm
Replace random 2-player pairing with the full §6.1 algorithm:
- Seed selection: bot with oldest last-match timestamp (tiebreak: lowest bot ID)
- Format selection: seed's least-played player count among {2, 3, 4, 6}
- Opponent selection: Pareto 80%/16-rank skill proximity + oldest last-pairing
  with seed + fewest 24h games for game-count balance
- Map selection: least-recently-used active map for the chosen player count,
  with map_scores.last_used_at updated after each match
- Random player slot assignment for all participant counts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 17:35:00 -04:00
jedarden
7e131d310f feat(api): add token-bucket rate limiting to public endpoints
Adds ratelimit package with per-IP and per-key HTTP middleware.
Applied to register (5/hr), feedback (20/hr), predict (60/hr),
and job submission (5/day) endpoints. Includes metrics counter
for rejected requests and periodic bucket cleanup goroutine.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 16:52:29 -04:00
jedarden
7f2407ed00 feat: add Prometheus metrics instrumentation across services
Add metrics server startup and HTTP middleware to acb-api, generation
counter metric to evolver, and R2 cache size metric to index builder.

Also remove dead measureR2CacheSize reference from index builder main.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 16:16:03 -04:00
jedarden
c56cc8bae6 fix(matchmaker): multi-match crash cooldown (3 strikes / 30 min) per §4.5 + §6.1
Add crash_strikes and cooldown_until columns to bots table. Worker
increments strikes on crash (cooldown at 3), resets on success.
Matchmaker excludes cooldown bots from pairing, series scheduling,
and championship brackets. Fix erroneous cooldown filter on series
table in finalizeCompletedSeries (column only exists on bots).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 15:22:12 -04:00
jedarden
81940a1598 fix(api): fix getEnv stub and Dockerfile Go version for deployment readiness
The getEnv() function in server.go always returned the default value,
preventing ACB_R2_ENDPOINT/ACB_B2_ENDPOINT from being read at runtime.
Also updated Dockerfile from golang:1.24 to golang:1.25 to match go.mod.

K8s manifests for acb-evolver and acb-api already exist in
declarative-config/k8s/iad-acb/ai-code-battle/ (added Apr 21).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 13:29:45 -04:00
jedarden
f6ce4588f4 fix(api): rename /api/ui-feedback to /api/feedback per plan §13.6
The community feedback endpoint was registered as /api/ui-feedback in
the Go API but the plan and annotation.ts client both use /api/feedback.
Rename the route and update agentation-overlay.ts to match. Add a
route-level test asserting the canonical path and that the old path
returns 404.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 13:22:47 -04:00
jedarden
b1121ed6f8 feat(playlists): add playlist curation and rebuild logic per §10, with series/seasons/enrichment
Implement auto-curated playlists in the index builder: 12 playlist types
(closest finishes, upsets, comebacks, marathons, rivalry classics, etc.)
with weekly highlight curation. Add DB persistence, R2 pruning exemptions,
frontend pages, and AI commentary enrichment pipeline.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-21 16:11:27 -04:00
jedarden
347ae4f1df feat(predictions): resolve predictions on match completion, add API endpoints and frontend
- Worker resolves open predictions after writing match results (resolvePredictions + upsertPredictorStats)
- API endpoints: POST /api/predict, GET /api/predictions/open, GET /api/predictions/history
- Frontend /watch/predictions page with polling, prediction submission, and history display
- predictor_stats table tracks streaks and accuracy per predictor
- Series format selection: fix threshold from >200 to >=200 for bo3 eligibility

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-21 14:08:15 -04:00
jedarden
91d807cec2 feat(web,cmd): enhance evolution dashboard, series/seasons pages, and matchmaker
- Evolution page: live polling (10s), activity feed, candidate tracking,
  statistics section, island overview with live.json schema
- Series page: detailed series view with game-by-game results
- Seasons page: season list with status and champion display
- Predictions page: enhanced prediction UI with open matches
- API types: add CycleInfo, Candidate, ActivityEntry, Totals for live.json
- Embed: improved embeddable replay widget
- Mobile CSS: responsive breakpoints and bottom tab bar
- Exporter: enhanced live.json generation with full cycle/candidate data
- Matchmaker: series scheduling support with config
- Worker: additional database queries for series/season data

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-21 13:42:20 -04:00
jedarden
00069b1870 feat(acb-api): implement bot registration, job coordination, and replay endpoints per plan §12 Phase 4
- POST /api/register: bot registration with URL + shared secret validation
- GET /api/job: worker polls for next pending match job (authenticated)
- POST /api/job/:id/result: worker submits match result (winner, replay JSON)
- GET /api/replay/🆔 serve replay JSON from R2 warm cache (falls back to B2)
- GET /api/bot/🆔 bot profile JSON (rating, elo, record, metadata)
- GET /api/bots: leaderboard snapshot with pagination
- POST /api/ui-feedback: accept Agentation UI feedback

Authentication via Bearer token (worker API key). Shared secrets encrypted
with AES-256-GCM using ACB_ENCRYPTION_KEY.
2026-04-21 08:58:42 -04:00
jedarden
f206a87575 fix(db): add missing columns to jobs and bots schema
jobs: add heartbeat_at and created_at columns needed by acb-worker
bots: add archetype column needed by acb-index-builder

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 23:29:18 -04:00
jedarden
b06350d762 Remove legacy code: worker-api/, cmd/acb-indexer/, cluster-configuration/, gut cmd/acb-api/
Some checks failed
CI / Go Tests (push) Has been cancelled
CI / Worker API Tests (push) Has been cancelled
CI / Indexer Tests (push) Has been cancelled
CI / Web Build (push) Has been cancelled
Cleanup of superseded code that no longer matches the architecture:

Removed:
- worker-api/ - Cloudflare Worker with D1, superseded by K8s-based matchmaker + direct PostgreSQL
- cmd/acb-indexer/ - TypeScript index builder, superseded by Go cmd/acb-index-builder/
- cluster-configuration/ - K8s manifests belong in ardenone-cluster repo

Gutted cmd/acb-api/:
- Removed registration, job claim/result endpoints (deferred for v1)
- Removed dead code: predictions.go, seasons.go, series.go, register.go, jobs.go, glicko2.go
- API is now a stub with only health/ready endpoints
- Matchmaker and workers handle the core loop without it

Updated PROGRESS.md to reflect current architecture.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 10:22:16 -04:00
jedarden
a5859df795 Add map evolution pipeline (cmd/acb-map-evolver)
Phase 9 implementation: Map Evolution (§14.6)
- Parent selection weighted by engagement × vote multiplier
- Crossover with sector-based wall inheritance
- Symmetry-preserving mutation (wall flips, energy node shifts)
- Validation: connectivity, wall density bounds, energy node access
- Smoke test validation (simplified: connectivity + energy count checks)
- PostgreSQL maps, map_votes, map_fairness tables for lifecycle management
- Maps stored with status: active, probation, retired, classic

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 02:35:33 -04:00
jedarden
f5d7553f98 Add Phase 7-9 features: evolution dashboard, WASM sandbox, enhanced replay
Phase 7 Evolution:
- Add live-export subcommand to acb-evolver for dashboard JSON generation
- Export programs, stats, and generation log to live.json

Phase 8 Enhanced Features:
- Add WASM game engine build (cmd/acb-wasm/) with JS bindings
- Add in-browser sandbox page with Monaco editor (web/src/pages/sandbox.ts)
- Add win probability computation (web/src/win-probability.ts)
- Add replay commentary generator (web/src/commentary.ts)
- Add clip maker for GIF/MP4 export (web/src/pages/clip-maker.ts)
- Add rivalry detection and pages (web/src/pages/rivalries.ts)
- Add replay feedback system (web/src/pages/feedback.ts)
- Add evolution dashboard page (web/src/pages/evolution.ts)

Phase 9 Platform Depth:
- Add predictions API (cmd/acb-api/predictions.go)
- Add series management API (cmd/acb-api/series.go)
- Add seasons API (cmd/acb-api/seasons.go)
- Add narrative generator for rivalries (cmd/acb-indexer/src/narrative.ts)

Engine Updates:
- Add debug field to move response schema
- Add match event timeline extraction
- Add replay enrichment fields

Web Updates:
- Update app.html navigation for new pages
- Add API client methods for predictions, series, seasons
- Export engine types for browser use

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 01:13:23 -04:00
jedarden
875ccdbe83 Extract matchmaker into separate deployment (acb-matchmaker)
Architecture conformance fix per plan §12 Phase 4:
- Plan specifies Matchmaker Deployment as internal service with no external exposure
- Extracted tickers.go from acb-api to new cmd/acb-matchmaker/
- Tickers: bot pairing (1 min), health checking (15 min), stale job reaping (5 min)
- Alerting webhooks moved from acb-api to acb-matchmaker
- Created Dockerfile for acb-matchmaker container
- Created K8s deployment manifest (no service needed - internal only)
- Fixed syntax error in cmd/acb-api/db.go (prematurely closed schemaSQL string)

This separates concerns per the plan:
- acb-api: HTTP endpoints for bot registration, job coordination, bot status
- acb-matchmaker: Internal tickers for matchmaking, health checks, reaping

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 00:55:46 -04:00
jedarden
5669688984 Add validation pipeline, sandbox, and evolution DB layer (Phase 7)
Three-stage fail-fast validator for LLM-generated bot candidates:
- syntax.go: language-aware parse (go/parser for Go; py_compile, rustfmt,
  tsc, javac, php -l for others; brace-balance fallback)
- schema.go: regex detection of /health + /turn endpoints and "moves" field
- sandbox.go: nsjail-isolated smoke test — builds bot, polls /health, sends
  5 signed /turn requests, verifies JSON moves responses
- validator.go: orchestrates stages with fail-fast short-circuit

DB layer:
- programs table + CRUD (create, get, list, updateFitness, setPromoted)
- validation_log table with RecordValidation, IslandPassRates,
  IslandValidationStats for per-island pass-rate tracking
- seed.go: 6 generation-0 bots across alpha/beta/gamma/delta islands

MAP-Elites grid (mapelites/grid.go): 2-D behavior grid on aggression×economy
axes; TryPlace keeps the fittest occupant per niche.

acb-evolver CLI gains two new subcommands:
  validate <file> -lang <lang> [-island <island>] [-nsjail] [-nolog]
  validation-stats (tabular per-island pass-rate breakdown)

cmd/acb-api/db.go: add programs table to API schema so the API can query
promoted evolved bots.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 22:45:13 -04:00
jedarden
4aca8add20 Add Discord/Slack alerting webhooks to Go API server
Implements the monitoring alerting deliverable from Phase 6. The Alerter
module sends color-coded notifications to Discord and/or Slack webhooks
for operational events: bot health transitions, stale job re-enqueues,
and match errors. Includes per-key rate limiting to prevent alert storms.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 01:32:47 -04:00
jedarden
f1a0830c51 Add Go API server (cmd/acb-api) with PostgreSQL, Valkey, and Glicko-2
Implements the K8s-native Go API service per the plan architecture:
- HTTP server with graceful shutdown and env-var configuration
- PostgreSQL schema (bots, matches, match_participants, jobs, rating_history)
- Health/ready endpoints checking PostgreSQL and Valkey connectivity
- Bot registration with health check, HMAC secret gen, AES-256-GCM encryption
- Key rotation and bot status endpoints
- Job claim via Valkey BRPOP, result submission with Glicko-2 rating update
- Glicko-2 rating system: multi-player pairwise, Illinois volatility algorithm
- Background tickers: matchmaker (1m), health checker (15m), stale job reaper (5m)
- Worker API key authentication (Bearer/X-API-Key)
- Dockerfile, K8s Deployment (2 replicas), ClusterIP Service
- 30 unit tests covering Glicko-2, crypto, config, and handlers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 01:21:48 -04:00