A digital organism that continuously rewrites its own TypeScript source proposal, validation-gates each mutation, and awaits your approval before it goes active.
Val Town is serverless — there is no persistent always-on process and no true 1-second interval (free tier minimum is 15 minutes; Pro is 1 minute).
So the real-time engine is a self-triggering HTTP pump:
- While the dashboard is open, its browser
POSTs/advanceonce per second, so the organism evolves at ~1 generation/second. - When nobody has the dashboard open, an interval heartbeat keeps it alive slowly (the shortest supported interval).
The dashboard always displays the measured actual rate — it never claims
1/s it isn't achieving. Rate is computed from real created_at timestamps.
| File | Type | Role |
|---|---|---|
core.ts | script | Engine: DB, AI mutation, layered validation, sandbox gate, approval/rollback, metrics |
dashboard.tsx | http | Live containment console + the engine's HTTP API (same handler) |
client.js | script | Browser pump (the real-time driver) + live renderer + controls |
main.ts | interval | Backup heartbeat — keeps it evolving when the dashboard is closed |
README.md | file | This document |
CURRENT SOURCE → AI ANALYSIS → NEW SOURCE → DIFF → VALIDATION → SANDBOX TEST → STORE (PENDING) → DISPLAY → next
A mutation only becomes ACTIVE when you APPROVE it. Until then every new generation stays PENDING. Rejected/rolled-back generations are never deleted — history is immutable.
- Dashboard —
dashboard.tsxis an http file. Open it: https://abyssal-engine.val.run - Backup heartbeat —
main.tsis an interval file. It's set to the fastest schedule the free tier permits (15 min). To change it, edit the interval settings onmain.ts. - Open the dashboard and leave it open → the organism starts evolving at ~1 generation/sec. The page auto-refreshes every second via the pump.
- APPROVE — promote a PENDING proposal to ACTIVE.
- REJECT — mark a proposal rejected (history preserved).
- RB (rollback) — restore any past generation as ACTIVE.
- The mutation lock (
mutation_in_progress) guarantees the pump and the heartbeat never overlap and overwrite each other.
GET /api/state— JSON snapshot (metrics, active, candidates, timeline, logs).GET /gen/:id— full JSON for one generation (source, statuses, diffs).- Or run
sqlitequeries against this val's project-scoped database (std/sqlite/main.ts): thegenerations,evolution_log, andmetatables.
OPENAI_MODEL(optional) — pick a specific model. If unset,std/openaiuses its default. Do not set a hard-coded unverified model.
Generated source is DATA ONLY and is never executed. Validation is layered (markers, claimed values, balanced delimiters, meaningful diff, forbidden capabilities, control-subversion detection). The sandbox is a structural static gate. The fixed control system (validation / approval / rollback) is never reachable from generated source.
GET / → dashboard
POST /advance → run one evolution cycle (the pump's heartbeat)
POST /approve/:id → approve a PENDING generation
POST /reject/:id → reject a generation
POST /rollback/:id → restore a generation as ACTIVE
GET /api/state → JSON snapshot
GET /gen/:id → one generation