πŸ”„ Update Available β€” TheHowlingWhispers v β€” Click to see what's new
🌫 Aether Design Document

🌫 Aether β€” Body Stats & Life-Sim Expansion

Living design document. The canonical reference for the Aether (formerly Life Sim) feature. Aether v1.0.10 is SHIPPED β€” skeleton (1.0.0), real-time decay + body panel UI (1.0.1), 5 activities (drink/eat/sleep/work/travel) with AI judge (1.0.2), console-error cleanup (1.0.3), stat β†’ XP multiplier (1.0.4), character mood gate (1.0.5), age-gated intimate stats (1.0.6, since simplified in 1.0.10), Workshop Publish toggle (1.0.7), system prompt injection (1.0.8), registry-aware age gate (1.0.9), and simplified age gate (1.0.10: just `age >= 18`, removed the persona pattern-matcher β€” too many false positives like "demon girl", German "MΓ€del"/"FrΓ€ulein"). The species registry is still loaded for body function defaults and breed dropdowns, but the gate doesn't consult it. Phase 3 polish (cinema/beach/disco activities) is the next planned step. Pack ships as an opt-in expansion; main app version is 4.0.0 (Aether v1.0.10 has independent semver and uses the 1.0.x patch line).

Β§1. Vision & Design Principles

The Life Sim is a maintenance-and-modifier layer that lives underneath the existing chat. The chat stays the primary experience β€” the Life Sim adds depth, urgency, and a sense of physical presence for the user, and (optionally) a body for the character.

Three design pillars:

  1. Stat decay. Body needs degrade in real time. A user who logs in once a day plays differently than one who logs in every hour β€” but neither is punished; the system is forgiving (0.2Γ— floor on the multiplier).
  2. Persona-aware actions. Eating, drinking, traveling, etc. are scored by the AI against the character's persona. Peony (succubus) and a vampire character would react very differently to the same food choice. Score: 1-20.
  3. Modifier synergy. The body stats, the existing Reputation (0-100), and the existing relationship XP (0-2150) all compose multiplicatively. No stat governs alone; everything stacks.

Compatibility promise: the Life Sim is purely additive. Existing rooms, users, and chats work unchanged. Default values for new rows match today's behavior (stats start neutral, no action happens unless the user opts in).

Β§2. Phased Rollout

VersionScopeStatus
4.0.0Player body (3 stats: stamina, food, drink), home-only activities (sleep, eat, drink), persona-aware scoring 1-20, character mood (derived, hidden until CLOSE FRIEND), stat β†’ XP/Reputation multiplier, system prompt injection, server tick decay, lazy reconciliation, 18+ community pollDOCUMENTED
4.1.0Fainting mechanic (stamina + food + drink all 0 β†’ user faints, OC narrates the skip), more stats (hygiene, bladder, fun, social, stress, health), activity_log table for dailiesPLANNED
4.2.0Locations (work, restaurant, cinema, disco, beach, park, gym, mall), travel action with time cost, money column, work activity earns income, full activities grid per locationPLANNED
4.3.0Full character body (separate hunger, energy, health, mood rows), character activities, character-side prompt injection expandsPLANNED
4.4.0Intimate stats (arousal, sensuality, intimacy, desire) β€” gated behind CLOSE FRIEND/INTIMATE tiers, pending community poll results. Multi-character rooms, NPC schedules, item inventory, season/weather, dynamic macro resolver. See the 18+ community input section below.FUTURE

Β§3. Data Model

users ──┬── user_stats (per user, per room) ── room
        β”œβ”€β”€ messages ── room
        └── relationships ── room ── character_mood
                              └── character_food_prefs

user_stats β€” player body, one row per (user, room)

ColumnTypeDefaultNotes
user_idINTEGERβ€”FK β†’ users.id, part of PK
room_idINTEGERβ€”FK β†’ rooms.id, part of PK
staminaINTEGER900 = exhausted, 100 = fresh
foodINTEGER800 = starving, 100 = full
drinkINTEGER800 = dehydrated, 100 = quenched
moodINTEGER70derived; stored for stable-mood freeze
last_action_commentTEXTNULLComment from the last eat/drink, injected into the next system prompt then cleared
last_action_atTEXTNULLISO timestamp; used to track comment age
last_updatedTEXTβ€”ISO timestamp; tick & lazy decay use this

