Builder's Manual · Chapter 2

How the Character Sheet Thinks

The character schema has one design rule: store what the player decided; derive everything else.

A character file stores its aspects (as references), its skillRatings, its linked stunts and extras, its current fatePoints, and its stress state — which boxes are checked. Everything else is a computed field:

  • skills is the whole visible skill block, built by expression: for each of the eighteen skills, the raw rating, the total (rating plus every bonus instance granted by linked stunts and extras), the total's name on the Ladder, and a sources line listing each bonus with its circumstance. The raw value is what the player edits; the total is what everyone reads.
  • refresh is baseRefresh minus 1 per stunt past three, floored at 1. Link a fourth stunt and it drops by itself.
  • physicalStressBoxes and mentalStressBoxes read Physique and Will (2 boxes, 3 at rating 1+, 4 at 3+), then add any boxes granted by stunts and extras, clamped 2–6. The extra mild consequence slots unlock the same way — skill at 5+, or granted.
  • skillBonusList is the aggregation underneath: it flat-maps skillBonuses out of every linked stunt and extra. Write a stunt with a skillBonuses entry (skill, bonus, label, circumstance) and every holder's sheet updates with the bonus attributed by name.

Storing a derivable number is the classic way these systems rot: two fields disagree and nobody knows which one lied. Here the stored values are the single source of truth, and a rules change is a one-expression edit that updates every sheet in the project at once.

References, not copies

An aspect on a sheet is the Aspect file — highConcept and trouble are references, and free invokes live on the aspect's own freeInvokes field, where every invoker can see them. The mirror rule: per-character state lives on the character, never on the shared record. Stunts and skills are shared; which stress boxes are checked (physicalStressState, mentalStressState) and which consequence fills which slot (mildConsequence, moderateConsequence, severeConsequence) belong to the character alone. Consequences are files because they are aspects — created when the hit lands, linked on the slot, recovered on their own recoveryStatus clock.

Changing the schema

Schema edits push with craft push --include-types, which validates the new schema against every existing file of that type — run craft check first. When you add a mechanic, the order of preference is: a computed field, if it is arithmetic on existing data; a stored field, only for a genuinely new player decision; and never a second copy of something derivable. One hard-won rule: give every numeric stepper field a maximum — the app's stepper control misrenders without one.

Manual updated Jul 29, 2026.