--- title: "Sprint 21 — Server Briefing" description: "Template definition format, template-to-instance mapping, cross-template triangle generation" type: sprint status: archived sprint: 21 team: "server" --- # Sprint 21: Instantiate — Server Tasks **Goal:** The template system becomes executable — templates spawn NPCs, assign triangles, and place them in world space; cross-template triangles link social sites; the client gains save/load game flow; and the generator pipeline gets its architectural design. **Branch:** `server` **Agents:** Dudley (simulation dev), Tyre (arch), Hoshe (QA) ## New Tickets | # | Title | Blocked by | |---|-------|------------| | #159 | Tier 2 template definition format | — (#158 done) | | #166 | Template-to-instance mapping | — (#163, #164, #165 done) | | #161 | Template instantiation engine | #166 | | #108 | Cross-template triangle generation | — (#106, #107 done) | | #109 | Triangle validation | — (#107 done) | | #85 | Error handling & recovery | — | | #246 | Basic environmental interaction | — | Use `tooling/db/ticket show ` for full details on any ticket. ## Key Decisions - `decisions/content.md` — D-023 (three-tier content model), D-024 (NPC generation model, 10 axes), D-025 (social site as atomic template unit), D-028 (dialogue tagged pools), D-029 (population entanglement ratio) - `decisions/architecture.md` — D-020 (Godot + Rust IPC, ObserverSnapshot), D-010 (deterministic simulation), D-087 (v0.1 triangle configuration), D-088 (3-state pause, server-authoritative), D-089 (self-contained forks, no cascade) ## Notes **#159 — Tier 2 template definition format** - `server/src/content/template.rs` already defines `RoleSchema`, `SpaceSpec`, `TriangleDef` (Sprint 20). `#158` (Tier 1 drama module schema) is done — use it as a reference for YAML conventions. - This ticket extends that to the full Tier 2 document: roles, spaces, triangles, dialogue pool references, NPC routines, and spatial spec in one YAML document. - `server/data/templates/` directory exists (created by #385). Place the canonical Tier 2 schema definition and at least one authored example template here. - Acceptance: a complete Tier 2 template YAML round-trips cleanly through `RoleSchema` / `SpaceSpec` deserialization. **#166 — Template-to-instance mapping** - Depends on the schema from #159, but #159 is partially stubbed already — Dudley can start here in parallel if schema is stabilising. - Core task: given a loaded `TemplateOwnership` + `SpaceSpec`, spawn NPC entities for each role slot, assign relationships, and record the mapping in `TemplateReferenceMap`. - Existing hook: `server/src/content/spawn.rs`. The `TemplateOwnership` component (Sprint 20) already tracks which template owns an entity. This ticket wires spawning to that system. - Instance lifecycle: entities spawned from a template must be tagged such that they can be despawned/reset cleanly (gauntlet room reset pattern in `server/src/test_world/` is a reference). - Acceptance: unit test spawns a 4-NPC template, asserts all role slots filled, `TemplateOwnership` set correctly on each entity, `TemplateReferenceMap` entries present. **#161 — Template instantiation engine** - Blocked by #166. Once mapping works, this ticket wires the full pipeline: load YAML → deserialize → call spawn → generate triangles via `server/src/content/template.rs:assign_triangle_roles()` → register ownership. - Instance lifecycle management: track active instances, support unloading (for zone transitions and save/load). - Integration point with #166: the instantiation engine calls the mapping layer, not the raw spawn functions. - Acceptance: end-to-end test — load `server/data/templates/` logistics_hub YAML, instantiate it, assert NPCs exist with correct roles and 2+ `TriangleState` components generated. **#108 — Cross-template triangle generation** - Sprint 20 landed intra-template triangles (#107). This ticket adds the 1 cross-template triangle required by D-024 ("2 per template minimum, 1 cross-template"). - The existing `assign_triangle_roles()` in `server/src/content/template.rs` takes `&[TriangleDef]` — extend to accept role slots from two different `TemplateOwnership` sources. - D-025 ownership model: NPCs are owned by one template but can hold reference roles in another. The cross-template triangle uses `TemplateReferenceMap` reference links (carrying relationship metadata) not direct ownership links. - Acceptance: test world with two instantiated templates (logistics hub + bar) produces 1 cross-template `TriangleState` with role assignments spanning both templates. **#109 — Triangle validation** - Quality checks on generated triangles. Three checks minimum: (1) conflict viability — the three role slots have at least one opposing Want axis, (2) relationship coherence — at least one Relationships entry links the three roles, (3) interest divergence — no two roles share identical Want+Secret combination. - Validation runs at instantiation time (not a separate pass). Return `Result, ValidationError>` from `assign_triangle_roles()`. - Hoshe: unit tests for each failure mode — triangle that fails conflict viability, triangle that fails coherence, triangle that fails divergence. - Acceptance: `cargo test -p server -- triangle_validation` passes, covering all three failure modes plus a valid triangle that passes all checks. **#85 — Error handling & recovery** - Handle three categories: (1) simulation panics / process crashes, (2) protocol deserialization errors, (3) desync detection between client state and server state. - Server side: `server/src/bridge/local.rs` is the IPC entry point. Add a supervision layer that catches panics from the tick loop and sends a structured `SimError` message to the client before dying, rather than an abrupt disconnect. - Protocol errors: `server/src/bridge/types.rs` — ensure malformed input returns a typed error response, not a panic. The existing `malformed_input_in_batch_rejects_entire_batch` test (#479, done) is the baseline. - Desync: add a `state_hash` field to `ObserverSnapshot` (a fast hash of key mutable state — player position, NPC count, tick number). Client logs hash mismatches for debugging. No automatic recovery in v0.1 — detect and report only. - Acceptance: integration test sends a deliberately malformed message mid-session, asserts the server emits a `SimError` message and continues running (does not exit). **#246 — Basic environmental interaction** - `ObjectType` enum is already in `server/src/bridge/types.rs` (extended by #421, #422). `Interactable` component is in `server/src/simulation/interaction.rs`. - Currently `ObjectType::Door`, `ObjectType::Terminal`, `ObjectType::Readable`, `ObjectType::Container`, `ObjectType::Furniture` exist with verb sets. - This ticket: implement the _behaviour_ behind Door (toggle `walkable` on the blocking tile(s), emit a zone-crossable notification), Examinable objects (return examine text from content), and usable Terminals (trigger a `TerminalInteracted` event for future dialogue hook). - Door state must be tracked in `SaveStateV1` (currently a field gap — add `open_doors: Vec` to the save struct in `server/src/simulation/save_state.rs`). - Acceptance: unit test — player interacts with a Door entity, asserts walkability flips; interacts again, asserts it flips back. Examine on a Readable entity returns non-empty text. ## Dependency Chain ``` #159 (Tier 2 template format) → #166 (template-to-instance mapping) → #161 (instantiation engine) #107 (done: intra-template triangles) → #108 (cross-template triangles) → #109 (triangle validation) #85 (error handling) — standalone #246 (environmental interaction) — standalone ``` Parallel tracks: #159→#166→#161 and #108→#109 can run concurrently. #85 and #246 are independent. ## PR Workflow When ready to submit, create a PR with `tea` CLI: ```bash tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(simulation): Sprint 21 template instantiation" --description "body" --base main --head server ```