0.5m sim tiles for movement/LOS granularity, 1m visual tiles for proportional art and readable spaces (2x retina factor). All world geometry constrained to 2x2 sim tile minimum so cover/LOS maps 1:1 with visuals. Entities occupy 1x1 sim tiles for fine positioning. Updates: D-043, D-044, D-051, D-056, D-059 annotations, workshop outcomes (art direction + control/interaction), sprint 6 briefings, decision index, and CLAUDE.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
15 KiB
Sprint 6: Touch — Joint Integration
Goal: Movement stances, fog rebuild, multi-verb interactions, and smuggler inventory
Teams: Server, Client, Copy Agents: All implementation agents (Dudley, Stig, Tyre, Hoshe, Mellanie, Paula, Gestalt)
Sprint Overview
Sprint 6 is the control and interaction sprint. Sprint 1-5 built the simulation, the bridge, the rendering pipeline, the content loading, and the FRIEND NPCs. Sprint 6 delivers the player's direct interface to the world: how they move (stances), how they see (fog shader), how they interact (multi-verb system), and what they carry (inventory).
This sprint emerged from the Control & Interaction Workshop (2026-02-13), which produced 11 decisions (D-053 through D-065) and 33 tickets under epic #416. Sprint 6 implements the critical-path subset: 18 tickets across server, client, and copy teams.
Team Distribution
| Team | Ticket Count | Load |
|---|---|---|
| Server | 9 tickets | Heavy (stance system, tile occupancy, two-phase verb computation, smuggler inventory, bridge v6) |
| Client | 6 tickets | Heavy (cursor states, fog shader rebuild, interaction list, world radial menu, inventory UI, stance UI) |
| Copy | 1 ticket | Light (3 smuggler item specs) |
Pre-Sprint Requirements
Two open questions were resolved during the workshop and ticket creation:
- OQ-01: Tile size — Resolved to 0.5m x 0.5m sim tiles (ticket #444, done). Amended by D-066: dual-scale grid with 1m visual tiles (2x retina factor). All world geometry 2x2 sim tile minimum.
- OQ-24: Inventory capacity — Resolved to 3x3 grid = 9 slots universal (ticket #445, done)
All blocking decisions are confirmed. No pre-sprint work required.
Critical Path
Sprint 6 has three parallel tracks with one critical integration point:
Server track (stance + movement):
#449 (ObserverSnapshot v6) → client #438 (inventory UI), client #439 (stance UI)
#417 (Stance system)
├─→ #418 (MovementProfile)
├─→ #419 (Sprint suppression)
└─→ #420 (TilePresence, parallel)
Server track (interaction verbs):
#421 (ObjectType) → #422 (Two-phase verb computation) → client #432 (interaction list)
Server track (inventory):
#424 (Smuggler inventory) → client #438 (inventory UI)
Copy #441 (item specs) → informs server #424 content
Client track (cursor + fog):
#429 (Cursor states) → #432 (interaction list)
#430 (Fog shader rebuild) → standalone, large rewrite
#433 (World radial menu) → standalone
Client track (UI):
#438 (Inventory UI) → blocked by server #449
#439 (Stance UI) → blocked by server #449
Critical integration point: Server #449 (ObserverSnapshot v6) unblocks client #438 and #439. Server #417 (stance system) and #424 (inventory) must land before client UI can integrate.
Cross-Team Integration Points
Server → Client: ObserverSnapshot v6 (#449)
Server deliverable: Add two new fields to ObserverSnapshot (bridge wire protocol):
player_stance: MovementStance(enum: Sprint/Walk/Careful/Crouch)player_inventory: Vec<VisibleItem>(items carried by player)
Client consumers:
- #438 (Inventory UI) reads
player_inventoryto render 3x3 grid - #439 (Stance UI) reads
player_stanceto show HUD indicator
Timeline: Server #449 should land early in sprint (day 1-2) to unblock client UI work. Client can scaffold UI in parallel, but cannot test until #449 lands.
Coordination: Dudley (server) and Stig (client) coordinate on wire format. Use existing ObserverSnapshot pattern (see server/src/bridge/types.rs line 29-48 for current v5).
Server → Client: Two-phase verb computation (#422 → #432)
Server deliverable: Refactor interaction verb computation into Phase 1 (ObjectType → max verb set) and Phase 2 (observer KG filter → final verbs). Populate nearby_interactions in ObserverSnapshot with 2-4 filtered verbs per entity.
Client consumer: #432 (entity interaction list) reads nearby_interactions and renders vertical list. Clicking a verb sends PlayerAction::Interact with target + verb.
Timeline: Server #421 (ObjectType) + #422 (two-phase) must land before client #432 can integrate. Client can build UI skeleton in parallel (test with mock data).
Coordination: Dudley (server) defines verb wire format (verb name, display text, tooltip). Stig (client) consumes format and renders insert-styled list per Araminta's D-056/D-057 spec.
Copy → Server: Smuggler item specs (#441 → #424)
Copy deliverable: YAML item specs for 3 smuggler items (manifest copy, access token, comm log). Each item includes name, description, flavor text, knowledge link (FactId), contraband flag.
Server consumer: #424 (smuggler inventory) reads item specs, spawns items as world entities with CarriedBy component, implements Take/Place verbs.
Timeline: Copy #441 can land anytime during sprint (small authoring task, ~2-3 hours). Server #424 can proceed without item specs (use placeholder data), then swap in real content once copy delivers.
Coordination: Paula (copy) and Dudley (server) agree on YAML schema format early in sprint. Server defines schema, copy authors content.
Sprint Completion Proof
At the end of Sprint 6, the following must be observable in-game:
Movement and Stances
- Stance toggle works: Press C (or Ctrl) to cycle through Sprint → Walk → Careful → Crouch. HUD indicator updates (#439).
- Movement speed changes: Sprint = 1 tile/1 tick (fast). Walk = 1 tile/2 ticks (default). Careful = 1 tile/3 ticks (slow). Observable by walking across 10 tiles and counting ticks.
- Monologue rate changes: Sprint suppresses monologue (fewer lines). Careful enhances monologue (more lines, enhanced observation). Observable by changing stances in monologue-rich area (bar, hub).
- Sprint suppresses interactions: While sprinting, interaction prompts disappear (no verb list shown, even when hovering over NPC). Walk/Careful/Crouch restore interactions.
- Same-tile occupancy works: Two NPCs can occupy the same tile if one is Standing and one is Seated/Prone. Collision detection prevents two Standing entities on same tile.
Fog and Visibility
- Fog shader renders: Launch game, observe 5-layer fog system:
- Clear cone with soft gradient edge (no hard line)
- Light fog (peripheral) with animated Perlin noise, desaturated colors
- Deep fog (previously explored) with zone temperature tint (bar=warm, corridor=neutral)
- Unexplored (with maps app) shows wireframe outlines
- Unexplored (no maps) shows solid near-black
- Fog breathes: Noise animation cycles over 8-10s (light fog) and 15-20s (deep fog). Fog feels alive, not static.
Interaction and Verbs
- Cursor states work: Hover over empty tile = default ticks. Hover over NPC = entity hover (ticks expand, D-033 color). Hover over object = X-shape grey cursor. All transitions 150ms.
- Entity interaction list renders: Hover over NPC with multiple verbs → vertical list appears (2-4 options max), anchored to entity, insert-styled. Click verb → PlayerAction::Interact sent to server.
- World radial menu works: Right-click anywhere → radial menu opens with 2 spokes (Observe + Insert). Drag-release or click-click to select. Renders on z-layer 6.
- Two-phase verb computation: Same object shows different verbs per character. Smuggler hovers over crate → sees "Move/Stash". Detective hovers → sees "Scan/Flag". Character-archetype differentiation via KG filter.
Inventory
- Inventory UI renders: Smuggler character → bottom-right 3x3 grid appears. Icons for 3 items (manifest copy, access token, comm log). Detective character → 2 items (or empty if no items carried). Press 1-9 keys → item selection feedback.
- Take/Place verbs work: Approach item on ground → interaction list shows "Take". Click Take → item disappears from world, appears in inventory UI. Inventory icon click + right-click world → "Place" verb appears. Click Place → item returns to world.
- Info boundary respected: Items in smuggler's inventory are NOT visible to NPCs (no "What are you carrying?" monologue unless confrontation/scan mechanic triggered, deferred to future sprint #425).
Integration
- ObserverSnapshot v6 wire works: Client receives
player_stanceandplayer_inventoryfields from server. HUD updates reflect server state (no desyncs). - All systems compose: Stance + fog + verbs + inventory all work simultaneously. No system breaks another.
Validation Tests
Simulation:
# Stance system tests
cargo test simulation::movement::stance
# Tile occupancy tests
cargo test simulation::movement::tile_presence
# Two-phase verb computation tests
cargo test simulation::interaction::two_phase
# Inventory tests
cargo test simulation::interaction::carried_by
Client rendering:
# Godot client launches without errors
cd client && godot --headless --quit
# Shader compilation (fog shader)
# Manual test: launch game, observe fog rendering with no errors in console
Content validation:
# Smuggler item specs validate
make validate-content
# Item YAML loads in server
cargo run --bin line-previewer -- content/campaigns/main/systems/krenn/sova/sova-transit/items/smuggler-inventory.yaml
Test Plan Alignment (D-030)
Sprint 6 is in Phase 2 (integration tests) transitioning to Phase 3 (simulation depth).
Key test requirements:
Phase 2 (integration):
- Bridge protocol test: ObserverSnapshot v6 serializes/deserializes correctly with new fields
- Interaction pipeline test: PlayerAction::Interact → verb computation → ObserverSnapshot update → client rendering
- Movement integration: stance toggle → movement speed change → monologue rate change (full pipeline)
Phase 3 (simulation depth):
- Stance system: all 4 stances (Sprint/Walk/Careful/Crouch) produce correct tick multipliers
- Tile occupancy: collision detection respects posture layers
- Two-phase verbs: Phase 1 (ObjectType) + Phase 2 (KG filter) produce correct verb sets
- Inventory: Take/Place verbs respect info boundary (carried items private)
Hoshe's involvement: QA review on #449 (ObserverSnapshot v6 — critical bridge change), #422 (two-phase verbs — complex KG integration), #430 (fog shader — large rewrite, performance regression risk).
Integration Risks
Risk: ObserverSnapshot v6 wire format changes break existing client rendering.
Mitigation: Server #449 lands early (day 1-2). Stig tests client with new wire format before implementing #438 and #439. If deserialization breaks, revert #449 and coordinate with Dudley on schema fix.
Risk: Fog shader rebuild (#430) is a complete rewrite. High risk of regressions (performance, visual artifacts, z-layer conflicts).
Mitigation: Stig implements #430 on feature branch, tests in isolation before merging. Performance target: <1ms/frame (monitor with Godot profiler). If performance regresses, scale back noise animation complexity (reduce cycle count or simplify Perlin shader).
Risk: Two-phase verb computation (#422) is architecturally complex. Risk of Phase 1/Phase 2 boundary mismatches or KG query bugs.
Mitigation: Dudley implements #421 (ObjectType) first to validate Phase 1 logic. Add integration tests for Phase 2 KG filter (verify correct verbs per character archetype). Tyre reviews architecture before merge.
Risk: Copy #441 (item specs) might not align with server #424 YAML schema expectations.
Mitigation: Dudley defines YAML schema early in sprint (day 1), shares with Paula. Paula authors item specs against known schema. Server #424 uses placeholder data until copy delivers, so no blocking dependency.
Risk: Sprint has 18 tickets across 3 teams. High ticket count = coordination overhead.
Mitigation: Parallel tracks reduce blocking. Server #449 unblocks client early. Fog shader (#430) and world radial menu (#433) are standalone (no cross-team dependencies). Copy #441 is small (2-3 hours). Most complexity is server-side (#417, #422, #424) where Dudley has focused scope.
Definition of Done
Sprint 6 is complete when:
- All 18 tickets marked
donein database - All server code committed to
serverbranch and tested - All client code committed to
clientbranch and tested - All copy content committed to
copybranch and validated - PRs created for all three teams
- Sprint completion proof checklist verified (all 16 observable criteria met)
- Team Leader reviews in-game playtest: stance toggle, fog shader, interaction verbs, inventory UI all working together without desyncs or visual regressions
PR Coordination
Three team PRs will be created:
-
Server team PR:
- Branch:
server - Scope: ObserverSnapshot v6, stance system, tile occupancy, two-phase verb computation, smuggler inventory
- Review focus: Bridge protocol compatibility, simulation correctness, KG integration
- Branch:
-
Client team PR:
- Branch:
client - Scope: Cursor states, fog shader rebuild, interaction list, world radial menu, inventory UI, stance UI
- Review focus: Rendering performance, visual consistency with Araminta spec, z-layer correctness
- Branch:
-
Copy team PR:
- Branch:
copy - Scope: Smuggler item specs (3 items)
- Review focus: Content quality, voice consistency, knowledge graph integration
- Branch:
All PRs target main branch. Server PR should merge first (provides wire format for client). Client and copy can merge in parallel after server lands.
Notes for Team Leader
Sprint 6 is the tactile sprint. After 5 sprints of infrastructure, this is the first sprint where the player's hands touch the world:
- Movement feels deliberate: Stance toggle creates tactical choices (sprint ahead to position, careful to observe, walk when safe). Speed is not just convenience — it's intention.
- Fog feels alive: The shader rebuild (D-059) replaces the current flat fog with breathing, animated, knowledge-graph-driven fog. This is the visual signature of asymmetric information.
- Interaction feels responsive: Cursor states (D-056) and vertical lists (D-057) replace generic "E to interact" with character-aware, knowledge-gated verb menus. The world responds to who you are, not just where you are.
- Inventory feels risky: Smuggler carries contraband (manifest, token, log). These items are leverage and liability. Detective carries authority, not objects. Character differentiation through what you hold.
Sprint 6 delivers D-027 criterion #4: "observe → notice → follow → discover sequence emerges from systems not scripts." The stance system (observe in Careful), the verb system (notice contradictions), the fog system (follow entities in fog), and the inventory system (discover evidence) compose into emergent detective gameplay.
Quality bar: All systems must compose without breaking each other. Stance + fog + verbs + inventory running simultaneously with no desyncs, no performance regressions, no visual artifacts. Integration is the success metric.