Files
settled-reach/docs/test-plans/sprint-11-combine.md
T
jpmschweitzerandClaude Opus 4.6 9d2ab53302 docs(docs): add frontmatter to test plans, test reports, and audits
Standardized YAML frontmatter on 7 files across docs/test-plans/,
docs/test-reports/, and docs/audits/.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 18:55:30 +01:00

143 lines
8.1 KiB
Markdown

---
title: "Sprint 11 Combine — #507 and #522"
description: "Test plan for Sprint 11 combining WRONG button ring buffer (#507) and OQ-07 no-insert interaction behaviour (#522), covering happy paths, edge cases, integration, and performance tests."
type: test-plan
status: active
ticket: "#507, #522"
created: 2026-02-19
updated: 2026-02-19
---
# Test Plan: Sprint 11 Combine — #507 and #522
- **Date**: 2026-02-19
- **Sprint**: 11 (Combine)
- **Spec references**: D-056, D-057, D-030, D-020
- **Tickets**: #507 (WRONG button ring buffer), #522 (OQ-07 no-insert behavior)
- **QA Engineer**: Hoshe
---
## #507: WRONG Button Full Captures
### Spec reference
D-030 (testability), D-020 (ObserverSnapshot boundary). Sprint 11 client.md §Notes #507.
### What's changing from MVP (#495)
MVP (done Sprint 9): F12 → pause → single snapshot → render.txt + snapshot.json + description.txt.
Upgrade: 60-tick rolling ring buffers (inputs + snapshots), seed file, replay compatibility.
### Happy path tests
1. **Ring buffer capacity**: `_get_buffer_capacity()` returns 60.
2. **Buffer pre-allocation**: Buffer array has 60 slots immediately after `_ready()`, no lazy allocation.
3. **Input push fills buffer**: After pushing 10 ticks of inputs, buffer has 10 entries.
4. **Snapshot push fills buffer**: After pushing 10 snapshots, snapshot buffer has 10 entries.
5. **JSONL format — inputs**: `_format_inputs_jsonl()` returns N lines for N ticks pushed, each line is valid JSON array.
6. **JSONL format — snapshots**: `_format_snapshots_jsonl()` returns N lines for N ticks, each line is valid JSON.
7. **JSONL line format matches replay.rs**: Each line is a JSON array of PlayerInput objects (`[{"tick":N,"action":"..."}]`), parseable by `tooling/test-client --replay`.
8. **Empty tick flush**: An idle tick pushes an empty array `[]` to input buffer; flushes as `[]` line.
9. **seed.txt present**: `seed.txt` is written to the report directory on capture.
10. **description.txt unchanged**: Description, tick, room, stance, facing, position all still present.
11. **Directory name unchanged**: `gauntlet-t{tick}-{timestamp}/` format preserved.
12. **Existing files preserved**: `snapshot.json` and `render.txt` still written (MVP files).
### Edge cases
13. **Ring buffer circular overwrite**: After pushing 61 ticks, buffer has 60 entries (oldest evicted, newest kept).
14. **Ring buffer 60 exact**: After pushing exactly 60 ticks, all 60 present, none evicted.
15. **Pre-F12 no inputs**: Before any tick inputs are pushed, flush produces empty or correct minimal JSONL.
16. **Snapshot before any tick**: Flush with no snapshots pushed produces empty JSONL or safe fallback.
17. **Seed missing in snapshot**: If server hasn't sent seed yet, `seed.txt` is written with "unknown" or zero value (not crash).
18. **Directory creation failure**: If `user://bug-reports/` is unwritable, `push_error` fires but no crash.
### Integration tests
19. **Inputs JSONL → replay roundtrip**: JSONL produced by flush is valid input for `tooling/test-client --replay` (format matches `replay.rs` parse contract).
20. **F12 capture → file structure**: Full F12 flow produces expected directory with all 5 files: `snapshot.json`, `render.txt`, `description.txt`, `inputs.jsonl`, `snapshots.jsonl`, `seed.txt`.
21. **Ring buffer does not affect render.txt**: Text render output is unchanged from MVP.
### Performance tests
22. **No per-tick allocation**: Pushing inputs in a tight loop does not allocate new Array objects — buffer reuses pre-allocated slots.
23. **Flush is O(60)**: Flushing 60 entries completes in < 1ms.
### Regression markers
- MVP `_save_report()` behavior: `snapshot.json`, `render.txt`, `description.txt` unchanged.
- F12 → pause → capture → unpause lifecycle unchanged.
- `test_anti_tedium.gd` tests must still pass.
---
## #522: Resolve OQ-07 — No-Insert Interaction Behavior
### Spec reference
D-056 (cursor states), D-057 (entity interaction). OQ-07 resolution.
### Decision context
Three options were proposed. Expected resolution: **(a) cursor reverts to default shape only, no verb labels** — "the character still physically orients to the target, but receives no information from their insert." This is the most diegetically consistent option per D-056's "diegetic test" framing.
Spec contract regardless of which option is chosen: **"If the insert is off, labels disappear."**
### Happy path tests
**Interaction list (z-layer 6) — diegetic test:**
1. **Insert-off hides list**: When `insert_active == false`, interaction list is not visible.
2. **Insert-on shows list**: When `insert_active == true` and verbs are present, list is visible.
3. **Re-enable restores list**: Toggling insert off then on with verbs present shows the list again.
**Cursor (option a — shape changes, labels suppressed):**
4. **Insert-off still transitions cursor shape**: With `insert_active == false`, hovering over an NPC sets cursor to EntityHover state (shape changes, character physically orients).
5. **Insert-off suppresses should_show_interactions()**: `cursor.should_show_interactions()` returns false when `insert_active == false`.
6. **Insert-on restores interactions**: After `set_insert_active(true)`, `should_show_interactions()` returns true (unless in weapon mode).
**Cursor (option b — full suppression, if chosen instead):**
4b. **Insert-off locks cursor to Default**: With `insert_active == false`, hovering over an NPC does NOT change cursor state.
5b. **Same `should_show_interactions()` behavior**.
### Edge cases
7. **Insert off + weapon mode**: `insert_active == false` AND `weapon_mode_active == true``should_show_interactions()` returns false (not double-false confusion).
8. **Insert off + Shift held**: `insert_active == false` AND `_shift_held == true` — labels STILL suppressed (insert-off trumps shift override).
9. **Insert off at startup**: Default state with insert off from the start — no state corruption.
10. **Rapid toggle**: Toggling insert on/off rapidly does not leave state machine in inconsistent state.
11. **Insert off during active hover**: If player is hovering over an NPC and insert goes off — behavior updates correctly next frame.
### Integration tests
12. **Cursor and list agree**: When `insert_active == false`, BOTH cursor's `should_show_interactions()` AND interaction list's `is_showing()` return false. They must be consistent.
13. **GameState.insert_active propagates**: Changes to `GameState.insert_active` are picked up by both systems on next update.
14. **Decision amendment recorded**: The resolved OQ-07 decision is documented in `decisions/perception.md` or `decisions/scope.md` as an amendment to D-056 or D-057.
### Regression markers
- **Existing cursor state tests pass**: All 19 tests in `test_cursor_states.gd` must still pass.
- **Existing interaction list tests pass**: All tests in `test_interaction_list.gd` must still pass, including `test_insert_off_hides_interaction_list`.
- **Sprint suppression still works**: `test_sprint_suppresses_interaction_list` still passes.
- **Weapon mode suppression unchanged**: `test_weapon_mode_suppresses_interactions` still passes.
- **D-045 invariance**: Cursor behavior does NOT change by zone or narrative state.
---
## Test Files
- `client/tests/test_bug_report_ring_buffer.gd` — automated tests for #507 ring buffer
- `client/tests/test_insert_off_behavior.gd` — automated tests for #522 insert-off behavior
## Run Command
```bash
make test-client
```
Or headless via gdUnit4:
```bash
cd client && godot --headless --quit --path . addons/gdUnit4/bin/GdUnitCmdTool.gd \
--testsuites "tests/test_bug_report_ring_buffer.gd,tests/test_insert_off_behavior.gd"
```
## Verification Checklist (fill in after implementations land)
- [ ] All happy path tests pass
- [ ] All edge case tests pass
- [ ] All integration tests pass
- [ ] Regression: `test_cursor_states.gd` — unchanged
- [ ] Regression: `test_interaction_list.gd` — unchanged
- [ ] Regression: `test_anti_tedium.gd` — unchanged
- [ ] `decisions/perception.md` or related file updated with OQ-07 resolution
- [ ] `inputs.jsonl` format verified against `tooling/test-client --replay` manually
- [ ] `seed.txt` present in captured bug report