feat(simulation): Sprint 8 React — dialogue pipeline, perception, determinism #26

Closed
jpmschweitzer wants to merge 0 commits from server into main
Owner

Summary

Sprint 8 server delivery: activate the dialogue pipeline end-to-end — player talks to NPCs, NPCs respond, the world reacts.

Features (5 tickets)

  • #305 Dialogue selection pipeline — 4-layer filtering engine (access tier, situation, trust, topic+mood weighted scoring)
  • #452 ContentSlug component for stable entity identity across save/load
  • #427 Walk-away KG recording with IncompleteInteraction events (D-064)
  • #450 Anomaly detection wired to urgent cognitive delay (0.3s vs 0.6s)
  • #451 Recognition monologue fires during cognitive delay window, not after (D-060)

Fixes (4 determinism fixes)

  • #456 visible_ids HashSet → BTreeSet for stable iteration
  • #457 Sort visible entities in snapshot by entity_id
  • #458 Sort movers by Entity bits in validate_movement
  • Pause guard widened to block all actions (not just movement) while paused

Infrastructure

  • #459 Server --test-mode, --port 0, --seed CLI flags with LISTENING:{port} stdout signal

Tests (50+ new tests, 467 total, 0 failures)

  • #461-463, #468 Pause guard suite (7 tests)
  • #466 Determinism gauntlet — 20-tick replay regression test
  • #467 Per-fix determinism unit tests
  • #469 EntityRegistry lifecycle tests
  • #471 Boundary value encode/roundtrip (41 values)
  • #472 14 raw + 5 snapshot boundary fixtures
  • #473 Encoding asymmetry tests (GDScript signed → Rust unsigned)
  • #479 Malformed batch rejection test

Protocol

  • Bumped v7 → v8 (dialogue_response field in ObserverSnapshot, #[serde(default)] for backward compat)

Test plan

  • cargo test — 467 tests pass, 0 failures
  • Client integration: protocol v8 dialogue_response field decode
  • End-to-end: Talk verb → NPC greeting in dialogue box
  • Walk-away: WASD during dialogue → KG records incomplete interaction

🤖 Generated with Claude Code

## Summary Sprint 8 server delivery: activate the dialogue pipeline end-to-end — player talks to NPCs, NPCs respond, the world reacts. ### Features (5 tickets) - **#305** Dialogue selection pipeline — 4-layer filtering engine (access tier, situation, trust, topic+mood weighted scoring) - **#452** ContentSlug component for stable entity identity across save/load - **#427** Walk-away KG recording with IncompleteInteraction events (D-064) - **#450** Anomaly detection wired to urgent cognitive delay (0.3s vs 0.6s) - **#451** Recognition monologue fires during cognitive delay window, not after (D-060) ### Fixes (4 determinism fixes) - **#456** visible_ids HashSet → BTreeSet for stable iteration - **#457** Sort visible entities in snapshot by entity_id - **#458** Sort movers by Entity bits in validate_movement - Pause guard widened to block all actions (not just movement) while paused ### Infrastructure - **#459** Server --test-mode, --port 0, --seed CLI flags with LISTENING:{port} stdout signal ### Tests (50+ new tests, 467 total, 0 failures) - **#461-463, #468** Pause guard suite (7 tests) - **#466** Determinism gauntlet — 20-tick replay regression test - **#467** Per-fix determinism unit tests - **#469** EntityRegistry lifecycle tests - **#471** Boundary value encode/roundtrip (41 values) - **#472** 14 raw + 5 snapshot boundary fixtures - **#473** Encoding asymmetry tests (GDScript signed → Rust unsigned) - **#479** Malformed batch rejection test ### Protocol - Bumped v7 → v8 (dialogue_response field in ObserverSnapshot, `#[serde(default)]` for backward compat) ## Test plan - [x] `cargo test` — 467 tests pass, 0 failures - [ ] Client integration: protocol v8 dialogue_response field decode - [ ] End-to-end: Talk verb → NPC greeting in dialogue box - [ ] Walk-away: WASD during dialogue → KG records incomplete interaction 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jpmschweitzer added 7 commits 2026-02-17 17:42:38 +01:00
Replace HashSet with BTreeSet for visible_ids, sort visible_tiles by
coordinates, sort visible entities in snapshot by entity_id, and sort
movers by Entity bits in validate_movement. Required by D-010 principle 4
(deterministic simulation). Fixes #456, #457, #458.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add CLI argument parsing for test infrastructure: --test-mode enables
deterministic seed (42) and warn-level tracing to stderr, --port allows
OS-assigned ports (--port 0), --seed overrides RNG seed. Prints
LISTENING:{port} to stdout after bind for test harness discovery.
Extracts setup_proof_room() for reuse. Fixes #459.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add AnomalyMarker component and detect_anomalies() system that flags
entities with KG relationship PersonOfInterest or Contradicted state
for urgent cognitive delay (0.3s vs 0.6s normal). Add
trigger_recognition_monologue() that fires monologue at delay START
(when grey blob appears), not at completion — the monologue IS the
recognition process per D-060. Includes v0.1 fallback recognition
lines and cooldown tracking. Fixes #450, #451.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement full dialogue selection pipeline (D-028): 4-layer filtering
engine with access tier, situation derivation, trust tier, and weighted
topic+mood scoring via SimRng. Add ContentSlug component for stable
content identity across save/load. Add walk-away KG recording with
IncompleteInteraction events per D-064 three-phase consequences. Bump
protocol to v8 with DialogueResponseEvent. Fixes #305, #427, #452.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 50+ tests: pause guard suite (movement, unpause, roundtrip, stance,
interact, batch, tick_rate), EntityRegistry lifecycle (stale mapping,
re-register, unknown unregister), boundary value encode/roundtrip (41
values), encoding asymmetry (GDScript signed→Rust unsigned), malformed
batch rejection, determinism gauntlet (20-tick replay), per-fix
determinism unit tests, and recognition monologue integration tests.
Fix pause guard to block all actions except Pause/Unpause while paused.
Fixes #461-463, #466-469, #471-473, #479.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update existing snapshot fixtures for protocol v8 (dialogue_response
field). Add 14 raw boundary value fixtures and 5 snapshot boundary
tick fixtures for encoding edge case coverage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author
Owner

