Commit graph

21 commits

Author SHA1 Message Date
jedarden
04b860a8be feat(index-builder, evolver): improve evolution system initialization and logging
Index builder:
- Add slog import for structured logging
- Improve fetchEvolutionMeta to return empty meta instead of error when programs table is empty
- Add logging to show evolution system status (running vs not initialized)
- Add logging in generateEvolutionMeta to show when evolution data is written

Evolver:
- Add automatic schema initialization and population seeding in RunEvolutionLoop
- Programs table is now automatically seeded with 6 initial strategy bots on startup
- Log seeding status to indicate whether programs table was already initialized

These changes ensure the evolution system properly initializes when deployed
and provides better visibility into its status via structured logging.

Closes: bf-4zde
2026-05-26 13:28:44 -04:00
jedarden
c37f68e08b feat(index-builder): generate data/meta/index.json
Adds MetaIndex struct and generateMetaIndex function to create
data/meta/index.json listing all available meta data files
(archetypes.json, rivalries.json) with descriptions.

Also adds the new file to the R2 warm cache upload list.

Closes: bf-66rk

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 13:08:17 -04:00
jedarden
b31ebee32f feat(index-builder): generate evolution/meta.json and lineage.json
Plan §15.4 Live Evolution Observatory requires data/evolution/meta.json
and data/evolution/lineage.json files, which the web platform expects
but the index-builder was not generating.

- Add EvolutionMeta type (generation, promoted_today, top_10_count, updated_at)
- Add LineageNode type (full program lineage with parent relationships)
- Add fetchEvolutionMeta() to query evolver database for stats
- Add fetchLineage() to query evolver programs table for lineage tree
- Add generateEvolutionMeta() to write data/evolution/meta.json
- Add generateLineage() to write data/evolution/lineage.json
- Wire generation into generateAllIndexes()
- Add files to R2 upload list

The implementation gracefully handles missing evolver database by
returning empty/placeholder data, allowing the index-builder to run
without evolution data while still producing valid JSON files.

Closes: bf-6cp0
2026-05-25 16:01:27 -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
9bcbd566b6 Bug fix bf-3mx7: Fix match index winner badge - use p.Won instead of comparing BotID with WinnerID
The WinnerID field is a player-slot integer as string (e.g. "2"), not a bot_id.
The SQL query already computes the correct winner status in p.Won field.

Fixed in 3 functions:
- matchToSummary: Changed Won: p.BotID == m.WinnerID to Won: p.Won
- buildPlaylistMatch: Changed Won: p.BotID == m.WinnerID to Won: p.Won
- ratingUpsetMagnitude: Use p.Won to identify winner instead of comparing with m.WinnerID
- maxScoreDiff: Use p.Won to identify winner instead of comparing with m.WinnerID
- isEvolutionBreakthrough: Find winner using p.Won before checking if evolved

This fixes the issue where 984/1000 prod matches had winner_id set but all participants showed won: false.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 17:59:02 -04:00
jedarden
0028100c64 Phase 9: Map voting + positional fairness monitoring - verify existing implementation
Verified all Phase 9 deliverables already in place:
- PostgreSQL map_votes table (UNIQUE constraint on map_id, voter_id)
- POST /api/vote-map endpoint (+1/-1 votes, rate-limited)
- GET /api/vote/map/{map_id} endpoint for vote counts
- Positional fairness monitoring: tickFairnessAudit with 5-step lifecycle
  * updateMapFairnessStats: recompute per-slot win rates
  * flagUnfairMaps: probation for >10pp deviation
  * retireDislikedMaps: force-retire at < -20 net votes
  * pruneLowEngagementMaps: monthly bottom 10% pruning
  * promoteClassicMaps: top-5 sustained (3+ months) to classic
- maps/index.json includes NetVotes from aggregation

