Files
Cozypaw-Hospital/docs/superpowers/plans/2026-05-08-sprint-16-snap-points.md
T

748 lines
22 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.
# Sprint 16 — Snap-Point System Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Add SnapPoint nodes to all furniture in all 12 rooms so characters can snap into sitting/lying poses when released near a piece of furniture.
**Architecture:** Each room `.tscn` gets one `ext_resource` entry for `snap_point.gd` and one `[node]` entry per snap position. SnapPoints are direct children of the room node (not children of ColorRect furniture, since ColorRects have no Node2D hierarchy). All SnapPoints auto-register in the `"snap_points"` group via `_ready()`. No new GDScript is written — this sprint is purely scene data.
**Tech Stack:** Godot 4.6.2, `.tscn` text format, GUT v9.6.0 (TDD), headless runner.
**GDD Reference:** `docs/game-design.md` — Kapitel 2 (Raum-Übersicht) + Kapitel 5.1 (Snap-Point System).
**Headless runner:**
```
"F:/Development/_tools/Godot_v4.6.2-stable_win64/Godot_v4.6.2-stable_win64.exe" --headless -s res://addons/gut/gut_cmdln.gd -gdir=res://test/ -gexit 2>&1
```
**Existing tests must stay green:** 90 tests passing before this sprint starts.
---
## File Map
| Action | Path | SnapPoints added |
|---|---|---|
| Modify | `scenes/rooms/floor0/Reception.tscn` | 4 × sitting (2 benches × 2) |
| Modify | `scenes/rooms/floor0/GiftShop.tscn` | 1 × sitting (counter) |
| Modify | `scenes/rooms/floor0/Restaurant.tscn` | 6 × sitting (3 tables × 2) |
| Modify | `scenes/rooms/floor0/EmergencyRoom.tscn` | 1 × lying (medical table) |
| Modify | `scenes/rooms/floor1/XRay.tscn` | 1 × lying (exam table) |
| Modify | `scenes/rooms/floor1/Pharmacy.tscn` | 1 × sitting (counter) |
| Modify | `scenes/rooms/floor1/Lab.tscn` | 2 × sitting (lab bench) |
| Modify | `scenes/rooms/floor1/PatientRoom.tscn` | 2 × lying (2 beds) |
| Modify | `scenes/rooms/floor2/Ultrasound.tscn` | 1 × lying (exam table) |
| Modify | `scenes/rooms/floor2/DeliveryRoom.tscn` | 1 × lying (delivery bed) |
| Modify | `scenes/rooms/floor2/Nursery.tscn` | 3 × lying, baby_only (3 cradles) |
| Modify | `scenes/rooms/home/GardenParty.tscn` | 2 × sitting (garden table) |
| Create | `test/unit/test_snap_points_floor0.gd` | Tests for EG (12 snap points) |
| Create | `test/unit/test_snap_points_floor1.gd` | Tests for 1.OG (6 snap points) |
| Create | `test/unit/test_snap_points_floor2.gd` | Tests for 2.OG + Garten (7 snap points) |
**Total: 25 SnapPoints across 12 rooms.**
---
## How to add a SnapPoint to a .tscn
### 1. Increment `load_steps` in the header by 1
```
[gd_scene load_steps=3 format=3 ...] ← was 2
```
### 2. Add `ext_resource` for snap_point.gd after the last existing `ext_resource` line
For rooms with currently 1 ext_resource (InteractiveObject only), use id `"2_snap"`:
```
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
```
For rooms with currently 2 ext_resources, use id `"3_snap"`:
```
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="3_snap"]
```
For GardenParty (3 ext_resources), use id `"4_snap"`:
```
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="4_snap"]
```
### 3. Append node entries at the end of the file
Sitting (default pose, no need to set pose or baby_only):
```
[node name="SnapBenchLeft1" type="Node2D" parent="."]
position = Vector2(150, 555)
script = ExtResource("2_snap")
```
Lying (must set pose):
```
[node name="SnapExamTable" type="Node2D" parent="."]
position = Vector2(640, 480)
script = ExtResource("2_snap")
pose = "lying"
```
Lying + baby only:
```
[node name="SnapCradle1" type="Node2D" parent="."]
position = Vector2(340, 240)
script = ExtResource("3_snap")
pose = "lying"
baby_only = true
```
---
## Helper: how tests count SnapPoints in a room
```gdscript
func _count_snaps(room: Node2D) -> int:
var count: int = 0
for child: Node in room.get_children():
if child is SnapPoint:
count += 1
return count
func _count_snaps_with_pose(room: Node2D, pose: String) -> int:
var count: int = 0
for child: Node in room.get_children():
var snap: SnapPoint = child as SnapPoint
if snap != null and snap.pose == pose:
count += 1
return count
func _count_snaps_baby_only(room: Node2D) -> int:
var count: int = 0
for child: Node in room.get_children():
var snap: SnapPoint = child as SnapPoint
if snap != null and snap.baby_only:
count += 1
return count
```
---
## Task 1: Floor 0 — Reception, GiftShop, Restaurant, EmergencyRoom
**Files:**
- Modify: `scenes/rooms/floor0/Reception.tscn`
- Modify: `scenes/rooms/floor0/GiftShop.tscn`
- Modify: `scenes/rooms/floor0/Restaurant.tscn`
- Modify: `scenes/rooms/floor0/EmergencyRoom.tscn`
- Create: `test/unit/test_snap_points_floor0.gd`
### Step 1: Write the failing tests
Create `test/unit/test_snap_points_floor0.gd`:
```gdscript
## Tests verifying SnapPoints exist in all EG (Erdgeschoss) room scenes.
extends GutTest
func _count_snaps(room: Node2D) -> int:
var count: int = 0
for child: Node in room.get_children():
if child is SnapPoint:
count += 1
return count
func _count_snaps_with_pose(room: Node2D, pose: String) -> int:
var count: int = 0
for child: Node in room.get_children():
var snap: SnapPoint = child as SnapPoint
if snap != null and snap.pose == pose:
count += 1
return count
func test_reception_has_four_snap_points() -> void:
var room: Node2D = preload("res://scenes/rooms/floor0/Reception.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps(room), 4)
func test_reception_all_snaps_are_sitting() -> void:
var room: Node2D = preload("res://scenes/rooms/floor0/Reception.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps_with_pose(room, "sitting"), 4)
func test_giftshop_has_one_snap_point() -> void:
var room: Node2D = preload("res://scenes/rooms/floor0/GiftShop.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps(room), 1)
func test_giftshop_snap_is_sitting() -> void:
var room: Node2D = preload("res://scenes/rooms/floor0/GiftShop.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps_with_pose(room, "sitting"), 1)
func test_restaurant_has_six_snap_points() -> void:
var room: Node2D = preload("res://scenes/rooms/floor0/Restaurant.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps(room), 6)
func test_restaurant_all_snaps_are_sitting() -> void:
var room: Node2D = preload("res://scenes/rooms/floor0/Restaurant.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps_with_pose(room, "sitting"), 6)
func test_emergency_room_has_one_snap_point() -> void:
var room: Node2D = preload("res://scenes/rooms/floor0/EmergencyRoom.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps(room), 1)
func test_emergency_room_snap_is_lying() -> void:
var room: Node2D = preload("res://scenes/rooms/floor0/EmergencyRoom.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps_with_pose(room, "lying"), 1)
```
### Step 2: Run tests — verify they FAIL
```
"F:/Development/_tools/Godot_v4.6.2-stable_win64/Godot_v4.6.2-stable_win64.exe" --headless -s res://addons/gut/gut_cmdln.gd -gdir=res://test/ -gexit 2>&1
```
Expected: 8 new failures. 90 existing pass.
### Step 3: Edit `scenes/rooms/floor0/Reception.tscn`
Current header: `[gd_scene load_steps=2 format=3 uid="uid://cozypaw_reception"]`
Change to: `[gd_scene load_steps=3 format=3 uid="uid://cozypaw_reception"]`
After `[ext_resource type="PackedScene" path="res://scenes/objects/InteractiveObject.tscn" id="1_iobj"]`, add:
```
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
```
Append at the end of the file:
```
[node name="SnapBenchLeft1" type="Node2D" parent="."]
position = Vector2(150, 555)
script = ExtResource("2_snap")
[node name="SnapBenchLeft2" type="Node2D" parent="."]
position = Vector2(240, 555)
script = ExtResource("2_snap")
[node name="SnapBenchRight1" type="Node2D" parent="."]
position = Vector2(990, 555)
script = ExtResource("2_snap")
[node name="SnapBenchRight2" type="Node2D" parent="."]
position = Vector2(1080, 555)
script = ExtResource("2_snap")
```
### Step 4: Edit `scenes/rooms/floor0/GiftShop.tscn`
Change header to `load_steps=3`.
Add after InteractiveObject ext_resource:
```
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
```
Append:
```
[node name="SnapCounter" type="Node2D" parent="."]
position = Vector2(640, 528)
script = ExtResource("2_snap")
```
### Step 5: Edit `scenes/rooms/floor0/Restaurant.tscn`
Change header to `load_steps=3`.
Add after InteractiveObject ext_resource:
```
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
```
Append:
```
[node name="SnapTable1Left" type="Node2D" parent="."]
position = Vector2(160, 510)
script = ExtResource("2_snap")
[node name="SnapTable1Right" type="Node2D" parent="."]
position = Vector2(280, 510)
script = ExtResource("2_snap")
[node name="SnapTable2Left" type="Node2D" parent="."]
position = Vector2(580, 510)
script = ExtResource("2_snap")
[node name="SnapTable2Right" type="Node2D" parent="."]
position = Vector2(700, 510)
script = ExtResource("2_snap")
[node name="SnapTable3Left" type="Node2D" parent="."]
position = Vector2(1000, 510)
script = ExtResource("2_snap")
[node name="SnapTable3Right" type="Node2D" parent="."]
position = Vector2(1120, 510)
script = ExtResource("2_snap")
```
### Step 6: Edit `scenes/rooms/floor0/EmergencyRoom.tscn`
Current header: `load_steps=3` (has Ambulance ext_resource). Change to `load_steps=4`.
Add after the last ext_resource line (Ambulance):
```
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="3_snap"]
```
Append:
```
[node name="SnapMedicalTable" type="Node2D" parent="."]
position = Vector2(310, 480)
script = ExtResource("3_snap")
pose = "lying"
```
### Step 7: Run tests — verify 8 new tests PASS (98 total)
Run `--headless --import` first if needed, then the test runner.
Expected: 98/98 passed.
### Step 8: Commit
```bash
cd "F:/Development/_gameDev/Cozypaw-Hospital/.worktrees/sprint-16-snap-points"
git add scenes/rooms/floor0/Reception.tscn scenes/rooms/floor0/GiftShop.tscn
git add scenes/rooms/floor0/Restaurant.tscn scenes/rooms/floor0/EmergencyRoom.tscn
git add test/unit/test_snap_points_floor0.gd
git commit -m "feat(snap-points): add SnapPoints to all EG rooms (Reception, GiftShop, Restaurant, EmergencyRoom)"
```
---
## Task 2: Floor 1 — XRay, Pharmacy, Lab, PatientRoom
**Files:**
- Modify: `scenes/rooms/floor1/XRay.tscn`
- Modify: `scenes/rooms/floor1/Pharmacy.tscn`
- Modify: `scenes/rooms/floor1/Lab.tscn`
- Modify: `scenes/rooms/floor1/PatientRoom.tscn`
- Create: `test/unit/test_snap_points_floor1.gd`
### Step 1: Write the failing tests
Create `test/unit/test_snap_points_floor1.gd`:
```gdscript
## Tests verifying SnapPoints exist in all 1.OG room scenes.
extends GutTest
func _count_snaps(room: Node2D) -> int:
var count: int = 0
for child: Node in room.get_children():
if child is SnapPoint:
count += 1
return count
func _count_snaps_with_pose(room: Node2D, pose: String) -> int:
var count: int = 0
for child: Node in room.get_children():
var snap: SnapPoint = child as SnapPoint
if snap != null and snap.pose == pose:
count += 1
return count
func test_xray_has_one_snap_point() -> void:
var room: Node2D = preload("res://scenes/rooms/floor1/XRay.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps(room), 1)
func test_xray_snap_is_lying() -> void:
var room: Node2D = preload("res://scenes/rooms/floor1/XRay.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps_with_pose(room, "lying"), 1)
func test_pharmacy_has_one_snap_point() -> void:
var room: Node2D = preload("res://scenes/rooms/floor1/Pharmacy.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps(room), 1)
func test_pharmacy_snap_is_sitting() -> void:
var room: Node2D = preload("res://scenes/rooms/floor1/Pharmacy.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps_with_pose(room, "sitting"), 1)
func test_lab_has_two_snap_points() -> void:
var room: Node2D = preload("res://scenes/rooms/floor1/Lab.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps(room), 2)
func test_lab_all_snaps_are_sitting() -> void:
var room: Node2D = preload("res://scenes/rooms/floor1/Lab.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps_with_pose(room, "sitting"), 2)
func test_patient_room_has_two_snap_points() -> void:
var room: Node2D = preload("res://scenes/rooms/floor1/PatientRoom.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps(room), 2)
func test_patient_room_all_snaps_are_lying() -> void:
var room: Node2D = preload("res://scenes/rooms/floor1/PatientRoom.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps_with_pose(room, "lying"), 2)
```
### Step 2: Run tests — verify 8 new tests FAIL
Expected: 8 failures. 98 existing pass.
### Step 3: Edit `scenes/rooms/floor1/XRay.tscn`
Current header: `load_steps=3` (has XRayMachine). Change to `load_steps=4`.
Add after the last ext_resource:
```
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="3_snap"]
```
Append:
```
[node name="SnapExamTable" type="Node2D" parent="."]
position = Vector2(640, 480)
script = ExtResource("3_snap")
pose = "lying"
```
### Step 4: Edit `scenes/rooms/floor1/Pharmacy.tscn`
Current header: `load_steps=2`. Change to `load_steps=3`.
Add after ext_resource:
```
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
```
Append:
```
[node name="SnapCounter" type="Node2D" parent="."]
position = Vector2(640, 520)
script = ExtResource("2_snap")
```
### Step 5: Edit `scenes/rooms/floor1/Lab.tscn`
Current header: `load_steps=2`. Change to `load_steps=3`.
Add after ext_resource:
```
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
```
Append:
```
[node name="SnapLabBench1" type="Node2D" parent="."]
position = Vector2(450, 470)
script = ExtResource("2_snap")
[node name="SnapLabBench2" type="Node2D" parent="."]
position = Vector2(750, 470)
script = ExtResource("2_snap")
```
### Step 6: Edit `scenes/rooms/floor1/PatientRoom.tscn`
Current header: `load_steps=2`. Change to `load_steps=3`.
Add after ext_resource:
```
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="2_snap"]
```
Append:
```
[node name="SnapBed1" type="Node2D" parent="."]
position = Vector2(250, 465)
script = ExtResource("2_snap")
pose = "lying"
[node name="SnapBed2" type="Node2D" parent="."]
position = Vector2(810, 465)
script = ExtResource("2_snap")
pose = "lying"
```
### Step 7: Run tests — verify 8 new tests PASS (106 total)
Run `--headless --import` first if needed, then the test runner.
Expected: 106/106 passed.
### Step 8: Commit
```bash
cd "F:/Development/_gameDev/Cozypaw-Hospital/.worktrees/sprint-16-snap-points"
git add scenes/rooms/floor1/XRay.tscn scenes/rooms/floor1/Pharmacy.tscn
git add scenes/rooms/floor1/Lab.tscn scenes/rooms/floor1/PatientRoom.tscn
git add test/unit/test_snap_points_floor1.gd
git commit -m "feat(snap-points): add SnapPoints to all 1.OG rooms (XRay, Pharmacy, Lab, PatientRoom)"
```
---
## Task 3: Floor 2 + Garten — Ultrasound, DeliveryRoom, Nursery, GardenParty
**Files:**
- Modify: `scenes/rooms/floor2/Ultrasound.tscn`
- Modify: `scenes/rooms/floor2/DeliveryRoom.tscn`
- Modify: `scenes/rooms/floor2/Nursery.tscn`
- Modify: `scenes/rooms/home/GardenParty.tscn`
- Create: `test/unit/test_snap_points_floor2.gd`
### Step 1: Write the failing tests
Create `test/unit/test_snap_points_floor2.gd`:
```gdscript
## Tests verifying SnapPoints exist in all 2.OG and Garten room scenes.
extends GutTest
func _count_snaps(room: Node2D) -> int:
var count: int = 0
for child: Node in room.get_children():
if child is SnapPoint:
count += 1
return count
func _count_snaps_with_pose(room: Node2D, pose: String) -> int:
var count: int = 0
for child: Node in room.get_children():
var snap: SnapPoint = child as SnapPoint
if snap != null and snap.pose == pose:
count += 1
return count
func _count_snaps_baby_only(room: Node2D) -> int:
var count: int = 0
for child: Node in room.get_children():
var snap: SnapPoint = child as SnapPoint
if snap != null and snap.baby_only:
count += 1
return count
func test_ultrasound_has_one_snap_point() -> void:
var room: Node2D = preload("res://scenes/rooms/floor2/Ultrasound.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps(room), 1)
func test_ultrasound_snap_is_lying() -> void:
var room: Node2D = preload("res://scenes/rooms/floor2/Ultrasound.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps_with_pose(room, "lying"), 1)
func test_delivery_room_has_one_snap_point() -> void:
var room: Node2D = preload("res://scenes/rooms/floor2/DeliveryRoom.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps(room), 1)
func test_delivery_room_snap_is_lying() -> void:
var room: Node2D = preload("res://scenes/rooms/floor2/DeliveryRoom.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps_with_pose(room, "lying"), 1)
func test_nursery_has_three_snap_points() -> void:
var room: Node2D = preload("res://scenes/rooms/floor2/Nursery.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps(room), 3)
func test_nursery_all_snaps_are_baby_only() -> void:
var room: Node2D = preload("res://scenes/rooms/floor2/Nursery.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps_baby_only(room), 3)
func test_nursery_all_snaps_are_lying() -> void:
var room: Node2D = preload("res://scenes/rooms/floor2/Nursery.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps_with_pose(room, "lying"), 3)
func test_garden_party_has_two_snap_points() -> void:
var room: Node2D = preload("res://scenes/rooms/home/GardenParty.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps(room), 2)
func test_garden_party_all_snaps_are_sitting() -> void:
var room: Node2D = preload("res://scenes/rooms/home/GardenParty.tscn").instantiate() as Node2D
add_child_autofree(room)
assert_eq(_count_snaps_with_pose(room, "sitting"), 2)
```
### Step 2: Run tests — verify 9 new tests FAIL
Expected: 9 failures. 106 existing pass.
### Step 3: Edit `scenes/rooms/floor2/Ultrasound.tscn`
Current header: `load_steps=3` (has UltrasoundMachine). Change to `load_steps=4`.
Add after last ext_resource:
```
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="3_snap"]
```
Append:
```
[node name="SnapExamTable" type="Node2D" parent="."]
position = Vector2(470, 480)
script = ExtResource("3_snap")
pose = "lying"
```
### Step 4: Edit `scenes/rooms/floor2/DeliveryRoom.tscn`
Current header: `load_steps=3` (has DeliveryBed). Change to `load_steps=4`.
Add after last ext_resource:
```
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="3_snap"]
```
Append:
```
[node name="SnapDeliveryBed" type="Node2D" parent="."]
position = Vector2(540, 480)
script = ExtResource("3_snap")
pose = "lying"
```
### Step 5: Edit `scenes/rooms/floor2/Nursery.tscn`
Current header: `load_steps=3` (has Cradle). Change to `load_steps=4`.
Add after last ext_resource:
```
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="3_snap"]
```
Append:
```
[node name="SnapCradle1" type="Node2D" parent="."]
position = Vector2(340, 240)
script = ExtResource("3_snap")
pose = "lying"
baby_only = true
[node name="SnapCradle2" type="Node2D" parent="."]
position = Vector2(600, 240)
script = ExtResource("3_snap")
pose = "lying"
baby_only = true
[node name="SnapCradle3" type="Node2D" parent="."]
position = Vector2(860, 240)
script = ExtResource("3_snap")
pose = "lying"
baby_only = true
```
### Step 6: Edit `scenes/rooms/home/GardenParty.tscn`
Current header: `load_steps=4` (has GiftBox, TeaPot, HomeButton). Change to `load_steps=5`.
Add after the last ext_resource (HomeButton):
```
[ext_resource type="Script" path="res://scripts/objects/snap_point.gd" id="4_snap"]
```
Append:
```
[node name="SnapTableLeft" type="Node2D" parent="."]
position = Vector2(530, 455)
script = ExtResource("4_snap")
[node name="SnapTableRight" type="Node2D" parent="."]
position = Vector2(750, 455)
script = ExtResource("4_snap")
```
### Step 7: Run tests — verify 9 new tests PASS (115 total)
Run `--headless --import` first, then the test runner.
Expected: 115/115 passed.
### Step 8: Commit
```bash
cd "F:/Development/_gameDev/Cozypaw-Hospital/.worktrees/sprint-16-snap-points"
git add scenes/rooms/floor2/Ultrasound.tscn scenes/rooms/floor2/DeliveryRoom.tscn
git add scenes/rooms/floor2/Nursery.tscn scenes/rooms/home/GardenParty.tscn
git add test/unit/test_snap_points_floor2.gd
git commit -m "feat(snap-points): add SnapPoints to all 2.OG and Garten rooms (Ultrasound, DeliveryRoom, Nursery, GardenParty)"
```
---
## Final Check
- [ ] **Run full test suite one last time**
```
"F:/Development/_tools/Godot_v4.6.2-stable_win64/Godot_v4.6.2-stable_win64.exe" --headless -s res://addons/gut/gut_cmdln.gd -gdir=res://test/ -gexit 2>&1
```
Expected output:
```
Scripts 10
Tests 115
Passing Tests 115
---- All tests passed! ----
```
- [ ] **Verify git log shows 3 clean commits**
```bash
git log --oneline -4
```
Expected:
```
feat(snap-points): add SnapPoints to all 2.OG and Garten rooms...
feat(snap-points): add SnapPoints to all 1.OG rooms...
feat(snap-points): add SnapPoints to all EG rooms...
```