Files
settled-reach/wiki/authoring/culture-authoring-guide.md
T
jpmschweitzer 23d9ff0a58 Merge remote-tracking branch 'origin/main' into planning
# Conflicts:
#	CHANGELOG.md
#	content/_meta/README.md
#	content/_meta/npc-authoring-style-guide.md
#	wiki/_templates/cultural-group.md
#	wiki/_templates/institution.md
#	wiki/_templates/star-system.md
#	wiki/characters/devra.md
#	wiki/characters/drin.md
#	wiki/characters/harek.md
#	wiki/characters/lera-sessik.md
#	wiki/characters/maret-korr.md
#	wiki/characters/naia-tamm.md
#	wiki/characters/nils-davan.md
#	wiki/characters/pell.md
#	wiki/characters/renn.md
#	wiki/characters/resha.md
#	wiki/characters/sabel.md
#	wiki/characters/sera-venn.md
#	wiki/characters/torek-lintar.md
#	wiki/characters/voss.md
#	wiki/star-systems/krenn/index.md
2026-03-14 00:24:53 +01:00

21 KiB
Raw Blame History

Culture Authoring Guide — The Settled Reach

Ticket: #653 Author: Mellanie Status: canonical Last updated: 2026-03-13


Purpose

Every NPC in The Settled Reach is voiced through their culture. The voice pipeline (D-138) uses a culture profile as its primary LLM prompt — the culture injector is the single biggest determinant of how an NPC sounds. Culture files are authored once and used thousands of times across every generated NPC in that system.

This guide explains how to author a new culture RON file from scratch. The target: one experienced author can produce a complete, Spike-validated culture profile in approximately one working day.

Three reference cultures exist in content/global/:

  • culture-van-maanens-star.ron — Mid-Reach, freight, working-class pragmatic (the Spike 1/2 reference)
  • culture-vael.ron — Core-adjacent, administrative/research, institutional-formal
  • culture-osse.ron — Deep Frontier, extraction industry, terse-utilitarian

Step 1: Establish the cultural parameters (30 minutes)

Before writing a single word of the RON file, answer these five questions from docs/design/cultural-generation-guide.md:

  1. Reach Position: Core / Mid-Reach / Frontier / Deep Frontier → Determines authority attitude, institutional density, Commission presence

  2. Economic Base: Freight / Extraction / Manufacturing / Service / Research / Mixed → Determines daily vocabulary, rhythms, what NPCs care about

  3. Settlement Age: New (< 20 yr) / Established (20-80 yr) / Mature (80-200 yr) / Old (200+ yr) → Determines rootedness, architectural character, whether "here" is home

  4. Heritage Root: Frost / Tide / Iron / Dust / Stone / Vine / Salt → Determines spatial grammar and social privacy model (D-104/D-105)

  5. Institutional Ecosystem: Which institutions are visibly present? Which are resented?

Write these down before you open a RON file. They are the source of truth for everything that follows.


Step 2: Define the voice register (10 minutes)

Derive the voice register from your five parameters. Ask:

  • How does authority feel here? (Collegial / Distant / Resented / Absent)
  • What is the cost of saying too much? (Social / Physical / Legal / None)
  • What earns trust here? (Credential / Shared risk / Repeated interaction / Demonstrated skill)
  • What is the cultural mode of emotional expression? (Understatement / Direct / Suppressed / Public)

Write a one-sentence register description. This becomes speech.register in the RON.

Examples:

Culture Register
Van Maanen's Star direct, minimal pleasantries, gets to the point
Vael complete sentences, institutional framing, measured, precise
Osse terse, functional, equipment vocabulary, economy of language

Step 3: Author the naming conventions (15 minutes)

Naming conventions follow from Reach position + settlement age + economic base:

Parameter Naming tendency
Core, old settlement Polysyllabic, family-name-primary, formal phonemes
Mid-Reach, mature Mixed — 1-2 syllables, either name primary depending on sub-culture
Frontier, new Short, work-derived, first-name-only or work-name
Extraction industry Often functional; legal names exist but aren't used
Administrative Family names primary; given names reserved

IP check rule: All names must be checked against:

  • Hamilton (Contemporary English given names — avoid)
  • Banks (Whimsical/elaborate — avoid)
  • Reynolds Firefly (Earth-ethnic echoes — avoid)
  • Simmons (Greek/Latin — avoid overt register matches)

Generate 25-35 given names and 15-20 family names. The generator needs variety across playthroughs.


Step 4: Author the voice persona (60 minutes — the core work)

The voice_persona field is the LLM instruction that shapes all re-voiced output for NPCs from this culture. This is where one working day of authoring matters most.

Structure (6-block format, ~200-250 tokens total)

PERSONA: You are a [Culture] [role type].

[BLOCK 1 — REGISTER, ~25 tokens]
State the register style, why it exists, one distinguishing marker.

