Files
settled-reach/CHANGELOG.md
T
2026-02-12 01:16:02 +01:00

199 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Changelog
All notable changes to The Settled Reach project will be documented in this file.
Format based on [Keep a Changelog](https://keepachangelog.com/).
## [Unreleased]
### Fixed
- Type safety in GameState visible_tiles loop — validates Dictionary with x/y keys before access (PR #11 review)
- Entity renderer skips redundant modulate.a writes when alpha unchanged (PR #11 review)
### Added
- Knowledge graph system (#361, #362, #363, #365) — per-entity KnowledgeGraph component (D-041), StableEntityId + EntityRegistry, KnowledgeEventQueue, decay system, 4-level confidence hierarchy
- Direct observation knowledge flow (#364) — perception emits DirectObservation/LeftLOS events to knowledge graph, entities entering/leaving LOS tracked
- Protocol v2 decoder — extracts game_time, player_facing, visible_tiles, and per-entity visibility sectors from ObserverSnapshot v2
- D-033 entity color palette (#130) — relationship-based colors (teal/green/amber/red), Phase 1 defaults by entity kind
- Peripheral vision dimming — entities in peripheral vision rendered at 50% alpha (D-015)
- Player facing direction indicator — Polygon2D triangle on player entity showing 8-directional facing
- GameState v2 fields — game_time, player_facing, visibility_sectors stored from snapshot data
- Test snapshot updated to v2 format with visibility sectors, game_time, and player_facing
- Observer visibility query (#112) — replaces unfiltered generate_snapshot with LOS-filtered compute_observer_snapshot combining shadowcasting + vision cone
- Vision cone system (#111) — forward/peripheral/blind sectors per D-015, Facing component updated on movement
- Symmetric shadowcasting (#110, #359) — Albert Ford algorithm with rational fraction slopes, benchmarked 1.2-10.5x faster than recursive, symmetry guaranteed (D-035)
- ObserverSnapshot v2 schema (#358, #25) — version field, GameTime, FacingDirection, VisibleTile, VisibilitySector types, visibility tag on entities
- D-035 decision record — symmetric shadowcasting selected over recursive (resolves Q-018)
- Tile rendering engine (#129) — programmatic TileSet with floor/wall/door/object placeholders, renders from snapshot tile data
- Fog overlay rendering (#131) — three visibility states (visible/fog-edge/hidden) via TileMapLayer overlay
- Camera lock to character (#116) — Camera2D smoothing at 2x zoom, locked to player position (D-015)
- Test room environment — 8x8 room with corridor and Manhattan-distance visibility for development without server
- `ticket team` command and `--team` filter — comma-separated team assignment for tickets (server, client, joint, content)
### Changed
- `start-sprint` skill now requires plan mode — agent must create and get approval for a concrete sprint plan before starting implementation
### Fixed
- Entity renderer protocol field mismatches — "id"→"entity_id", "type"→"kind.variant", "position"→x/y fields now match Protocol.decode_entity() output
- Entity centering — entities (24x24) now centered within 32px tiles instead of top-left aligned
- `start-sprint` skill uses `git rev-parse --show-toplevel` for worktree-safe absolute paths — fixes "No such file or directory" errors on team branches
### Changed
- Background clear color set to near-black for unexplored areas (was default Godot gray)
- Scene render order: Tiles → FogOverlay → Entities (fog covers tiles, entities render on top)
- FogOverlay node type changed from Node2D to TileMapLayer for tile-based fog rendering
- GameState now stores visible_tiles and visible_positions from snapshots
- Test snapshot includes player entity (kind "Player"), second NPC entity, tile data, and visibility data
### Added
- Sprint 2 "See" briefings (server, client, joint) — fog of perception through the bridge
- `/plan-sprint` skill — automates sprint planning workflow and briefing file generation
- `ticket show` multi-ID support and `--brief` flag for compact human-readable output
- Q-018 through Q-023 — 6 open questions from architecture audit (shadowcasting, entity ID stability, collision resolution, tick overflow, pathfinding cache, debug visualization)
- 5 architecture spike workshop briefs (knowledge graph, observer pipeline, NPC AI state machines, save/load, map authoring)
- 17 tickets from architecture audit (#339-#355) — 7 Sprint 1 tasks, 5 Sprint 2+ tasks, 5 workshop epics
- End-to-end connection test (#81) — GDScript test spawning Rust server, connecting via LocalBridge, sending MoveNorth input, verifying player movement in snapshot response (D-030 Layer 3)
- Batch input encoding (Vec\<PlayerInput\> wire format) — Protocol.encode_player_inputs() batches all inputs per tick into one framed message matching server expectations
- EntityKind::Player fixture — snapshot_player.msgpack for cross-language testing, multi-entity fixture updated to include all 4 entity kinds
- 7 new tests (4 batch encoding, 1 framed batch roundtrip, 1 Player fixture decode, 1 E2E connection), 43 total client tests passing
- LocalBridge GDScript TCP transport (#79) — 4-byte big-endian length-prefix framing matching Rust server, StreamPeerTCP wrapper with partial read handling
- ServerProcess subprocess manager — spawns/stops Rust server via OS.create_process(), auto-cleanup on destruction
- SimBridge live transport integration — _process() polling loop for TCP receive/send, connection state machine (DISCONNECTED → CONNECTING → CONNECTED → ERROR)
- 8-directional input support — 4 diagonal movement variants (NE, SE, SW, NW) in InputMapper, SimBridge wire mapping, and project.godot input actions
- 12 LocalBridge tests (framing roundtrips, cross-layer Protocol+framing, diagonal wire mapping)
- 4 diagonal movement cross-language fixtures (Rust → GDScript, D-030 Layer 1)
- 33 total client tests passing (up from 20)
- TcpBridge transport for Godot client connection — TCP localhost IPC alongside existing Unix socket LocalBridge
- Input processing system (process_player_input) — drains InputQueue, converts PlayerActions to MoveIntent components, handles pause/unpause
- Snapshot generation system (generate_snapshot) — builds ObserverSnapshot from ECS state with render coordinate conversion
- Bridge I/O systems (receive_bridge_inputs, send_bridge_snapshot) — wire bridge to ECS pipeline with graceful disconnect detection
- Full game loop in main.rs — TCP accept, tick loop with ServerRunning resource, CLI/env addr config
- PlayerCharacter marker component, Player EntityKind variant, SnapshotBuffer resource
- E2E game_loop integration test verifying player movement through full pipeline
- 8 new tests (3 TCP bridge + 4 input processing + 1 E2E game loop), total 53
- Architecture audit framework (docs/audits/) — adversarial two-round review pattern by Tyre + Troblum
- Sprint 1 architecture review — full decision + code audit, GREEN architecture, AMBER implementation plan
- v0.1 content gap analysis workshop — 6 agents, 2 rounds, 9 content layers, 8 new decisions (D-032 through D-039)
- D-032: Separate monologue pools per playable character (hard partition, not filter)
- D-033: Entity color represents relationship to player character (asymmetric per character)
- D-034: THE FRIEND NPC pattern — production-level emotional centerpiece per character (Kael Davan, Sera Venn)
- D-035: Converged tag taxonomy for dialogue/monologue line pools (6 structural + 3 selection tags)
- D-036: Sova Transit District / Krenn System as v0.1 setting (first named star system)
- D-037: Contraband specification — unlicensed lattice components (moral ambiguity by design)
- D-038: Audio in v0.1 scope — 8 AI-generated files via Stable Audio Open
- D-039: All 6 wow moments promoted to v0.1 must-have scope
- LocalBridge IPC over Unix domain sockets (#78) — length-prefixed MessagePack framing, SimBridge implementation, BridgeResource ECS wrapper
- Tile collision system (#236) — TilePosition component, chunk-based WalkabilityMap (D-012), MoveIntent + validate_movement system
- TilePosition ↔ f32 render coordinate conversion (to_render_coords, from_render_coords) bridging simulation and wire format
- Chunk load/unload support in WalkabilityMap — HashMap<ChunkCoord, ChunkData> with 32x32 tile chunks
- 8-directional movement — diagonal PlayerAction variants (MoveNortheast/Northwest/Southeast/Southwest) + TilePosition::all_neighbors()
- Entity-entity collision in validate_movement — spatial occupancy check prevents multiple entities on same tile
- 25 new tests (4 framing + 2 IPC integration + 17 movement unit + 2 movement integration), total 45
- MessagePack serialization for GDScript (ticket #77) — Protocol codec decoding ObserverSnapshot/PlayerInput from Rust wire format, encoding PlayerInput for server
- Godot4MessagePack library (pure GDScript) for MessagePack encode/decode
- Rust fixture generator (gen_fixtures.rs) producing canonical .msgpack test fixtures with rmp_serde
- 8 cross-language protocol tests verifying Rust↔GDScript MessagePack compatibility (D-030 Layer 1)
- SimBridge wired to Protocol codec with receive_bytes()/drain_outbound() for transport layer
- `db/connectors/ticket` CLI — ergonomic ticket management (list, show, create, assign, sprint, deps, search, epics, children, count) with JSON output
- Sprint 1 "Run" created with 8 stories targeting moving character on screen via IPC bridge
- Ticket skill rewritten to use ticket CLI instead of raw SQL wrapper scripts
- Godot 4 client boilerplate (epic #277) — scenes, autoloads (SimBridge, GameState, InputMapper), rendering stubs, UI shell (HUD, minimap, monologue display), input system with semantic actions
- gdUnit4 test framework with 7 tests (2 smoke + 5 D-030 Layer 1 fixture tests for snapshot parsing)
- make ci-client pipeline (lint, build, test via gdUnit4 headless runner)
- Camera tracking locked to player position (D-015), monologue display wired to snapshot data (D-016)
- Gitea tea CLI instructions in CLAUDE.md — non-interactive flags, PR workflow patterns
- `/review-pr` skill — dual-agent PR review with Hoshe (code quality) and Tyre (architecture) in parallel, Gitea integration, vendor file exclusion patterns, local merge workflow, heredoc workaround
- Automated Rust install via `make setup` (tooling/install-rust script, rustup + clippy + rustfmt)
- Automated Godot download/install via `make setup` (tooling/install-godot script, installs to ~/bin/godot4)
- InputQueue tick ordering enforcement via debug_assert (determinism guard)
- Serialization roundtrip tests for all PlayerAction and EntityKind variants (D-030 Layer 1)
- Edge case tests: day wraparound at midnight, day() calculation, out-of-order input rejection
- Test runner switched to cargo-nextest (D-030 requirement)
- Rust/bevy_ecs simulation server boilerplate (epic 276) — Cargo project, module structure, core ECS types, plugin scaffolding, deterministic simulation resources, test infrastructure
- SimulationTime resource with D-031 time system (10 ticks/game-minute, 4 day phases)
- SimRng deterministic RNG resource (ChaCha20, seeded for replay)
- InputQueue resource for timestamped semantic player actions
- ObserverSnapshot and PlayerInput IPC types with MessagePack serialization (D-020)
- SimBridge trait abstracting client-server transport
- CauseChain production component for information provenance tracking (D-030)
- SimulationTier types with LRU eviction support (D-026: Active/Background/StateSaved/Ungenerated)
- NPC 10-axis model components (D-024: 7 essential + 3 supporting + CombatCapability)
- Server test infrastructure: 11 inline unit tests + 4 integration tests (smoke + serialization round-trips)
- make ci-server pipeline verified green (clippy, fmt, build, test)
- Round 18 v0.1 gap analysis workshop — 7 agents, 2 rounds, 4 tracks (concept proof, wow factor, missing systems, testability)
- D-030: Testability architecture — 8 sub-decisions for ticket #214 (gdUnit4, hybrid Rust testing, CauseChain component, three-layer IPC testing)
- D-031: Time system — 10 ticks = 1 game-minute, 4 day phases (Morning/Afternoon/Evening/Night), diegetic clock display
- 41 new tickets from gap analysis: 3 epics (Movement & Collision, Observation & Interaction, Game State Management) + 38 stories
- 15 priority promotions including 3 tickets to critical (deterministic replay, divergent knowledge, divergent relationships)
- 21 new dependency records mapping critical path through collision → pathfinding → NPC movement → routine execution
- Workshop directory convention established with per-workshop subdirectories
- Project directory scaffold: client/, server/, tooling/, tests/, .config/, .cache/
- Top-level Makefile with dev workflow targets (setup, build, run, test, lint, ci, clean)
- Whitelistable sqlite-init and sqlite-seed wrapper scripts completing the db/connectors/sqlite-* set
- Round 17 content architecture workshop — Full team (8 agents, 3 rounds) defining content pipeline
- D-023: Three-tier content model (authored drama modules, templated content, procedural filler) with life-sim substrate
- D-024: NPC generation model — 10 axes (7 essential + 3 supporting) with CombatCapability ECS component
- D-025: Social site / functional cluster as atomic Tier 2 template unit (4-8 NPCs, 15-40 tiles)
- D-026: Simulation tiers with timestamp-based LRU eviction (Active/Background/State-saved/Ungenerated)
- D-027: Vertical slice — smuggler + detective two-character proof-of-concept (supersedes D-006)
- D-028: Dialogue architecture — tagged line pools with four relational layers (access tiers, history, trust-gating, unprompted disclosure)
- D-029: Population entanglement ratio — 30% flat / 50% mundane triangles / 20% intrigue-entangled
- Content architecture workshop brief documenting the "life first, drama second" design philosophy
- Mellanie (Copywriter) activated from standby for content authoring phase
- Round 16 faction development — Full faction framework with lore, political analysis, mechanical grounding (session closed, awaiting team input for v0.1 selection)
- 3D reputation system: Trust × Usefulness × Exposure per faction
- Faction mechanical grounding: starting loadouts, information asymmetry, blind spots, resource loops
- Power dynamics analysis: formal vs. real power distribution across factions
- Character drama templates: whistleblower, inspector with conscience, dual-loyalty operative, reluctant conspirator
- Betrayal vectors and conspiracy potential for all six factions
- "First 30 Minutes" test demonstrating six mechanically distinct faction perspectives
- D-021: Official project title "The Settled Reach" confirmed, domain settledreach.com secured
- Round 14 worldbuilding — "The Settled Reach" original SF setting foundation with full team reactions
- Original terminology established: Settled Reach, Founder Gates, Span Gates, Interstitium, neural lattice, Meridian, imprint, re-embodiment, Perpetuals, the Unbound, Forking, Severance
- Four enhancement tiers: Baseline, Augmented, Transcendent, Elevated (plus the Threshold as endgame horizon)
- Two-tier death system: soft death (lattice intact) and hard death (lattice destroyed, imprint restore)
- Six factions: Concord Assembly, Syndics, Separatists, Guardians of Autonomy/Severance, Veil Institute, Lattice Commission
- Infrastructure-as-mystery: Builders inhabiting the Interstitium, Gyre events as leakage
- Miri's IP originality guardian role — flags concepts too close to source franchises
- Whitelistable wrapper scripts for SQLite and Qdrant connectors (sqlite-query, sqlite-exec, qdrant-search, qdrant-index, qdrant-health, qdrant-count)
- Architecture evaluation and risk assessment documents for Godot+Rust bridge approach
- Round 13 engine selection discussion — full team debate on engine paradigms
- D-020: Engine and architecture selection — Godot 4 client + Rust/bevy_ecs simulation server via subprocess/IPC
- Rejected alternatives R-004 through R-010 documented (pure Bevy, pure Godot, GDExtension, C++ GDExtension, Fyrox, custom framework, protobuf)
### Fixed
- create-skill references to nonexistent init_skill.py and package_skill.py scripts
- SimBridge wire format: inputs now batch-encoded as Vec\<PlayerInput\> array per server protocol (was sending individual inputs per frame)
- SimBridge server args: positional address format ("127.0.0.1:9876") matching server CLI, port default corrected to 9876
- Wire format mismatch: LocalBridge now uses rmp_serde::to_vec_named() (named maps) matching client Protocol.gd expectations
- EOF on bridge read now returns BridgeError::Transport for disconnect detection instead of empty Vec
- WalkabilityMap rewritten from flat Vec to chunk-based HashMap per D-012 architecture (Tyre review)
- LocalBridge mutex .unwrap() → .expect() for clearer panic messages (Hoshe review)
- Documented 16MB MAX_MESSAGE_SIZE rationale in framing.rs (Hoshe review)
- Client input_mapper double-check bug (redundant event.pressed + is_action_pressed)
- Bounds validation on snapshot position arrays in game_state.gd and entity_renderer.gd
- Deterministic test snapshots (replaced Time.get_ticks_msec() with incrementing counter)
- Tween overlap in monologue_display.gd (cancel active tween before creating new one)
- SubViewportContainer missing SubViewport child in minimap.tscn
- Cargo.toml edition 2024 → 2021 for broader toolchain compatibility
- Relationship.target_name: String → target_id: u64 for entity scalability (Tyre review)
- DayPhase enum now derives Serialize/Deserialize (consistent with other enums)
- Replaced all absolute paths (macOS and Linux) with project-relative paths across round-16 docs
- Removed duplicate ROUND-16-STATUS.md from project root (content already in round-16-session-notes.md)
- Added relative-path convention to Qatux agent persona for cross-system consistency
### Removed
- dotfiles/tmux.conf (no longer needed)
### Changed
- Q-018 (shadowcasting algorithm selection) resolved via D-035
- All 18 agent briefings updated for decisions/ directory split and DEVOPS.md references
- Implementation agents (Dudley, Hoshe, Justine, Oscar, Si, Stig, Tyre) now include Development Workflow sections with Makefile targets
- Q-009 (time system) resolved via D-031
- Ticket catalog expanded from 232 to 273 tickets with sprint sequencing (Run → Feel → Content → Validate)
- Ticket skill updated to use wrapper scripts exclusively (no more direct python3 calls)
- Miri's role updated from Canon Guardian to Worldbuilder & Setting Designer (original IP pivot)
- Project description updated to reflect D-020 engine decision
- Connector usage instructions now reference wrapper scripts instead of python3 directly
- Q-001 (engine selection) resolved via D-020