Review: server → main (type: code)

Hoshe (Code Quality): REQUEST_CHANGES

Solid, well-structured PR with good test density. Three warnings need addressing.

# File Severity Issue
1 serialization.rs:~82 warning WalkAway variant missing from exhaustive all_player_action_variants_roundtrip — D-030 wire contract gap
2 dialogue.rs:400-406 warning speaker_entity_id: 0 silent fallback when target not in registry — client gets wrong speaker
3 monologue.rs:84-96 warning shown_ids: Vec<String> grows unbounded, O(n) scan per tick — use HashSet or cap
4 input.rs:329-368 suggestion handle_talk no server-side range check before TalkRequest
5 dialogue.rs:411-415 suggestion process_talk_interaction may overwrite active ActiveDialogue without IncompleteInteraction
6 determinism.rs:end suggestion different_seed_produces_different_replay untestable — add Talk to exercise SimRng
7 serialization.rs:161 suggestion panic! on unknown fixture — use assert for cleaner failure
8 serialization.rs:536-537 suggestion Two VerbKind variants share label "Observe" — could mask serde collision

Tyre (Architecture): REQUEST_CHANGES

Substantial and well-architected. D-028 four-layer pipeline clean, determinism fixes correct, --test-mode handshake elegant. One warning-level ordering gap.

# File Severity Issue
1 bridge/mod.rs + perception/mod.rs warning trigger_recognition_monologue reads AnomalyMarker but no cross-plugin ordering with detect_anomalies — latent determinism bug
2 dialogue.rs:~155 warning Secret trust tier permanently unreachable — ignores KG confidence. Add TODO minimum
3 dialogue.rs:75-100 suggestion DialogueCooldownTracker.used Vec → BTreeMap (D-041 mandate, O(log n))
4 bridge/mod.rs suggestion process_walk_away and process_talk_interaction have no ordering — add .after(process_talk_interaction)
5 main.rs:~110 suggestion Dead conditional — both branches call setup_proof_room. Collapse until Gauntlet loader

Verdict: CHANGES REQUESTED

Key issues:

  1. System ordering gap: trigger_recognition_monologue.after(detect_anomalies) needed
  2. WalkAway missing from wire roundtrip test (D-030 gap)
  3. speaker_entity_id: 0 silent fallback — skip or warn
  4. shown_ids unbounded growth — Vec → HashSet/BTreeSet
  5. Secret trust tier unreachable — needs TODO comment