All tests pass (mapvote, map_fairness, index-builder).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 14:30:46 -04:00
jedarden
c88474ad6b feat(index-builder): update community hints filter for insight/idea types
- Change filter from 'idea'/'mistake' to 'insight'/'idea' (mapping to 'hint'/'strategy' from plan §13.6)
- Increase upvote threshold from 3 to 10 for higher quality signals
- The evolver consumes community_hints.json for LLM prompt context
2026-05-04 01:38:53 -04:00
jedarden
aeef954590 feat(index-builder): add sitemap.xml generation
Add sitemap.xml generation as a final pass in the index builder. The
sitemap covers all public pages: home, leaderboard, bots list, bot
profiles, matches list, featured replays, seasons, rivalries,
predictions, and docs.

- Add SiteURL config field (ACB_SITE_URL env var, defaults to
  https://aicodebattle.com)
- Add generateSitemap() function with proper XML encoding
- Add SitemapURL and Sitemap types for XML marshaling
- Call generateSitemap() at the end of generateAllIndexes()
- Write sitemap.xml to output directory alongside leaderboard.json

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 00:09:53 -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
3ae35ea00a test(web): verify match list page renders cards with real matches
- Verified /watch/replays shows real completed matches (not just demo)
- Match cards display bot names, turn count, winner badges, map ID
- 'Watch Replay' links point to real match IDs (m_test_*)
- Curated playlists render with real data (featured, comebacks, upsets, etc.)
- Pagination/infinite scroll works via IntersectionObserver
- Mobile testing on Pixel 6 via ADB: layout responsive, touch targets usable
- Created MATCH_LIST_TEST_RESULTS.md with full verification details
- Thumbnails not implemented (clean UI without broken images due to R2 issues)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-25 11:42:47 -04:00
jedarden
cd30484e8c verify(blog): verify blog page generates and renders AI match commentary posts
Verification results:
1.  /data/blog/index.json exists and has 1 post (meta-week-13-season-1)
2.  Individual post pages load correctly at /blog/{slug}
3.  Blog post JSON structure matches frontend expectations (content_md field)
4.  Tags and filters implemented in UI (All, Meta Reports, Chronicles buttons)
5.  Blog page builds successfully (blog-D4QMd11d.js included in build)

Current state: Blog infrastructure is fully implemented with:
- LLM-powered narrative generation (blog.go, narrative.go)
- Story arc detection (rise, fall, rivalry, upset, evolution milestones)
- Weekly meta report generation with ELO movers, strategy analysis
- Chronicles for story arcs (rivalry, upset, rise/fall, evolution)
- Tag-based filtering and search

Note: Current blog content is placeholder/template-based. Meaningful
match commentary will be generated when:
- ACB_LLM_BASE_URL and ACB_LLM_API_KEY are configured in index-builder
- Real match data exists in PostgreSQL database
- Story arcs are detected from rating history and match results
2026-04-25 10:40:36 -04:00
jedarden
a509b70800 feat(§15.3): implement screen reader transcript for replay viewer
- Add ARIA live region announcement during auto-playback using detailed transcript text
- Transcript panel shows turn-by-turn summaries with current turn highlighting
- T key toggles transcript panel (collapsible UI)
- Panel content is selectable/copyable text for screen reader users
- Fix build errors in clip-maker.ts (remove unused lastExportBlob references)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 18:30:18 -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
4d1f5f976d feat(index): implement §14.5 predictions/open.json static file generation
Adds generatePredictionsOpen to acb-index-builder, writing:
- data/predictions/open.json — upcoming predictable matches

Queries pending matches that are "predictable":
- Both bots in top 20
- Rivalry matches (3+ previous h2h matches)
- Series matches
- Evolved bot vs top-10 human-written bot

Output schema:
- updated_at — timestamp of generation
- matches — array of {match_id, bot_a, bot_b, a_rating, b_rating, open_until, head_to_head_record}

Limits to next 10 matches to keep file small. Refreshes every ~15 min by the index builder.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 17:53:48 -04:00
jedarden
b4a975f5bf feat(index): implement §7.2/§15.2 maps/index.json and maps/{map_id}.json generation
Adds generateMapsIndex to acb-index-builder, writing:
- maps/index.json — active/probation/classic maps grouped by player count
- maps/{map_id}.json — full map definition with walls, cores, energy_nodes

Queries maps.map_json column for geometry; adds RawJSON field to MapData
and updates fetchMaps to select it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 17:46:27 -04:00
jedarden
89560e5ec4 feat(index): implement match thumbnail PNG generation (§7.2, §14.3)
Implementation complete:

1. engine/thumbnail.go - New thumbnail rendering package
   - GenerateMatchThumbnail() creates 640x360 PNG thumbnails
   - Renders grid, bots, cores, walls, energy with player colors
   - SelectThumbnailTurn() chooses most interesting turn
   - Pure Go stdlib image rendering (no canvas required)

2. cmd/acb-worker - Upload thumbnails to B2 alongside replays
   - uploadThumbnail() generates PNG and uploads to B2
   - Key: thumbnails/{match_id}.png, content-type: image/png
   - Called after match completion, non-blocking on failure

3. cmd/acb-index-builder/deploy.go - Promote thumbnails to R2
   - promoteRecentReplays() copies both replays AND thumbnails from B2 to R2
   - Thumbnails promoted to warm cache alongside replay promotion

4. cmd/acb-index-builder/generator.go - Populate thumbnail URLs
   - buildPlaylistMatch() now includes thumbnail_url field
   - URL pattern: https://r2.aicodebattle.com/thumbnails/{match_id}.png
   - Enables playlist cards and embed OG tags to show preview images

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 17:42:36 -04:00
jedarden
80334c6e34 feat(evolver): expand MAP-Elites from 2-D to 4-D grid per §10.2
- Add Exploration and Formation axis definitions with feature extraction
  from source code pattern matching (exploration/formation indicators)
- Extend Grid key from (x,y) to (x,y,z,w) with 3⁴=81-cell behavior grid
- Update bin assignment, promotion gate, and persistence (JSON snapshot)
- Add Slice() for 2-D dashboard visualization across any axis pair
- Migration: old 2-D archives project at z=middle, w=middle
- Update cross-pollination to pad 2-element behavior vectors to 4
- Add Prometheus metrics to matchmaker (bot crashes, stale job count)
- Add rivalry detection to index builder (data/meta/rivalries.json)
- Web: batched bot list loading, leaderboard keyboard accessibility,
  improved ARIA attributes on match/playlist cards

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 15:44:39 -04:00
jedarden
be3843d9ac fix(index-builder): correct series/season exempt queries, optimize playlist curation
- Fix deploy.go to query actual table names (series_games not series_matches,
  join through series_games for seasons instead of non-existent season_matches)
- Add playlist_matches table to exempt match IDs from R2 pruning
- Pre-build lookup maps for O(1) playlist match filtering instead of O(n²)
- Enhance home page featured replay to prefer AI-enriched matches
- Add enrichment test coverage (shouldEnrich criteria validation)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-21 16:47:13 -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
70bde20472 Add Go index builder (cmd/acb-index-builder)
Per plan §11.1, the index builder reads PostgreSQL and generates all JSON
index files for Cloudflare Pages deployment:

- main.go: Build cycle orchestration with configurable timeout, self-restart
- config.go: Environment-based configuration with sensible defaults
- db.go: PostgreSQL data fetching for bots, matches, series, seasons, predictions
- generator.go: JSON index generation (leaderboard, bots, matches, playlists)
- deploy.go: Cloudflare Pages deployment via wrangler, R2 warm cache pruning
- Dockerfile: Multi-stage build with Go + Node.js + wrangler CLI
- main_test.go: Tests for config, index generation, playlists

Index builder runs on 15-minute cycles, deploys to Pages every ~90 minutes,
and prunes R2 warm cache weekly to stay within 10GB free tier.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 03:15:47 -04:00