diff --git a/decisions/README.md b/decisions/README.md index f9dad28af..116587353 100644 --- a/decisions/README.md +++ b/decisions/README.md @@ -12,7 +12,7 @@ Cross-domain decisions live in one file with cross-reference notes in related fi |------|--------|-----------| | [architecture.md](architecture.md) | Technical foundation | D-008, D-009, D-010, D-012, D-020, D-026, D-030, D-031, D-041, D-042, D-054, D-055, D-066, D-068, D-073, D-085, D-088, D-094, D-096, D-097, D-099, D-100, D-101, D-102, D-103, D-106, D-108, D-109, D-113, D-133, D-134, D-135, D-136, D-137 | | [perception.md](perception.md) | Player observation | D-011, D-015, D-016, D-017, D-018, D-019, D-033, D-035, D-043, D-044, D-045, D-046, D-047, D-048, D-049, D-052, D-056, D-057, D-058, D-059, D-060, D-061, D-067, D-069, D-070, D-071, D-072, D-076, D-077, D-078, D-086 | -| [content.md](content.md) | NPC, dialogue, templates | D-023, D-024, D-025, D-028, D-029, D-032, D-034, D-035, D-036, D-037, D-050, D-062, D-063, D-064, D-074, D-075, D-084, D-090, D-092, D-093, D-095, D-098, D-104, D-105, D-107, D-121, D-122, D-123, D-124, D-125, D-126, D-127, D-128, D-129, D-130, D-131, D-132, D-138 | +| [content.md](content.md) | NPC, dialogue, templates | D-023, D-024, D-025, D-028, D-029, D-032, D-034, D-035, D-036, D-037, D-050, D-062, D-063, D-064, D-074, D-075, D-084, D-090, D-092, D-093, D-095, D-098, D-104, D-105, D-107, D-121, D-122, D-123, D-124, D-125, D-126, D-127, D-128, D-129, D-130, D-131, D-132, D-138, D-139, D-140, D-142 | | [scope.md](scope.md) | Game concept, prototype | D-001, D-003, D-005, D-006, D-007, D-013, D-014, D-027, D-038, D-039, D-051, D-053, D-065, D-087, D-089, D-091, D-114, D-115, D-116, D-117, D-118, D-119, D-120 | | [process.md](process.md) | Team, workflow | D-004, D-021, D-022, D-040 | | [questions.md](questions.md) | Open questions (index) | Q-001 through Q-054 | diff --git a/decisions/content.md b/decisions/content.md index e676afe82..e1e47ccac 100644 --- a/decisions/content.md +++ b/decisions/content.md @@ -325,8 +325,9 @@ How narrative, NPCs, and world content are created: content tiers, NPC generatio - **Source:** Where's the Fun? Workshop (original); LLM Voice Pipeline Workshop (amendment) - **Raised by:** Team Leader (Jeroen) - **Dissent:** None on amendment +- **Amendment attribution:** The two-mode distinction (build-time authoring tool vs. runtime background enhancement) and the six dialogue re-voicing quality constraints are Paula's contribution from LLM Voice Pipeline Workshop Round 3. The two-mode framing is the organizing principle: build-time mode inherits the original D-123 safety model (human review); runtime mode operates under a different safety model (three-layer fallback) that was validated in Spikes 1 and 2. - **Amended by:** [D-138](#d-138-llm-re-voicing-pipeline-for-npc-voice) (LLM Voice Pipeline Workshop, 2026-03-07) -- **Cross-reference:** [D-121](#d-121-voice-is-culture-driven--job-as-modifier) (culture-primary voice), [D-128](#d-128-culture-implicit-in-starting-location--krenn-system-equals-krenn-culture) (culture profile as generator input) +- **Cross-reference:** [D-121](#d-121-voice-is-culture-driven--job-as-modifier) (culture-primary voice), [D-128](#d-128-culture-implicit-in-starting-location--krenn-system-equals-krenn-culture) (culture profile as generator input), [D-140](#d-140-dialogue-re-voicing-quality-constraints--paulas-six-rules) (dialogue re-voicing quality constraints) ### D-124: In-game ollama for live NPC dialogue — ~~deferred~~ SUPERSEDED by D-138 - **Date:** 2026-03-05 @@ -411,7 +412,7 @@ How narrative, NPCs, and world content are created: content tiers, NPC generatio - **Date:** 2026-03-07 - **Decision:** NPC observable behaviors and dialogue are processed through an LLM re-voicing pipeline that translates culture-neutral semantic base text into character-voiced output. The pipeline is a background runtime enhancement, not a live generation system. Tell behaviors are base-text passthrough — always. Active tell state influences the re-voicing prompt for surrounding content (tells are read-only inputs to the LLM, never LLM outputs). The game is complete and functional without the pipeline; it is an enhancement that elevates voice quality for players with sufficient hardware. - **Architecture:** - - **Model:** Gemma 2 2B IT Q4_K_M (~1.6GB), bundled as `server/models/gemma2.gguf`. No fallback model. *(Amended 2026-03-07: Phi-3 dropped entirely after Spike 1 — Gemma 2B produces superior culturally-differentiated output at the same quantization. Original GGUF: `gemma-2-2b-it-Q4_K_M.gguf` from Hugging Face bartowski/gemma-2-2b-it-GGUF.)* + - **Model:** Gemma 2 2B IT Q4_K_M (~1.6GB), bundled as `server/models/gemma2.gguf`. No fallback model. *(Amended 2026-03-07: Phi-3 dropped entirely after Spike 1 — Gemma 2B produces superior culturally-differentiated output at the same quantization. Original GGUF: `gemma-2-2b-it-Q4_K_M.gguf` from Hugging Face bartowski/gemma-2-2b-it-GGUF.)* **Model provenance policy (Jeroen, 2026-03-07):** Chinese-origin models (Qwen/Alibaba and equivalents) are excluded. Preference: Google (Gemma) primary, Microsoft (Phi) as fallback class. Constraint applies to any future model change — if benchmarks require a different model, this provenance policy is re-checked first. Apache 2.0 or MIT license required. - **Runtime:** `llama-cpp-rs` with GGUF format. Separate inference thread pool at below-normal priority. *(Amended 2026-03-07, Spike 2: IPC is stdin/stdout JSONL pipes, not HTTP. Each worker owns a piped `sr-voice` child process — no network ports. This satisfies Gemma 2 Terms & Conditions: model is only reachable through the game server's queue, never exposed as a service.)* - **Content tiers:** Baked (hub zones, build-time, human-reviewed) → Pre-voiced (background queue, priority-ordered) → Base text fallback (always present). - **Tell treatment:** Passthrough always. Tell state flows into re-voicing prompts as universal tone injectors. Cultural flavor is conditional and additive — humans are humans first; micro-expressions and body language must remain universally recognizable. Per-culture tell-tone tables are optional enrichment, not a launch requirement. *(Amended 2026-03-07, Spike 2: Tell differentiation at 2B — 3/5 tells produce distinguishable output (Nervous, Guarded, Angry). Friendly and RoutineDeviation are inert at 2B capacity — model cannot reliably differentiate them from neutral. Deferred to post-ship or larger model. Angry tell requires length-aware injectors: short/medium content gets standard compression, long content (≥16 words) gets an explicit "keep full claim intact" instruction to prevent destructive information loss.)* @@ -431,7 +432,7 @@ How narrative, NPCs, and world content are created: content tiers, NPC generatio - **Amends:** [D-123](#d-123-generative-ai-for-npc-content--build-time-authoring-tool-and-runtime-voice-pipeline) (scope extended from authoring tool to authoring + runtime) - **Supersedes:** [D-124](#d-124-in-game-ollama-for-live-npc-dialogue--deferred-superseded-by-d-138) (in-game AI no longer deferred) - **Resolves:** Q-057 (composable behavior generation), Q-012 (generation expansion method) -- **Cross-reference:** [D-010](architecture.md#d-010) (information boundaries), [D-121](#d-121-voice-is-culture-driven--job-as-modifier) (culture-primary voice), [D-122](#d-122-all-npcs-generated--named-npcs-deferred) (all NPCs generated), [D-128](#d-128-culture-implicit-in-starting-location--krenn-system-equals-krenn-culture) (culture as generator input), [D-029](#d-029-population-entanglement-ratio--305020) (NPC tier model), [D-092](perception.md#d-092) (anchor lines) +- **Cross-reference:** [D-010](architecture.md#d-010) (information boundaries), [D-121](#d-121-voice-is-culture-driven--job-as-modifier) (culture-primary voice), [D-122](#d-122-all-npcs-generated--named-npcs-deferred) (all NPCs generated), [D-128](#d-128-culture-implicit-in-starting-location--krenn-system-equals-krenn-culture) (culture as generator input), [D-029](#d-029-population-entanglement-ratio--305020) (NPC tier model), [D-092](perception.md#d-092) (anchor lines), [D-140](#d-140-dialogue-re-voicing-quality-constraints--paulas-six-rules) (dialogue re-voicing quality constraints) ### D-139: Composable behavior primitives — three-layer assembly model - **Date:** 2026-03-13 @@ -448,6 +449,78 @@ How narrative, NPCs, and world content are created: content tiers, NPC generatio - **Resolves:** Q-057 (composable behavior generation — data structure definition) - **Cross-reference:** [D-138](#d-138-llm-re-voicing-pipeline-for-npc-voice) (resolved pipeline, this resolves data format), [D-121](#d-121-voice-is-culture-driven--job-as-modifier) (culture-primary voice), [D-122](#d-122-all-npcs-generated--named-npcs-deferred) (all NPCs generated) +### D-140: Dialogue re-voicing quality constraints — Paula's six rules +- **Date:** 2026-03-13 +- **Decision:** Six binding constraints govern the LLM re-voicing queue for all dialogue lines. These rules protect the information asymmetry mechanic (D-005), character voice integrity, and game narrative legibility. They are implemented in the prompt engineering layer and validated in baked content review. + - **D-140-R1 — Secret-tier passthrough:** Lines tagged `trust: secret` (D-028 Layer 3) never enter the re-voicing queue. They are served as authored base text unconditionally. Re-voicing risks dramatization (inflating the disclosure) or trivialization (flattening the weight of the secret) — both failures corrupt the earned relationship payload. + - **D-140-R2 — Epistemic weight must not shift:** Certainty level of factual claims must survive re-voicing unchanged. Hedge words ("I think," "I heard," "might be," "probably") and direct evidential markers ("I saw," "I was there," "he told me") must appear in re-voiced output with the same epistemic force as in the base text. Epistemic drift is the dialogue re-voicing failure mode most invisible to reviewers and most damaging to gameplay — the player reads voiced text and constructs a knowledge model. A shifted hedge changes what the player knows. + - **D-140-R3 — Access tier feel must be preserved:** The social register appropriate to the D-028 access tier tag must survive re-voicing. `public` stays neutral-transactional; `peer` stays lateral-relaxed; `insider` stays familiar-complicit; `authority` stays institutional-asymmetric; `hostile` stays minimal-closed. The tag governs eligibility; the register governs feel. An `insider` line re-voiced into institutional language reads as `authority` to the player regardless of tag. Implementation: access tier injected as a constraint clause alongside the culture injector. + - **D-140-R4 — Named entities are passthrough within output:** Any proper noun in the base text (NPC names, location names, faction names, technology terms) must appear verbatim in the re-voiced output. Named entities carry specific information — "Kael" and "that dock worker" are not interchangeable in an information-asymmetry game. Implementation: extraction step before re-voicing; protected entity list injected as a hard constraint. The extractor need not understand lore — capitalized terms are sufficient for identification. + - **D-140-R5 — Relationship-specific lines are passthrough:** Any dialogue line naming a specific third-party NPC or describing a specific interpersonal event is not re-voiced. It is served as authored base text. These lines carry social information whose phrasing is load-bearing — the hesitation, the neutral delivery, the precise ambiguity are all authored intentionally. Re-voicing risks substituting the named NPC with a reference, dramatizing the event, or adding social judgment not in the original. + - **D-140-R6 — Tell-context modifier cannot override culture register:** When a tell-context injector is active, it shapes emotional inflection within the culture register — it does not replace the register. A Krenn NPC with a Nervous tell still speaks in Krenn register (direct, minimal pleasantries, working-class pragmatic) while the content reflects nervous pressure. Culture is primary (D-121); tell-context is situational. Implementation: culture injector is always applied before tell-context modifier; tell-context is framed as inflection, not override. +- **Rationale:** D-138 established the architecture; these rules operationalize the quality floor for dialogue content specifically. Dialogue re-voicing carries higher information risk than behavior re-voicing — dialogue is direct player-NPC exchange where epistemic signals and relationship registers matter most. These rules scale with the pipeline: at 300 systems and thousands of NPCs, the prompt engineering layer must enforce these constraints programmatically, not through per-line human review. The constraints are formalized here so server team, copy team, and QA can reference them independently. +- **Scaling note:** R4 (named entity extraction) requires a proper noun tagger that works across all culture naming conventions — Krenn names differ structurally from other cultures. The extractor approach (capitalized terms as proxy) is sufficient for the Krenn launch system but must be culture-aware for systems with non-capitalized or logographic naming conventions. This is a DLC-scope concern, not a v0.2 blocker. +- **Source:** LLM Voice Pipeline Workshop (2026-03-07), Paula Round 3 (`docs/workshops/llm-voice-pipeline/paula-round3.md`) +- **Raised by:** Paula (LLM Voice Pipeline Workshop, Round 3) +- **Dissent:** None +- **Cross-reference:** [D-123](#d-123-generative-ai-for-npc-content--build-time-authoring-tool-and-runtime-voice-pipeline) (pipeline modes), [D-138](#d-138-llm-re-voicing-pipeline-for-npc-voice) (full architecture), [D-028](#d-028-four-relational-dialogue-layers) (access tier model), [D-005](scope.md#d-005-core-concept---single-character-first-person-story-generator) (single character, information asymmetry as core), [D-092](perception.md#d-092) (anchor lines) + +### D-142: Zone-type template architecture for scalable NPC behavior +- **Date:** 2026-03-13 +- **Decision:** Behavior primitives are zone-type-generic, not per-location. The content architecture for NPC behavior across 300+ systems is a three-layer composition model: + + **Layer 1 — Zone-type primitives (what the body does):** Universal physical stage directions per role, defined at the zone-type level. A `farmer` role in a `rural_agricultural` zone does the same base actions in any system. Primitives are authored once per role per zone type. They are context-tagged (`OnShift`, `OffDuty`, `Social`) and carry an optional `modifier_hint` for category-matched culture assembly. + + **Layer 2 — Culture modifiers (how this culture does it):** Clauses appended to primitives at assembly time, defined on `CultureProfile`. Seven categories: `work_pace`, `physical_manner`, `social_signal`, `task_completion`, `environmental_scan`, `offduty_posture`, `authority_response`. Culture modifiers are authored once per culture, work with all zone types immediately. + + **Layer 3 — Gemma LLM flavor (what's happening here and now):** Runtime enrichment only. Adds location-specific sensory and environmental detail: weather, time of day, lighting, ambient sound, physical environment state. Layer 3 is **culture-neutral** — it must not introduce cultural vocabulary, must not generate named entities, must not override culture register (D-140-R6), must not alter epistemic markers (D-140-R2). Layer 3 follows the pre-voiced three-layer safety model from D-138 (base-text fallback on failure, validated injector vocabulary, contamination filter for named entities). If Layer 3 fails or is unavailable, the Layer 1+2 assembly is served as-is. + + **Standalone readability constraint:** Layer 1+2 assembly (base text) must be playable and informative without the LLM. A player reading base text must be able to read what an NPC is doing. "Works a crop row, stopping to pull weeds, without wasted motion" is informative; "farms" is not. This constraint governs primitive authoring across all zone types. + + **Location spec format:** Location files (`content/locations/{system}-{zone}.ron`) declare a `zone_type` identifier and reference a `culture`. They carry metadata (economic_level, population_density, role weights, social sites) but contain **no primitives**. All behavior content lives at the zone-type and culture layers. + +- **Zone-type taxonomy (31 types, v1.0):** The following zone types constitute the canonical behavior template library. Each produces a distinct NPC behavior pool and distinct map generator layout template. Zone types sharing a group prefix differ enough in physical layout to require separate templates. + + | Group | Zone Types | + |-------|-----------| + | Rural | `rural_agricultural`, `rural_pastoral`, `rural_aquaculture`, `rural_orbital` | + | Industrial | `industrial_freight`, `industrial_manufacturing`, `industrial_processing` | + | Port | `port_space`, `port_surface`, `port_maritime`, `port_fishing` | + | Extraction | `extraction_space`, `extraction_surface`, `extraction_platform` | + | Commercial | `commercial_market`, `commercial_transit` | + | Administrative | `administrative_civil`, `administrative_judicial` | + | Single | `research_station`, `medical_facility`, `military_garrison`, `security_checkpoint`, `entertainment_hospitality`, `entertainment_venue`, `residential_station`, `residential_surface`, `residential_dispersed`, `detention_facility`, `archaeological_site`, `wilderness_frontier`, `diplomatic_elite` | + + Subtype distinctions within groups are map-generator-significant: a `port_space` (docking bays, airlocks, approach corridors) generates a physically different layout from `port_maritime` (piers, wharves, waterfront) or `port_fishing` (jetties, small craft, catch processing), and the NPC actions differ accordingly. + +- **POI system (three-tier):** Points of interest that create narrative destinations (monuments, gatebuilder ruins, prisons, pilgrimage sites, abandoned installations) are handled at three levels without requiring new zone types for each: + + *Tier 1 — POI-as-zone-type:* Sites large enough to have distinct layout, NPC population, and behavior pool are zone types. `archaeological_site` and `detention_facility` are in the canonical 31. Additional large POI zone types can be added as content permits. + + *Tier 2 — `abandoned` flag:* Any zone type can carry `abandoned: true` on its location spec. The map generator produces a decay variant of the base layout; the behavior pool switches to a cross-cutting scavenger/squatter/investigator primitive set. This generates abandoned station variants, ruined industrial facilities, collapsed residential blocks, and derelict extraction rigs without pre-authoring each as a separate zone type. + + *Tier 3 — `poi_overlay` field:* Small POIs (monuments, memorials, commemorative markers, shrines, public art) exist within an existing zone rather than as their own map. The location spec carries a `poi_overlay` list; the map generator places overlay elements within the zone layout. No new behavior pool required. + + The combination handles the full POI design space: `gatebuilder_ruin` = `archaeological_site` zone type; `abandoned_station` = any station zone type + `abandoned: true`; `monument` = `poi_overlay` on a `commercial_transit` or `residential_surface` zone; `pilgrimage_site` = `poi_overlay` cluster on appropriate base zone, or its own zone type if narrative scale warrants. + +- **Scale math:** 31 zone types × ~4 roles × ~15 primitives = ~1,860 authored primitive lines. 300+ cultures × ~12 modifiers = ~3,600+ modifier clauses. ~5,500 authored lines produce behavior across unlimited locations. Authoring cost is O(zone_types + cultures), not O(locations). New location: pick zone type + culture + metadata — zero behavior authoring. New culture: ~12 modifiers + voice persona — works with all 31 zone types immediately. New zone type: ~60 primitives — works with all cultures immediately. + +- **File layout:** + - Zone-type templates: `content/global/zone-types/{zone_type}.ron` + - Culture profiles: `content/global/culture-{name}.ron` (existing) + - Location specs: `content/locations/{system}-{zone}.ron` (metadata only, no primitives) + +- **Rationale:** The per-location primitive model (current `typical_behaviors` and per-location `behavior_primitives` arrays) does not scale to 300 systems. A Krenn farmer and a Vael farmer doing the same physical work in the same zone type are authoring the same primitives twice — the content that differs between them is the *how* (culture), not the *what* (the physical action). Separating these dimensions reduces authoring cost by an order of magnitude and ensures that adding a new system is a metadata operation, not a content sprint. The standalone readability constraint ensures the system degrades gracefully when the LLM is unavailable, which is a runtime reliability requirement for a 300-system game, not just a fallback policy. + +- **Layer 3 grammar constraint:** When Gemma appends environmental flavor to Layer 1+2 assembled text, the flavor clause must grammatically attach as a prepositional phrase or coordinating conjunction. Absolute and participial phrases (e.g., "tool already in hand") require a leading comma separator. Culture-specific modifier clauses that use absolute-phrase construction must include the separator (e.g., ", tool already in hand") or be rewritten as prepositional form ("with tool in hand") to ensure clean assembly. This constraint applies to all culture profile modifier authoring. + +- **Source:** Sprint 26 zone-type taxonomy discussion (2026-03-13); behavior review (#634); user requirements for 300-system scalability +- **Raised by:** Paula (zone-type taxonomy and POI system); Gestalt (assembly engine); Mellanie (primitive content); Tyre (architectural review) +- **Dissent:** None +- **Supersedes:** Per-location behavior pool approach from current zone spec format (`behavior_primitives` arrays on location RON files). Location files retain metadata but behavior content migrates to zone-type template files. +- **Amends:** [D-139](#d-139-composable-behavior-primitives-three-layer-assembly) — D-139 defined the assembly mechanics (BehaviorPrimitive, BehaviorModifier, assemble_behaviors); this decision defines the content architecture that feeds it. D-139 remains the implementation record; D-142 is the content architecture record. +- **Cross-reference:** [D-138](#d-138-llm-re-voicing-pipeline-for-npc-voice) (LLM pipeline — Layer 3 safety model), [D-140](#d-140-dialogue-re-voicing-quality-constraints--paulas-six-rules) (quality constraints — R4, R6 apply to Layer 3), [D-139](#d-139-composable-behavior-primitives-three-layer-assembly) (assembly mechanics), [D-121](#d-121-voice-is-culture-driven--job-as-modifier) (culture-primary voice), [D-036](#d-036-sova-transit-district--krenn-system-setting) (Krenn setting origin of first zone specs), [D-128](#d-128-culture-is-implicit-in-starting-location) (culture implicit in location) + --- -*39 decisions. Last updated: 2026-03-13 (D-139 composable behavior primitives — Sprint 26 #633)* +*41 decisions. Last updated: 2026-03-13 (D-142 zone-type template architecture — Sprint 26; D-140 dialogue re-voicing quality constraints — Sprint 26 #647; D-139 composable behavior primitives — Sprint 26 #633)*