Recent Improvements - March 2026
This document summarizes all major improvements, bug fixes, and new features added to Hyperscape in early March 2026.Table of Contents
- Branding & Assets
- Object Pooling & Memory Management
- Streaming & Deployment
- Database & Infrastructure
- Testing & Stability
- Dependency Updates
Branding & Assets
Git LFS for Branding Files (PR #981)
Commits: f334c57b, 468da2ee, 2dd85d34 Binary branding assets (~28MB) are now tracked via Git LFS to prevent repository bloat: New Files:publishing/branding/- Official logo files in multiple formats.gitattributes- Git LFS configuration for binary assets
hyperscape_logo_color- Full wordmark with gold gradient (primary)hyperscape_logo_black- Solid black for print/light backgroundshyperscape_logo_white- Solid white for dark backgroundshyperscape_logo_icon_color- “HS” icon for favicons/app icons
- SVG (text, tracked by Git): Source of truth for digital use
- EPS, PDF, PNG, JPG, AI (binary, tracked by Git LFS): Print and raster formats
publishing/branding/README.md for complete usage guidelines.
Object Pooling & Memory Management
Zero-Allocation Event Emission (Commit 4b64b148)
Problem: Combat system fires events every 600ms tick per combatant, causing significant GC pressure from object allocations. Solution: Comprehensive object pooling for event payloads eliminates hot-path allocations. New Infrastructure:packages/shared/src/utils/pools/EventPayloadPool.ts- Factory for type-safe event payload poolspackages/shared/src/utils/pools/PositionPool.ts- Pool for{x, y, z}position objectspackages/shared/src/utils/pools/CombatEventPools.ts- Pre-configured pools for combat events
damageDealt(64 initial, 32 growth)projectileLaunched(32 initial, 16 growth)faceTarget(64 initial, 32 growth)clearFaceTarget(64 initial, 32 growth)attackFailed(32 initial, 16 growth)followTarget(32 initial, 16 growth)combatStarted(32 initial, 16 growth)combatEnded(32 initial, 16 growth)projectileHit(32 initial, 16 growth)combatKill(16 initial, 8 growth)
- Automatic growth when exhausted (warns every 60s)
- Leak detection (warns when payloads not released, max 10 warnings then suppressed)
- Statistics tracking (acquire/release counts, peak usage)
- Global registry for monitoring all pools
- Eliminates per-tick object allocations in combat hot paths
- Memory stays flat during 60s stress test with agents in combat
- Verified zero-allocation event emission in CombatSystem and CombatTickProcessor
- Reduces GC pressure by 90%+ in high-frequency combat scenarios
release() after processing. Failure to release causes pool exhaustion and memory leaks.
Streaming & Deployment
Graceful Restart API (Commit c76ca516)
Problem: Deploying new code during an active duel interrupts the stream and breaks the viewer experience. Solution: Zero-downtime deployment API that waits for the current duel to complete before restarting. New Endpoints:POST /admin/graceful-restart- Request restart after current duel endsGET /admin/restart-status- Check if restart is pending
- If no duel active (IDLE/ANNOUNCEMENT): restart immediately via SIGTERM
- If duel in progress (FIGHTING/RESOLUTION): wait until RESOLUTION phase completes
- PM2 automatically restarts the server with new code
- No interruption to active duels or streams
Placeholder Frame Mode (Commit 83056565)
Problem: Twitch/YouTube disconnect streams after 30 minutes of “idle” content (no significant visual changes). Solution: Send minimal placeholder frames during idle periods to keep the stream alive. Configuration:- Detects when no frames received for 5 seconds
- Switches to placeholder mode, sending minimal JPEG frames at configured FPS
- Automatically exits placeholder mode when live frames resume
- Uses minimal 16x16 JPEG (~300 bytes) scaled by FFmpeg to output size
RTMPBridge.startPlaceholderMode()- Start sending placeholder framesRTMPBridge.stopPlaceholderMode()- Resume live framesRTMPBridge.generatePlaceholderJpeg()- Generate minimal JPEG buffer
Streaming Status Check Script (Commit 61c14bc8)
New Script:scripts/check-streaming-status.sh
Quick diagnostic for verifying streaming health on Vast.ai deployments.
Usage:
- Server health endpoint
- Streaming API status
- Duel context (fighting phase, contestants)
- RTMP bridge status and bytes streamed
- PM2 process status
- Recent logs (last 20 lines)
- ✓ Green checkmarks for healthy services
- ⚠ Yellow warnings for idle/waiting states
- ✗ Red errors for failures
- Summary of stream status (LIVE, ACTIVE, or issues)
Model Agent Spawning (Commit fe6b5354)
Problem: Fresh deployments with empty databases can’t run duels because no agents exist. Solution: Automatic agent creation when database is empty. Configuration:- Checks if database has any agents on startup
- If empty, spawns model agents automatically
- Allows duels to run immediately on fresh deployments
- Useful for testing and demo environments
WebGPU Initialization Improvements
Secure Context Fix (Commit 579124b6, ebd197f2):- Changed WebGPU preflight test from
about:blanktolocalhost:3333 about:blankis NOT a secure context, causingnavigator.gputo be undefined- Localhost HTTP server ensures proper WebGPU API exposure
- Falls back to direct adapter properties when
requestAdapterInfo()unavailable - Older Chromium versions don’t have
adapter.requestAdapterInfo() - Ensures WebGPU diagnostics work across all Chrome versions
- Increased from 60s to 120s for WebGPU shader compilation on first load
- Prevents timeout errors during initial shader compilation
- Consolidate multiple
--enable-featuresflags into single comma-separated flag - Add
isSecureContextcheck to understand WebGPU availability - Add
hasGpuPropertycheck to distinguish undefined vs falsynavigator.gpu - Add Dawn swiftshader backend for SwiftShader mode
- Print navigator GPU-related properties for debugging
- Wait 60s for streaming bridge to initialize after PM2 start
- Capture PM2 logs to diagnose streaming issues
- Detect crash loops and dump error logs automatically
Database & Infrastructure
Railway Database Detection (Commits a5a201c0, d8c26d2f)
Problem: Railway uses pgbouncer connection pooling which doesn’t support prepared statements, causing XX000 errors. Solution: Automatic detection of Railway proxy connections with appropriate configuration. Detection Methods:RAILWAY_ENVIRONMENTenv var (most reliable, auto-set by Railway)- Hostname patterns:
.rlwy.net,.railway.app,.railway.internal
- Disables prepared statements when using Railway proxy
- Uses lower connection pool limits (max: 6 instead of 10-20)
- Prevents “too many clients already” errors
PostgreSQL Connection Pool Optimization (Commits 0c8dbe0f, 454d0ad2, 56f9067e)
Problem: Crash loops cause connection exhaustion, leading to “too many clients already” errors. Solution: Reduced connection pool size and increased restart delays. Configuration Changes:Deployment Process Improvements (Commits 087033fa, 58d88f4c, dbd4332d)
Targeted Process Killing (Commit 087033fa):- Use specific process names instead of blanket
pkill -f bun - Prevents deploy script from killing itself
- Graceful PM2 shutdown with delays between commands
- Kill processes and wait 30s for DB connections to close before running migrations
- Prevents “too many clients” errors during database migrations
- Ensures clean state before schema changes
- Deploy from
mainbranch instead ofhackathonbranch - Ensures production deployments use stable code
- Fixed
upload-artifactversion (v7 → v4) for compatibility - Fixed build order (shared must build before impostors/procgen)
- Fixed heredoc variable expansion in deploy-vast.yml
Testing & Stability
Vitest 4.x Upgrade (Commit a916e4ee)
Problem: Vitest 2.x is incompatible with Vite 6.x, causing__vite_ssr_exportName__ errors.
Solution: Upgraded vitest and @vitest/coverage-v8 from 2.1.0 to 4.0.6.
Migration:
Anchor Test Skip (Commit 8b7d1261)
Problem: Anchor localnet tests fail in CI when Solana CLI is not installed, causing false failures. Solution: Automatically skip Anchor localnet tests in CI when Solana CLI is unavailable. Implementation:- Check for
solanacommand availability before running tests - Skip tests with clear message if Solana CLI not found
- Prevents CI failures on environments without Solana toolchain
Type Fixes (Commit b61a34e7)
Fixed Issues:- Added ‘banking’ goal type to
CurrentGoalinterface - Removed non-existent
lootStarterChestActionimport - Added
getDuelHistorystub method toAutonomousBehaviorManager - Fixed CombatSystem projectile event using wrong property name (
flightTimeMs→travelDurationMs) - Updated gold-betting-demo IDL files
API Documentation
Admin Routes
Graceful Restart Endpoints:StreamingDuelScheduler API
New Methods:- If no active duel: triggers immediate restart via SIGTERM
- If duel in progress: waits for RESOLUTION phase to complete
- PM2 handles the actual restart
- Returns false if restart already pending
Environment Variables
New Variables
Streaming Configuration:Scripts & Commands
New Commands
Streaming Status Check:Migration Notes
Breaking Changes
Vitest 4.x Required:- All packages using Vitest must upgrade to 4.x for Vite 6 compatibility
- Update
vitestand@vitest/coverage-v8to^4.0.6 - No API changes - tests work as-is
- Event listeners MUST call
release()after processing pooled payloads - Failure to release causes pool exhaustion and memory leaks
- Add
CombatEventPools.{poolName}.release(payload)to all combat event listeners
Recommended Actions
For Railway Deployments:- Set
POSTGRES_POOL_MAX=6(or lower) in.env - Set
POSTGRES_POOL_MIN=0to not hold idle connections - Increase
restart_delay=10sin PM2 config - Railway detection is automatic - no manual configuration needed
- Use
bun run vast:provisionto automatically rent WebGPU-capable instances - Ensure instances have
gpu_display_active=true - Set
STREAM_PLACEHOLDER_ENABLED=trueto prevent 30-minute disconnects - Use
bun run duel:statusto monitor streaming health
- Set
NODE_ENV=productionorDUEL_USE_PRODUCTION_CLIENT=true - Use pre-built client for faster page loads
- Enable placeholder frames to prevent disconnects
- Use graceful restart API for zero-downtime deployments
Performance Metrics
Object Pooling Impact
Before:- ~1000 object allocations per second during active combat
- Heap growth of ~50MB over 60s stress test
- Frequent GC pauses (10-20ms)
- Zero allocations in combat hot paths after warmup
- Flat memory usage during 60s stress test
- GC pressure reduced by 90%+
Streaming Improvements
Page Load Time:- Dev server: 30-180s (JIT compilation)
- Production build: 5-10s (pre-compiled)
- Placeholder mode prevents 30-minute disconnects
- Graceful restart enables zero-downtime deployments
- Automatic recovery from WebGPU initialization failures
Dependency Updates
Major Version Updates
Bun Runtime:- Updated from v1.1.38 to v1.3.10 (Commit bc3b1bcf)
- Docker image:
oven/bun:1.3.10-alpine
- Updated from v2.1.0 to v4.0.6 (Commit a916e4ee)
- Required for Vite 6.x compatibility
actions/configure-pages: v4 → v5 (Commit ab81e50b)actions/upload-artifact: v4 → v7 (Commit 7a65a2a8)appleboy/ssh-action: v1.0.3 → v1.2.5 (Commit 3040c29f)
Summary
This release focused on three main areas:- Memory Management: Object pooling eliminates GC pressure in combat hot paths
- Streaming Reliability: Placeholder frames, graceful restarts, and improved WebGPU initialization
- Infrastructure: Railway detection, connection pool optimization, deployment process improvements
- 90%+ reduction in GC pressure during combat
- Zero-downtime deployments for duel arena
- Automatic Railway/Vast.ai configuration
- Improved test stability with Vitest 4.x