--- title: "Content Structure — Canonical Template (v0.2+)" description: "Post-cleanup canonical directory layout for campaign content, superseding v0.1 content-directory-structure" type: design status: active ticket: "#656" decision_refs: [D-117, D-138] author: "" created: 2026-03-13 updated: 2026-03-13 --- # Content Structure — Canonical Template (v0.2+) **Created:** 2026-03-13 (Sprint 26, #656 cleanup) **Supersedes:** `content-directory-structure.md` v0.1 design spec (that doc describes the *removed* structure) This document defines the canonical directory layout for campaign content after removal of v0.1 hand-authored dead weight. It is the template to replicate across 300 systems. --- ## Actual Directory Hierarchy The real hierarchy (note: diverges from old design doc which used `content/districts/`): ``` content/ global/ # Cross-system content culture-{name}.ron # Voice pipeline persona (LIVE GENERATOR INPUT) culture-{name}.example.ron # Example output for reference zone-identity-spec.example.ron # Zone identity template example factions/ # Faction profiles (one per faction) knowledge/ # Shared FactId catalog (one per category) enums/ # Shared enum definitions contraband/ # Contraband item profiles technology/ # Technology definitions campaigns/ main/ systems/ {system-slug}/ # e.g. van-maanens-star/ system.yaml # System metadata stations/ {station-slug}/ # e.g. sova/ station.yaml # Station metadata districts/ {district-slug}/ # e.g. transit/ district.yaml # Zone metadata (CANONICAL METADATA) locations/ # Physical location definitions templates/ # Social site role-slot definitions triangles/ # Drama triangles (3-NPC clusters) environmental/ # Environmental text (signs, terminals, docs) routines/ # NPC schedule definitions ticker/ # News ticker content modules/ tier1/ # Tier 1 drama modules (authored) {module-slug}.yaml gauntlet/ # Test world (immutable — do not modify) rooms/ _schema/ # JSON Schema validation files _meta/ # Infrastructure metadata schemas/ # (additional schemas) ``` --- ## What Each Piece Is | Path | Type | Who produces it | Notes | |------|------|-----------------|-------| | `global/culture-{name}.ron` | **Generator input** (authored) | Copy team | Voice pipeline persona. One per culture. DO NOT DELETE. | | `global/factions/*.yaml` | **Authored** | Copy team | Faction profiles. One per faction. | | `global/knowledge/*.yaml` | **Authored** | Copy team | FactId catalog by category. | | `global/enums/*.yaml` | **Authored** | Copy team | Shared enum definitions (situations, moods, etc.) | | `system.yaml` | **Metadata** | Copy team | System display name, factions present, setting notes. | | `station.yaml` | **Metadata** | Copy team | Station description, district list. | | `district.yaml` | **Metadata** | Copy team | Zone display name, location list, target NPC count. | | `locations/*.yaml` | **Metadata** | Copy team | One file per location: display name, description, type. | | `templates/*.yaml` | **Authored** | Copy team | Role slot definitions (what roles exist, capacity range). Survives to v0.2+. The `v01_assignments` field is v0.1-only — clear for generated content. | | `triangles/*.yaml` | **Authored** | Copy team | Drama triangles with fork conditions and resolution states. Template material for generated equivalents. | | `environmental/*.yaml` | **Authored** | Copy team | Environmental text objects with optional dual-lens properties (v0.1 remains). | | `routines/schedules.yaml` | **Authored** | Copy team | NPC daily routines. Will be generated per-NPC in v0.2+. | | `ticker/*.yaml` | **Authored** | Copy team | News ticker content for this district. | | `modules/tier1/*.yaml` | **Authored** | Copy team | Drama modules (Paula's schema). | --- ## What Was Removed (v0.1 Dead Weight) These directories and files existed in v0.1 and have been deleted (Sprint 26, #656/#657): | Removed | Reason | |---------|--------| | `npcs/*.yaml` | Hand-authored named NPC profiles. Replaced by generator output. All 23 files deleted. | | `dialogue/` | Hand-authored NPC dialogue pools per role/location. Replaced by voice pipeline. | | `monologue/detective/` | Detective player monologue. Detective archetype removed per D-117. | | `monologue/smuggler/` | Smuggler player monologue. Smuggler archetype removed per D-117. | | `insert/detective.yaml` | Detective insert HUD content. | | `insert/smuggler.yaml` | Smuggler insert HUD content. | | `items/smuggler-inventory.yaml` | Smuggler item definitions. | | `pools.yaml` | v0.1 NPC candidate pool definitions. All candidates referenced deleted NPCs. | | `content/global/knowledge/investigation.yaml` | Investigation facts. Detective system removed. (Deleted in #657.) | | `content/global/factions/lattice-commission.yaml` | Detective faction. (Deleted in #657.) | | Several `docs/design/` detective/smuggler docs | Archetype design docs. (Deleted in #657.) | --- ## Canonical Template: New System Checklist When adding a new system for v0.2+ (target: 300 systems), replicate this pattern: ``` content/campaigns/main/systems/{system-slug}/ system.yaml # 1. Author system metadata stations/ {station-slug}/ station.yaml # 2. Author station metadata districts/ {district-slug}/ district.yaml # 3. Author district metadata locations/ # 4. Define locations (5-10 per district) {location-slug}.yaml templates/ # 5. Define social site templates (role slots) {template-slug}.yaml routines/ # 6. Author schedule structure schedules.yaml # (v0.2: generated per NPC) ticker/ # 7. Author news ticker content {location-slug}.yaml ``` **Note:** `environmental/` and `triangles/` are authored for hand-crafted districts. For generated districts, these may be generated or omitted in v0.2+. **No NPCs.** No dialogue. No monologue. Those are generator outputs, not authored inputs. --- ## Culture RON File Reference Culture files are the primary input for the voice pipeline. One file per culture, living at `content/global/culture-{name}.ron`. **Use `content/global/culture-van-maanens-star.ron` as the authoring template — not `culture-van-maanens-star.example.ron`.** The example file is an older stub without voice pipeline fields. ### Required fields (must be present) ``` id: "slug" # kebab-case, matches filename name: "Display Name Culture" description: "Single sentence: settlement age, location type, economic base, social character" naming: ( style: # prose: phoneme style, casing norms given_names: [...] # 30-50 names minimum for adequate generator variety family_names: [...] # 10-20 names family_name_used_socially: bool ) speech: ( register: # prose: formality, rhythm, directness filler_words: [...] # 4-8 words greetings: [...] # 3-6 phrases farewells: [...] # 3-6 phrases exclamations: [...] # 4-8 oath/exclamation phrases ) values: ( description: # prose: core value system favored_traits: [...] # subset of valid traits (see below) disfavored_traits: [...] # subset of valid traits ) ``` ### Optional fields (omit or include as needed) ``` voice_persona: Some("PERSONA: ...") # Full LLM prompt persona block voice_examples: [ # 3-5 input/output pairs (input: "...", output: "..."), ] occasional_injections: [ # Rolled per-prompt at given frequency ( kind: "oath" # human-readable category label clause: "When ... use ...", # LLM instruction text example: Some((input: "...", output: "...")), # optional frequency: 0.25, # 0.0–1.0 suppress_on_tells: [Guarded], # optional: omit injection when these tells active ), ] behavior_modifiers: [ # Culture-specific action modifier clauses (#633) (category: "work_style", clause: "with mechanical efficiency"), ] ``` ### Valid enum values **PersonalityTrait** (for `favored_traits` / `disfavored_traits`): `Cautious, Bold, Honest, Deceptive, Compassionate, Ruthless, Curious, Incurious, Social, Reclusive` **TellCategory** (for `suppress_on_tells`): `Nervous, Angry, Friendly, Guarded, RoutineDeviation` ### voice_persona: NOT-list requirement (D-138, Spike 2) Spike 2 found that **explicit NOT-lists in the persona block are critical** for voice quality. Without them, the LLM defaults to register-neutral generic output. Add an explicit "NEVER:" or "NOT:" section at the end of the persona block: ``` voice_persona: Some( "PERSONA: ...\n [positive instructions]\n\n NEVER: [list 3-5 explicit negatives that define what this culture does NOT sound like]" ), ``` Example negatives for Van Maanen's Star (currently explicit in `culture-van-maanens-star.ron`): - Never corporate or institutional language - Never effusive, never polished, never deferential to rank - Never flowery or verbose - Never use family names in casual conversation - Never express deference to authority that hasn't earned it `culture-van-maanens-star.ron` has a full NEVER block in `voice_persona`. All three culture files (Van Maanen's Star, Vael, Osse) now include explicit NOT-lists. *(Updated Sprint 26 #653)* ### behavior_modifiers: status All culture files (`culture-van-maanens-star.ron`, `culture-vael.ron`, `culture-osse.ron`) now populate `behavior_modifiers` with 11-12 clauses across all seven hint categories (`work_pace`, `physical_manner`, `social_signal`, `task_completion`, `environmental_scan`, `offduty_posture`, `authority_response`). The decomposed behavior system (#633/#634) shipped in Sprint 26. New culture files must populate this field. *(Updated Sprint 26 #634)* --- ## Scale Readiness Audit ### Passes at 300 systems | Structure | Ready | Notes | |-----------|-------|-------| | `content/campaigns/main/systems/` | Yes | One directory per system. No monolithic files. | | `content/global/factions/` | Yes | One file per faction — will grow to ~20-50 factions across 300 systems | | `content/global/knowledge/` | Mostly | Knowledge catalog is organized by category, not by system. Flat list works to ~500 facts. | | `content/global/culture-{name}.ron` | Yes | One file per culture (expected ~10-20 cultures total). | | `templates/*.yaml` | Yes | Role slot definitions are reusable across systems of the same type. | | `modules/tier1/` | Yes | Flat directory. Drama modules are self-contained. | ### Needs attention at scale | Structure | Issue | Recommendation | |-----------|-------|----------------| | `content/global/knowledge/investigation.yaml` | **Deleted** — was detective-system-only. Other knowledge files need review for detective/smuggler references. | Audit surviving knowledge files post-#657. | | `environmental/*.yaml` | Has v0.1 `dual_lens` (smuggler/detective) properties in the terminal/bar/corridors files. These are dead properties once archtypes are removed. | Flag to client team — strip `dual_lens` field from environmental schema for v0.2. | | `templates/` v01_assignments | Fields reference deleted named NPCs. Not validated but stale. | Remove `v01_assignments` and `reference_links` from templates when generating v0.2+ content. | | `triangles/` members | Reference deleted named NPCs (e.g., `npc:voss`, `npc:kael-davan`). These are unresolvable after NPC deletion. | These triangles are v0.1 examples. Either delete or annotate as templates for generated equivalents. |