[BLOCK 2 — CULTURAL CONTEXT, ~25 tokens]
One sentence: what shaped this culture's voice. The social or environmental fact.

[BLOCK 3 — VOCABULARY, ~40 tokens]
Exclamations: [closed list — ONLY these expressions. No invented variants.]
Greetings: [closed list]
Address conventions: [family-name-primary, first-name-only, etc.]

[BLOCK 4 — VALUES, ~20 tokens]
Two core values as behavioral instructions. "You do X." not "This culture values X."

[BLOCK 5 — NOT-LIST, ~20 tokens]
2-3 exclusions SPECIFIC to this culture. (Universal NIs cover global constraints.)
Start with: "Do not use..."

[BLOCK 6 — EXAMPLE PAIRS (~70-80 tokens): go in voice_examples field, not here]

The NEVER: block — most important element

Format: The NEVER: block is a separate, explicitly labeled section at the END of the persona string. It must not be embedded as a numbered instruction.

[positive instructions 1-8]\n\nNEVER: [3-5 explicit negatives defining what this culture does NOT sound like]

Why it matters: Spike 2 finding — explicit NEVER: blocks are critical for voice quality. Without them, the LLM defaults to register-neutral generic output. The numbered instructions alone are insufficient. The NEVER: section must be visually and structurally distinct — not "8. Do not use..." but a labeled block after the numbered list.

The not-list prevents register leakage. Write it by asking: what does this culture NEVER sound like?

Culture NEVER block content
Van Maanen's Star Corporate/institutional language, effusive or polished register, deference to unearned rank, family names in casual use, verbosity
Vael Void-adjacent exclamations (frontier register), casual contractions, sentence fragments, direct emotional expression, physical labor as value ground
Osse Institutional framing or courtesy protocols, formal complete sentences, Commission-world vocabulary, Core-system exclamations, elaboration where a number suffices

The NEVER: content must be culture-specific. Global constraints (no religious language, no Earth references) go in the universal RULES const — do not repeat them per-culture.

Writing the persona instructions

Use second-person imperative: "Be direct." not "This culture is direct."

Each numbered instruction should target a DIFFERENT speech dimension so trait modifiers can stack cleanly:

  • Instruction 1 → delivery style (brevity, formality)
  • Instruction 2 → cultural context (why they speak this way)
  • Instruction 3 → address conventions (name usage)
  • Instruction 4 → emotional register (how feelings appear in speech)
  • Instruction 5 → institutional framing (how authority is referenced)
  • Instruction 6 → exclamation vocabulary (closed, explicit list)
  • Instruction 7 → trust signal (how the culture verifies credibility)
  • Instruction 8 → not-list (what this voice never does)

Test before committing: Read the persona out loud. Can you imagine an NPC responding to you from this profile? Would a speaker from this culture be clearly distinct from Van Maanen's Star if you heard both without labels?


Step 5: Author voice examples (20 minutes)

Write 3-5 (input, output) example pairs for the voice_examples array.

Input: A culture-neutral semantic description of an action (same as base text format) Output: That action rendered in the culture's voice

Example pairs are the model's pattern anchors — small LLMs are pattern matchers before instruction-followers. The examples matter as much as the instructions.

Rules for example pairs:

  1. Cover the range: neutral, positive relationship, refusal/deflection, high-affect
  2. Output should be short (1-2 sentences). Long outputs lose the pattern.
  3. Each output must be recognizably THIS culture — read them side by side with Van Maanen's Star examples. They should sound like different people.
  4. Do not use real NPC names in examples — use generic role references

Cross-cultural contrast test

Before finalizing examples, run this test. Take the same three base-text inputs and write outputs in Van Maanen's Star, Vael, and Osse voices. If the outputs are hard to distinguish, the culture persona needs sharpening.

Example inputs for the test:

  • "declines to answer a question about an overnight run"
  • "acknowledges a colleague's greeting while continuing to work"
  • "thanks a colleague for covering a shift"
Input Van Maanen's Star Vael Osse
Declines question "Look, that's not mine to say." "I'm not in a position to speak to that. You'd want to refer to the relevant operations log." "Not my section. Ask Grek."
Acknowledges greeting "Hey. Yeah. Catch you at shift end." "Harthen. Good. I'll be with you in a moment." "Doss. Yeah."
Thanks colleague "Appreciated. See you at handoff." "That was well handled. I've noted it." "Solid. Owe you one."

If all three rows sound similar, the culture personas need work.


Step 6: Author occasional injections (15 minutes)

occasional_injections are cultural vocabulary or speech patterns that should appear occasionally but not always — oath vocabulary, institutional references, equipment ground truth. The composition engine handles frequency; the author specifies what and when.

