Files
settled-reach/docs/workshops/wiki-review/round4-tyre.md
T
jpmschweitzerandClaude Opus 4.6 0100b33635 docs(workshops): archive wiki review workshop (4 rounds + lead interview)
Long-term content strategy workshop: 300-world generator model,
cultural ingredients menu, three-system NPC architecture (9 patterns
x 6 motivations), Sacred/Profane/Middle Kingdom framework. 9 agents
across 4 rounds plus lead interview establishing the production path
from hand-authored Sova to generated 300 worlds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 16:18:56 +01:00

39 KiB
Raw Blame History

Round 4 — Tyre (Technical Architect)

Responding to the lead's direction. cracks knuckles — the 300-world reframe is architecturally transformative. Let me be honest about what this means technically: it doesn't just scale up my Round 3 proposals. It changes what the architecture IS.


The Architectural Pivot

Round 3 assumption: The simulation server loads authored content from a directory. The content directory is a repository of YAML files. The content loader is a 6-phase pipeline that reads files.

Round 4 reality: The simulation server generates most content at world-creation time from parameter spaces. The content directory is a generator input repository — style briefs, ingredient definitions, pool templates, constraint rules. The content loader becomes a content GENERATOR that produces district instances from parameters.

This is a fundamentally different architecture. Not harder — arguably more elegant. But different.

What stays the same (Sacred architecture)

These Round 3 proposals survive intact:

  • Client-server separation (D-010, D-020) — unchanged
  • Information boundaries — unchanged, possibly more important at scale since generated content must respect the same occlusion rules
  • Entity structure (bevy_ecs components) — unchanged, a generated NPC has the same components as an authored one
  • Tick processing — unchanged
  • Knowledge graph model (D-041) — unchanged
  • Simulation tiers (D-026) — unchanged, but the tier boundaries matter more: 300 worlds means the vast majority are State-saved or Ungenerated at any given time

What changes fundamentally

System Round 3 Round 4
Content directory Repository of authored YAML Generator input repository — parameter spaces, style briefs, pool definitions, constraint rules
Content loader 6-phase file reader Generation pipeline — takes parameters, produces district instances
Content addressing canonical_id pointing to files canonical_id pointing to either authored files OR generator output. Two-tier addressing: authored content has stable IDs, generated content has seed-derived IDs
Runtime content Loaded from disk, immutable per seed Generated at world-creation, cached to disk, immutable thereafter
Content validation Schema checks on authored YAML Schema checks PLUS generator output validation PLUS quality gates
NPC instantiation Load profile from YAML → spawn entity Generate profile from parameters → validate → cache → spawn entity
District initialization Read district/ directory → populate Run District Composer with parameters → write to cache → load from cache

1. Cultural Ingredient Menu — Parameter Space Design

The lead says: cultures are assembled from ingredient dimensions, not defined as fixed taxonomies. Architecturally, this is a combinatorial parameter space, and the generator's job is to produce coherent societies from dimension selections.

The parameter space

# content/ingredients/schema.yaml
cultural_parameter_space:
  heritage_roots:
    type: enum_set          # pick 1-3
    pool: heritage_roots/   # directory of authored heritage definitions
    min_selections: 1
    max_selections: 3

  settlement_motivation:
    type: enum
    pool: motivations/      # economic_opportunity, political_exile, religious_freedom, etc.

  economic_function:
    type: enum
    pool: economic_functions/ # trade_hub, extraction, agriculture, manufacturing, etc.

  philosophical_alignment:
    type: enum_set
    pool: philosophies/
    min_selections: 1
    max_selections: 2

  corporate_presence:
    type: float_range       # 0.0 (none) to 1.0 (corporate-dominated)
    affects: [trust_defaults, economic_parameters, access_tiers]

  drift_stage:
    type: ordinal           # 1 (recent settlement) to 5 (ancient civilization)
    affects: [naming_drift, cultural_coherence, heritage_visibility]

Constraint rules

Not all combinations are valid. Some are interesting friction, some are contradictory. The generator needs constraint rules:

