chore(sprints): add sprint 21 "Instantiate" briefings
12 tickets across 5 teams: server (7), client (2), visual (1), ci (1), planning (1). Template instantiation pipeline, cross-template triangles, save/load flow, fog shader tuning, generator workshop. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
# Sprint 21: Instantiate — CI 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:** `ci`
|
||||
**Agents:** Justine (build/deploy)
|
||||
|
||||
## New Tickets
|
||||
|
||||
| # | Title | Blocked by |
|
||||
|---|-------|------------|
|
||||
| #274 | Move connector scripts from db/connectors/ to tooling/db/ | — |
|
||||
|
||||
Use `db/connectors/ticket show <id>` for full details.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- `decisions/process.md` — tooling conventions and project structure
|
||||
|
||||
## Notes
|
||||
|
||||
**#274 — Move connector scripts from db/connectors/ to tooling/db/**
|
||||
- Current location: `db/connectors/` — contains `sqlite_connector.py`, `qdrant_connector.py`, `config.json`, and all wrapper scripts (`sqlite-query`, `sqlite-exec`, `sqlite-init`, `sqlite-seed`, `qdrant-search`, `qdrant-index`, `qdrant-health`, `qdrant-count`, `ticket`, `sprint`, `decision`).
|
||||
- Target location: `tooling/db/` — consolidates all tooling under `tooling/` per project structure conventions. The `db/` directory retains schema and seed data only.
|
||||
- Steps:
|
||||
1. Create `tooling/db/` directory.
|
||||
2. Move all scripts and `config.json`. Preserve executable bits (`chmod +x` on wrapper scripts).
|
||||
3. Update `CLAUDE.md` table ("CLI tools" section) to reference new paths.
|
||||
4. Update `docs/DEVOPS.md` if it references `db/connectors/` paths.
|
||||
5. Update any `Makefile` targets that call `db/connectors/` directly.
|
||||
6. Update agent briefings and skill files that reference `db/connectors/` paths — check `.claude/skills/` and `.claude/agents/`.
|
||||
7. Leave a `db/connectors/` stub or symlink pointing to `tooling/db/` if any external scripts depend on the old path. Remove after one sprint.
|
||||
- Do NOT move `db/schema.sql`, `db/seed.sql`, or `settledreach.db` — those stay in `db/`.
|
||||
- The `settledreach.db` lives in the parent directory (`../settledreach.db` relative to the worktree root) and is not tracked in git — no change needed there.
|
||||
- Acceptance: `make ci` passes. `db/connectors/ticket list` either works via symlink or has been replaced by `tooling/db/ticket list` everywhere it is referenced.
|
||||
|
||||
## Dependency Chain
|
||||
|
||||
```
|
||||
#274 (connector script move) — standalone
|
||||
```
|
||||
|
||||
## PR Workflow
|
||||
|
||||
When ready to submit, create a PR with `tea` CLI:
|
||||
|
||||
```bash
|
||||
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "chore(ci): move db/connectors/ to tooling/db/" --description "body" --base main --head ci
|
||||
```
|
||||
@@ -0,0 +1,56 @@
|
||||
# Sprint 21: Instantiate — Client 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:** `client`
|
||||
**Agents:** Stig (dev), Hoshe (QA)
|
||||
|
||||
## New Tickets
|
||||
|
||||
| # | Title | Blocked by |
|
||||
|---|-------|------------|
|
||||
| #257 | Save/load game flow | — (#256 done) |
|
||||
| #561 | Housekeeping: move debug_overlay.gd to ui/ directory | — |
|
||||
|
||||
Use `db/connectors/ticket show <id>` for full details on any ticket.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- `decisions/architecture.md` — D-020 (Godot = pure renderer, no game logic in GDScript), D-085 (per-game save directories under `user://saves/<game-id>/`), D-088 (3-state pause: Normal/Overlay/Paused, server-authoritative)
|
||||
- `decisions/scope.md` — D-027 (vertical slice: smuggler + detective, two-character proof)
|
||||
|
||||
## Notes
|
||||
|
||||
**#257 — Save/load game flow**
|
||||
- Server-side serialization (`SaveStateV1`, `SaveLoadCommand`) landed in Sprint 19 (#553, #553). The client `SessionManager` autoload (`client/scripts/autoloads/session_manager.gd`) already creates per-game directories and tracks `current_game_id`. The `input.rs` server-side hook for `SaveLoadCommand::Save` and `SaveLoadCommand::Load` is in place.
|
||||
- What's missing: the client UI flow — save-to-file and load-from-file screens, and F5/F6 quicksave/quickload keybinds wired to `PlayerInput`.
|
||||
- `client/ui/main_menu.gd` exists. Add a "Load Game" screen that calls `SessionManager.list_game_dirs()` and lets the player select a save.
|
||||
- F5 quicksave flow: send `PlayerInput { action: QuickSave }` → server responds with serialised save data → client writes to `user://saves/<game-id>/quicksave.sav`. F6 quickload: reverse.
|
||||
- Loading screen: a minimal full-screen overlay ("Resuming...") during the round-trip to prevent input during load. No elaborate animation needed for v0.1.
|
||||
- D-020 constraint: no game logic in client. The client never constructs save data — it only sends the command and receives the file bytes from the server.
|
||||
- Existing stub in `session_manager.gd` line 71 notes: "The actual F5 save will be wired here once server supports SaveCommand." Server supports it now — wire it.
|
||||
- Acceptance: (1) F5 in-game triggers quicksave, file appears at correct path. (2) F6 reloads it, player position and NPC state match save. (3) Main menu "Load Game" lists existing saves sorted by date.
|
||||
|
||||
**#561 — Housekeeping: move debug_overlay.gd to ui/ directory**
|
||||
- `client/scripts/ui/debug_overlay.gd` is the odd one out — all 17 other UI components live in `client/ui/`. This was flagged in a code review.
|
||||
- Steps: move `client/scripts/ui/debug_overlay.gd` (and its `.uid` file) to `client/ui/debug_overlay.gd`. Update any `preload()` or `load()` references. Update the `.tscn` that instances it if one exists.
|
||||
- Check `client/scripts/rendering/` and `client/scripts/autoloads/` for any imports of the old path.
|
||||
- If moving would break more than 3 references and the distinction is intentional (debug overlay is a script, not a scene-based UI), document the distinction in a comment at the top of the file instead, and close the ticket as "documented not moved."
|
||||
- Acceptance: `make ci-client` passes with the file at its new location, or the distinction is documented in-file.
|
||||
|
||||
## Dependency Chain
|
||||
|
||||
```
|
||||
#257 (save/load game flow) — standalone
|
||||
#561 (debug_overlay housekeeping) — standalone, parallel
|
||||
```
|
||||
|
||||
Both tickets are independent and can be developed in parallel.
|
||||
|
||||
## PR Workflow
|
||||
|
||||
When ready to submit, create a PR with `tea` CLI:
|
||||
|
||||
```bash
|
||||
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(client): Sprint 21 save/load game flow" --description "body" --base main --head client
|
||||
```
|
||||
@@ -0,0 +1,116 @@
|
||||
# Sprint 21: Instantiate — Joint Coordination
|
||||
|
||||
**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.
|
||||
|
||||
## Pre-Sprint Decisions
|
||||
|
||||
No blocking pre-sprint decisions are required. All selected implementation tickets have their upstream decisions confirmed.
|
||||
|
||||
| Decision | Status | Impact |
|
||||
|----------|--------|--------|
|
||||
| D-025 (social site as atomic template unit) | Confirmed | Server #159/#166/#161 schema and instantiation shapes |
|
||||
| D-024 (NPC 10-axis model, 2 triangles minimum per template, 1 cross-template) | Confirmed | Server #108/#109 triangle requirements |
|
||||
| D-087 (v0.1 triangle config: 3 active forks, 2 passive tensions) | Confirmed | #108 must produce triangle types consistent with T1-T5 fork taxonomy |
|
||||
| D-089 (self-contained forks, no cross-triangle cascade) | Confirmed | #108 cross-template triangle uses reference links, not shared state |
|
||||
| D-085 (per-game save directories) | Confirmed | Client #257 save/load flow writes to `user://saves/<game-id>/` |
|
||||
| D-020 (Godot = pure renderer) | Confirmed | Client #257 never constructs save data — sends command, receives file bytes |
|
||||
| D-059 (fog: five layers, shader-based) | Confirmed | Visual #564 tuning target — alpha values must match D-059 layer specs |
|
||||
| D-066 (dual-scale grid, 6-8 sim tile fog gradient) | Confirmed | Visual #564 must not alter `CLEAR_THRESHOLD`/`PERIPHERAL_LOW` constants that define gradient width |
|
||||
|
||||
**One open question to monitor:**
|
||||
- **Q-036 (district skeleton as generator output)** — actively being resolved in #562 this sprint. Resolution will gate #144 (Chunk generation system) and shape the Sprint 22 map pipeline tickets. SI will create follow-up tickets once #562 closes.
|
||||
|
||||
## Planning Ticket
|
||||
|
||||
| # | Title | Team | Agents |
|
||||
|---|-------|------|--------|
|
||||
| #562 | Generator architecture workshop — district/block/chunk pipeline | planning | Gestalt, Tyre, Miri, Araminta, Nigel, Qatux, SI |
|
||||
|
||||
**#562 — Generator architecture workshop**
|
||||
|
||||
Workshop brief: `docs/workshops/generator-architecture/workshop-brief.md`
|
||||
|
||||
**Purpose:** Establish the top-down procedural generator pipeline architecture — from geography down to individual chunk fill — that will power the 300-world model. The v0.1 Transit District is hand-authored; this workshop defines what the generator must be able to reproduce and what stub interfaces v0.1 must leave behind.
|
||||
|
||||
**Context documents to read before the discussion:**
|
||||
- `decisions/content.md` — D-025 (social site template as atomic unit)
|
||||
- `decisions/scope.md` — D-012 (chunk-based map system), D-036 (Sova as v0.1 setting)
|
||||
- `decisions/questions.md` — Q-036 (district skeleton as generator output), Q-037 (generator pipeline phases), Q-039 (gate topology generation)
|
||||
- `docs/design/sova-station-profile.md` — district types and 6-district layout
|
||||
- `docs/design/spatial-layout-terminal-v01.md`, `docs/design/spatial-layout-bar-v01.md` — hand-authored chunk cluster examples
|
||||
- `decisions/architecture.md` — D-093/D-094 (Sova spatial hierarchy: chunk/block/district naming and sizes)
|
||||
|
||||
**Three rounds:**
|
||||
1. **Domain Inventory** — each participant states what their domain requires from the generator (Gestalt: gameplay loop guarantees; Tyre: technical constraints on chunk size and hierarchy depth; Miri: cultural/economic variation inputs for 300 worlds; Araminta: visual coherence constraints on chunk fill and sub-chunk quarter system; Nigel: variation and replayability guarantees).
|
||||
2. **Pipeline Proposals** — propose pipeline stages, name the spatial hierarchy levels with tile dimensions, describe the district skeleton data structure.
|
||||
3. **Convergence** — resolve conflicts, lock spatial hierarchy, define district skeleton output format, set v0.1/generator boundary, draft D-record.
|
||||
|
||||
**Required outputs:**
|
||||
- D-record in `decisions/architecture.md`: pipeline stages, spatial hierarchy, sub-chunk quarter rules, multi-block reservation protocol, district skeleton data structure, v0.1/generator boundary
|
||||
- Resolution of Q-036 (district skeleton as atomic output — yes/no + formal definition)
|
||||
- Resolution of Q-037 scope (which phases land in which version window)
|
||||
- Follow-up implementation tickets: chunk data structure update (#143), district skeleton schema, zoning pass stub, block generation stub
|
||||
|
||||
**SI role in this workshop:** Create follow-up tickets from the D-record outputs and assign to Sprint 22 candidates. Update Q-036 and Q-037 status in `decisions/questions.md`.
|
||||
|
||||
## Sprint Completion Proof
|
||||
|
||||
The sprint is done when all of the following are observable:
|
||||
|
||||
1. **Template instantiation pipeline end-to-end:** Load a Tier 2 YAML from `server/data/templates/`, call the instantiation engine, assert NPCs spawn with correct roles, `TemplateOwnership` set, and 2+ `TriangleState` components generated. `cargo test -p server -- instantiation` passes.
|
||||
|
||||
2. **Cross-template triangle produced:** A test world with two instantiated templates (logistics hub + bar) generates exactly 1 cross-template `TriangleState` with role assignments spanning both templates. `cargo test -p server -- cross_template_triangle` passes.
|
||||
|
||||
3. **Triangle validation catches bad inputs:** Unit tests confirm that a triangle failing conflict viability, relationship coherence, or interest divergence returns a typed `ValidationError`, not a panic.
|
||||
|
||||
4. **Save/load round-trip works end-to-end:** F5 in-game writes a quicksave file to `user://saves/<game-id>/quicksave.sav`. F6 reloads it. Player position and NPC state (including open doors from #246) match the save. `make ci-client` passes.
|
||||
|
||||
5. **Environmental interaction:** A Door entity in a test world toggles walkability on player interaction. An Examinable entity returns examine text. Door state survives a save/load round-trip (open_doors persists in `SaveStateV1`).
|
||||
|
||||
6. **Error handling does not crash:** Sending a malformed IPC message mid-session produces a structured `SimError` response and leaves the server running. Integration test asserts this.
|
||||
|
||||
7. **Fog shader tuned:** Fog Theater gauntlet room — entities in peripheral zone are visibly dimmed but not opaque; deep fog shows a readable zone temperature tint; vision cone edge is soft. `make ci-client` passes.
|
||||
|
||||
8. **Generator architecture decided:** #562 closes with a confirmed D-record, Q-036 marked resolved, Q-037 scope defined. SI creates Sprint 22 candidate tickets for the chunk/district pipeline implementation.
|
||||
|
||||
## Test Plan Alignment (D-030)
|
||||
|
||||
Sprint 21 is Phase 3+ territory. The template instantiation system introduces the first simulation structures that compose content from YAML definitions into live ECS entities.
|
||||
|
||||
| Ticket | Test scope | Priority |
|
||||
|--------|------------|----------|
|
||||
| #159 | Unit: YAML round-trip, full Tier 2 document | High |
|
||||
| #166 | Unit: spawn + TemplateOwnership, TemplateReferenceMap entries | High |
|
||||
| #161 | Integration: YAML → instantiation engine → ECS entities + triangles | High |
|
||||
| #108 | Unit: cross-template role assignment, reference link creation | High |
|
||||
| #109 | Unit: all three validation failure modes + passing case | High |
|
||||
| #85 | Integration: malformed input → SimError, server survives | High |
|
||||
| #246 | Unit: Door walkability toggle, examine text return | High |
|
||||
| #257 | End-to-end: F5 save → F6 load → state match | High |
|
||||
| #561 | Regression: `make ci-client` passes at new file path | Medium |
|
||||
| #564 | Visual: Fog Theater gauntlet room manual check | High |
|
||||
| #274 | Regression: `make ci` passes with scripts at new paths | High |
|
||||
|
||||
## Cross-Team Integration Points
|
||||
|
||||
| Server ticket | Client dependency | Notes |
|
||||
|---------------|-------------------|-------|
|
||||
| #246 (`open_doors` in `SaveStateV1`) | #257 (save/load round-trip) | Server must add `open_doors: Vec<StableId>` to save struct before client can verify state restored correctly |
|
||||
| #85 (`SimError` message type) | #257 (loading screen) | Loading screen should handle `SimError` gracefully — show error state, not spinner forever |
|
||||
|
||||
| Planning ticket | Downstream impact | Notes |
|
||||
|-----------------|-------------------|-------|
|
||||
| #562 (generator architecture) | #143, #144 (chunk system) | D-record output gates Sprint 22 chunk pipeline work |
|
||||
|
||||
The #246/#257 dependency is soft — client can stub the door state verification in save/load tests until #246 lands.
|
||||
|
||||
## Deferred to Sprint 22
|
||||
|
||||
Natural Sprint 22 candidates once this sprint's foundation lands:
|
||||
|
||||
- **#155** (Hand-crafted location authoring) — build the v0.1 Transit District locations in Godot tilemap; requires #153 (done) and the district topology from that D-record
|
||||
- **#188** (Triangle instantiation in v0.1 content) — wire the 5 v0.1 triangles into the instantiation engine; requires #161
|
||||
- **#162** (Storyteller module activation) — draw Tier 1 modules from pool at game start; requires #161
|
||||
- **#143** (Chunk data structure) — blocked until #562 workshop defines the spatial hierarchy
|
||||
- **#176** (NPC pool generation: flat/mundane/entangled ratio) — requires #161 instantiation engine
|
||||
- Generator pipeline tickets — created by SI from #562 D-record outputs
|
||||
@@ -0,0 +1,91 @@
|
||||
# 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 `db/connectors/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
|
||||
```
|
||||
@@ -0,0 +1,66 @@
|
||||
# Sprint 21: Instantiate — Visual 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:** `visual`
|
||||
**Agents:** Araminta (art direction)
|
||||
|
||||
## New Tickets
|
||||
|
||||
| # | Title | Blocked by |
|
||||
|---|-------|------------|
|
||||
| #564 | Fog shader too opaque — tune alpha for semi-transparent layers per D-059 | — |
|
||||
|
||||
Use `db/connectors/ticket show <id>` for full details.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- `decisions/perception.md` — D-059 (fog: shader-based, five layers, knowledge-graph-driven), D-011 (fog of perception non-negotiable, same system for NPCs and player)
|
||||
- `decisions/architecture.md` — D-066 (dual-scale grid: 0.5m sim tiles, 1m visual tiles; fog gradient edge = 6-8 sim tiles = 3-4 visual tiles), D-043 (visual style: "functional warmth", Godot Light2D pipeline, sprites are shape templates the lighting completes)
|
||||
|
||||
## Notes
|
||||
|
||||
**#564 — Fog shader too opaque — tune alpha for semi-transparent layers per D-059**
|
||||
|
||||
The fog shader is implemented and structurally correct. The issue is that the alpha values for Layer 2 (peripheral) and Layer 3 (deep fog) are heavier than D-059 specifies, making the fog feel like a dark wall rather than limited visibility.
|
||||
|
||||
**File to edit:** `client/shaders/fog.gdshader`
|
||||
|
||||
**Current alpha values (reference fog_shader.gd for context):**
|
||||
- Layer 2 (peripheral, `vis` between `PERIPHERAL_LOW=0.55` and `CLEAR_THRESHOLD=0.85`): alpha `mix(0.55, 0.25, coverage) + noise * 0.1` — peaks at 0.55–0.65 at the peripheral edge
|
||||
- Layer 3 (deep fog, `explored > 0.3`): alpha `mix(0.78, 0.90, noise_val)` — near-fully opaque
|
||||
|
||||
**D-059 intent:**
|
||||
- Layer 2 (light fog / peripheral): "desaturated 40–50%, brightness -30%". This implies entities and world geometry are still partially visible — something in the 30–45% alpha range at the peripheral boundary, fading smoothly toward clear.
|
||||
- Layer 3 (deep fog / previously explored): "near-monochrome with ~10% zone temperature tint". The zone tint (`zone_tint_tex`) must be readable through the fog. The current 0.78–0.90 alpha buries it. Targeting 0.60–0.75 range should let tint breathe without revealing too much detail.
|
||||
- Layer 1 (clear, vision cone): the soft gradient edge should span 6-8 sim tiles = 3-4 visual tiles (D-066). Verify the `smoothstep(CLEAR_THRESHOLD, 1.0, vis)` range still produces this after alpha changes. `CLEAR_THRESHOLD = 0.85` and `PERIPHERAL_LOW = 0.55` are the knobs — do not change these unless the gradient edge width breaks.
|
||||
|
||||
**What to tune:**
|
||||
1. Layer 2: reduce the heavy-end alpha from 0.55 → ~0.38, keep the light-end at 0.25. Adjust noise contribution proportionally. Entities behind peripheral fog should be dimmed and desaturated, but recognisable in silhouette.
|
||||
2. Layer 3: reduce the alpha range from `mix(0.78, 0.90, noise_val)` → `mix(0.62, 0.76, noise_val)`. Zone tint (10% contribution via `mix(vec3(0.04), zone_tint, 0.1)`) should now be faintly visible as a colour cast. The "fog breathes" effect is preserved — keep the noise animation as-is.
|
||||
3. Verify that Layer 5 (unexplored, no maps, `#12141a`, alpha 1.0) remains fully opaque — information zero, no change.
|
||||
|
||||
**How to test:**
|
||||
- The Fog Theater gauntlet room (accessible via the Gauntlet hub in the running game) exercises all five fog layers in a single space.
|
||||
- Observable pass criteria:
|
||||
1. An NPC standing in the peripheral zone (Layer 2) is visibly dimmed and slightly desaturated — their D-033 relationship colour is still readable.
|
||||
2. A previously-explored room (Layer 3) shows a faint zone temperature tint (bar zone = warm, hub zone = cool, corridor = neutral) rather than uniform near-black.
|
||||
3. The vision cone edge is soft — no visible hard line between clear and peripheral.
|
||||
4. Unexplored tiles remain fully black.
|
||||
- Also run `make ci-client` to confirm no shader compilation regressions.
|
||||
|
||||
**Note:** `client/scripts/rendering/fog_shader.gd` (the GDScript controller) does not need changes — it sets uniforms, not alpha values. `client/scripts/autoloads/fog_state.gd` generates the textures fed to the shader — verify the zone tint texture is being populated correctly if Layer 3 tint still doesn't show after alpha reduction.
|
||||
|
||||
## Dependency Chain
|
||||
|
||||
```
|
||||
#564 (fog alpha tuning) — standalone
|
||||
```
|
||||
|
||||
## PR Workflow
|
||||
|
||||
When ready to submit, create a PR with `tea` CLI:
|
||||
|
||||
```bash
|
||||
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "fix(visual): tune fog shader alpha per D-059" --description "body" --base main --head visual
|
||||
```
|
||||
Reference in New Issue
Block a user