Fields:

  • kind — a string identifier (e.g., "oath", "protocol_cite", "equipment_ground")
  • clause — the LLM instruction when this injection fires
  • exampleSome((input, output)) showing correct usage, or None
  • frequency — float 0.01.0 (how often the composition engine fires this injection)
  • suppress_on_tells — tells that should suppress this injection (e.g., oath suppressed when Guarded)

Frequency guidelines:

  • 0.25 — Van Maanen's Star oath vocabulary (appears in ~1 in 4 high-affect contexts)
  • 0.20 — Vael protocol citation (appears occasionally in procedural exchange)
  • 0.15 — Osse equipment ground (appears in work-adjacent contexts)

Start with one injection per culture. More can be added after Spike validation confirms the base persona is clean.


Step 7: Author the tell-tone table (15 minutes)

Each culture profile should include a tell-tone table mapping each TellCategory to how that tell expresses in this culture's register. This table is not in the RON file — it's authoring documentation used when tell-context injectors are written.

Include this table in a comment block in the RON file header, or maintain it separately in the culture's authoring notes.

Format:

TellCategory How it reads in this culture
Nervous [culture-specific description]
Angry [culture-specific description]
Friendly [culture-specific description]
Guarded [culture-specific description]
RoutineDeviation [culture-specific description]

Design principle (from D-138): Humans are humans first. Universal baseline (phenomenon-class behavior) is always readable across cultures. Cultural flavor is conditional and additive — the LLM adds cultural texture only if it doesn't significantly change the information conveyed. Per-culture tell-tone tables are optional enrichment.


Step 8: Validate and commit

tooling/validate-ron content/global/culture-{id}.ron culture

A passing validation confirms:

  • All required fields are present and correctly typed
  • Trait names are valid enum values
  • RON syntax is correct

After validation, the culture profile is ready for Spike 1 prompt testing. Human review of voiced output is required before the culture goes into baked content.


Tell-tone reference tables

Van Maanen's Star tell-tone table

TellCategory Van Maanen's Star-inflected tonal register
Nervous Answers run shorter than usual. Eyes stay on task. Nothing's wrong — just things to do.
Guarded Direct past the point of directness. Closes conversation paths fast without being unfriendly.
Friendly One beat more than the exchange needed. A word of warmth lands casually, not performed.
Angry Steady. Even. The kind of steady that takes effort. Not hostile — just flat in a way that doesn't feel natural for Van Maanen's Star.
RoutineDeviation Unhurried. Unremarkably normal. Like nothing's worth noticing.

Vael tell-tone table

TellCategory Vael-inflected tonal register
Nervous Sentences become over-complete — more formal than the situation warrants. Qualifications multiply. "As I understand it" appears where it wasn't needed.
Guarded Responses are brief and technically correct. Every question answered with only what was asked. Institutional framing appears even in informal exchange.
Friendly Slightly less formal than baseline — a given name used where a family name would normally appear. The exchange closes with a word of genuine regard.
Angry Register becomes precisely correct — almost pedantically so. The effort to maintain composure shows as over-precision.
RoutineDeviation Procedures are cited where they wouldn't normally be. A person who deviates from routine anchors to institutional language as cover.

Osse tell-tone table

TellCategory Osse-inflected tonal register
Nervous Words get shorter. Already-minimal speech contracts to one-word answers and physical acknowledgment. The silence between words lengthens.
Guarded Assessment framing appears: "Why do you need to know?" — stated or implied. Eye contact shifts from reading-the-room to reading-you specifically.
Friendly Slightly more than the exchange needed — an extra beat, an unrequested detail, a "good shift" that lands with more weight. Not warm, just more.
Angry Everything slows down. Deliberate. Responses accurate, closed, no opening for follow-up.
RoutineDeviation The opposite of nervous: unusually conversational. When someone is off-routine on purpose, they over-normalize by saying more than usual.

