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>
7.8 KiB
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.rsalready definesRoleSchema,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/SpaceSpecdeserialization.
#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 inTemplateReferenceMap. - Existing hook:
server/src/content/spawn.rs. TheTemplateOwnershipcomponent (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,
TemplateOwnershipset correctly on each entity,TemplateReferenceMapentries 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+TriangleStatecomponents 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()inserver/src/content/template.rstakes&[TriangleDef]— extend to accept role slots from two differentTemplateOwnershipsources. - D-025 ownership model: NPCs are owned by one template but can hold reference roles in another. The cross-template triangle uses
TemplateReferenceMapreference links (carrying relationship metadata) not direct ownership links. - Acceptance: test world with two instantiated templates (logistics hub + bar) produces 1 cross-template
TriangleStatewith 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>fromassign_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_validationpasses, 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.rsis the IPC entry point. Add a supervision layer that catches panics from the tick loop and sends a structuredSimErrormessage 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 existingmalformed_input_in_batch_rejects_entire_batchtest (#479, done) is the baseline. - Desync: add a
state_hashfield toObserverSnapshot(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
SimErrormessage and continues running (does not exit).
#246 — Basic environmental interaction
ObjectTypeenum is already inserver/src/bridge/types.rs(extended by #421, #422).Interactablecomponent is inserver/src/simulation/interaction.rs.- Currently
ObjectType::Door,ObjectType::Terminal,ObjectType::Readable,ObjectType::Container,ObjectType::Furnitureexist with verb sets. - This ticket: implement the behaviour behind Door (toggle
walkableon the blocking tile(s), emit a zone-crossable notification), Examinable objects (return examine text from content), and usable Terminals (trigger aTerminalInteractedevent for future dialogue hook). - Door state must be tracked in
SaveStateV1(currently a field gap — addopen_doors: Vec<StableId>to the save struct inserver/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:
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(simulation): Sprint 21 template instantiation" --description "body" --base main --head server