# content/ingredients/constraints.yaml
constraints:
  - type: requires
    if: { drift_stage: [4, 5] }
    then: { heritage_roots: { min_selections: 2 } }  # ancient worlds show multiple heritage layers

  - type: tension
    when: [philosophical_alignment.includes("autonomist"), corporate_presence > 0.7]
    effect: { base_tension: +0.3, triangle_fuel: "corporate_resistance" }

  - type: incompatible
    pair: [settlement_motivation == "religious_freedom", corporate_presence > 0.9]
    resolution: "corporate takeover — original settlers marginalized"  # becomes thematic content

Architectural implications

Tier of difficulty: MODERATE. This is essentially a configuration-driven factory pattern. The schema defines the parameter space, the constraint rules prune invalid combinations and flag interesting ones, and the generator assembles coherent output from valid selections.

The key insight: constraint violations aren't errors — they're content. When heritage_roots clashes with corporate_presence, that's not a bug to filter out. That's a society with internal tension, which is exactly what generates interesting gameplay. The constraint system needs a "tension" category alongside "requires" and "incompatible."

What I need from Miri: Authored ingredient definitions for each dimension. Each ingredient needs: mechanical parameters (what it affects), flavor text (for the generator to use in naming/description), and compatibility notes (which other ingredients it creates interesting friction with).


2. Three NPC Systems + Composition — Data Model

The lead says: THREE separate systems, not one taxonomy. Thematic patterns, functional motivations, and composition rules. Let me design the data model.

System A: Thematic Patterns

// These define the NPC's narrative role — who they ARE in the player's story
#[derive(Component, Clone)]
pub enum ThematicPattern {
    Friend,      // warmth → contradiction → loss-or-reconciliation
    Mirror,      // reflects player's choices back at them
    Anchor,      // stability, the one who stays when everything moves
    Ghost,       // absence that shapes the present
    Catalyst,    // precipitates change, may not change themselves
    Threshold,   // guards a boundary — literal or metaphorical
    Remnant,     // living evidence of something that was
    System,      // embodies the system itself — bureaucrat, enforcer
    Nobody,      // background → foreground (dynamic tier promotion)
}

System B: Functional Motivations

// These define the NPC's gameplay role — what they DO in the simulation
#[derive(Component, Clone)]
pub enum FunctionalMotivation {
    Handler,   // directs player, gives tasks, manages information flow
    Witness,   // observes, reports, provides testimony — investigative thread
    Turncoat,  // divided loyalty, potential flip, information broker
    Civilian,  // just living their life — but affected by player actions
    Operator,  // runs something — business, network, system — player interacts with their operation
    Skeptic,   // questions everything, including the player's assumptions
}

System C: Composition Rules

This is the architecturally interesting part. Pattern + Motivation = specific NPC behavior template.

# content/npc/composition_rules.yaml
compositions:
  friend_handler:
    emotional_function: "warm relationship that also gives you work"
    gameplay_function: "primary quest-giver who you actually care about"
    content_requirements: [warmth_phase, contradiction_arc, task_chain]
    generation_weight: 0.8    # common — a friend who helps you is natural

  friend_turncoat:
    emotional_function: "warmth poisoned by divided loyalty"
    gameplay_function: "investigation thread — who is the friend actually loyal to?"
    content_requirements: [warmth_phase, loyalty_reveal, betrayal_or_redemption]
    generation_weight: 0.3    # rarer — but devastating when it occurs

  mirror_skeptic:
    emotional_function: "someone who sees through you AND questions why"
    gameplay_function: "forces player self-examination through dialogue"
    content_requirements: [reflection_dialogue, challenge_moments, optional_breakthrough]
    generation_weight: 0.5    # moderate — powerful but can be exhausting

  nobody_civilian:
    emotional_function: "invisible person in the background of your life"
    gameplay_function: "potential for discovery — attention reveals depth"
    content_requirements: [tier3_surface, tier2_latent, promotion_trigger]
    generation_weight: 1.0    # very common — most background NPCs are this

  # ... remaining valid combinations ...

  # Invalid/forbidden combinations
  ghost_handler:
    valid: false
    reason: "a ghost can't direct you — they're defined by absence"

  nobody_handler:
    valid: false
    reason: "handlers are noticed by definition — a nobody who gives tasks isn't a nobody"

The composition matrix

