docs(spec): races & classes mechanical design

Settles the §17 class-name reconcile (charter §8 vs mock callings) in
favor of the gritty callings, and gives every race trait a concrete rule.
Feeds M4 character creation; combat ability kit deferred to M5.

- Resolution model: deterministic value vs DC, LCK selects the borderline
  band (§7) — flat mods, no random d20, no advantage.
- 5 saves (LCK owns none); death saves = LCK.
- Races: features only, no stat mods; Nightsight ruling for darkvision.
- 7 callings (charter-7), 2 names [CANON-TBD]; casters=MP, martials=cooldowns.
- Flags two contract migrations for M4: canon-log gains `race`; deserter
  origin's allowed_classes migrates to new calling ids.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-11 14:11:07 -05:00
parent 1304f0aee7
commit aeb9ee4a9d

View File

@@ -0,0 +1,228 @@
# Races & Classes — mechanical design
**Date:** 2026-07-11
**Status:** Approved (design). Feeds M4 (character creation); combat kit hands off to M5.
**Charter refs:** §7 (Luck), §8 (stats & classes), §10 (combat), §11 (canon log), §16/§17 (mockups + the flagged reconciles).
This spec settles the **mechanics** of races and callings so M4 character creation has
rules to read. It resolves the §17 class-name reconcile (charter §8 vs the mock's
callings) and gives every race trait a concrete rule. **Lore/flavor is deliberately
out of scope** — it lives in a separate canon/worldbuilding effort; placeholders here
are marked `[CANON-TBD]`.
Scope choice (agreed): **full mechanical spec** — everything creation + the character
sheet read. The **combat ability kit is deferred to M5** (the action economy, damage
resolution, and DC bands aren't designed yet); this spec marks that seam everywhere it
touches it.
---
## 1. Foundations (the resolution spine)
### Attributes (6)
`STR · DEX · CON · FTH · MAG · LCK`. Modifier = `floor((score 10) / 2)` (matches the
Character Sheet mock's "score N" + modifier display). FTH/MAG replace WIS/INT (§8).
### Saving throws (5, not 6)
One save per attribute **except LCK**. LCK is never a save and never rolled — it is the
borderline-selector (§7). Saves: **STR · DEX · CON · FTH · MAG**. This keeps §7 airtight:
LCK cannot leak onto the character sheet as a number.
### Resolution model — deterministic + Luck-selects-borderline
The check model §7 actually describes (chosen over a random d20, which would reintroduce
the per-roll variance §7 exists to remove):
```
check value = ability_mod + (proficiency_bonus if proficient) + situational
compare to a DC:
value DC ≥ +band → success (deterministic, repeatable, plannable)
value DC ≤ band → failure (deterministic, repeatable)
within the band → LCK selects the branch (§7)
```
`band` size is **M5 tuning**. Consequences:
- **LCK is the only randomizer in the game.** Every other number is reproducible.
- Race/class features are **flat modifiers** that shift you across thresholds — never
dice, never advantage/disadvantage. (Mock talents using "advantage" language, e.g.
*Reckless Swing*, translate to flat mods.)
- **Death saves** become the purest expression of the model: a downed character sits in
the borderline band and **LCK selects** stabilize-vs-slip. No new system; reuses the
band; delivers §7's whole "am I cursed?" thesis at the highest-stakes moment.
### HP, MP, and the anti-spam gate
- **HP:** `L1 max HP = hit_die_max + CON_mod`. Per-class hit die (§4). Level curve → M5.
- **MP:** caster callings (FTH/MAG-primary) get an MP pool sized off their casting stat;
martials have **0 MP**. Pool formula + spell costs → M5.
- **The spam-gate is the action economy, not MP.** One **Action** + one **Bonus** + one
**Move** per turn (§10) caps everyone at one big thing per turn. On top of that:
- **Casters** spend **MP** — a *depleting reservoir* (decision: attrition — dump or ration).
- **Martials** use **cooldowns** — a *recharging cadence* (decision: rhythm — is it back yet?).
- Basic attack is the free, repeatable option; signature abilities compete for the one Action.
This is why §10 says the tactics live "in the action economy and resources, not the map."
With no grid, decisions live in what you spend your Action on and whether your good options
are available (MP left / cooldown ready).
### Proficiency bonus
+2 at level 1 (mock). Scales with level — curve deferred (creation is L1 only).
---
## 2. The six attributes — roles + skill map
Adopts the mock's **9 skills verbatim**. LCK owns no save, no skill, no display.
| Attr | Save | Skills | Combat role | Out-of-combat (§8) |
|---|---|---|---|---|
| **STR** | STR | Athletics, Intimidation | Melee attack + damage | Carry, forcing things |
| **DEX** | DEX | Stealth, Sleight of Hand, Acrobatics | Initiative, finesse/ranged attack, light-armor AC | Sleight, escape |
| **CON** | CON | Endurance | HP pool | Resist poison / exhaustion / infection (affliction track) |
| **FTH** | FTH | Perception, Faith-Lore | Divine casting, spell DC | Conviction in dialogue, awareness |
| **MAG** | MAG | Sorcery | Arcane casting, spell DC | Recall, deduction |
| **LCK** | — | — | Selects borderline branches, crit thresholds | Fires Improviser; boon vs humiliation |
- **Perception under FTH** (not a standalone WIS) honors §8's FTH/MAG-replace-WIS/INT — a
Priest/Bonesetter is also the party's best lookout, giving FTH its out-of-combat teeth.
- **Death saves = LCK** (see §1).
**Flags (adopting the mock as-is, noting thinness — not expanding now):**
- MAG has only 1 skill (Sorcery), CON only 1 (Endurance). §8 says MAG governs recall/
deduction — an "Arcana/Lore" skill would fit. **Deferred** to a later content pass.
- **SPEED** (mock's 30', "Old Knee 5") has no grid to matter on (§10) → treated as
**narrative-only flavor** (chases/fleeing in prose), not a tactical value.
---
## 3. Races (4)
Under **features only, no stat mods**, and **flat modifiers**. Each race = one headline
feature with real teeth + one minor feature. All upside; downsides live in flavor.
**Nightsight ruling** (resolves darkvision/low-light with no light grid): the character
**ignores darkness-based penalties on checks** — a situational flat modifier (others take
X in the dark, you take 0). Bites on the DM's exploration awareness checks.
| Race | Headline feature | Minor feature | Mock trait resolved |
|---|---|---|---|
| **Human** | **+1 to all 5 saves** | **+1 skill proficiency of choice** at creation | "+1 to every save" |
| **Elf** | **Perception proficiency** (+2) | **Nightsight** | "low-light sight · keen senses" |
| **Dwarf** | **+2 to CON saves vs poison & the infection/affliction track** (may also halve duration) | **Nightsight** | "poison resist · darkvision" |
| **Beastfolk** | **Natural claws** — innate unarmed attack (STR or DEX, light-weapon damage, always available even disarmed/grappled) | **Keen scent** — flat situational bonus to detect hidden / track by smell | "natural claws · keen scent" |
- **Dwarf's resist maps onto the mock's own affliction track** ("Infected Bite: CON save
each dawn") — the character who shrugs off the rot the gritty tone (§3) inflicts.
- **Beastfolk is the only race with a combat-*action* feature** (claws) — the aggressive pick.
- **No race touches an attribute score** — keeps the point-buy pure.
- **Human's bonus skill** is an addition beyond the mock's bare "+1 all saves" (agreed:
keep it) so Human = "the adaptable one" with an actual creation choice.
- **Beastfolk's "taxed twice at every gate"** (a mechanical shop/disposition downside) is
**deferred** to the canon session + the shop economy (M8). Race mechanics stay
upside-only for now.
---
## 4. Callings (7)
The full charter-7 (§8), gritty calling names (§17 reconcile resolved in favor of the
mock's village-names, which honor §8's "named for the role in the world" better than
§8's own list). Two need names from the canon session — marked `[CANON-TBD]`.
Static kit only — **the combat ability kit (the bar) is deferred to M5.** This is what
creation + the character sheet read.
| Calling | Archetype | Primary | Hit die | Save profs | Skill profs | Resource | Armor | L1 talent (stub) |
|---|---|---|---|---|---|---|---|---|
| **Sellsword** | Fighter | STR | d10 | STR, CON | 2 | Cooldowns | Heavy | **Second Wind** — once/rest, claw back HP |
| **[CANON-TBD]** ⚔ | Barbarian | STR | d12 | STR, CON | 2 | Cooldowns | Medium | **Blood Fury** — rage: soak + hit harder, per-encounter |
| **Cutpurse** | Rogue | DEX | d8 | DEX, MAG | 4 | Cooldowns | Light | **Backstab** — bonus dmg vs an unaware/first-strike target |
| **Trapper** | Ranger | DEX | d10 | DEX, CON | 3 | Cooldowns | Light | **Set Snare** — place a control trap, cooldown |
| **Hedge-Mage** | Wizard | MAG | d6 | MAG, FTH | 2 | MP (MAG) | None | **Hexbolt** — signature MP-free arcane basic |
| **Bonesetter** | Cleric | FTH | d8 | FTH, CON | 2 | MP (FTH) | Medium | **Mend** — heal HP, gritty field-medic |
| **[CANON-TBD]** 🔥 | Warlock | FTH | d8 | FTH, MAG | 2 | MP (FTH) | Light | **Pact Mark** — curse a target, FTH/MP |
- **Two STR martials differentiated by shape, not stat:** Sellsword = disciplined, heavy
armor + d10 + sustain (Second Wind); the Barbarian-calling = reckless, d12 + medium
armor + rage (soak via fury, not plate). Same primary, opposite feel.
- **Cutpurse gets 4 skills** (breadth is the rogue's identity); Trapper 3; others 2. Drawn
from the class's stat-appropriate slice of the 9-skill list, plus what race grants.
- **Casters** (Hedge-Mage / Bonesetter / Warlock-calling) have **MP**; martials have 0 and
live on cooldowns. MP pool formula → M5.
- **Backstab** — the mock's "advantage" phrasing becomes a **flat bonus vs an unaware/
first-strike target** under the resolution model; no positioning needed, fits gridless (§10).
- **Trapper is a pure martial** (traps = cooldown gadgets, no MP) — the D&D half-caster
ranger is deliberately not ported, to keep spell math out of the POC.
- **Armor categories** (Heavy/Medium/Light/None) are proficiency categories; specific gear
comes from origin grants + the item system (M7).
- **L1 talents are stubs** — full kit at M5.
---
## 5. Character-creation integration (M4) + canon-log contract
Folds into the proven point-buy model (rolled base + additive spend, LCK hidden).
**Order of operations:**
1. **Roll base attributes** — 3d6 with floors per stat. **LCK rolled hidden** (avg of 5 +
origin `luck_modifier`, §7) — never shown.
2. **Spend the +3 additive pool** — additive only; LCK untouchable.
3. **Apply race** — features only, no stat mods (saves / skill profs / Nightsight / claws).
4. **Apply calling** — hit die → `HP = hit_die_max + CON_mod`; save profs; skill profs; MP
pool if caster (from casting stat); armor category; L1 talent.
5. **Origin overlays**`build_constraints.allowed_classes` gates offered callings;
`luck_modifier` → LCK; inventory/disposition grants.
**Derived at creation** (all deterministic): HP, MP, AC (base + armor + DEX), the 5 saves,
9 skills, initiative (DEX), spell DC for casters (`8 + prof + casting_mod`), prof bonus +2.
**Two contract migrations this forces (flagged, do them at M4, not silently):**
- **Canon log gains a `race` field.** §11's player block is `{name, class, luck_descriptor}`
today; the Narrator/NPC need `race` to describe the player. Small schema bump to the M0
contract (`docs/schemas/canon-log.schema.json`). The full mechanical sheet stays in client
`GameState` — the canon log carries only what the AI narrates from (name, **race**, class,
luck_descriptor).
- **The deserter origin is stale.** `content/origins/deserter.json` has
`allowed_classes: ["sellsword","assassin","priest"]` — old charter names. Migrate to the
new calling ids (`cutpurse`/`bonesetter`/etc.) and the 7-calling roster. Origins gate
races only if they choose to (`allowed_races` omitted = all).
Creation stays **100% deterministic except the hidden LCK roll** — every derived number is
reproducible from the choices, which is exactly what §10's per-encounter seeding needs.
Character creation is the first place seeding matters.
---
## 6. Explicitly deferred (the seams)
Nothing here silently pre-empts a later brainstorm.
**→ M5 (combat):**
- Full ability kits / the bar; MP pool formula + spell + cooldown costs.
- The **damage-determinism reconcile** (§7/§10 vs the Combat HUD mock's ranges).
- The **borderline band size** (DC bands).
- Leveling — hit-die progression, prof-bonus scaling, talent tiers, XP curve. (Creation is L1.)
**→ Canon session (lore):**
- The two **[CANON-TBD]** calling names (Barbarian ⚔ / Warlock 🔥).
- All race/calling flavor, descriptions, origin fragments.
- The **beastfolk social tax** (mechanical downside, ties to M8 shop).
**→ Later content pass:**
- MAG/CON skill thinness (an Arcana/Lore skill).
- SPEED as narrative-only flavor.
---
## §2 accounting
Every system here is **state** (code owns it). Races and callings are code-owned data the
AI only *narrates from* — the canon log's new `race` field is the sole text-facing surface,
and it carries a value code decided. No AI system mutates any of this. Consistent with §2.