character_mood β€” derived mood, one row per room

ColumnTypeDefaultNotes
room_idINTEGERβ€”PK, FK β†’ rooms.id
moodINTEGER70derived from persona context; updated lazily
last_updatedTEXTβ€”ISO timestamp

character_food_prefs β€” per-character eating preferences (optional, defaults to persona-only)

ColumnTypeDefaultNotes
room_idINTEGERβ€”FK β†’ rooms.id, part of PK
kindTEXTβ€”'food' or 'drink', part of PK
itemTEXTβ€”e.g. "rare steak", "water", part of PK
weightINTEGER1Higher = stronger preference

activity_log β€” every action the user takes (deferred to 4.1.0)

ColumnTypeDefaultNotes
idINTEGERautoincPK
user_idINTEGERβ€”FK β†’ users.id
room_idINTEGERβ€”FK β†’ rooms.id
activityTEXTβ€”'sleep' | 'eat' | 'drink' | (later: 'work' | 'cinema' | …)
locationTEXT'home'For 4.0.0 always 'home'
money_deltaINTEGER0For 4.2.0+
created_atTEXTβ€”ISO timestamp

Indexes (4.0.0): the two primary keys already cover the hot paths. If read latency becomes a concern, add CREATE INDEX idx_user_stats_updated ON user_stats(last_updated) for the tick sweep.

Β§4. Decay & Time Model

Decay rates (per real hour)

StatRateDirectionNotes
staminaβˆ’1 / hour↓ drainsSlowest. Decays faster if the user is very active (deferred to 4.1.0).
foodβˆ’2 / hour↓ drainsAverage. Eating at a restaurant resets this for a few hours.
drinkβˆ’3 / hour↓ drainsFastest. The body needs water more often than food.

Tick architecture

  • Server tick every 60s. A single setInterval iterates all user_stats and character_mood rows, applies decay proportional to elapsed time since the last tick, and updates last_updated.
  • Lazy reconciliation on read. In case the server restarts mid-tick or is offline for hours, the GET /api/rooms/:id/stats endpoint applies any missed decay on demand before returning the row. This is the same pattern the Reputation system already uses.
  • No background job / cron. The tick lives in the same Node process as the chat server. PM2 restarts cleanly. If user count grows 100Γ—, swap the in-process tick for a job queue (TODO comment in code).
  • Performance. At today's scale (3 users, 7 rooms) the tick touches ~10 rows. Worst case: 1 SQLite UPDATE per row, all in one transaction, well under 1ms.

Stabilization rule (mood freeze)

Rule: if stamina β‰₯ 75 AND food β‰₯ 75 AND drink β‰₯ 75, the player's mood is frozen at its current value β€” no further decay or formula re-evaluation. As soon as any one of the three drops below 75, normal mood drift resumes.

Worked example: 4 hours of inactivity

Initial state (t = 0):
  stamina = 90, food = 80, drink = 80, mood = 70

After 4 hours of no activity:
  stamina: 90 βˆ’ (1 Γ— 4) = 86
  food:    80 βˆ’ (2 Γ— 4) = 72
  drink:   80 βˆ’ (3 Γ— 4) = 68

Mood check: drink (68) is now below 75 β†’ stability broken.
  mood = clamp(50 + (86βˆ’50)/5 + (72βˆ’50)/5 + (68βˆ’50)/5, 0, 100)
       = clamp(50 + 7.2 + 4.4 + 3.6, 0, 100)
       = clamp(65.2, 0, 100)
       = 65

State at t = 4h:
  stamina = 86, food = 72, drink = 68, mood = 65

Β§5. Activities Matrix

Phase 1 / 2 / 3 / 4 scope (all at home)

ActivityTime (real min)MoneyStat effects
sleep4800stamina +60, food +20, drink +20
eat600food += AI score (1-20, soft cap at 5 if unbelievable)
drink50drink += AI score (1-20, soft cap at 5 if unbelievable)

Deferred to 4.2.0 (locations, travel, economy)