9 patterns x 6 motivations = 54 cells. My estimate:

Category Count Notes
Primary (generation_weight > 0.6) 15-18 The bread and butter. Every district has several of these.
Secondary (weight 0.2-0.6) 12-15 Rarer, more memorable. Generator uses these for variety.
Rare (weight < 0.2) 5-8 Special cases. Only in districts with specific thematic textures.
Invalid 13-19 Conceptually contradictory. Generator never produces these.

Tier of difficulty: MODERATE. The composition system is essentially a weighted lookup table. The generator rolls a pattern, rolls a motivation, checks if the composition is valid, reads the composition rules for that pair, and generates accordingly. The HARD part isn't the lookup — it's authoring the 35-40 valid composition rules with enough specificity that the generator produces meaningfully different NPCs.

THE NOBODY — Dynamic Tier Promotion

This deserves special architectural attention because it's genuinely novel: an NPC whose content tier changes at runtime based on player behavior.

#[derive(Component)]
pub struct NobodyState {
    /// Current tier — starts at Tier 3, can promote to 2 or 1
    pub current_tier: ContentTier,

    /// Latent content — generated at world-creation but not active until promoted
    pub latent_tier2: Option<NpcProfile>,  // pre-generated but dormant
    pub latent_tier1: Option<FriendTemplate>, // only if this Nobody has FRIEND potential

    /// Attention tracking — how much the player has noticed this NPC
    pub attention_score: f32,  // 0.0 = invisible, 1.0 = fully noticed
    pub interaction_count: u32,
    pub last_interaction_tick: Option<u64>,

    /// Promotion thresholds
    pub tier2_threshold: f32,  // attention_score needed for Tier 2
    pub tier1_threshold: f32,  // attention_score needed for Tier 1 (if eligible)

    /// Promotion history — once promoted, tracks the journey
    pub promoted_at_tick: Option<u64>,
    pub promotion_context: Option<String>,  // what triggered the player's attention
}

The generation pipeline for NOBODYs:

  1. World creation: District Composer generates a Tier 3 surface for every NOBODY (name, routine, greeting, 3-5 generic lines). ALSO generates latent Tier 2 content (full 10-axis profile, relationships, backstory) — but this content is dormant.
  2. Runtime: Player interacts with NOBODY. Attention system tracks interactions. When attention_score crosses tier2_threshold, the latent Tier 2 content activates — the NPC suddenly has more to say, more opinions, more relationships the player can discover.
  3. Rare promotion to Tier 1: If a NOBODY's latent profile is flagged as FRIEND-eligible AND attention_score crosses tier1_threshold, the FRIEND template activates. This is a major narrative event — a background character becomes someone who matters.

Tier of difficulty: MODERATE-HARD. The generation part is straightforward — generate latent content alongside surface content. The HARD part is the attention tracking system and making promotion feel natural rather than mechanical. The player shouldn't feel a "click" when an NPC promotes — it should feel like they've been paying attention and the NPC was always this interesting, they just hadn't noticed.

Memory cost at 300 worlds: Latent content for NOBODYs. If a district has 20-30 Tier 3 NPCs and each has latent Tier 2 content, that's ~2-5KB per NPC in serialized YAML. For the Active simulation tier (30-80 NPCs), maybe 10-15 are NOBODYs: ~50-75KB. Trivial. For State-saved districts, latent content is on disk, not in memory. Fine.


3. 8 Fluid PC Archetypes — Archetype State Machine

The lead says: archetypes are fluid. Players can transition between them. This is a game mechanic, not just a character creation choice.

The state machine

#[derive(Component)]
pub struct ArchetypeState {
    /// Current archetype — determines voice, knowledge vocabulary, monologue triggers
    pub current: Archetype,

    /// Archetype affinity scores — how close the player is to each archetype
    /// Shaped by player actions, job choice, social connections, district
    pub affinities: BTreeMap<Archetype, f32>,

    /// Transition state — if currently transitioning
    pub transition: Option<ArchetypeTransition>,

    /// History — previous archetypes, for narrative callbacks
    pub history: Vec<(Archetype, u64)>,  // (archetype, tick_entered)
}

