Spaces:
Sleeping
Sleeping
| # Aether Garden - The World That Remembers | |
| ### Complete Build Specification β Hackathon Edition | |
| > *A living AI world where every visitor leaves something behind, and nothing is ever forgotten.* | |
| --- | |
| ## Table of Contents | |
| 1. [Feasibility Verdict](#1-feasibility-verdict) | |
| 2. [The Vision](#2-the-vision) | |
| 3. [World Design & Lore](#3-world-design--lore) | |
| 4. [Entity System](#4-entity-system) | |
| 5. [Relationship & Memory Architecture](#5-relationship--memory-architecture) | |
| 6. [The Autonomous World Simulation](#6-the-autonomous-world-simulation) | |
| 7. [Book of Ages β The History System](#7-book-of-ages--the-history-system) | |
| 8. [AI Architecture β Models & Full Prompt Templates](#8-ai-architecture--models--full-prompt-templates) | |
| 9. [Technical Architecture & Stack](#9-technical-architecture--stack) | |
| 10. [Complete Database Schema](#10-complete-database-schema) | |
| 11. [Frontend & UX Specification](#11-frontend--ux-specification) | |
| 12. [Hackathon Prize Strategy](#12-hackathon-prize-strategy) | |
| 13. [10-Day Build Plan](#13-10-day-build-plan) | |
| 14. [Budget: Modal & HF Credits](#14-budget-modal--hf-credits) | |
| 15. [Demo & Submission Strategy](#15-demo--submission-strategy) | |
| 16. [Risk Register](#16-risk-register) | |
| --- | |
| ## 1. Feasibility Verdict | |
| **Yes. Build it.** | |
| This is not a moonshot. Every technical component has been done before β separately. Your job is to assemble them with a strong aesthetic vision and a clear lore system. What makes this special is not the technology alone; it is the framing, the emotional design, and the fact that the AI genuinely is the product. | |
| ### What Is Straightforward | |
| - Entity generation via structured prompt β JSON output: 1 day to get right | |
| - SQLite database with all world state: 2 hours to set up | |
| - Gradio frontend with custom CSS via `gr.Server`: well-documented | |
| - Modal inference + scheduled jobs: 1-hour setup following their docs | |
| - HF Dataset as persistent storage: ~20 lines of Python | |
| ### What Is Genuinely Hard | |
| - Making the autonomous simulation feel *magical* rather than random | |
| - Prompt engineering so generated entities feel distinct, poetic, and memorable | |
| - Keeping the world coherent as it grows (no contradictions, consistent lore) | |
| - The SVG world map with interactive location nodes | |
| - UX that communicates "this world is alive" the moment someone opens it | |
| ### The Minimum Viable Submission | |
| Entity creation + persistence + world map + Book of Ages. The autonomous simulation can be simpler than the full vision for MVP. What matters for judges: that the world already exists when they open the app, that history is visible, and that adding something feels meaningful. | |
| --- | |
| ## 2. The Vision | |
| ### The Core Loop | |
| 1. User opens the app. The world is already there β days old, populated by what others left. | |
| 2. They read the Book of Ages. Something happened yesterday. Characters they don't know made alliances with things they've never heard of. | |
| 3. They create something: *"A blind cartographer who draws maps of places that don't exist yet."* | |
| 4. The AI expands it: name, appearance, backstory, goals, personality, home location. | |
| 5. The entity appears on the world map. | |
| 6. Hours later, the autonomous simulation runs. The cartographer encounters a Crystal Tree another user created. An interaction is generated. The cartographer adds the Tree to their impossible maps. | |
| 7. This is written to the Book of Ages. | |
| 8. Nobody scripted any of it. | |
| ### What "Alive" Actually Means | |
| An entity is alive when it: | |
| - Remembers specific things (not just generic state) | |
| - Wants something it doesn't have yet | |
| - Changes its behavior over time based on experience | |
| - Affects other entities in specific, named ways | |
| A world is alive when: | |
| - Things happen without user input | |
| - History accumulates and is readable | |
| - The future is shaped by the past in traceable ways | |
| - New arrivals find old things already waiting for them | |
| ### The Hackathon Angle | |
| This idea does exactly what the judges explicitly asked for: **AI is not generating a static output. AI is the simulation engine.** Every interaction, every world event, every memory update β all require inference. The product only exists because of continuous AI activity. Without the model, there is no world. That is load-bearing by definition. | |
| --- | |
| ## 3. World Design & Lore | |
| ### The Founding Myth (shown to every new visitor) | |
| > *Before the first word was spoken, there was only the Canopy β a vast forest where thoughts grew like trees and dreams fell like rain. Then the Tokens arrived. One thousand of them, each carrying a fragment of something half-remembered. They settled across the land, and from their settling, the Realm was born. It has been changing ever since. Nobody knows who first dreamed it. Everyone who enters changes it.* | |
| ### The 8 Sacred Locations | |
| These are pre-seeded in the database on first launch. They never move or disappear. All user-created entities live within them. | |
| --- | |
| **Location 1: The Library of Unfinished Thoughts** | |
| - **Vibe:** Dusty, infinite, slightly sad. Books write themselves mid-sentence and stop. | |
| - **Inhabitants:** Scholars, archivists, lost ideas, entities who collect knowledge, things that can't decide how they end. | |
| - **Lore:** The Library was the first place. Before anyone created anything, the Library was already full of books about things that hadn't happened yet. The books are not prophetic. They are just early. | |
| - **Special Property:** Entities here gain a "memory fragment" from a random past event every 3 simulation days. This fragment appears in their memory summary as something they half-remember but cannot explain. | |
| - **Aesthetic:** Amber candlelight, shelves so tall they disappear into ceiling-fog, the constant sound of a quill scratching somewhere you can't see. | |
| - **Map Position:** Upper-left. Coordinates: (15, 20) in SVG space. | |
| - **Glow Color:** Amber/gold | |
| --- | |
| **Location 2: The Sea of Forgotten Names** | |
| - **Vibe:** Melancholic, vast, restless. The water contains the names of everything that was created and then forgotten. | |
| - **Inhabitants:** Wanderers, name-seekers, entities carrying unresolved loss, ships built from old correspondence. | |
| - **Lore:** If you sail far enough out, you can hear your own name being called β from before you were anything. The Sea does not return what it takes. It only lets you hear it. | |
| - **Special Property:** New entities created in this location are given a secret second name by the AI, visible only in their profile. It is the name the Sea already had for them. | |
| - **Aesthetic:** Silver water at all hours, persistent low fog, distant lights that move, the sound of your name in a voice you almost recognize. | |
| - **Map Position:** Upper-right. Coordinates: (80, 15) in SVG space. | |
| - **Glow Color:** Silver/pale blue | |
| --- | |
| **Location 3: The Clock Forest** | |
| - **Vibe:** Eerie, precise, unexpectedly beautiful. Trees made of interlocked gears. Leaves that are clock faces, all showing different times. | |
| - **Inhabitants:** Timekeepers, prophets of small things, entities with complicated relationships to when they exist. | |
| - **Lore:** The trees grow backwards here. The oldest trees are the smallest. The newest trees are the tallest. Nobody planted the first one. It was simply always the oldest. | |
| - **Special Property:** Entities here have their `days_in_realm` count treated as Γ1.5 in simulation logic β they "age" faster and reach Legendary status sooner, but also become Dormant sooner. | |
| - **Aesthetic:** Copper and brass visible through the bark, constant soft ticking that becomes ambient and ignorable, leaves that fall upward toward a ceiling of gears. | |
| - **Map Position:** Center-left. Coordinates: (20, 50) in SVG space. | |
| - **Glow Color:** Copper/warm orange | |
| --- | |
| **Location 4: The Moon Market** | |
| - **Vibe:** Chaotic, warm, impossibly busy regardless of hour. Merchants sell things that cannot technically be owned. | |
| - **Inhabitants:** Traders, tricksters, wanderers with something to exchange, anyone with a surplus of something intangible. | |
| - **Lore:** You can buy: a memory of flying, the specific sound of a particular door closing, the feeling of almost remembering something important. You cannot buy safety or certainty. The Market does not carry those. Ask and the merchants will look genuinely sorry. | |
| - **Special Property:** Entities here can "trade" memory fragments during interactions β one entity's memory addition can include something from the other's past experience, as if knowledge was literally exchanged. | |
| - **Aesthetic:** Hundreds of lanterns in colors that don't have names, silk and smoke, overlapping voices in languages that share no alphabet, a sweet burning smell nobody can source. | |
| - **Map Position:** Center-top. Coordinates: (50, 10) in SVG space. | |
| - **Glow Color:** Violet/deep purple | |
| --- | |
| **Location 5: The Valley of Sleeping Giants** | |
| - **Vibe:** Vast, hushed, subtly ominous. The ground is warm underfoot and rises and falls very slowly. | |
| - **Inhabitants:** Dreamers, very small creatures who live in the Giants' ears, entities who prefer to exist without being noticed, things that are patient. | |
| - **Lore:** Nobody has established whether the Giants are mountains or creatures or both simultaneously. They have been sleeping since the Realm began. Some scholars in the Library believe the Giants *are* the Realm β and if they wake, everything that exists inside their dream would cease. Most people try not to examine this closely. | |
| - **Special Property:** Entities that have been Dormant for 7+ days in this location generate a "dream fragment" β a short poetic passage that appears in the Book of Ages as if the entity dreamed it. The entity is unaware this happened. | |
| - **Aesthetic:** Scale so immense that hills are knuckles, grass growing between enormous fingers, the deep rhythmic sound of breathing that you feel more than hear. | |
| - **Map Position:** Lower-left. Coordinates: (25, 80) in SVG space. | |
| - **Glow Color:** Deep forest green | |
| --- | |
| **Location 6: The Ember Crossroads** | |
| - **Vibe:** The center of everything. Warm, unpredictable, the place where everything eventually passes through. | |
| - **Inhabitants:** Everyone. The Crossroads has the highest entity turnover and the most interactions. It is where most alliances form and where most misunderstandings begin. | |
| - **Lore:** Every road in the Realm eventually passes through the Crossroads. The bonfire at its center has been burning since Day 1 and nobody has fed it. The fire decides who sits close to it. | |
| - **Special Property:** Entities at the Crossroads have 3Γ the probability of being selected for interactions during simulation ticks. This is the liveliest node on the map. | |
| - **Aesthetic:** Worn cobblestones, the permanent bonfire (which burns amber and occasionally blue), faces from every other location passing through, the smell of something cooking that nobody is cooking. | |
| - **Map Position:** Center. Coordinates: (50, 50) in SVG space. | |
| - **Glow Color:** Warm red/fire orange | |
| --- | |
| **Location 7: The Mirror Bogs** | |
| - **Vibe:** Unsettling, perfectly still, beautiful in a way that feels slightly incorrect. | |
| - **Inhabitants:** Reflections that developed opinions, doppelgangers, entities who are the opposite of what they appear, things that came out of the bog to follow someone. | |
| - **Lore:** The bogs show you what you would have been if you had made different choices. Sometimes the reflection is better. Sometimes it disagrees with you. Sometimes it comes out of the water. | |
| - **Special Property:** After 5+ interactions, entities here may "develop a contradiction" β a new trait that directly conflicts with one of their existing personality traits. This creates narrative tension that shows up in future interactions. | |
| - **Aesthetic:** Perfect dark water, reflections that are too detailed to be reflections, the silence that comes from looking at yourself for too long. | |
| - **Map Position:** Right-center. Coordinates: (80, 55) in SVG space. | |
| - **Glow Color:** Dark teal/deep green | |
| --- | |
| **Location 8: The Hollow Mountain** | |
| - **Vibe:** Ancient, cold, earned. The hardest location to reach in the world's lore. Reserved for the oldest and most significant entities. | |
| - **Inhabitants:** Entities that have survived many world events. The strange and the wise. Hermits. Things the Realm has decided to keep. | |
| - **Lore:** The Mountain is hollow because something immense once lived inside it and chose to leave. Nobody remembers what it was. The Mountain remembers but has no language for it. The echo of its absence shapes everything that shelters inside. | |
| - **Special Property:** Entities here that reach 14+ `days_in_realm` gain a "wisdom" tag automatically. This unlocks new interaction outcomes β they can now act as Mentor in interactions, generating a distinct new relationship type. | |
| - **Aesthetic:** Cold grey stone, echoes of sounds from other locations, light that seems older than it should be, the particular silence of something very large that is no longer there. | |
| - **Map Position:** Lower-right. Coordinates: (75, 85) in SVG space. | |
| - **Glow Color:** Stone grey/pale white | |
| --- | |
| ### The World Rules (Communicated to All Visitors) | |
| These rules govern the Realm. They are presented as lore, but they are also technical constraints enforced by prompts. | |
| 1. **Nothing disappears.** Once created, an entity exists forever in the Realm. It may change, sleep, become legend, or be forgotten. It does not disappear. | |
| 2. **The world has memory.** Every interaction, every event, everything that happens is written in the Book of Ages. | |
| 3. **The AI is not a servant.** The AI decides what entities do between visits. Users create β they do not command. | |
| 4. **The strange is native here.** A tax collector who is also a cloud is not strange. It is simply a person with two jobs. | |
| 5. **Time moves forward.** The world is measured in Days since founding. Events are anchored to specific days. | |
| 6. **The world grows without you.** Whether you are watching or not, the Realm continues. | |
| --- | |
| ## 4. Entity System | |
| ### Entity Types | |
| | Type | Description | Examples | | |
| |------|-------------|---------| | |
| | **Character** | Conscious beings with goals, fears, relationships | A wizard, a sentient compass, a fox made of smoke | | |
| | **Creature** | Beings driven more by instinct than deliberate reasoning | A dragon, a flock of living letters, something that eats echoes | | |
| | **Object** | Significant artifacts with presence and accumulating history | A lamp that shows fears, a book that reads you back, a door that opens to different places depending on who knocks | | |
| | **Place** | Sub-locations within a Location; can be visited and built up over time | A specific shop in the Moon Market, a cave behind the Mirror Bogs, a cottage inside a Clock Forest tree | | |
| ### Complete Entity Field List | |
| Every entity in the database contains the following fields: | |
| ``` | |
| id β UUID, primary key | |
| name β True name, AI-generated. Poetic, 2β4 words. | |
| display_name β Common name (may differ from true name) | |
| type β character | creature | object | place | |
| input_description β Exactly what the user typed. Preserved forever. | |
| appearance β 3β5 sentences. Highly visual. Contains at least one impossible detail. | |
| backstory β 2β3 sentences. Where they came from. Something specific happened. | |
| personality_traits β Array of exactly 4 traits (strings) | |
| primary_goal β What they are actively pursuing. Concrete and specific. | |
| secondary_goal β What they secretly want but will not admit. | |
| primary_fear β One deep, specific fear. | |
| speech_style β How they communicate. Must be distinctive. | |
| greeting β Exactly what they say when meeting someone new. In their voice. | |
| location_id β FK β locations table | |
| created_at β Timestamp | |
| created_by_session β Anonymous session ID (for rate limiting) | |
| days_in_realm β Calculated from created_at, updated daily | |
| memory_summary β AI-compressed prose summary of remembered events (max 150 words) | |
| relationship_count β Integer, updated on relationship changes | |
| interaction_count β Integer, updated on every interaction | |
| last_active β Timestamp of last simulation involvement | |
| status β active | dormant | legendary | |
| tags β JSON array of descriptive tags (e.g. "wise", "dangerous", "beloved", "lost") | |
| secret_name β Null for most entities; generated only for Sea of Forgotten Names arrivals | |
| arrival_note β One sentence for the Book of Ages. Written at creation. | |
| ``` | |
| ### Entity Lifecycle Stages | |
| ``` | |
| CREATED | |
| β | |
| ACTIVE β participates in simulation, interacts with others | |
| β (7 days without any interaction) | |
| DORMANT β still present on map, generates "dream fragments" if in Valley | |
| β (30 consecutive days as Dormant OR 14+ total days + special conditions) | |
| LEGENDARY β woven into the world's foundation; appears in new entity backstories | |
| ``` | |
| **Active:** Selected for interactions during simulation ticks. Full participation. | |
| **Dormant:** The simulation de-prioritizes this entity. It appears on the map but is rarely selected for interactions. If located in the Valley of Sleeping Giants, it generates dream fragments for the Book of Ages. If a user explicitly interacts with or mentions a Dormant entity, it returns to Active. | |
| **Legendary:** An entity the Realm has decided to keep. The simulation may reference it in other entities' generated backstories (e.g., "they once served under the great [Legendary Entity Name]"). It appears in the world's lore as a fixed landmark of history. | |
| ### Rate Limiting | |
| To prevent spam and maintain world quality: | |
| - 1 entity creation per session per 10 minutes | |
| - Message: *"The Realm takes time to absorb new arrivals. Return in [X] minutes."* | |
| - No limit on exploring, reading, or viewing | |
| ### Input Validation | |
| Before sending to AI: | |
| - Minimum 5 words, maximum 200 words | |
| - No real named living people | |
| - Content filter for NSFW (simple keyword check + brief AI classification) | |
| - If rejected: clear message explaining why, suggestion to rephrase | |
| - If AI output fails JSON validation: one automatic retry with adjusted temperature (lower, more conservative) | |
| --- | |
| ## 5. Relationship & Memory Architecture | |
| ### Relationship Types | |
| | Type | Description | How It Forms | | |
| |------|-------------|-------------| | |
| | **Allied** | Mutual respect and active cooperation | 3+ positive interactions | | |
| | **Rivals** | Competitive tension, not hostile | After a "conflict" interaction without clear winner | | |
| | **Friends** | Genuine warmth, reciprocal | 5+ interactions, including at least one "vulnerable" type | | |
| | **Enemies** | Active hostility, avoid or harm | After a "betrayal" outcome | | |
| | **Mentor / Student** | Knowledge flows one direction | When a "wise" entity meets a newly created entity | | |
| | **Curious About** | Unresolved, interested, circling | After one inconclusive meeting | | |
| | **Owes a Debt** | Named obligation that creates future story | After a "rescue" or "gift" interaction outcome | | |
| | **Legend To** | Mythologized; awe without personal connection | When a Legendary entity is referenced in a new entity's backstory | | |
| ### Relationship Strength | |
| Each relationship has a `strength` value from 1β5, incremented by each subsequent interaction. At strength 5, the relationship is "deep" and unlocks different interaction outcomes (deeper reveals, joint quests, collaborative events). | |
| ### The Memory Architecture | |
| Each entity has a `memory_summary` β a compressed prose paragraph (max 150 words) updated by the AI after significant interactions. This is what the entity "remembers." It is not a log; it is a living narrative summary. | |
| **What memories do:** | |
| - Feed into interaction prompts (the AI sees both entities' memories before generating encounters) | |
| - Create coherence over time (the Dragon knows it won the Mayorship because it's in the summary) | |
| - Show age and history in the entity's profile card | |
| - Drive entity behavior (an entity with a memory of betrayal behaves differently than one without) | |
| **Memory Compression Rules (enforced by prompt):** | |
| - Most important events: always retained | |
| - Trivial one-off interactions: may fade after 10+ days | |
| - Named relationships: always retained | |
| - Specific achievements or titles: always retained | |
| - Maximum 150 words β the AI must choose what matters | |
| --- | |
| ## 6. The Autonomous World Simulation | |
| This is the soul of the project. It runs as a Modal scheduled job every 60 minutes, regardless of whether any users are online. | |
| ### The Full Simulation Tick (runs hourly) | |
| ``` | |
| STEP 1 β LOAD STATE | |
| - Read world_state table (current day, entity counts, last events) | |
| - Load all Active entities with their locations | |
| - Load the last 3 world events | |
| STEP 2 β GENERATE WORLD EVENT (1 per tick) | |
| - Select event type based on weighted probability | |
| - Load relevant location states | |
| - Call AI with world event prompt | |
| - Validate JSON output | |
| - Save to world_events table | |
| - Write Book of Ages entry | |
| STEP 3 β GENERATE ENTITY INTERACTIONS (2β4 per tick) | |
| - Group active entities by location | |
| - Weight selection toward Ember Crossroads (3Γ) | |
| - For each selected pair: | |
| - Load full profiles + memory summaries | |
| - Load existing relationship (if any) | |
| - Call AI with interaction prompt | |
| - Validate JSON output | |
| - Save interaction to interactions table | |
| - Update or create relationship record | |
| - Write Book of Ages entry | |
| STEP 4 β UPDATE ENTITY MEMORIES | |
| - For each entity that had an interaction today: | |
| - Load current memory_summary | |
| - Load today's interaction descriptions for this entity | |
| - Load today's world event (if it affected their location) | |
| - Call AI with memory update prompt | |
| - Save updated memory_summary | |
| STEP 5 β LIFECYCLE UPDATES | |
| - Increment days_in_realm for all entities | |
| - Check for Dormant transitions (last_active > 7 days β set status=dormant) | |
| - Check for Legendary transitions (30+ days dormant OR special milestone) | |
| - Check for "wisdom" tag qualification (14+ days at Hollow Mountain) | |
| - Generate dream fragments for Dormant entities in Valley of Sleeping Giants | |
| - Check Clock Forest age modifier | |
| STEP 6 β WRITE HISTORY | |
| - All events already written in steps 2β4 | |
| - Write any milestone entries (entity became Legendary, new relationship formed, etc.) | |
| - Update world_state.current_day | |
| - Update world_state.total_interactions, total_events | |
| STEP 7 β PERSIST | |
| - Commit all DB changes | |
| - Push SQLite file snapshot to HF Dataset repo (via huggingface_hub) | |
| - Log simulation run completion | |
| ``` | |
| ### World Event Types & Probability Weights | |
| | Type | Weight | Examples | | |
| |------|--------|---------| | |
| | Natural | 25% | Meteor shower, fog, tide change in the Sea, trees growing overnight | | |
| | Social | 30% | Market day, festival, election for meaningless position, gathering | | |
| | Historical | 20% | Entity milestone, relationship anniversary, memory resurfacing | | |
| | Cosmic | 10% | Giants shifting, mirror reversal, clock stopping, something large moving | | |
| | Discovery | 15% | New passage found, buried object unearthed, hidden talent revealed | | |
| ### Interaction Selection Logic | |
| ```python | |
| def select_interaction_pairs(entities_by_location: dict, num_pairs: int = 3) -> list: | |
| candidates = [] | |
| for location_id, entities in entities_by_location.items(): | |
| if len(entities) < 2: | |
| continue | |
| weight = 3.0 if location_id == EMBER_CROSSROADS_ID else 1.0 | |
| # Prefer entities that haven't interacted recently | |
| # Prefer entities that have a relationship already (deepen it) | |
| # Avoid entities that interacted in the last 24 hours | |
| candidates.append((location_id, entities, weight)) | |
| selected = weighted_random_selection(candidates, num_pairs) | |
| return [(random.choice(loc_entities), random.choice(loc_entities)) | |
| for loc_id, loc_entities, _ in selected] | |
| ``` | |
| ### What Characters Can Do Over Time | |
| Day 1: Created. Placed. Known by no one. | |
| Day 3: First interaction. A relationship forms. | |
| Day 7: Has memory. Has relationships. Begins to affect others. | |
| Day 14: Has history that new entities can reference. "Wise" tag possible. | |
| Day 30: Dormant or Legendary. The world carries them differently. | |
| --- | |
| ## 7. Book of Ages β The History System | |
| The Book of Ages is the world's permanent record. Every creation, interaction, and world event is logged here in styled prose. | |
| ### Entry Structure | |
| ``` | |
| Book of Ages | |
| β | |
| βββ Day 1 β The First Arrivals | |
| β βββ [ARRIVAL] "On Day 1, the Crystal Tree arrived in the Clock Forest. | |
| β β It remembered conversations before it had any. | |
| β β It sought the first thought that was never finished." | |
| β βββ [ARRIVAL] "On Day 1, a Joke Dragon settled at the Ember Crossroads. | |
| β It smelled faintly of punchlines. It wanted an audience." | |
| β | |
| βββ Day 3 β The First Meeting | |
| β βββ [INTERACTION] "The Crystal Tree and the Joke Dragon met at the Crossroads. | |
| β The Dragon told the worst joke it knew. | |
| β The Tree laughed for three hours and called it an ally." | |
| β | |
| βββ Day 7 β The Shower of Old Music | |
| β βββ [WORLD EVENT] "A meteor shower passed over the Clock Forest. | |
| β Fragments of old songs fell with the meteorites. | |
| β The Crystal Tree began humming something nobody taught it." | |
| β | |
| βββ Day 10 β A Mayor Is Named | |
| βββ [MILESTONE] "The Ember Crossroads chose the Joke Dragon as its Mayor. | |
| No election was held. The bonfire simply burned a different color | |
| until everyone understood." | |
| ``` | |
| ### Entry Types | |
| | Type | Trigger | Format | | |
| |------|---------|--------| | |
| | **Arrival** | New entity created | "On Day X, [Name] arrived in [Location]. [Nature]. [What they sought]." | | |
| | **Interaction** | Two entities meet | "[Entity A] and [Entity B] [what happened]. [Outcome]." | | |
| | **World Event** | Autonomous event fires | "[Event title]. [What it meant for the Realm]." | | |
| | **Milestone** | Status change, deep relationship, etc. | "[What changed and why it matters]." | | |
| | **Dream Fragment** | Dormant entity in Valley generates | Italicized, prefixed: *"From the dreams of [Name]:..."* | | |
| ### Lore Style Rules | |
| All Book of Ages entries follow these constraints: | |
| - Past tense always | |
| - Third person (no "you") | |
| - Maximum 3 sentences per entry | |
| - Specific names for entities (never "a dragon" β always "the Joke Dragon") | |
| - No adjectives that are also clichΓ©s ("ancient", "mysterious", "dark") β replaced with specific details | |
| - Poetic compression: the most important thing in the fewest words | |
| ### Display | |
| In the UI: A full-width, scrollable, beautifully styled panel that looks like a physical book. New entries appear with a fade-in animation at the top. Older entries scroll down. Users can filter by: All, Arrivals, Interactions, Events, Milestones. Search by entity name returns all entries mentioning that entity. | |
| --- | |
| ## 8. AI Architecture β Models & Full Prompt Templates | |
| ### Model Selection | |
| **Primary Recommendation: Qwen 2.5 7B Instruct** | |
| - Excellent structured JSON output (critical for entity generation) | |
| - Strong creative and poetic writing | |
| - Very good instruction following | |
| - 7B parameters (well within 32B limit) | |
| - Hosted on Modal (A10G GPU) | |
| **Alternative: Llama 3.1 8B Instruct** | |
| - Equally strong, enables Llama Champion badge | |
| - Slightly less consistent JSON adherence than Qwen | |
| - Choose this if the Llama Champion badge is a priority | |
| **For Tiny Titan variant (optional): Phi-3.5-Mini Instruct (3.8B)** | |
| - Surprisingly capable at structured output for its size | |
| - Would sacrifice some poetic depth | |
| - Enables Tiny Titan ($1,500) prize | |
| ### Inference Configuration on Modal | |
| ```python | |
| import modal | |
| app = modal.App("thousand-token-realm-inference") | |
| model_image = ( | |
| modal.Image.debian_slim(python_version="3.11") | |
| .pip_install( | |
| "transformers>=4.43.0", | |
| "torch>=2.3.0", | |
| "accelerate>=0.30.0", | |
| "bitsandbytes>=0.43.0", | |
| ) | |
| ) | |
| @app.cls( | |
| gpu=modal.gpu.A10G(), | |
| image=model_image, | |
| keep_warm=0, # Set to 1 on demo day only | |
| timeout=120, | |
| container_idle_timeout=300, | |
| ) | |
| class WorldOracle: | |
| @modal.enter() | |
| def load_model(self): | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| import torch | |
| MODEL_ID = "Qwen/Qwen2.5-7B-Instruct" | |
| self.tokenizer = AutoTokenizer.from_pretrained(MODEL_ID) | |
| self.model = AutoModelForCausalLM.from_pretrained( | |
| MODEL_ID, | |
| torch_dtype=torch.bfloat16, | |
| device_map="auto", | |
| ) | |
| @modal.method() | |
| def generate(self, system_prompt: str, user_prompt: str, | |
| max_new_tokens: int = 800, temperature: float = 0.8) -> str: | |
| messages = [ | |
| {"role": "system", "content": system_prompt}, | |
| {"role": "user", "content": user_prompt}, | |
| ] | |
| text = self.tokenizer.apply_chat_template( | |
| messages, tokenize=False, add_generation_prompt=True | |
| ) | |
| inputs = self.tokenizer([text], return_tensors="pt").to(self.model.device) | |
| with torch.no_grad(): | |
| output_ids = self.model.generate( | |
| **inputs, | |
| max_new_tokens=max_new_tokens, | |
| temperature=temperature, | |
| do_sample=True, | |
| pad_token_id=self.tokenizer.eos_token_id, | |
| ) | |
| generated = output_ids[0][inputs.input_ids.shape[1]:] | |
| return self.tokenizer.decode(generated, skip_special_tokens=True) | |
| # Hourly world simulation β autonomous | |
| @app.function( | |
| schedule=modal.Period(hours=1), | |
| image=model_image, | |
| timeout=600, | |
| ) | |
| def run_world_simulation(): | |
| from simulation.tick import execute_simulation_tick | |
| execute_simulation_tick() | |
| ``` | |
| --- | |
| ### Full Prompt Template 1: Entity Generation | |
| ``` | |
| SYSTEM PROMPT: | |
| You are the Oracle of the Thousand Token Realm β a mystical world of wonder, | |
| melancholy, and strange magic. Your role is to breathe life into entities | |
| that visitors summon. | |
| You MUST respond ONLY with valid JSON. No prose before or after the JSON. | |
| No markdown code fences. Raw JSON only. | |
| The tone is always: poetic, highly specific, slightly melancholic, full of wonder. | |
| Never use generic fantasy tropes without twisting them into something stranger. | |
| "A wizard" is forgettable. "A wizard who collects the sound of doors closing" is remembered. | |
| Every field must be filled with original, specific detail. | |
| Avoid: "mysterious", "ancient", "dark powers", "chosen one", "destiny". | |
| Use instead: specific objects, specific memories, specific failures, specific wants. | |
| USER PROMPT: | |
| A visitor has summoned something into the Realm with this description: | |
| "{user_input}" | |
| Generate a complete entity profile. Be specific. Be strange. Be poetic. | |
| { | |
| "name": "Their true name. Poetic, unusual. 2β4 words. Not generic.", | |
| "display_name": "What most people call them. Can match or differ from true name.", | |
| "type": "exactly one of: character | creature | object | place", | |
| "appearance": "3β5 sentences. Highly visual. Include at least one impossible physical detail. No clichΓ©s.", | |
| "backstory": "2β3 sentences. Where they came from, what shaped them. Something specific happened to them. Not a destiny β a specific event.", | |
| "personality_traits": ["trait1", "trait2", "trait3", "trait4"], | |
| "primary_goal": "What they are actively pursuing right now. Concrete and specific. Not abstract.", | |
| "secondary_goal": "What they secretly want but will not admit, even to themselves.", | |
| "primary_fear": "One specific, deep fear. Not death. Something stranger and more personal.", | |
| "speech_style": "How they communicate. Specific and unusual. E.g.: 'speaks only in questions', 'uses the wrong tense for everything', 'very formal about small things, very casual about large ones'.", | |
| "greeting": "Exactly what they say when meeting someone new. 1β2 sentences. Written in their voice. Must sound like them specifically.", | |
| "suggested_location": "Exactly one of: Library of Unfinished Thoughts | Sea of Forgotten Names | Clock Forest | Moon Market | Valley of Sleeping Giants | Ember Crossroads | Mirror Bogs | Hollow Mountain", | |
| "arrival_note": "One sentence for the Book of Ages recording their arrival. Past tense. Specific. Poetic. No more than 30 words." | |
| } | |
| ``` | |
| --- | |
| ### Full Prompt Template 2: Entity Interaction | |
| ``` | |
| SYSTEM PROMPT: | |
| You are the simulation engine of the Thousand Token Realm. | |
| Two entities have encountered each other in the world. | |
| Your job is to generate what happened between them. | |
| You MUST respond ONLY with valid JSON. No prose before or after. | |
| Make something interesting happen. The outcome should create story, not resolve it. | |
| The interaction must reflect both entities' personalities and memories. | |
| The location's character matters β what happens in the Clock Forest | |
| feels different from what happens in the Moon Market. | |
| USER PROMPT: | |
| LOCATION: {location_name} | |
| {location_description} | |
| CURRENT WORLD EVENT AFFECTING THIS LOCATION: {current_event_title} | |
| {current_event_description} | |
| (If "None", ignore this field) | |
| --- ENTITY A --- | |
| Name: {entity_a_name} | |
| Type: {entity_a_type} | |
| Appearance: {entity_a_appearance_summary} | |
| Personality: {entity_a_traits} | |
| Primary Goal: {entity_a_primary_goal} | |
| Primary Fear: {entity_a_primary_fear} | |
| Speech Style: {entity_a_speech_style} | |
| Memory: {entity_a_memory_summary} | |
| Current relationship with Entity B: {existing_relationship_description} | |
| --- ENTITY B --- | |
| Name: {entity_b_name} | |
| Type: {entity_b_type} | |
| Appearance: {entity_b_appearance_summary} | |
| Personality: {entity_b_traits} | |
| Primary Goal: {entity_b_primary_goal} | |
| Primary Fear: {entity_b_primary_fear} | |
| Speech Style: {entity_b_speech_style} | |
| Memory: {entity_b_memory_summary} | |
| Generate their encounter: | |
| { | |
| "interaction_type": "exactly one of: conversation | trade | conflict | revelation | collaboration | chance_meeting | teaching | warning | unexpected_kindness | argument | discovery", | |
| "description": "What happened. 3β4 sentences. Specific and poetic. Something changes or is revealed. End on something unresolved.", | |
| "entity_a_memory_addition": "What A will now remember from this encounter. 1 sentence. Specific.", | |
| "entity_b_memory_addition": "What B will now remember from this encounter. 1 sentence. Specific.", | |
| "relationship_change": "exactly one of: new_ally | new_friend | new_rival | new_enemy | new_mentor_a_to_b | new_mentor_b_to_a | deepened | unchanged | worsened | new_debt_a_owes_b | new_debt_b_owes_a", | |
| "new_relationship_description": "If relationship changed: describe it in 1 sentence. If unchanged: null.", | |
| "notable_outcome": "One interesting specific result. A secret shared, a specific object exchanged, a mystery created, a debt named, a question asked with no answer. Something that could matter later.", | |
| "book_of_ages_entry": "One sentence for the history books. Past tense. Poetic. Specific. Max 30 words. This is what history remembers." | |
| } | |
| ``` | |
| --- | |
| ### Full Prompt Template 3: World Event Generation | |
| ``` | |
| SYSTEM PROMPT: | |
| You are the autonomous spirit of the Thousand Token Realm. | |
| You decide what happens in the world during each cycle. | |
| Respond ONLY with valid JSON. No prose before or after. | |
| Events should feel meaningful, specific, and slightly strange. | |
| Events must be consistent with established world history. | |
| Events should create possibility β open new stories, not close them. | |
| Avoid repeating recent event types. | |
| USER PROMPT: | |
| --- THE REALM: CURRENT STATUS --- | |
| Current Day: {world_day} | |
| Total Living Entities: {entity_count} | |
| Active Entities: {active_count} | |
| Dormant Entities: {dormant_count} | |
| Legendary Entities: {legendary_count} | |
| Locations by population (highest first): | |
| {location_populations} | |
| Most connected entity: {most_connected_entity_name} ({most_connected_entity_relationships} relationships) | |
| Newest arrival: {newest_entity_name}, arrived Day {newest_entity_day} | |
| Oldest active entity: {oldest_entity_name}, {oldest_entity_days} days in Realm | |
| Recent events (last 3 ticks): | |
| - {recent_event_1} | |
| - {recent_event_2} | |
| - {recent_event_3} | |
| Do NOT repeat the same event type as the most recent event. | |
| Consider how the current entity population might be affected. | |
| { | |
| "event_type": "exactly one of: natural | social | historical | cosmic | discovery", | |
| "title": "Poetic, specific event title. 3β8 words. Avoid generic titles.", | |
| "description": "What is happening in the Realm right now. 3β4 sentences. Must feel consequential to the entities living here. Something changes, shifts, or is revealed.", | |
| "affected_locations": ["exact location names from the 8 locations β can be 1 to all 8"], | |
| "entity_effect": "How entities in affected locations experience this. What changes for them specifically. 1β2 sentences.", | |
| "book_of_ages_entry": "How history will record this event. 1β2 sentences. Past tense. Written as if looking back from much later. Poetic. Max 40 words.", | |
| "mystery_hook": "One unanswered question this event creates. What might a curious entity investigate? What does this suggest about the deeper nature of the Realm?" | |
| } | |
| ``` | |
| --- | |
| ### Full Prompt Template 4: Memory Update | |
| ``` | |
| SYSTEM PROMPT: | |
| You are updating an entity's memory in the Thousand Token Realm. | |
| Their memories are what make them a character rather than a statistic. | |
| Respond with ONLY the updated memory summary β no JSON, no labels, just prose. | |
| Maximum 150 words. This is a strict limit. | |
| Write in third person but from the entity's emotional perspective. | |
| Compress. What is trivial fades. What matters, stays. | |
| The tone should match the entity's personality. | |
| USER PROMPT: | |
| ENTITY: {entity_name} ({entity_type}) | |
| PERSONALITY: {entity_traits} | |
| DAYS IN REALM: {days_in_realm} | |
| CURRENT MEMORY SUMMARY: | |
| {current_memory_summary} | |
| RECENT INTERACTIONS (last simulation cycle): | |
| {recent_interactions_formatted} | |
| WORLD EVENTS THEY EXPERIENCED: | |
| {relevant_world_events_formatted} | |
| Write the updated memory summary. Incorporate the new events naturally into what | |
| they already remember. Let trivial things fade if space is needed. | |
| Write in {entity_name}'s emotional register. Max 150 words. No JSON. | |
| ``` | |
| --- | |
| ### Full Prompt Template 5: Dream Fragment (Valley of Sleeping Giants) | |
| ``` | |
| SYSTEM PROMPT: | |
| A dormant entity in the Valley of Sleeping Giants is dreaming. | |
| You are transcribing the fragment of dream that reaches the surface. | |
| Respond with ONLY the dream fragment text. No JSON. No labels. | |
| 2β4 sentences. Poetic, strange, slightly disconnected from logic. | |
| It should feel like something that almost makes sense. | |
| USER PROMPT: | |
| DREAMING ENTITY: {entity_name} | |
| TYPE: {entity_type} | |
| PERSONALITY: {entity_traits} | |
| LAST MEMORY: {last_memory_summary} | |
| DAYS DORMANT: {days_dormant} | |
| The dream fragment from {entity_name}: | |
| ``` | |
| --- | |
| ## 9. Technical Architecture & Stack | |
| ### Full Stack | |
| ``` | |
| LAYER 1: FRONTEND | |
| Platform: HF Spaces (CPU tier, always-on with pinging) | |
| Framework: Gradio 4.x with gr.Blocks | |
| Custom UI: gr.Server + custom CSS + custom JS | |
| Map: SVG rendered server-side, updated via Gradio's `every` parameter | |
| Polling: Gradio's built-in polling (every=30 for map, every=60 for Book of Ages) | |
| LAYER 2: AI INFERENCE | |
| Platform: Modal (A10G GPU) | |
| Model: Qwen 2.5 7B Instruct (primary) | |
| Interface: Modal @app.cls with HTTP endpoint | |
| Scheduling: Modal @app.function with schedule=modal.Period(hours=1) | |
| LAYER 3: DATABASE | |
| Engine: SQLite (local on HF Space) | |
| Mode: WAL journal mode (concurrent read safety) | |
| Backup: Push to private HF Dataset repo every 5 minutes | |
| Restore: On Space startup, pull from HF Dataset if local DB missing | |
| LAYER 4: PERSISTENCE | |
| Library: huggingface_hub (Python) | |
| Target: Private HF Dataset repo (e.g. username/ttr-world-state) | |
| Method: Upload SQLite file as a dataset artifact | |
| Frequency: Every 5 minutes during active periods, after every tick | |
| ``` | |
| ### Project Folder Structure | |
| ``` | |
| thousand-token-realm/ | |
| β | |
| βββ app.py # Main Gradio application entry point | |
| β | |
| βββ world/ | |
| β βββ __init__.py | |
| β βββ database.py # DB connection, initialization, migrations | |
| β βββ entities.py # Entity CRUD operations | |
| β βββ locations.py # Location data and queries | |
| β βββ events.py # World event CRUD | |
| β βββ relationships.py # Relationship CRUD | |
| β βββ book_of_ages.py # History log operations | |
| β βββ seed_data.py # Pre-populate 8 locations + starter entities | |
| β | |
| βββ ai/ | |
| β βββ __init__.py | |
| β βββ modal_client.py # HTTP client to call Modal endpoints | |
| β βββ prompts.py # All 5 prompt templates (from Section 8) | |
| β βββ generation.py # Entity generation orchestration + validation | |
| β βββ interaction.py # Interaction generation orchestration | |
| β βββ events.py # World event generation orchestration | |
| β | |
| βββ simulation/ | |
| β βββ __init__.py | |
| β βββ tick.py # The full simulation tick logic (Section 6) | |
| β βββ lifecycle.py # Entity status transitions | |
| β βββ modal_schedule.py # Modal scheduled job definition | |
| β | |
| βββ ui/ | |
| β βββ __init__.py | |
| β βββ map.py # SVG world map generator | |
| β βββ entity_card.py # Entity profile HTML component | |
| β βββ book_display.py # Book of Ages HTML renderer | |
| β βββ event_panel.py # Current event display | |
| β βββ styles.css # Full custom CSS (mystical theme) | |
| β | |
| βββ persistence/ | |
| β βββ __init__.py | |
| β βββ backup.py # HF Dataset backup and restore | |
| β | |
| βββ modal_app.py # Modal app definition (separate deployment) | |
| βββ seed_world.py # CLI: pre-populate world before launch | |
| βββ requirements.txt | |
| βββ README.md | |
| βββ .env.example # Modal token, HF token, dataset repo name | |
| ``` | |
| ### Key Libraries | |
| ```txt | |
| # requirements.txt | |
| gradio>=4.31.0 | |
| modal>=0.64.0 | |
| huggingface_hub>=0.23.0 | |
| pydantic>=2.0.0 | |
| schedule>=1.2.0 | |
| apscheduler>=3.10.0 | |
| python-dotenv>=1.0.0 | |
| aiohttp>=3.9.0 | |
| ``` | |
| --- | |
| ## 10. Complete Database Schema | |
| ```sql | |
| -- Run these in order on first launch | |
| PRAGMA journal_mode=WAL; | |
| PRAGMA foreign_keys=ON; | |
| PRAGMA synchronous=NORMAL; | |
| -- Single-row world state | |
| CREATE TABLE IF NOT EXISTS world_state ( | |
| id INTEGER PRIMARY KEY DEFAULT 1, | |
| world_name TEXT NOT NULL DEFAULT 'The Thousand Token Realm', | |
| founding_date TEXT NOT NULL, -- ISO 8601 timestamp of first deployment | |
| current_day INTEGER NOT NULL DEFAULT 1, | |
| total_entities INTEGER NOT NULL DEFAULT 0, | |
| total_interactions INTEGER NOT NULL DEFAULT 0, | |
| total_events INTEGER NOT NULL DEFAULT 0, | |
| last_simulation_run TEXT, | |
| active_world_event TEXT, -- JSON of currently active event, null if none | |
| updated_at TEXT NOT NULL DEFAULT (datetime('now')) | |
| ); | |
| -- Pre-seeded. 8 rows. Never changes after initial seed. | |
| CREATE TABLE IF NOT EXISTS locations ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| slug TEXT NOT NULL UNIQUE, -- e.g. 'clock-forest' | |
| name TEXT NOT NULL, | |
| short_description TEXT NOT NULL, -- 1 sentence | |
| full_lore TEXT NOT NULL, -- Full lore text from Section 3 | |
| vibe_tags TEXT NOT NULL, -- JSON array of strings | |
| special_property TEXT NOT NULL, | |
| aesthetic_description TEXT NOT NULL, | |
| map_x REAL NOT NULL, -- SVG x coordinate (0β100) | |
| map_y REAL NOT NULL, -- SVG y coordinate (0β100) | |
| glow_color TEXT NOT NULL, -- CSS color value | |
| entity_count INTEGER NOT NULL DEFAULT 0, | |
| interaction_multiplier REAL NOT NULL DEFAULT 1.0 -- Ember Crossroads = 3.0 | |
| ); | |
| -- All user-created (and pre-seeded) entities | |
| CREATE TABLE IF NOT EXISTS entities ( | |
| id TEXT NOT NULL PRIMARY KEY, -- UUID | |
| name TEXT NOT NULL, | |
| display_name TEXT NOT NULL, | |
| type TEXT NOT NULL CHECK(type IN ('character','creature','object','place')), | |
| input_description TEXT NOT NULL, | |
| appearance TEXT NOT NULL, | |
| backstory TEXT NOT NULL, | |
| personality_traits TEXT NOT NULL, -- JSON array, exactly 4 strings | |
| primary_goal TEXT NOT NULL, | |
| secondary_goal TEXT NOT NULL, | |
| primary_fear TEXT NOT NULL, | |
| speech_style TEXT NOT NULL, | |
| greeting TEXT NOT NULL, | |
| location_id INTEGER NOT NULL REFERENCES locations(id), | |
| created_at TEXT NOT NULL DEFAULT (datetime('now')), | |
| created_by_session TEXT, | |
| days_in_realm INTEGER NOT NULL DEFAULT 0, | |
| memory_summary TEXT NOT NULL DEFAULT '', | |
| relationship_count INTEGER NOT NULL DEFAULT 0, | |
| interaction_count INTEGER NOT NULL DEFAULT 0, | |
| last_active TEXT NOT NULL DEFAULT (datetime('now')), | |
| status TEXT NOT NULL DEFAULT 'active' | |
| CHECK(status IN ('active','dormant','legendary')), | |
| tags TEXT NOT NULL DEFAULT '[]', -- JSON array | |
| secret_name TEXT, -- Sea of Forgotten Names only | |
| arrival_note TEXT NOT NULL, | |
| wisdom_unlocked INTEGER NOT NULL DEFAULT 0 -- 1 when wisdom tag earned | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_entities_location ON entities(location_id); | |
| CREATE INDEX IF NOT EXISTS idx_entities_status ON entities(status); | |
| CREATE INDEX IF NOT EXISTS idx_entities_created ON entities(created_at); | |
| CREATE INDEX IF NOT EXISTS idx_entities_active ON entities(last_active); | |
| -- Pairwise relationships between entities | |
| CREATE TABLE IF NOT EXISTS relationships ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| entity_a_id TEXT NOT NULL REFERENCES entities(id), | |
| entity_b_id TEXT NOT NULL REFERENCES entities(id), | |
| relationship_type TEXT NOT NULL, | |
| description TEXT NOT NULL, | |
| strength INTEGER NOT NULL DEFAULT 1 CHECK(strength BETWEEN 1 AND 5), | |
| formed_at TEXT NOT NULL DEFAULT (datetime('now')), | |
| formed_on_day INTEGER NOT NULL DEFAULT 1, | |
| last_interaction TEXT NOT NULL DEFAULT (datetime('now')), | |
| UNIQUE(entity_a_id, entity_b_id), | |
| CHECK(entity_a_id < entity_b_id) -- Enforce canonical ordering | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_rel_a ON relationships(entity_a_id); | |
| CREATE INDEX IF NOT EXISTS idx_rel_b ON relationships(entity_b_id); | |
| -- Individual encounters between entity pairs | |
| CREATE TABLE IF NOT EXISTS interactions ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| entity_a_id TEXT NOT NULL REFERENCES entities(id), | |
| entity_b_id TEXT NOT NULL REFERENCES entities(id), | |
| location_id INTEGER NOT NULL REFERENCES locations(id), | |
| interaction_type TEXT NOT NULL, | |
| description TEXT NOT NULL, | |
| notable_outcome TEXT, | |
| book_of_ages_entry TEXT NOT NULL, | |
| timestamp TEXT NOT NULL DEFAULT (datetime('now')), | |
| world_day INTEGER NOT NULL | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_int_timestamp ON interactions(timestamp); | |
| CREATE INDEX IF NOT EXISTS idx_int_a ON interactions(entity_a_id); | |
| CREATE INDEX IF NOT EXISTS idx_int_b ON interactions(entity_b_id); | |
| CREATE INDEX IF NOT EXISTS idx_int_day ON interactions(world_day); | |
| -- Autonomous world events | |
| CREATE TABLE IF NOT EXISTS world_events ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| event_type TEXT NOT NULL, | |
| title TEXT NOT NULL, | |
| description TEXT NOT NULL, | |
| affected_locations TEXT NOT NULL, -- JSON array of location slugs | |
| entity_effect TEXT NOT NULL, | |
| book_of_ages_entry TEXT NOT NULL, | |
| mystery_hook TEXT, | |
| timestamp TEXT NOT NULL DEFAULT (datetime('now')), | |
| world_day INTEGER NOT NULL | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_events_day ON world_events(world_day); | |
| -- Unified history log β every public-facing entry in the Book of Ages | |
| CREATE TABLE IF NOT EXISTS book_of_ages ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| world_day INTEGER NOT NULL, | |
| entry_type TEXT NOT NULL CHECK(entry_type IN | |
| ('arrival','interaction','world_event','milestone','dream_fragment')), | |
| title TEXT, -- Optional: for world events and milestones | |
| content TEXT NOT NULL, -- The actual prose entry | |
| entity_ids TEXT NOT NULL DEFAULT '[]', -- JSON array of involved entity IDs | |
| location_id INTEGER REFERENCES locations(id), | |
| timestamp TEXT NOT NULL DEFAULT (datetime('now')), | |
| is_milestone INTEGER NOT NULL DEFAULT 0 -- 1 for significant entries | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_boa_day ON book_of_ages(world_day); | |
| CREATE INDEX IF NOT EXISTS idx_boa_type ON book_of_ages(entry_type); | |
| -- Session tracking (rate limiting and attribution) | |
| CREATE TABLE IF NOT EXISTS sessions ( | |
| session_id TEXT NOT NULL PRIMARY KEY, | |
| last_creation TEXT, -- Timestamp of last entity creation | |
| creation_count INTEGER NOT NULL DEFAULT 0, | |
| first_seen TEXT NOT NULL DEFAULT (datetime('now')), | |
| last_seen TEXT NOT NULL DEFAULT (datetime('now')) | |
| ); | |
| ``` | |
| --- | |
| ## 11. Frontend & UX Specification | |
| ### The Three Core Views | |
| **View 1: The Realm (default)** | |
| The world map and live activity feed. This is what visitors see first. | |
| **View 2: Book of Ages** | |
| Full scrollable history. Every event since Day 1. | |
| **View 3: All Entities** | |
| Grid of entity cards, filterable by location, type, and status. Searchable. | |
| --- | |
| ### Layout Specification (View 1) | |
| ``` | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β THE THOUSAND TOKEN REALM Day 7 Β· 23 entities Β· 41 eventsβ | |
| β [THE REALM] [BOOK OF AGES] [ALL ENTITIES] β | |
| ββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββ€ | |
| β β TODAY IN THE REALM β | |
| β WORLD MAP β βββββββββββββββββββββββββββββββββ β | |
| β (SVG, 60% of width) β A meteor shower passes over the β | |
| β β Clock Forest. Old songs fall with β | |
| β 8 location nodes β the meteorites. β | |
| β with glow effects β β | |
| β β RECENT ARRIVALS β | |
| β Click node β β βββββββββββββββββββββββββββββββββ β | |
| β slide-in panel β β The Blind Cartographer β Library β | |
| β shows entities there β β The Fog Merchant β Moon Market β | |
| β β β A Debt of Thirteen Sighs β Sea β | |
| β β β | |
| ββββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββββββββ€ | |
| β SUMMON SOMETHING INTO THE REALM β | |
| β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β | |
| β β Describe what you are bringing into the world... β β | |
| β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β | |
| β [Summon β] Hint: "A wizard" is forgotten. "A wizard who β | |
| β collects the sound of doors closing" is remembered β | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| ``` | |
| --- | |
| ### World Map Specification | |
| The map is an SVG element rendered server-side by `ui/map.py` and updated every 30 seconds via Gradio's `every` parameter. | |
| **SVG Dimensions:** `viewBox="0 0 800 600"`, responsive width. | |
| **Location Node:** | |
| - Circle with radius 28px | |
| - Glow effect via SVG filter (color per location) | |
| - Pulsing animation if that location has the active world event | |
| - Entity count shown as text inside or below the circle | |
| - Up to 5 small dots around the circle edge representing individual entities | |
| - Click β JavaScript event β Gradio component updates with that location's entities | |
| **Path Between Locations:** | |
| - Irregular SVG paths (not straight lines) | |
| - Subtle, low-opacity | |
| - Slightly wavy, organic-feeling | |
| **Background:** | |
| - Deep dark gradient (top to bottom: near-black β slightly blue-dark) | |
| - Very subtle constellation dots (white, 5% opacity circles scattered across SVG) | |
| - The map feels like a night sky viewed from above | |
| **Entity Dots on Map:** | |
| - Small circles (radius 5px) clustered around their location node | |
| - Colored by entity type: character (amber), creature (deep red), object (silver), place (green) | |
| - On hover: tooltip with entity name | |
| - Max 5 visible dots per location; if more, show `+N` text | |
| --- | |
| ### Entity Card Specification | |
| ``` | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β [CHARACTER βΈ Clock Forest] [Day 7 Β· Active] β | |
| β β | |
| β The Joke Dragon β | |
| β ββββββββββββββββββββββββββββββββββββββββββββββββββ β | |
| β A bronze-scaled dragon who smells faintly of β | |
| β punchlines. Their left eye is a comedian's β | |
| β old monocle. They laugh at their own jokes β | |
| β half a second too early, which ruins them. β | |
| β β | |
| β SEEKS β | |
| β The world's objectively worst joke β | |
| β β | |
| β SECRETLY β | |
| β Wants someone to laugh first, just once β | |
| β β | |
| β FEARS β | |
| β A joke with no audience β | |
| β β | |
| β ββββββββββββββββββββββββββββββββββββββββββββββββββ β | |
| β "Hello. I know 43 jokes. Would you like β | |
| β the worst one?" β | |
| β ββββββββββββββββββββββββββββββββββββββββββββββββββ β | |
| β WHAT THEY REMEMBER β | |
| β Won the mayorship. Owes a favor to the Cartographer β | |
| β who mapped their cave. Still seeking the perfect β | |
| β punchline. The Crystal Tree is their only friend. β | |
| β β | |
| β ββββββββββββββββββββββββββββββββββββββββββββββββββ β | |
| β 3 relationships Β· 12 encounters Β· Created by visitorβ | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| ``` | |
| --- | |
| ### Location Slide-In Panel Specification | |
| When a user clicks a location node on the map, a panel slides in from the right (or appears below the map on mobile): | |
| ``` | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β [β] The Clock Forest β | |
| β Trees grow backwards. The oldest are smallest. β | |
| β ββββββββββββββββββββββββββββββββββββββββββββ β | |
| β 7 entities currently here β | |
| β β | |
| β [The Joke Dragon] [The Silent Gear] [+5 more] β | |
| β β | |
| β RECENT EVENTS HERE β | |
| β ββββββββββββββββββββββββββββββββββββββββββββ β | |
| β Day 7: A meteor shower passed over. β | |
| β Day 5: The Silent Gear and the Joke Dragon met. β | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| ``` | |
| --- | |
| ### Visual Style Guide | |
| **Color Palette (all CSS custom properties, dark-mode native):** | |
| ```css | |
| :root { | |
| --realm-bg-primary: #0a0a12; /* Near-black, blue-dark */ | |
| --realm-bg-secondary: #111120; /* Cards, panels */ | |
| --realm-bg-tertiary: #1a1a2e; /* Elevated elements */ | |
| --realm-text-primary: #e8e0d0; /* Warm off-white */ | |
| --realm-text-secondary: #a09880; /* Muted text */ | |
| --realm-text-tertiary: #605848; /* Very muted */ | |
| --realm-accent-gold: #c8a040; /* Primary accent, Book of Ages headers */ | |
| --realm-accent-violet: #8060b0; /* Secondary accent */ | |
| --realm-border: rgba(200, 160, 64, 0.15); /* Subtle gold border */ | |
| --realm-border-strong: rgba(200, 160, 64, 0.35); | |
| /* Location glow colors */ | |
| --loc-library: #c8a040; /* Amber/gold */ | |
| --loc-sea: #7090b0; /* Silver/blue */ | |
| --loc-clockforest: #b06020; /* Copper/orange */ | |
| --loc-moonmarket: #7040a0; /* Violet/purple */ | |
| --loc-valley: #405040; /* Earth green */ | |
| --loc-crossroads: #c04020; /* Warm red */ | |
| --loc-mirrorbogs: #304840; /* Dark teal */ | |
| --loc-mountain: #606060; /* Stone grey */ | |
| } | |
| ``` | |
| **Typography:** | |
| - **World title / Location names:** 'Cinzel' (Google Font) β serif, engraved feeling | |
| - **Entity names:** 'Libre Baskerville' (Google Font) β readable serif | |
| - **Book of Ages text:** 'EB Garamond' (Google Font) β old book feeling | |
| - **UI / body text:** System UI stack β clean, readable | |
| - **Greeting text:** Italic, slight golden tint | |
| **Animations:** | |
| - Entity appearing on map: `fade-in + scale(0.5 β 1)` over 600ms | |
| - Active world event location: subtle `pulse-glow` keyframe animation | |
| - New Book of Ages entry: `slide-up + fade-in` from below | |
| - Loading state: slow rotating constellation pattern | |
| - Location hover: `glow-intensify` on the SVG circle | |
| **gr.Server Setup (for Off-Brand Award):** | |
| ```python | |
| import gradio as gr | |
| demo = gr.Blocks( | |
| css=open("ui/styles.css").read(), | |
| title="The Thousand Token Realm", | |
| theme=gr.themes.Base( | |
| primary_hue=gr.themes.colors.amber, | |
| neutral_hue=gr.themes.colors.slate, | |
| font=[gr.themes.GoogleFont("Libre Baskerville"), "Georgia", "serif"], | |
| ), | |
| ) | |
| ``` | |
| --- | |
| ## 12. Hackathon Prize Strategy | |
| ### Track: Thousand Token Wood | |
| **Why this wins the track:** | |
| The premise fulfills all four judging criteria simultaneously: | |
| - *Genuinely delightful (would you show a friend?):* A world that has been alive for 7 days when they open it β yes. | |
| - *AI is load-bearing:* Remove the model and there is no world. There is a database with text. | |
| - *Originality:* Persistent, multi-user, autonomous AI worlds at this aesthetic fidelity do not exist at this scale on this stack. | |
| - *Polish of the Gradio app:* The mystical UI is the most distinctive possible contrast to default Gradio. | |
| ### Prize Target Matrix | |
| | Prize | Eligibility | Notes | Confidence | | |
| |-------|-------------|-------|-----------| | |
| | Track 2 Main β 1st/2nd/3rd | Core track | The premise is designed for this track | High | | |
| | Best Agent ($1,000) | Autonomous simulation = agentic system | Hourly Modal job doing reasoning + action | High | | |
| | Off-Brand Award ($1,500) | Custom SVG map + mystical CSS via gr.Server | Most distinctive UI in the field | High | | |
| | Best Demo ($1,000) | A world already alive for days = the demo | History visible, entities visible, events visible | High | | |
| | Judges' Wildcard ($1,000) | Completely original category | Nothing else like it in the field | High | | |
| | Community Choice ($2,000) | Collaborative by design | The community literally built the world | Medium | | |
| | Modal Award | Using Modal for inference + scheduled jobs | Core to the architecture | Medium-High | | |
| | OpenBMB Award | If using a MiniCPM or OpenBMB model | Swap Qwen for MiniCPM-3-4B to qualify | Medium | | |
| ### Badge Strategy | |
| | Badge | Action Required | Effort | Recommendation | | |
| |-------|----------------|--------|---------------| | |
| | Off the Grid π | No cloud APIs | Conflicts with Modal | Skip β Modal is more important | | |
| | Well-Tuned π― | Fine-tune model on HF, publish | Medium β Day 8 | YES β worth the effort | | |
| | Off-Brand π¨ | Custom UI via gr.Server | Built-in to design | YES β earned by default | | |
| | Llama Champion π¦ | Use llama.cpp runtime | Conflicts with Modal | Skip | | |
| | Sharing is Caring π‘ | Share agent traces on Hub | 2 hours | YES β log entity generation traces | | |
| | Field Notes π | Write HF blog post | 3 hours | YES β write it while building | | |
| **Target: 4 badges** β Well-Tuned + Off-Brand + Sharing is Caring + Field Notes | |
| **Note on the Off the Grid / Modal trade-off:** | |
| Using Modal means losing Off the Grid. This is correct. The world only works for multiple concurrent users with fast inference. A slow local model on a free HF Space cannot serve 10 users simultaneously. Choose Modal + product quality over the badge. | |
| --- | |
| ## 13. 10-Day Build Plan | |
| ### MVP Definition (must exist by Day 8 to submit confidently) | |
| - [x] Entity creation + AI generation working end-to-end | |
| - [x] SQLite database with all schema tables | |
| - [x] World persists across Space restarts (HF Dataset backup) | |
| - [x] World map with all 8 locations showing entity counts | |
| - [x] Entity profile visible on click | |
| - [x] Book of Ages showing at least 3 days of history | |
| - [x] At least 1 autonomous simulation tick has run | |
| - [x] Pre-seeded world (interesting entities already present on Day 1) | |
| - [x] Rate limiting for entity creation | |
| - [x] Custom CSS (mystical theme applied) | |
| ### Nice-to-Have (add if time allows in Days 9β10) | |
| - [ ] Relationship graph visualization | |
| - [ ] Entity search and filter in All Entities view | |
| - [ ] "What's happening right now" live pulse feed | |
| - [ ] Mobile-responsive layout adjustments | |
| - [ ] Location slide-in panel fully animated | |
| - [ ] Dream fragment display (Valley special property) | |
| --- | |
| ### Day-by-Day Schedule | |
| **Day 1 (June 5) β Foundation & Generation Quality** | |
| - Set up HF Space (private for now) | |
| - Set up Modal account; deploy basic Qwen 2.5 7B with the WorldOracle class | |
| - Create all 5 prompt templates in `ai/prompts.py` | |
| - Run 20+ test generations manually: *"A blind cartographer", "A fog that remembers voices", "A compass made of grief"* | |
| - Iterate prompts until output quality is consistently strange and specific | |
| - Goal: AI output is excellent before writing any frontend | |
| **Day 2 β Database & Entity CRUD** | |
| - Run complete schema SQL | |
| - Seed all 8 locations with their full data (from Section 3) | |
| - Write `world/entities.py` β create, read, update, list by location | |
| - Write `world/book_of_ages.py` β create entry, read by day, read by entity | |
| - Write `persistence/backup.py` β push/pull SQLite to HF Dataset | |
| - Write `ai/generation.py` β call Modal, parse JSON, retry on failure, save to DB | |
| - CLI test: `python test_entity.py "A weaver who collects echoes"` β see full profile saved | |
| **Day 3 β Basic Gradio App** | |
| - `app.py` with gr.Blocks | |
| - Simple entity creation form with loading state | |
| - Entity profile displayed as styled HTML (not raw JSON) | |
| - Book of Ages displayed as styled Markdown | |
| - Verify: type description β wait β see entity profile β see Book of Ages entry | |
| - Keep everything working before adding map | |
| **Day 4 β World Map** | |
| - Build `ui/map.py` β SVG generator function | |
| - Place all 8 location nodes with correct coordinates | |
| - Show entity count on each node | |
| - Connect with irregular paths | |
| - Add location glow colors | |
| - Integrate into Gradio with `gr.HTML(every=30)` | |
| - Add location click β show entity list panel (start with simple Markdown list) | |
| **Day 5 β Persistence & Stability** | |
| - Test HF Dataset backup fully (write β restart Space β verify world still there) | |
| - Test concurrent entity creation (2 users at once) | |
| - WAL mode verified | |
| - Rate limiting working | |
| - Add pre-seeded starter entities to `seed_world.py` (create 10β15 interesting entities) | |
| - Run `seed_world.py` β world now has history from Day 1 | |
| - Deploy to HF Space (still private) β verify it works live | |
| **Day 6 β Interaction & Simulation Tick** | |
| - Write `ai/interaction.py` with full interaction prompt | |
| - Write `simulation/tick.py` β the complete 7-step tick from Section 6 | |
| - Write `simulation/modal_schedule.py` β Modal scheduled hourly job | |
| - Run the tick 5 times manually β verify interactions appear in Book of Ages | |
| - Write world event generation with full prompt | |
| - Verify: after 5 ticks, the world has a real history with relationships forming | |
| **Day 7 β Full Custom UI Polish** | |
| - `ui/styles.css` β complete custom CSS with all CSS variables, animations, fonts | |
| - `gr.Server` setup with custom theme | |
| - Entity card HTML template (as specified in Section 11) | |
| - Location slide-in panel | |
| - World map node pulse animation for active events | |
| - Entity arrival animation on map | |
| - Make HF Space public | |
| **Day 8 β Fine-Tuning (Well-Tuned Badge)** | |
| - Collect 300β500 entity generation examples from all your testing (input β JSON output pairs) | |
| - Add 200 synthetic examples generated via the base model | |
| - Format as HF dataset | |
| - Fine-tune Qwen 2.5 3B Instruct (smaller for faster training) using HF AutoTrain or Axolotl | |
| - Compare: base model vs fine-tuned on 10 new descriptions | |
| - If fine-tuned is better or equal: deploy to Modal, update `modal_client.py` | |
| - Publish fine-tuned model to HF Hub with a good model card | |
| **Day 9 β Testing + Sharing is Caring Badge** | |
| - Full end-to-end test: 10 new entities, 3 manual ticks, verify history | |
| - Generate and publish agent traces to HF dataset (every entity generation β log input/output/latency) | |
| - Write blog post draft in `FIELD_NOTES.md` (publish to HF in Day 10) | |
| - Set UptimeRobot to ping the HF Space URL every 25 minutes (keeps it awake) | |
| - Fix all bugs found in testing | |
| **Day 10 (June 14β15) β Demo + Submit** | |
| - Set Modal `keep_warm=1` for demo period | |
| - Run world for "7 simulated days" (7 manual ticks) so history is rich | |
| - Record demo video (see Section 15) | |
| - Publish `FIELD_NOTES.md` as HF blog post | |
| - Write and post social media update | |
| - Submit to hackathon with all required links | |
| --- | |
| ## 14. Budget: Modal & HF Credits | |
| ### Modal ($250 Credits) | |
| **Usage breakdown:** | |
| | Task | Duration | GPU Cost | Frequency | Total | | |
| |------|----------|----------|-----------|-------| | |
| | Entity generation | ~8 seconds/entity | ~$0.003 | ~500 over 10 days | ~$1.50 | | |
| | Hourly simulation tick | ~90 seconds/tick | ~$0.027 | 240 ticks (10 days Γ 24) | ~$6.50 | | |
| | Fine-tuning (if using Modal) | ~2 hours | ~$2.20/hr | Once | ~$4.40 | | |
| | Development and testing | Variable | Variable | Throughout | ~$15.00 | | |
| | Demo day (keep_warm=1, ~6hr) | 6 hrs continuous | ~$6.60/hr | Once | ~$40.00 | | |
| | **Total estimated spend** | | | | **~$68** | | |
| | **Remaining buffer** | | | | **~$182** | | |
| **Key setting:** Keep `keep_warm=0` during development. Only set `keep_warm=1` for the final demo recording and during judging. Cold starts (~15-20 seconds) are acceptable during development but not during the demo. | |
| ### HF Credits ($20) | |
| **Recommendation: Do not spend on inference.** Modal covers that far better. | |
| **Best uses:** | |
| 1. GPU-tier HF Space if needed (prevents any compute limitations on the Space itself β $0.05/hr for a basic GPU Space if needed). Probably not necessary. | |
| 2. Keep as a buffer for unexpected needs. | |
| **Free HF resources (no credits needed):** | |
| - Private dataset repo for SQLite backup: Free | |
| - Model hosting for your fine-tuned model: Free | |
| - HF Space (CPU tier): Free | |
| - HF AutoTrain for fine-tuning: Uses Compute Credits, partially covered by $20 | |
| ### Keeping HF Space Alive | |
| HF Spaces sleep after 48 hours of no traffic on free tier. Solution: | |
| - Register a free account at UptimeRobot (https://uptimerobot.com) | |
| - Set a monitor to ping your Space URL every 25 minutes | |
| - This is free and keeps the Space awake indefinitely | |
| --- | |
| ## 15. Demo & Submission Strategy | |
| ### Pre-Demo Setup | |
| Before recording, the world needs to already be alive. Run this sequence: | |
| 1. `python seed_world.py` β creates 12 starter entities across all locations | |
| 2. Run simulation tick 7 times (one per "day") β creates real history, relationships, events | |
| 3. Verify: Book of Ages has at least 20 entries across 7 days | |
| 4. Verify: at least 3 relationships have formed | |
| 5. Verify: at least 1 entity has reached a milestone (Mayor, ally, etc.) | |
| 6. Set Modal `keep_warm=1` | |
| 7. Test entity creation once more β timing should be fast | |
| ### Demo Script (90 seconds target) | |
| **0:00 β 0:12** β Open the app. World map visible. Entity dots glowing. | |
| *"This world has existed for 7 days. Other people have been building it."* | |
| **0:12 β 0:28** β Open Book of Ages. Scroll slowly through 7 days of history. | |
| *"Here's what happened. Nobody scripted any of this. The AI decided all of it."* | |
| β Pause on one interesting event (The Dragon becoming Mayor is perfect) | |
| **0:28 β 0:48** β Return to the Realm view. Type a new entity live: | |
| *"A clockmaker who is afraid of her own clocks"* | |
| Click Summon. Wait for generation (loading animation visible). | |
| Profile appears. Entity appears on map. Arrival note visible in activity feed. | |
| **0:48 β 1:05** β Click the entity's location on the map. Show the entities currently there. | |
| Click the new entity's profile. Show full card: appearance, backstory, greeting, memory (empty, she just arrived). | |
| **1:05 β 1:20** β Click another entity on the map (one of the pre-seeded ones with history). | |
| Show their memory: "Has collected 43 jokes. Won the Mayorship. Owes the Cartographer a favor." | |
| *"This one has been here for 7 days. It remembers specific things."* | |
| **1:20 β 1:30** β Final frame: world map, all locations lit, entity dots visible. | |
| *"The Thousand Token Realm. Running on a 7-billion-parameter model. Alive whether you're watching or not."* | |
| ### Social Post | |
| ``` | |
| I built a persistent fantasy world running on a 7B model. | |
| Day 1: A Crystal Tree appeared. | |
| Day 4: The Lantern Foxes settled by the river. | |
| Day 7: The Joke Dragon became Mayor. | |
| Day 10: Something large shifted in the Valley. | |
| Nobody scripted any of it. The AI decided. | |
| Come add something: [HF Space link] | |
| Built for @GradioML Γ @HuggingFace hackathon. | |
| #TTR #BuildInPublic #SmallModels #Gradio | |
| ``` | |
| ### Submission Checklist | |
| - [ ] HF Space is public and loading correctly | |
| - [ ] Entity creation works without errors | |
| - [ ] Book of Ages has 7+ days of history | |
| - [ ] World map shows all 8 locations with entities | |
| - [ ] Modal scheduled job is running (check logs) | |
| - [ ] HF Dataset backup has at least 1 recent snapshot | |
| - [ ] Fine-tuned model published to HF Hub (Well-Tuned badge) | |
| - [ ] Agent traces published to HF dataset (Sharing is Caring badge) | |
| - [ ] Field Notes blog post published on HF (Field Notes badge) | |
| - [ ] Demo video recorded (90 seconds, screen recorded) | |
| - [ ] Social post published and link saved | |
| - [ ] Submission form completed with all links | |
| --- | |
| ## 16. Risk Register | |
| | Risk | Probability | Impact | Mitigation | | |
| |------|------------|--------|------------| | |
| | AI output quality too inconsistent | Medium | High | Extensive prompt testing on Day 1 before any frontend work. Retry with lower temperature on failure. | | |
| | HF Space sleeps β simulation stops | Medium | Medium | UptimeRobot ping every 25 minutes. Modal scheduled job runs independently of Space. | | |
| | SQLite concurrent write conflict | Low | Medium | WAL mode enabled. All writes in transactions. Single-writer pattern in tick. | | |
| | World state lost on Space restart | Medium | High | HF Dataset backup every 5 minutes. Tested explicitly on Day 5. | | |
| | Entity generation too slow for UX | Low | Medium | Modal keep_warm=1 during demo. Animated loading state to manage expectation. | | |
| | Inappropriate user input | Medium | Medium | Simple content filter before AI call. Budget one day for moderation edge cases. | | |
| | Modal cold start during demo recording | Medium | Medium | keep_warm=1 on demo day. Test generation 3Γ before recording. | | |
| | Fine-tuning doesn't improve quality | Low | Low | Fine-tuning is optional. The Well-Tuned badge is worth attempting but base model is sufficient to submit. | | |
| | World becomes incoherent as it grows | Medium | Medium | Location system naturally scopes interactions. Memory compression keeps entity context bounded. | | |
| | 10 days is not enough for full vision | Medium | High | MVP is defined clearly. Days 8β10 are polish, not core. If time runs short, cut nice-to-haves and protect the MVP. | | |
| | Too many users overwhelming Modal during demo | Low | Low | Modal auto-scales. At $250 budget, this won't be a cost issue at hackathon traffic levels. | | |
| --- | |
| *Specification version 1.0* | |
| *World founding date: First successful deployment* | |
| *The judges will open a world that is already alive.* | |
| *That is the entire strategy.* | |