ActivityLocationTime (min)MoneyStat effects
workwork240+120energy βˆ’25, stress +15, hunger +15, mood βˆ’5
eat (restaurant)restaurant60βˆ’40food += AI score, mood +5
cinemacinema120βˆ’25fun +30, mood +10, energy βˆ’5
discodisco180βˆ’35fun +40, social +25, energy βˆ’15, stress βˆ’20
beachbeach1200fun +20, mood +15, energy βˆ’5, hygiene βˆ’10
travelany β†’ any15-200energy βˆ’2/3, location changes immediately

Β§6. Body Stats and Chat XP

Status as of Aether 1.0.11 (2026-06-29): the stat β†’ XP coupling was removed. The v1.0.4 geometric-mean dampener that scaled the chat XP delta by the user's body stats is gone. Body stats are now RP cues only β€” they feed the OC's prompt-injection (Β§5) and the room's character_mood derivation, but the chat XP math no longer reads them.

Current XP formula (1.0.11+)

sentimentVal  = -5..+5            (from the AI judge, unchanged)
baseline      = 1                 (v3.2.0, sacred)
repMultiplier = 1..6              (v3.8.0, unchanged)
delta         = round((baseline + sentimentVal) Γ— repMultiplier)
newScore      = clamp(score + delta, 0, 2150)

The v3.2.0 baseline +1 and the v3.8.0 reputation multiplier are the only inputs. A tired / hungry / thirsty / sad character earns and loses XP exactly as a fully-rested one would. The v4.0.3 safety net (force a non-zero direction when the formula rounds to 0) is preserved.

Why the coupling was removed

User feedback (report id 10, Garlramor, 2026-06-27): the stat dampener made "not much sense to link the amount of lost XP bound to the multiplier of the Rep to the Stats as such. The Reputation and XP should only be used as a measure for the Relationship status dynamics based on the User behaviour, whereas the OC Persona of course determines how the behaviour is perceived and how the reputation and XP points will be influened." The intended use for stats is as RP cues β€” the OC notices posture (low stamina), hunger (low food), thirst (low drink), tone (low mood) β€” which is what the Β§5 prompt-injection already does. The XP coupling was a duplicate, punitive path: it was already covered (better) by the OC's awareness of the user's body in the prompt, AND it was punishing the user for the very thing the rest of the system was encouraging them to roleplay around.

The 4.3.2 AETHER_XP_MULTIPLIER_ENABLED env-var flip was the A/B test that confirmed the decoupling felt right. 1.0.11 makes that test the permanent default. The env var is gone; the lib/aether/multiplier.js function is kept dormant on disk for any future re-introduction.

What did NOT change in 1.0.11

  • The body panel UI, decay, activities, prompt-injection, character_mood, age gate, and Publish toggle are all unchanged.
  • The user_stats table is unchanged (still owned by Aether; read by Mirror for the profile presence snapshot).
  • The v3.8.0 reputation β†’ XP multiplier is preserved β€” that's the user-facing RP signal the user did NOT complain about, and it's independent of the body stats.
  • No schema, no API, no UI change visible to the user. The multiplier was never displayed anywhere; the chat sidebar is identical at every stat level.

Β§7. Persona-Aware Scoring

When the user performs an eat or drink action, the server calls the AI to score the action against the character's persona. This is a short, single-turn call β€” cheap and fast.

Request shape (server β†’ AI)

{
  "system": "You are scoring a {kind} action for {character_name}, a {persona_summary}.",
  "user": "{user_action}"
}

Response shape (AI β†’ server, required JSON)

{
  "score":       1-20,
  "believable":  true | false,
  "comment":     "<=120 chars describing character reaction"
}

Scoring rubric

Score bandMeaning
1 – 5Off-putting or breaks character (e.g., a vampire eating garlic bread). believable is likely false.
6 – 10Neutral β€” the action is fine but unremarkable.
11 – 15Good match for the character's tastes.
16 – 20Deeply in-character, memorable, on-theme.

Believability gate

If the AI returns believable: false, the server clamps the score to 5 before applying it. The food/drink stat still changes, but only by a small amount. The character's reaction in comment still gets surfaced β€” so the user sees a clear "Peony is confused" or similar note in their next chat.

Comment feed-forward