#[derive(Clone)]
pub struct ArchetypeTransition {
    pub from: Archetype,
    pub to: Archetype,
    pub progress: f32,       // 0.0 = just started, 1.0 = complete
    pub trigger: TransitionTrigger,
    pub monologue_played: bool,
}

pub enum TransitionTrigger {
    JobChange(String),        // took a new job in a different domain
    DistrictMove(String),     // moved to a district with different social structure
    SocialShift,              // friend group or social network changed significantly
    PlayerChoice,             // explicit choice in a narrative moment
    GradualDrift,             // affinity crossed threshold through accumulated actions
}

Generator implications for 300 worlds

Every generated district must support all 8 archetypes. This isn't optional — it's a generator constraint. The District Composer's acceptance criteria include:

# content/generators/district_composer/archetype_validation.yaml
archetype_constraints:
  per_district:
    - every archetype has at least 1 viable social site role
    - every archetype has at least 1 potential FRIEND candidate
    - every archetype has at least 3 NPCs with compatible access tiers
    - every archetype has at least 1 economic activity (job/trade/task)
    - no archetype's starting knowledge reveals more than 30% of district secrets

  transition_support:
    - every district supports at least 3 inbound transition triggers
    - every district supports at least 3 outbound transition triggers
    - no archetype is a "dead end" in any district (always a path out)

Tier of difficulty: MODERATE. The archetype state machine itself is straightforward — it's a weighted affinity system with transition rules. The generator constraint is the hard part: ensuring 300 generated districts all support 8 archetypes without any dead ends. This requires the generator to run archetype viability checks as a post-generation validation step, and regenerate if constraints aren't met.

Rollout architecture

The archetype system must be designed for incremental addition. When archetype 4 launches, all 300 worlds must support it. This means:

  1. Archetype definitions are global, not per-district. An archetype's voice card, moral arc structure, and knowledge vocabulary live in content/archetypes/{name}/ — not embedded in districts.
  2. Per-district archetype support is generated. The District Composer has an archetype support module that produces: social site role mappings, NPC access tier adjustments, economic activity slots, starting knowledge filters — for each archetype, for each district.
  3. Adding an archetype = adding a definition + re-running the archetype support generator. The district content doesn't change. Only the archetype-district mappings are regenerated.

This is actually easier at 300 worlds than at 20 hand-authored districts. At 20 districts, adding an archetype means 20 manual content updates. At 300 worlds, it means 1 archetype definition + 1 generator re-run.


4. Sacred/Profane/Middle Kingdom — System Architecture Mapping

The lead approved Nigel's framework. Let me map it across every major system in the architecture, because this framework is genuinely powerful — it gives us a principled answer to "what's fixed, what varies, what's structured-but-variable" for every system.

System-by-system classification

System Sacred (rules, never change) Profane (parameters, drawn from pools) Middle Kingdom (sacred structure, profane cast)
Simulation Tick rate, entity structure, component types, system execution order NPC attribute values, relationship values, tension levels Simulation tiers (structure is sacred; which NPCs are in which tier is profane)
Information Occlusion model, knowledge graph structure, confidence levels What each NPC knows, perception ranges, access tier assignments Access tier system (tiers are sacred; who has which tier is profane)
Content tiers Tier 1/2/3 definitions, content requirements per tier Which NPCs are which tier, FRIEND/MIRROR assignments, pool contents THE NOBODY (tier structure is sacred; tier promotion is profane — the structure permits movement)
Cultural system Ingredient dimensions, constraint types, parameter schema Specific ingredient selections per world, cultural parameter values Cultural composition rules (the rules for combining ingredients are sacred; which ingredients exist is profane)
NPC system Thematic patterns, functional motivations, composition rule structure Specific NPCs, their pattern/motivation assignments, their attributes Composition rules (pattern + motivation structure is sacred; the specific rules per combination are profane — authors can add new composition flavors)
Gate topology Number of gates per system type, connectivity rules, path guarantees Which specific systems are connected, which peripherals are accessible Gate graph generation algorithm (algorithm is sacred; inputs are profane)
PC archetypes Archetype state machine, transition mechanics, affinity system Starting affinity values, transition thresholds, specific trigger conditions Archetype definitions (structure is sacred; specific archetypes are profane — 8 at v1.0, could grow)
Storyteller Event types, tension model, pacing rules Specific events, timing parameters, district-specific triggers Decision node DSL (the language is sacred; the specific decision trees are profane)

