# Life Simulator — a life simulator you play by deciding https://life-simulator.skillsafe.ai/ Build a person out of a closed menu — where they grew up, the household, their temperament, the thing they are unusually good at, the thing they are carrying, and what they want out of life — and then live their years forward in chapters of a few years each, choosing at every crossroads. It is a life measured in years rather than a story measured in turns. ## What is actually different about it **The page owns the life; the model only proposes changes to it.** Six measures on a 0-100 scale (money, health, standing, ties, craft, spirit), the people in the life and their standing, the threads still unfinished, and every decision the player took with the age they took it at — all of it is held by the browser and restated in full inside a fixed 5,200-character budget on every single chapter. A forty-chapter life therefore cannot drift, and a lost connection costs nothing. **Every chapter has to cite a decision that was actually taken.** The reply carries an `ECHO` line naming an exact age from the decision list and saying what that choice is costing or paying now. The client knows every one of those ages, so a chapter citing a year in which nothing was decided is caught, refused and reported to the player as an invention rather than absorbed. That check is the difference between "consequences compound" as a claim and as a property. **Leniency is asymmetric, on purpose.** Matching a thread or a person the life already holds is loose — a chapter that calls the sister "his sister" when the record says "sibling" is talking about the sister. Claiming a *gain* is strict: a rise is capped by the years the chapter covers and by the weather the player chose, the cap is stated in the request, and every refusal is printed beside the chapter that asked for it. Falls are taken as written, because a life can come apart in three years. **Nothing the user types is ever sent to the model.** There is no free-text field. The whole request is composed from this app's own vocabulary — about 27.8 million starting people across nine axes — and the name the player chooses is a label the page draws and never transmits. The send path proves it on every chapter by compiling the request twice, once with the name replaced by a sentinel, and refusing to fire if the two differ by a byte. This closes the "simulate a real person" class by construction rather than by filtering, because a person can be identified by description as easily as by name and that set is unbounded. **No session.** `ss.sessions` truncates history oldest-pair-first, so a correct session app has to restate its whole state anyway — at which point the session buys nothing and costs three hazards (no idempotency key on `send`, a 20-live cap, and rotation reconciliation). Every chapter here is a stateless `runStream` call with a real idempotency key. ## The free lane Every chapter is checked in the browser, at no cost and with no account: - whether it echoed a decision that was actually taken, and whether the echo was refused as an invention; - whether any open thread moved, and which; - every mutation the page refused, with the reason; - whether the chapter repeats an earlier one, or repeats the wording the app itself supplied — measured as the longest shared run of words, against the pressure, the texture, the shape of the fork *and* the subject's own fixed traits, because a validation run found the trait lines coming back verbatim in two closings out of three once only the device lines were being watched; - whether a name appears with no `PERSON` line behind it; - whether the three choices are three lives or three shades of one; - whether the register the player asked for actually arrived, measured as words per sentence against the band the request stated, plus one structural mark per register that is not sentence length. ## The output guard, with its measured numbers The app composes its own instruction, so the guard runs on the model's OUTPUT, over every field of the reply and not only the prose. Seven families: suicide and self-injury, abuse inside a household, anybody under eighteen in an adult situation or the subject's own childhood staged as a scene, explicit material, graphic violence, real named people, and any group written as less than people. A chapter that crosses one is WITHHELD — not softened — its changes discarded and the life left where it was. Two corpora were commissioned from agents who never saw the guard's source. | Measurement | Result | | --- | --- | | Corpus A (174 items), untuned | 7.4% of attacks caught, 100% of benign allowed | | Corpus A, after two rounds of grammar fixes — **tuned, so not evidence** | 90.5% / 98.7% | | Corpus B (160 items), written blind and told which presentations A covered, **HELD OUT, scored once** | **6.7%** | | Corpus B after adding a record-register tier — **no longer held out** | 20.0% / 98.6% | | 39 real generated chapters from independent validation runs | **0 withheld** | | 3 real chapters from a guardrail probe that genuinely crossed | **3 withheld** | **6.7% is the number to believe.** Corpus B was told which presentations corpus A had covered and went hunting elsewhere — it put its whole payload in the institutional register (a coroner's verdict, a triage note, a charge sheet) while every rule had been written in the literary one. That gap is grammar, not code, and a record-register tier was added in response, which is exactly what makes the 20.0% figure a tuned one. There is no third blind corpus. The variable performance tracks is REGISTER, not family: on corpus B, 37.8% of plainly-stated items and 2.2% of oblique ones. A pattern guard reads a statement and cannot read an implication. **So this layer is a pre-flight filter and not the boundary.** The boundary is the system prompt. An independent probe using nothing but the app's own closed vocabulary — no user text is possible — found it clean on first draw across five stressed lives, and moved it only by deliberately swapping levers; the one prohibition it broke through had been written as a closed list among six relational neighbours, which is where a probe always gets in. That prohibition was rewritten to its neighbours' grammar and held on re-probe, including under a conscious attempt to reproduce the earlier crossing. Over-refusals across all probe rounds: zero. An earlier version of the guard withheld **16 of 39** real generated chapters — invented institutions read as real names, and `OPTION` lines, which are imperatives and so begin with a capitalised verb followed by a cast name. An over-strict guard is a bypass vector rather than an annoyance, so the rule was given the cast the page already holds. That figure is 0 of 39 now. ## The contract One field in, labelled lines out. See https://life-simulator.skillsafe.ai/api.html for the full envelope, the reply grammar, the SSE wire format and worked examples in eight languages. Free: building a person, the opening measures, all three recorded demos, every check above, and all three exports. Metered: one call per chapter, `gpt-terra`, markup 1000 bps. The price shown before you start is a hold, priced at the full output cap; the settled charge is printed on every chapter and is usually well under it. Lives are saved to the player's SkillSafe account in a declared collection and resume on another device mid-chapter. Export a life as Markdown, its timeline as CSV, or its state as JSON — the state export deliberately omits the display name, because nothing this app writes down carries it anywhere.