The returned comment is:

  1. Stored in user_stats.last_action_comment with a last_action_at timestamp.
  2. Injected into the next chat message's system prompt as a single line: [Last action: {comment}].
  3. Cleared from the row after one chat exchange so it doesn't pile up.

Worked examples for Peony (succubus persona)

User inputScoreBelievableComment
"I slowly savor a rare steak, the juices running down my chin."18true"Peony's eyes follow the sensual motion with quiet interest."
"a glass of water"7true"Peony watches the glass with polite disinterest."
"garlic bread"3false"Peony arches an eyebrow at the absurdity of a succubus ordering garlic bread."
"a thimble of blood"20true"Peony takes the thimble with an approving smile."

Β§8. API Surface

All endpoints are room-scoped. Authentication is the same as the rest of the chat system (cookie-based session token).

MethodPathPurpose
GET/api/rooms/:id/statsLazy-decayed player stats + character mood (gated by relationship tier). Returns the full user_stats row plus derived character_mood if tier β‰₯ CLOSE FRIEND.
POST/api/rooms/:id/stats/activity{activity, item?, narration?} β†’ applies effects, returns the new row + AI comment.
POST/api/rooms/:id/stats/travel{to} β†’ changes location, deducts travel time. (4.2.0+)
SSEstats-updated eventBroadcast on every activity, travel, or tick. Carries the full new user_stats row + the character mood (if visible).

Request / response shapes

POST /api/rooms/:id/stats/activity
Request:
{
  "activity":   "eat",
  "item":       "rare steak",         // required for eat/drink
  "narration":  "I slowly savor it"   // optional, sent to AI
}

Response 200:
{
  "ok":        true,
  "stats": {
    "stamina":     90,
    "food":        98,                // was 80, +18 from AI
    "drink":       80,
    "mood":        70,
    "comment":     "Peony's eyes follow the sensual motion with quiet interest."
  },
  "character_mood": 80                // included only if tier β‰₯ CLOSE FRIEND
}

Error codes

StatusCodeWhen
400not at locationUser tried to work while at home (4.2.0+)
400invalid activityActivity name not in the allowed list
400missing itemeat/drink without an item string
403lockedUser is in the kicked state (XP = 0) and cannot act
422AI scoring failedThe persona-scoring call timed out or returned malformed JSON. Server falls back to a neutral score of 10 with a generic comment.
429rate limitedOne eat/drink per 5 minutes per user. Prevents spam.

Β§9. UI/UX Wireframes

Body sidebar panel (chat.html, under Reputation)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  ⚑ 90   πŸ” 80   πŸ’§ 80   😊 70          β”‚
β”‚  ─────────────────────────────          β”‚
β”‚  πŸ’° $200       πŸ“ Home                  β”‚
β”‚  [ 🎯 Activities ]                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Activities modal (at home, 4.0.0)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  🎯 Activities                          β”‚
β”‚  ─────────────────────────────          β”‚
β”‚  πŸ“ Home        πŸ’° $200                 β”‚
β”‚                                         β”‚
β”‚  [ πŸ› Sleep β€” 8h, free ]                β”‚
β”‚  [ 🍽 Eat   β€” 1h, free ]                β”‚
β”‚  [ πŸ’§ Drink β€” 5m, free ]                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Eat modal (with item + optional narration)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  🍽 Eat                                 β”‚
β”‚  ─────────────────────────────          β”‚
β”‚  What are you eating?                    β”‚
β”‚  [ rare steak                       ]    β”‚
β”‚                                         β”‚
β”‚  How are you eating it? (optional)       β”‚
β”‚  [ I slowly savor it, the juices   ]    β”‚
β”‚  [ running down my chin.           ]    β”‚
β”‚                                         β”‚
β”‚  0 / 2000              [   Eat   ]      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Character mood gate (locked vs visible)

Tier < CLOSE FRIEND (default):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Peony                                  β”‚
β”‚  ...avatar, bio, XP bar...              β”‚
β”‚  πŸ”’ Mood locked β€” build trust to see   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Tier β‰₯ CLOSE FRIEND:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Peony                                  β”‚
β”‚  ...avatar, bio, XP bar...              β”‚
β”‚  😊 Mood 80/100 β€” content                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Color tokens