The key architectural insight

Sacred systems are the ENGINE. Profane content is the DATA. Middle Kingdom is the GENERATOR layer.

This maps perfectly to the 300-world reframe:

  • We build the Sacred engine once (v0.1-v0.2)
  • We define Middle Kingdom generators (v0.2-v0.5)
  • We author and expand Profane content forever (v0.5+)

The Sacred/Profane/Middle Kingdom framework IS the generator architecture, just named differently. The Middle Kingdom IS the content generation layer — it's the set of rules and templates that take Sacred structure and Profane parameters and produce game content.

Proposed decision: D-050 (Sacred/Profane/Middle Kingdom Framework). Every system in the architecture must classify its components into Sacred (engine, locked after v0.2), Profane (content, expandable forever), and Middle Kingdom (generators/templates, stable after v0.5). This classification drives: what requires code changes vs. data changes, what can be modded, what is DLC-expandable, and what the build pipeline produces.


5. Gate Topology — Generation Algorithm

The lead says: core worlds always connected (Sacred), peripheral systems vary per playthrough (Profane), number accessible fixed but which ones varies (Middle Kingdom).

The generation algorithm

INPUTS:
  - core_graph: Sacred connectivity (always the same)
  - peripheral_pool: all possible peripheral systems (Profane)
  - target_count: how many systems are accessible this playthrough (Sacred)
  - connectivity_rules: min/max connections per system type (Sacred)
  - seed: playthrough seed (determines all random selections)

ALGORITHM:
  1. Start with core_graph (always the same)
  2. Calculate peripheral_slots = target_count - |core_graph|
  3. Select peripheral_slots systems from peripheral_pool (seed-determined)
  4. For each selected peripheral:
     a. Determine connection points to existing graph (connectivity_rules)
     b. Verify path guarantees (every system reachable from starting system)
     c. If unreachable, add bridge connection or reselect
  5. Assign cultural parameters to each system (ingredient menu + seed)
  6. Generate districts per system from cultural parameters
  7. Validate: all archetypes viable in starting system, path diversity sufficient

OUTPUT:
  - Complete system graph with gate connections
  - Cultural parameter assignments per system
  - Starting system designation
  - Critical path identification (for narrative pacing)

Scale implications

At 300 worlds with, say, 10-15 core worlds and 285-290 peripheral possibilities:

  • Core graph: Hand-authored connectivity. Maybe 10-15 systems that are ALWAYS present. These are the narrative spine — starting system, political capital, trade hub, frontier gateway, etc. Their cultural parameters are authored, not generated. Their districts are benchmark quality (some hand-authored, some generated from high-quality parameters with human review).
  • Peripheral pool: 285-290 possible systems, of which each playthrough selects maybe 40-60 (based on gate topology). Cultural parameters generated from ingredient menu. Districts fully generated.
  • Per playthrough: Player sees ~50-75 systems (core + selected peripherals). Maybe visits 15-25 deeply. The rest exist in the simulation at Background or State-saved tier.

Tier of difficulty: MODERATE. Graph generation with constraints is a well-understood problem. The novel part is integrating it with the cultural parameter system — ensuring that a randomly-connected graph produces interesting cultural adjacencies (a trade hub bordering a frontier station creates different dynamics than a trade hub bordering another trade hub).

Macro randomization payoff

This is where the Sacred/Profane/Middle Kingdom framework really shines for replayability. On playthrough 1, the player's region has a Frontier Station connected to an Agricultural World. On playthrough 2, the same structural slot connects to a Research Outpost. Same gameplay mechanics (navigation, trade, social infiltration). Completely different cultural texture, different NPCs, different moral dilemmas. Same Sacred structure, different Profane cast.

What Nigel needs to validate: Does the gate topology generator produce sufficient variety? If 300 peripheral systems exist but the connectivity rules strongly constrain selection, players might see 80% overlap between playthroughs. The pool needs to be large enough (or the selection algorithm varied enough) that two playthroughs feel like different regions of the same universe.


6. Generator Architecture — The Content Pipeline

