Files
settled-reach/docs/sprints/sprint-21/server.md
T
jpmschweitzerandClaude Opus 4.6 bc226d8baf chore(db): move db/connectors/ to tooling/db/ (#274)
Consolidates all connector scripts under tooling/ per project
structure conventions. Symlink at db/connectors → tooling/db/
preserves backwards compatibility (remove after Sprint 22).

Updated references in CLAUDE.md, Makefile, DEVOPS.md, all skill
files, agent files, rules, schema comments, and Sprint 21
briefings. Python scripts updated with correct SCHEMA_PATH
(now relative to WORKTREE_ROOT/db/schema.sql).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 11:08:00 +01:00

92 lines
7.8 KiB
Markdown

# 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 <id>` 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<Vec<TriangleState>, 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<StableId>` 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
```