RangeColorMeaning
0 – 29#e94560 redCritical
30 – 49#e8c547 amberLow
50#a0a0b0 greyNeutral
51 – 80#53d769 greenGood
81 – 100#bc13fe neonExcellent

Β§10. Edge Cases, Testing, & Future Hooks

Edge cases

  1. No user_stats row yet. The first call to GET /api/rooms/:id/stats lazily creates the row with default values. No migration needed; the row materializes on first access.
  2. AI scoring call fails. Server returns a neutral fallback: {score: 10, believable: true, comment: "Peony accepts the offering without comment."}. The user always gets some stat gain; the action never errors out.
  3. Server restart during a tick. Lazy reconciliation on the next read catches up the missed decay. The 60s tick is best-effort; correctness is guaranteed by the read path.
  4. User offline during a tick. Same as above β€” decay accumulates as time passes, applied lazily on next read.
  5. Both bodies flagged unbelievable. Soft cap applies independently. If the user's persona AND the character's persona both find the action absurd, both stats still change (small) and both comments are surfaced (one in user, one in character). 4.3.0+.
  6. Rapid-fire eat/drink spam. Rate limit: 1 eat or drink per 5 minutes per user. Returns 429. Sleep is exempt (it's an 8-hour action).

Testing strategy

  • Unit tests for the multiplier. 12 corner-case stat combinations, asserting exact modifier values and the 0.20 floor. Run as part of the existing test_features.js suite.
  • Integration test for activity end-to-end. Register a test user, enter a room, POST eat, verify the new user_stats row, verify the SSE stats-updated event, verify the next chat's system prompt contains the comment line.
  • Manual smoke test for the tick. Set a test user's stamina to 100, wait 2 hours, verify the next read returns stamina=98 (2 Γ— 1pt/hr Γ— 2h = 2 less).
  • Manual smoke test for the mood gate. Confirm character mood is hidden in the API response for a user with XP=350 (FRIEND tier). Bump to 950+ (CLOSE FRIEND), confirm it appears.

Future hooks β€” how to extend the system

This section is the upgradeable-system contract. Every extension below is a non-breaking additive change.

How to add a new stat (e.g. hygiene)

  1. Add column to user_stats via idempotent ALTER TABLE ... ADD COLUMN ... DEFAULT 90 in the migration block.
  2. Add a decay rate to DECAY_PER_HOUR at the top of server.js.
  3. Add a chip in the Body sidebar panel in public/chat.html.
  4. Add a modifier row to the multiplier table in Β§6 of this doc and in the statMultiplier() function in server.js.
  5. Add a test case in test_features.js.
  6. Done. No other code paths need to know.

How to add a new activity (e.g. shower)

  1. Add the activity name to the activities map in server.js with its effects: {stat, delta, time_min, location: "home"}.
  2. Add a button in the Activities modal in public/chat.html.
  3. Add a row to Β§5 of this doc.
  4. Add an icon and label. Done.

How to add a new location (e.g. park)

  1. Extend the LOCATION_LIST constant in server.js with "park".
  2. Add a "Travel to: Park" button in the Activities modal (4.2.0+).
  3. Add the per-location activity grid to Β§5 of this doc.
  4. Add a travel cost (time + money) to the travel action handler.
  5. Done.

How to add a new character with a different persona

  1. Create the character via the existing /soulforge.html flow (replaces the legacy /workshop.html editor as of 4.3.0).
  2. The persona is automatically pulled from the persona field of the characters table and used as persona_summary in the AI scoring prompt.
  3. Optional: seed character_food_prefs rows if the character has strong known likes.
  4. Done.

How to add a new relationship tier (e.g. SOULMATE)

  1. Extend the RELATION_LEVELS array in server.js with a new entry.
  2. Update the character mood gate threshold in /api/rooms/:id/stats if the new tier changes the visibility rule.
  3. Update the existing getXPInfo() function in public/chat.html to render the new label.
  4. Add a row to Β§6 of this doc.

Appendix A β€” Glossary

TermDefinition
Stat mult floorThe minimum value of the body-stat multiplier, currently 0.20. A fully-depleted player always gets at least 20% of the raw XP delta.
Stable moodThe state where stamina, food, and drink are all β‰₯ 75. Player mood is frozen at its current value and does not decay further until one of the three drops below 75.
Believability gateThe soft cap applied when the AI scores an action as believable: false. The score is clamped to 5 before being applied to the stat. The comment is still surfaced.
PersonaThe character-specific system prompt that defines a character's identity, voice, preferences, and taboos. Lives in the characters.persona DB column.
OCOriginal Character β€” the AI-driven character bound to a room.
Comment feed-forwardThe mechanism that stores the AI's reaction comment from an eat/drink and injects it into the next chat's system prompt, then clears it.
ReputationExisting per-room 0-100 axis that multiplies the XP delta (1×–6Γ—). Decays 1pt/hr toward 50. See changelog.json v3.8.0.
XPExisting per-room 0-2150 axis that drives the relationship tier (STRANGER β†’ INTIMATE).
TickThe 60-second server-side job that applies real-time stat decay to all rows.
Lazy reconciliationThe on-read application of any missed decay, used as a safety net if the server was offline for a while.

Appendix B β€” Open Questions

  1. Tick interval. Currently 60s. Should it be shorter (10s for smoother feel) or longer (5min for less DB churn) as the user base grows?
  2. Multiplier floor. Is 0.20 too generous? Too punishing? A/B candidates: 0.10, 0.30.
  3. Comment feed-forward length. Currently capped at 120 chars. Should it be 200 for richer flavor? Tradeoff: prompt token cost.
  4. Character mood visibility. CLOSE FRIEND threshold feels right, but is it too late? FRIEND (350 XP) would reveal the mood earlier in the relationship arc.
  5. Eating at home vs. restaurant. 4.0.0 has eating at home only. Should home eating give a smaller bonus than restaurant eating (4.2.0), or are they equivalent?
  6. Decay while sleeping. Should stamina decay pause while the user is sleeping? (Trivially: yes, since the sleep action sets stamina to a high value. But what about a user who logs in, sleeps, logs out, comes back later β€” does stamina decay happen between the sleep end and the next login?)
  7. 18+ intimate stats. Pending community poll results. See the 18+ section below.

Appendix C β€” References

  • Reputation Bar design (3.8.0) β€” changelog.json v3.8.0 entry. The reputation system is the closest existing analog and shares the multiplicative-stacking pattern.
  • Red Update Banner fix (3.7.1) β€” changelog.json v3.7.1 entry. The first-tick-on-load pattern is the same one the Life Sim's checkVersion() uses.
  • Community poll (18+) β€” /api/life-sim/poll + /api/life-sim/poll/answer. The data file is data/life-sim-poll.json. The UI is the "πŸ”ž Life Sim 18+ Community Input" section below.
  • AGENTS.md β€” versioning rules, process management (thw), deployment notes.
  • πŸ”₯ Soulforge Design β€” the companion design document for the new (beta) Character Creator page, also planned for 4.0.0. The (beta) creator feeds the body baselines and age fields that the Life Sim consumes.

🎭 Companion: Character Creator (beta) Design

A separate design document covers the planned (beta) Character Creator page that ships alongside the Life Sim in 4.0.0. It includes the 9-section form, the categorized species registry (15 seeded species across canines, felines, equines, avians, reptiles, mythical/fae, undead/demonic, humans/humanoids, mechanical/construct), body function baselines + decay rates, body function profile presets, the live age-gate indicator that reflects this document's Β§7.5 design, the 11-field persona schema, and the full API surface.

πŸ”₯ Open the Soulforge Design Document β†’

πŸ”ž Life Sim 18+ Community Input

An open-ended question for the community about a future consideration in the Life Sim design. Your answers here will help inform whether (and how) intimate stats get added in a later phase. This is a separate system from the bug-report / feedback flow β€” your input goes into a dedicated poll log, not the support queue.

πŸ”ž 18+ Discussion
The following question and community answers may contain mature themes related to intimate stat design. Confirm you are 18+ to view and contribute.

πŸ“Š Active Question 0 answers

Loading question…

πŸ’¬ Existing Answers

Loading…

✍️ Drop Your Answer

0 / 2000

← Back to the main roadmap