SI nailed this in Round 4: "Tooling IS the product." Let me design the generator architecture. This is the Middle Kingdom — the layer between Sacred engine and Profane content.

Pipeline overview

[Authored Inputs]          [Generator Pipeline]           [Runtime Content]
                           (Middle Kingdom)

Style Briefs ─────────┐
Ingredient Defs ──────┤
Pool Templates ───────┤
Composition Rules ────┤─── World Seed Generator ──────── World Manifest
Constraint Rules ─────┤         │
Naming Algorithms ────┘         │
                                ├── Cultural Param Generator ── Cultural Params per System
                                │         │
                                ├── Gate Topology Generator ─── System Graph
                                │         │
                                ├── District Composer ─────────── District Content (cached)
                                │    │    │    │
                                │    │    ├── NPC Generator (Tier 2) ── NPC Profiles
                                │    │    ├── NPC Generator (Tier 3) ── NPC Sketches
                                │    │    ├── Social Site Generator ─── Social Sites
                                │    │    ├── Triangle Generator ────── Triangles
                                │    │    └── NOBODY Latent Generator ─ Latent Content
                                │    │
                                │    ├── FRIEND Skinner ───────── FRIEND Instances
                                │    └── MIRROR Skinner ──────── MIRROR Instances
                                │
                                ├── Pool Compositor ──────────── Per-District Pools
                                └── Archetype Support Gen ────── Per-District Archetype Maps

                     ┌── Schema Validation
                     ├── Cross-Reference Validation
[Validation Layer] ──┤── Archetype Viability Check
                     ├── Pool Coverage Check
                     └── Name Collision Check