Checklist: culture profile complete?

  • Five parameters documented (Reach Position, Economic, Age, Heritage Root, Institutions)
  • Register statement authored and distinctive
  • 25+ given names, 15+ family names, phoneme pattern consistent
  • family_name_used_socially accurately reflects the culture
  • Voice persona: 8 numbered instructions, ~200-250 tokens
  • Explicit NEVER: block at end of persona string (separate from numbered instructions)
  • NEVER block content is culture-specific (not repeating universal constraints)
  • Cross-cultural contrast test passed (Van Maanen's Star/Vael/Osse comparison)
  • 3-5 voice examples authored, range covered
  • At least 1 occasional injection with suppression logic
  • Tell-tone table authored (5 TellCategories)
  • tooling/validate-ron content/global/culture-{id}.ron culture passes


Addendum: Behavior Modifiers (#634)

Added Sprint 26. Applies to all culture files after the composable behavior engine (#633) ships.

What behavior_modifiers does

The composable behavior engine assembles observable behavior strings from two parts:

BehaviorPrimitive.action  +  BehaviorModifier.clause  →  assembled behavior string

Example:

  • Action: "moves freight containers"
  • Modifier: "without wasted motion" (Van Maanen's Star, work_pace)
  • Result: "moves freight containers without wasted motion"

A culture provides a pool of modifier clauses. When the engine assembles a behavior, it looks for a modifier whose category matches the primitive's modifier_hint string. If no match exists, it falls back to any modifier in the pool. If no modifiers exist at all, the action text is used as-is.

Modifier clauses must grammatically trail any action text. They are appended with a space. Test by mentally substituting different action verbs: does the clause still read naturally?

BehaviorContext: when to use each tag

Every BehaviorPrimitive carries a context field that gates when it is eligible for selection. The composition engine filters by context before modifier selection.

Context Use for Example action
OnShift Physical task execution, work-site behaviors, role-specific routines "checks a manifest against a handheld scanner", "guides a freight container into position"
OffDuty Break-room behaviors, personal downtime, non-work physical states "slumps into a break room chair and stares at nothing", "unwraps a meal packet standing at the counter"
Social Social-site behaviors (bars, cantinas, communal spaces) — may overlap with OffDuty but specifically at a social venue "nurses a drink at the end of the bar", "trades short words with a neighbor"
Any Behaviors valid in any context — ambient, universal physical states "rubs the back of their neck", "pauses and looks at nothing for a moment"

Decision rule:

  • If the behavior only makes sense on a work site → OnShift
  • If the behavior only makes sense in a break room or personal space → OffDuty
  • If the behavior specifically happens at a social venue → Social
  • If the behavior could appear anywhere → Any
  • When unsure, prefer Any over a specific context — you can always narrow later

Modifier category vocabulary (the contract)

These seven categories define the interface between primitives (Mellanie, role-action templates) and modifiers (culture authors). A primitive's modifier_hint must use one of these strings for a culture modifier to match it.

Category What it inflects Example modifier (Van Maanen's Star)
work_pace Speed and intensity of physical task execution "without wasted motion"
physical_manner Body language and movement quality during tasks "without looking up from the task"
social_signal Brief acknowledgments made during or between tasks "with a short nod"
task_completion How tasks are finished, wrapped up, or handed off "and moves on"
environmental_scan Awareness or vigilance while in a space "with one eye still on the floor"
offduty_posture Body language and social stance when off-shift "without making a show of it"
authority_response Behavior when supervisors or authority figures are present "at the same pace as before"

The fallback is safe but less targeted. A primitive with no modifier_hint gets a random modifier from the full culture pool. This still produces culturally inflected output — just without category precision. Prefer leaving modifier_hint unset over using an incorrect category string.

Authoring behavior_modifiers for a new culture

Minimum: 2 modifiers for each of the 7 categories = 14 modifiers total. Fewer categories will still work (fallback to any), but full coverage ensures every action type gets the right cultural texture.

Process:

  1. For each category, ask: How does this culture DISTINCTIVELY express this dimension?
    • Not "how does any person do this" but "what is the cultural tell for this culture specifically?"
  2. Write the clause as a short trailing phrase (4-8 words). Test: does it read naturally after "moves freight containers ___"?
  3. Avoid clauses that are too action-specific — they need to trail any verb, not just one type
  4. Run tooling/validate-ron content/global/culture-{id}.ron culture to confirm syntax

Three-culture contrast for modifiers (same as voice persona contrast test):

Category Van Maanen's Star Vael Osse
work_pace "without wasted motion" "with practiced deliberation" "at extraction pace"
physical_manner "without ceremony" "with institutional correctness" "tool already in hand"
social_signal "with a short nod" "with a measured acknowledgment" "with a word or a look"
task_completion "and moves on" "with the relevant entry already updated" "gear stowed before moving on"
environmental_scan "with one eye still on the floor" "aware of who is observing" "pressure and exits both in range"
offduty_posture "without making a show of it" "maintaining composed reserve" "with one ear still on the work floor"
authority_response "at the same pace as before" "with appropriate professional deference" "without a change in pace"

If your new culture's modifiers would fit in any of the existing columns above without sounding different — the culture needs more work before modifiers are authored.

Updated checklist

Add these items to the culture profile checklist:

  • behavior_modifiers array populated with at least 2 clauses per category (14 minimum)
  • Each clause tested: grammatically trails "moves freight containers ___" and "checks a manifest ___"
  • Three-culture contrast check: modifiers are clearly distinct from Van Maanen's Star, Vael, and Osse
  • tooling/validate-ron still passes after adding modifiers

Addendum: Sprint 26, #634 (composable behavior content). Category vocabulary established jointly by Gestalt (culture modifiers) and Mellanie (behavior primitives). Add new categories only by agreement between both sides — unmatched categories silently fall back to any modifier.