## Review: server → main (type: code) ### Hoshe (Code Quality): REQUEST_CHANGES Solid, well-structured PR with good test density. Three warnings need addressing. | # | File | Severity | Issue | |---|------|----------|-------| | 1 | serialization.rs:~82 | warning | `WalkAway` variant missing from exhaustive `all_player_action_variants_roundtrip` — D-030 wire contract gap | | 2 | dialogue.rs:400-406 | warning | `speaker_entity_id: 0` silent fallback when target not in registry — client gets wrong speaker | | 3 | monologue.rs:84-96 | warning | `shown_ids: Vec<String>` grows unbounded, O(n) scan per tick — use HashSet or cap | | 4 | input.rs:329-368 | suggestion | `handle_talk` no server-side range check before TalkRequest | | 5 | dialogue.rs:411-415 | suggestion | `process_talk_interaction` may overwrite active ActiveDialogue without IncompleteInteraction | | 6 | determinism.rs:end | suggestion | `different_seed_produces_different_replay` untestable — add Talk to exercise SimRng | | 7 | serialization.rs:161 | suggestion | `panic!` on unknown fixture — use assert for cleaner failure | | 8 | serialization.rs:536-537 | suggestion | Two VerbKind variants share label "Observe" — could mask serde collision | ### Tyre (Architecture): REQUEST_CHANGES Substantial and well-architected. D-028 four-layer pipeline clean, determinism fixes correct, --test-mode handshake elegant. One warning-level ordering gap. | # | File | Severity | Issue | |---|------|----------|-------| | 1 | bridge/mod.rs + perception/mod.rs | warning | `trigger_recognition_monologue` reads `AnomalyMarker` but no cross-plugin ordering with `detect_anomalies` — latent determinism bug | | 2 | dialogue.rs:~155 | warning | `Secret` trust tier permanently unreachable — ignores KG confidence. Add TODO minimum | | 3 | dialogue.rs:75-100 | suggestion | `DialogueCooldownTracker.used` Vec → BTreeMap (D-041 mandate, O(log n)) | | 4 | bridge/mod.rs | suggestion | `process_walk_away` and `process_talk_interaction` have no ordering — add `.after(process_talk_interaction)` | | 5 | main.rs:~110 | suggestion | Dead conditional — both branches call `setup_proof_room`. Collapse until Gauntlet loader | ### Verdict: CHANGES REQUESTED **Key issues:** 1. System ordering gap: `trigger_recognition_monologue.after(detect_anomalies)` needed 2. `WalkAway` missing from wire roundtrip test (D-030 gap) 3. `speaker_entity_id: 0` silent fallback — skip or warn 4. `shown_ids` unbounded growth — Vec → HashSet/BTreeSet 5. `Secret` trust tier unreachable — needs TODO comment
jpmschweitzer added 2 commits 2026-02-17 18:13:13 +01:00
Warnings fixed:
- Add WalkAway to all_player_action_variants_roundtrip test
- Warn and skip on unresolvable speaker_entity_id (was silent 0)
- Change MonologueState.shown_ids from Vec to HashSet (O(1) lookup)
- Add cross-plugin ordering: trigger_recognition_monologue after
  detect_anomalies (latent determinism bug)
- Add TODO for unreachable Secret trust tier

Suggestions addressed:
- Server-side range check for Talk verb in handle_talk (CLOSE_RANGE)
- Emit IncompleteInteraction before overwriting ActiveDialogue
- Add different_seed_produces_different_replay determinism test
- Replace panic with assert for unknown fixture naming convention
- Fix duplicate "Observe" label: ExamineNpc now uses "Examine NPC"
- Change DialogueCooldownTracker.used from Vec to BTreeMap (D-041)
- Add .after(process_talk_interaction) to process_walk_away ordering
- Collapse dead conditional in main.rs (both branches identical)

468 tests pass, 0 failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author
Owner

Re-Review: server → main (type: code) — Round 2

Hoshe (Code Quality): APPROVE

All 8 original items + 5 Tyre fixes verified. 468 tests pass. No regressions.

Tyre (Architecture): APPROVE

All 13 items correctly addressed. System ordering fixes sound per D-010/D-030. Cross-plugin constraints acyclic. Ordering graph complete.

Verdict: APPROVED ✓

## Re-Review: server → main (type: code) — Round 2 ### Hoshe (Code Quality): APPROVE All 8 original items + 5 Tyre fixes verified. 468 tests pass. No regressions. ### Tyre (Architecture): APPROVE All 13 items correctly addressed. System ordering fixes sound per D-010/D-030. Cross-plugin constraints acyclic. Ordering graph complete. ### Verdict: APPROVED ✓
jpmschweitzer closed this pull request 2026-02-17 18:22:02 +01:00

Pull request closed

This pull request cannot be reopened because the branch was deleted.
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jpmschweitzer/settled-reach#26