Generation phases (replaces Round 3's 6-phase loader)

Phase Input Output When Cache?
1. Manifest Playthrough seed World manifest: system count, core graph, peripheral selections New game start Yes — defines the playthrough
2. Global Manifest + authored global content Global pools, archetype definitions, composition rules, naming algorithms New game start Yes — global content is shared
3. System Manifest + cultural ingredients Per-system cultural parameters, gate connections New game start Yes — systems are stable
4. District System params + all generator inputs Complete district content: NPCs, social sites, triangles, pools On-demand (when system enters Active tier) Yes — generated once, cached
5. Latent District content + NOBODY definitions Latent Tier 2/Tier 1 content for NOBODYs With district generation Yes — stored alongside district
6. Hot-Reload Content patches, new archetypes Updated content for specific systems/districts Runtime (rare) Replace cache

Build-time vs. runtime generation

Critical design decision: When do the generators run?

Option A: All at new-game-start. Generate all 300 worlds when the player starts a new game. Pros: everything is consistent. Cons: potentially long initial load (minutes?), and all content exists even if the player never visits most worlds.

Option B: Core at new-game-start, peripheral on-demand. Generate core systems at start, generate peripheral systems when the player first approaches (enters Adjacent tier). Pros: fast start, lazy generation. Cons: need to ensure cross-system references are consistent even for ungenerated systems.

My recommendation: Option B, with forward references.

Generate the manifest (system graph + cultural parameters) at new-game-start. This is cheap — it's just parameter selection, no content generation. Generate district content on-demand when a system enters Active tier. Forward references (e.g., "this NPC mentions a cousin on System X") are generated from the manifest's cultural parameters — the cousin's specific identity is resolved when System X is actually generated.

This keeps new-game-start fast (<5 seconds), distributes generation load across gameplay, and handles the fact that most players will visit 15-25 of 300 systems deeply. No point generating the other 275 in detail.

Tier of difficulty: HARD. Not because any individual generator is hard, but because the generators must be coordinated. The manifest constrains the cultural generator. The cultural generator constrains the district composer. The district composer constrains the NPC generator. The NPC generator must respect composition rules. And the whole pipeline must be deterministic (same seed = same output) for save/load compatibility and multiplayer consistency (D-010).

Determinism guarantee

Every generator must be deterministic given a seed. This is non-negotiable (D-010). At 300 worlds, it means:

world_seed (from save file)
  └── system_seed = hash(world_seed, system_id)
        └── district_seed = hash(system_seed, district_id)
              └── npc_seed = hash(district_seed, npc_slot_index)

Each level derives its seed from its parent. Regenerating System 47 always produces the same result, regardless of when it's generated during gameplay. This is what makes on-demand generation safe — the order of generation doesn't matter.


7. What Changes Fundamentally at 300-World Scale

Let me flag everything that breaks, changes, or needs rethinking.

Things that are EASIER at 300 worlds

  1. Adding PC archetypes. One definition + one generator re-run vs. 20+ manual district updates. The generator-based model is inherently archetype-agnostic.

  2. Content variety. 300 worlds with cultural ingredients means far more combinatorial variety than 20 hand-authored districts could ever achieve. The parameter space is enormous.

  3. DLC/expansion. Add new ingredients to the menu, add new peripheral systems to the pool, re-run generators. No need to hand-author entire new districts.

  4. Modding. Modders add ingredients, patterns, archetypes, or systems to the pools. The generators incorporate them automatically. Nigel's modding platform is EASIER with generators than with hand-authored content.

  5. Anti-metagaming. With 300 possible worlds and seed-based selection, no two playthroughs share the same map. The fundamental structure varies per playthrough.

Things that are HARDER at 300 worlds

  1. Quality assurance. Can't hand-review 300 worlds. Must trust automated validation + spot-checks. The FRIEND/MIRROR review bottleneck that SI identified (150-200h) is real and irreducible.

  2. Cross-system narrative. If there's a plot thread that spans systems ("the conspiracy has agents on three worlds"), the generator must coordinate across systems. This requires a narrative threading layer above the district composer — a system that plants cross-references during manifest generation and resolves them during district generation.

  3. Generator debugging. When a generated district feels flat or broken, the debugging question is: which generator input caused this? Which ingredient? Which composition rule? This requires extensive logging and a "regenerate with verbose output" debug mode.

  4. Save file compatibility. If we change a generator (fix a bug, improve quality), existing save files reference content generated by the OLD generator. Options: (a) version the generators and always use the version that matches the save file, (b) regenerate affected content on load and handle any inconsistencies. I recommend (a) — versioned generators with backward compatibility.

  5. Performance at generation time. Generating a full district (30-80 NPCs, 5-8 social sites, 10-15 triangles, naming, dialogue) might take 2-10 seconds. For the on-demand model, this happens when the player approaches a new system. Need to pre-generate during the player's travel (gate transit animation = generation time) or have the generation be fast enough to be imperceptible.

Things that are DIFFERENT (not harder or easier, just changed)

  1. The content team's role. Writers become generator input authors. They write style briefs, ingredient definitions, FRIEND templates, voice cards, and seed dialogue. They don't write districts. This is a fundamentally different skill set — more like writing design documents than writing prose.

  2. Quality metrics. Instead of "is this district good?" the question becomes "does this generator produce districts that are indistinguishable from hand-authored?" The quality metric is GENERATOR quality, not content quality. Content quality is a function of generator quality + input quality.

  3. The content directory structure. Round 2's directory structure (districts/ with per-district YAML) becomes input-focused:

content/
  sacred/              # Engine definitions — locked after v0.2
    patterns/          # Thematic pattern definitions (9)
    motivations/       # Functional motivation definitions (6)
    tiers/             # Content tier definitions
    simulation/        # Simulation tier parameters

  profane/             # Pool content — grows forever
    ingredients/       # Cultural ingredient definitions (30-50)
    friends/           # FRIEND template pool (30-50)
    mirrors/           # MIRROR template pool (15-25)
    voices/            # Voice card library (30+)
    archetypes/        # PC archetype definitions (8+)
    contraband/        # Contraband type pool
    names/             # Naming algorithm definitions per heritage

  middle_kingdom/      # Generator configs — stable after v0.5
    generators/        # Generator definitions and configs
    composition/       # Composition rules (pattern × motivation)
    constraints/       # Cultural constraint rules
    templates/         # District templates, social site templates
    validation/        # Validation rule definitions

  authored/            # Hand-authored content (benchmark + core)
    core_systems/      # The 10-15 always-present systems
    benchmark/         # Quality benchmark districts (5-8)

  generated/           # Generator output cache (gitignored)
    systems/           # Per-system generated content
    manifests/         # Per-seed world manifests

8. Technical Risk Assessment

Risk Severity Likelihood Mitigation
Generator produces flat/samey output CRITICAL MEDIUM Extensive variety testing. Measure statistical distribution of NPC attributes across 100 generated districts. If variance is too low, add more randomization sources.
Cross-system narrative incoherence HIGH MEDIUM Manifest-level narrative threading. Forward references resolved at generation time. Validation layer checks cross-references.
Save file incompatibility after generator changes HIGH HIGH (will happen) Versioned generators from day 1. Save files record generator version. Load always uses matching version.
Generation performance (player-facing latency) MEDIUM LOW-MEDIUM Pre-generate during travel animations. Background generation for adjacent systems. Profile and optimize hot paths.
Ingredient explosion (too many combinations) LOW MEDIUM Start with 30-50 ingredients. Measure output quality. Add more only when generators can handle the variety. Constraint rules prune degenerate combinations.
NOBODY promotion feels mechanical MEDIUM MEDIUM Attention scoring must be invisible. No UI indicator of "attention score." Promotion triggers must feel organic — the NPC has more to say because the player asked, not because a threshold was crossed.

9. What I Got Wrong in Round 3

Round 3 Proposal Status at Round 4
6-phase content loader Replaced by 6-phase generation pipeline. Same structure, different function.
Content directory as "runtime-visible file tree" Replaced by content/ as generator input tree + generated/ as output cache.
Decision node DSL (~10-15 operations) Still valid — the storyteller's decision language is Sacred. What changes is that most decision trees are generated, not hand-authored.
Cultural distance model (4-level hierarchy) Replaced by ingredient menu. The "distance" between cultures is now a function of ingredient overlap, not a taxonomic hierarchy. More emergent, less prescriptive. Better.
9 core engine patterns Expanded and reclassified: patterns are now one of THREE systems (pattern + motivation + composition). The 9 I proposed map to the thematic patterns. Motivations are a separate system. This is cleaner.
~15-20 sprints for platform build Still roughly accurate for the Sacred + Middle Kingdom layers. But the nature of the work shifts: less content authoring tooling, more generator development.
canonical_id addressing Still valid, but needs two-tier model: authored content has human-readable canonical_ids, generated content has seed-derived canonical_ids. Both types use the same addressing system in the simulation.

10. Proposed Decisions

Based on this round, I'm flagging these for formalization:

ID Decision Rationale
D-050 Sacred/Profane/Middle Kingdom framework adopted for all systems Principled classification for fixed/variable/templated content across entire architecture
D-051 Content generation pipeline (6-phase: Manifest → Global → System → District → Latent → Hot-Reload) Replaces Round 3's content loader; generation is the core architecture
D-052 Deterministic seed-derived generation (world_seed → system_seed → district_seed → entity_seed) Required by D-010 (multiplayer-ready). Same seed = same world, regardless of generation order.
D-053 On-demand generation with forward references (core at start, peripherals on approach) Performance optimization: don't generate 300 worlds upfront. Manifest provides forward reference targets.
D-054 Three NPC systems: Thematic Patterns (9) + Functional Motivations (6) + Composition Rules Clean separation of narrative role, gameplay role, and combination rules
D-055 THE NOBODY as dynamic tier promotion system Tier 3 → Tier 2 (→ Tier 1) based on player attention. Latent content generated at world-creation, activated at runtime.
D-056 Versioned generators with backward-compatible save files Save files record generator versions. Content always regenerated with matching version on load.
D-057 Fluid PC archetype state machine with affinity-based transitions 8 archetypes at v1.0, transitions via job change / district move / social shift / gradual drift

Tyre out. The 300-world reframe isn't a scaling challenge — it's an architecture change. And honestly? It's more elegant. The generator-based model solves problems that hand-authoring COULDN'T solve: true anti-metagaming, easy archetype addition, natural DLC expansion, moddability by design. The Sacred/Profane/Middle Kingdom framework gives us a principled language for every "what's fixed vs. what varies" conversation for the rest of the project. I'm genuinely excited about this architecture. It's one of those cases where the constraint (300 worlds) forces a design (generators) that's actually BETTER than what we'd have built otherwise.