The POST /api/register endpoint sets status='active' for newly registered
bots, and the matchmaker queries for all active bots. Integration is complete;
no code changes required.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Verified that commit 7e8c9d7 completed all registration requirements:
- Added to §5.8 Starter Kit table
- Added to file structure section
- Added to published template repos table
- CI workflow already exists
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Complete the file structure section by including csharp/ alongside the other 7 starter kits. The C# starter kit is already fully documented in §5.8 and §11.2 tables.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The bead task indicated missing CI workflow and plan §5.8 coverage,
but verification found all components already in place from commit 55c594c.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add acb-starter-csharp to §5.8 starter kit table
- Add acb-starter-csharp to §11.2 template repos table
- Update evolution validation test suite language list
The C# starter kit exists at starters/csharp/ with full implementation
including ASP.NET Core minimal API, HMAC auth, grid utilities, tests,
Dockerfile, and CI workflow. It was simply missing from plan documentation.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The JavaScript starter kit was officially registered via commit 7e8c9d7,
which added it to plan §5.8, the file structure section, and the published
template repos table. This notes file documents the completion status.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add `acb-starter-javascript` to §5.8 Starter Kit table
- Add javascript/ to file structure section
- Add `acb-starter-javascript` to published template repos table
The JavaScript starter already exists in starters/javascript/ with:
- Dockerfile, CI workflow, README, package.json
- Node.js built-in http module, zero dependencies
This registers it as an official starter kit alongside the other 6 languages.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add /opt to nsjail bindmounts so Rust toolchain (/opt/rust) is accessible
during sandboxed validation of Rust bots
- Explicitly enable Alpine community repository in Dockerfile to ensure
nsjail package can be installed (nsjail lives in community, not main)
- nsjail integration was already optional (falls back to plain exec if
unavailable), but these changes ensure it actually works when enabled
This addresses bead bf-3f29: nsjail was listed in apk add but /opt wasn't
bindmounted, causing Rust validation to fail when UseNsjail=true.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The evolver's validation pipeline supports Rust and Java bots, but the
container image was missing rustc and javac runtimes. Additionally, nsjail
was documented as part of the sandbox stage but not installed.
Changes:
- Add nsjail package (from Alpine community repo) for sandbox isolation
- Add openjdk-17-jdk for Java bot validation
- Install Rust toolchain (rustc) via rustup to /opt/rust for shared access
- Set PATH to include Rust binaries for the acb user
The validator already had graceful fallback when nsjail wasn't found in PATH,
but with nsjail installed, the sandbox stage now provides proper CPU/memory
resource limits during smoke testing.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Verified complete implementation of §16.9 directed attack arrows feature:
- Engine emits combat_death events with killers array (bot_id, owner, position)
- TypeScript types properly define CombatDeathKiller and CombatDeathDetails
- Viewer draws solid arrows from each killer to victim with attacker player color
- Arrowheads point to victim tile center
- Backward compatibility maintained for old replays (proximity-inference fallback)
- Red explosion flash and X marker for death visualization
Related commits: 8e0aa5e (engine), 323c1e8 (viewer)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Verified that the feature implemented in commits 8e0aa5e (engine) and 323c1e8 (viewer) is complete and working:
Engine (engine/turn.go):
- executeCombat emits EventCombatDeath with killers[] array
- Each killer entry includes bot_id, owner, and position
Viewer (web/src/replay-viewer.ts):
- drawCombatEffects() handles combat_death events with killers[]
- Draws solid colored arrows from each killer to the victim
- Includes red explosion flash and X marker for death
- Maintains backward compatibility with old replays (proximity-inference fallback)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The feature was already fully implemented in commits 8e0aa5e and 323c1e8.
This commit documents the verification of that implementation.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Updated CombatDeathDetails type to include killers[] array with each killer's bot_id, owner, and position
- Modified drawCombatEffects() to handle combat_death events by drawing solid arrows from each killer to the victim
- Added drawArrow() helper method to draw arrows with arrowheads
- Maintained backward compatibility: old replays without combat_death events use proximity-inference lines
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Modified executeCombat to emit EventCombatDeath events with a killers
array containing all enemy bots within attack radius of the killed bot.
Each killer entry includes bot_id, owner, and position, matching the
replay schema specification.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Each player now starts with 2 cores and a bot at each, placing forces
mid-map from turn 1 and creating earlier conflict.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add display: flex and align-items: center to .participant on mobile
- Change .participant-name from flex-shrink: 1 to flex: 1 for proper space allocation
- Add margin-left spacing to .participant-score and .winner-badge
- Ensures all participant info (name, score, winner badge) is visible on mobile
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Change .match-participants to column layout on mobile for better width distribution
- Allow .participant elements to shrink (flex-shrink: 1)
- Remove max-width constraint from .participant-name
- Ensures participant names, scores, and Winner badge are all visible
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Investigated why all matches have enriched: false. Root cause is
corrupted R2 credentials in OpenBao that prevent the acb-enrichment
service from uploading AI commentary.
Key findings:
- R2 credentials at secret/rs-manager/ai-code-battle/r2 are corrupted
- endpoint/secret-key values are swapped
- Enrichment service cannot upload to R2
- Fix script exists but requires cluster access
Blocker: Expired kubeconfig (bf-5nap) prevents cluster access
and execution of the fix.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When navigating to /watch/replay/:id (e.g., from the "Closest Match" link in rivalries), params.url was undefined, causing the viewer to show "Enter a replay URL to load" message. Fixed by constructing the URL from params.id when params.url is not set, using the pattern /r2/replays/MATCHID.json.gz.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The worker was only configured with B2 (ARMOR) credentials, so replays were
being uploaded to B2 but not to R2. The index builder's B2→R2 promotion
cycle only covers the last 24 hours, so older replays were not available
in R2, causing 404 errors when clicking "Watch Replay".
This fix adds R2 credentials to the worker deployment, allowing it to
upload replays directly to R2 (hot cache) in addition to B2 (cold archive).
This makes replays immediately available for viewing without waiting for
the promotion cycle.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The bug fix was already applied in commit 9bcbd56. Updated notes to reflect:
- Fix is already in the codebase (using p.Won instead of p.BotID == m.WinnerID)
- Index builder will automatically regenerate static JSON on next 15m cycle
- No manual intervention required - production deployment will pick up the fix automatically
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The code fix for the winner badge bug has been applied. The index
builder needs to be run in an environment with Go installed to
regenerate static JSON files with correct winner badges.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The code fix was already applied in commit 6fe778b. This commit
adds documentation noting that the index builder needs to be run
to regenerate static JSON with correct winner badges.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
Matches stopped being created after 2026-05-09. The iad-acb kubeconfig on
ex44 has expired credentials, preventing cluster access for diagnosis.
Created comprehensive diagnostic documentation covering:
- Cluster architecture and components (matchmaker, workers)
- Step-by-step diagnostic procedures for kubectl access
- Pod status checks and log analysis commands
- Database verification queries
- Service restart procedures
- Known issues from prior incidents (R2 credentials corruption)
Next steps:
1. Renew iad-acb token from Rackspace Spot UI
2. Update kubeconfig on ex44
3. Execute diagnostic commands to identify root cause
4. Restart services as needed
5. Verify match creation resumes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix TestBuildNarrativePrompt_Comeback to check for current ELO
instead of old rating (comeback arc shows bottom 25%→top 25%)
- Fix TestDetectRivalryArcs to use 10+ matches (grudge match spec)
instead of only 5 matches
Story arc detection (per §3.7 chronicles):
✓ Comeback bots: recovered from bottom 25% to top 25%
✓ Grudge matches: same pair meets 10+ times
✓ Underdog victories: bottom-10 beats top-10
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Fix /docs/api route to go directly to API docs page instead of redirecting
- Fix docs.ts link to point to /compete/docs/api instead of itself
- Add download button for replay-schema-v1.json in API docs
- Reorder router routes to ensure /docs/api is matched before /docs
The API documentation at /docs/api now correctly shows the OpenAPI-style
endpoint documentation for all static JSON file paths on Pages, R2, and B2,
including the versioned replay format specification.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Added comprehensive keyboard shortcuts overlay modal and missing shortcuts
for the replay viewer:
- New keyboard shortcuts overlay (activated by ? or / key) showing all
available shortcuts in an accessible modal dialog
- Added missing shortcuts: V (cycle view mode), E (toggle event timeline),
C (toggle commentary), Shift+arrows (jump 10 turns)
- Updated visible shortcuts list in sidebar to include all shortcuts
- Modal is fully accessible with ARIA roles, keyboard navigation, and
respects prefers-reduced-motion
- All shortcuts are WCAG 2.1 Level AA compliant
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Evolver writes live.json to R2 every cycle. Observatory page polls and
renders live feed + lineage tree + meta shift chart.
- Added ACB_R2_UPLOAD_ENABLED env var to enable automatic R2 upload during run loop
- CycleState tracks real-time evolution cycle status (generation, phase, candidate, validation, evaluation)
- Export() now includes cycle info when cycleState is provided
- runCycle() integrated with live observatory exports at each phase transition
- exportLiveQuiet() for mid-cycle status updates without verbose logging
- Fixed function signature mismatches for exportLiveQuiet calls
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The win probability sparkline component is now fully integrated:
1. Worker (engine/winprob.go): Monte Carlo rollout computes per-turn win
probabilities, detectCriticalMoments identifies turns where win prob
shifts >15% with template-based descriptions.
2. Replay storage (engine/replay.go): win_prob and critical_moments arrays
stored in replay JSON, written by match worker after each match.
3. Web component (web/src/components/win-prob.ts): WinProbSparkline class
renders the graph with critical moment markers (dashed vertical lines),
click-to-scrub interaction, and current turn indicator.
4. Replay page integration (web/src/pages/replay.ts): initWinProb() sets up
the sparkline with player colors, legend, prev/next critical moment
navigation buttons, and keyboard shortcuts ([/]).
The sparkline displays one line per player with area fill gradient,
percentage labels (0%, 50%, 100%), critical moment diamonds with
delta labels, and updates in real-time as the replay plays.
- Client-side event extraction from replay turn data
- Icon ribbon overlaid on replay viewer timeline
- Click-to-jump to event moment
- Computed events: mass death (5+ bots), spawn wave (3+ spawns),
momentum shift (win prob crosses 50%), critical moment (>15% shift)
- Energy milestone detection (3+ energy collected)
- Hover tooltips with event descriptions
- Updated icons matching plan §14.8 specification
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Per §14.10 of the plan, implemented shareable bot profile cards:
- Canvas-rendered PNG cards (800x450) with bot stats and branding
- Open Graph tags for social sharing (og:image points to /r2/cards/{bot_id}.png)
- "Share Card" button on bot profile page downloads the card as PNG
- Card displays: name, rating, rank badge, owner, archetype, win rate, stats
- Evolved badge, signature move, and recent rival info
- Responsive styles for desktop and mobile
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add optional debug field in move response schema with extended telemetry:
- values: key-value pairs for debug display (metrics, state flags)
- heatmap: 2D grid overlay for visualization (threat maps, influence maps)
Engine changes:
- Add Values and Heatmap fields to DebugInfo struct in bot_http.go
- Add DebugHeatmap struct with name and 2D data array
Web viewer changes:
- Extend DebugInfo interface in types.ts with values and heatmap
- Implement heatmap rendering with blue→red gradient overlay
- Add getHeatmapColor helper for normalized value visualization
- Update debug panel to display values as key-value table
- Show heatmap info with name and dimensions
Schema updates:
- Add DebugHeatmap definition to replay-schema-v1.json
- Extend DebugInfo with values and heatmap properties
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- All 5 presets implemented: Landscape (1920×1080), Square (1080×1080), Portrait (1080×1920), GIF compact (640×360), GIF square (480×480)
- MP4/WebM export via MediaRecorder API
- Custom GIF encoder with LZW compression and 256-color palette
- Share panel with Twitter, Reddit, Discord integration
- Web Share API support for native sharing
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- WASM game engine (cmd/acb-wasm/) with loadState/step/runMatch API
- Pre-compiled 6 strategy bots to WASM (web/public/wasm/bots/)
- In-browser sandbox with Monaco editor (web/src/pages/sandbox.ts)
- WASM upload mode with interface validation
- Opponent selector (up to 3 opponents for 2-4 player matches)
- Replay viewer integration with fog-of-war toggle and view modes
- All tests pass, go vet clean, npm build succeeds
The reveal() function was trying to return the result of setXP()
which returns void. Fixed by setting XP first, then returning
the threshold value.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Fastify HTTP server with HMAC-SHA256 authentication
- Full TypeScript type definitions for game protocol
- Grid utilities: toroidal distance, BFS, neighbors
- HMAC signing/verification via Node.js crypto
- Multi-stage Dockerfile for production builds
- GitHub Actions workflow for CI/CD
- Placeholder strategy that moves toward energy
- ES modules with Node.js 20+ support
Add .gitignore to exclude Rust build artifacts from version control.
This matches the pattern used by other starter kits and keeps the
repository clean of build outputs.
- Add Clone derive to AppState for axum compatibility
- Import Digest trait from sha2 for hash computation
- Use String instead of &str in response headers for lifetime safety
- Add Position import to grid.rs module
- Make Position Copy for easier cloning
- Replace constant_time_eq with custom hmac_equal function
- Add musl-dev to Dockerfile for Alpine build compatibility
The Rust starter kit now compiles and builds successfully with
cargo check and Docker, matching the requirements from plan §5.3
and §12 (Phase 2).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Complete Go starter kit for AI Code Battle with:
- main.go: HTTP server with HMAC authentication, placeholder computeMoves()
- game/ package: Shared utilities (types, auth, grid) for reuse
- types.go: Game state types, Direction constants, Position, etc.
- auth.go: HMAC-SHA256 signing/verification with timestamp validation
- grid.go: Toroidal distance, BFS pathfinding, neighbor functions
- Tests: Comprehensive test coverage for grid and auth utilities
- Dockerfile: Multi-stage build with Go 1.24-alpine
- README: Complete documentation with examples and protocol reference
The starter kit provides a minimal working bot that holds position
by default. Participants implement their strategy in computeMoves()
using the provided grid utilities.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Flask HTTP server (~130 lines) with HMAC-SHA256 signing, game state
type definitions, stub strategy, and Dockerfile.
- Flask-based /turn and /health endpoints
- HMAC-SHA256 request verification and response signing
- Type-annotated compute_moves() stub (holds all bots in place)
- Grid utilities: toroidal distance, BFS, neighbor enumeration
- README with quickstart, protocol spec, and customization guide
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>