- ObjectPlacer load: scale=0 clamped to 1.0, missing scale field
defaults to 1.0 (locks in the load-side guard at line 346).
- ObjectPlacer save→load: uniqueId values survive a full round
trip (locks in the explicit uniqueId preservation behavior the
ADT round-trip relies on).
Adds object_placer.cpp to test_editor_units sources.
Locks in the recent unpack truncation guard. Hand-writes a WCP
that declares dataSize=1000 but only ships 50 bytes; verifies
the unpack returns false AND that no partial file landed on disk.
6 tests covering ContentPacker::unpackZone defenses:
- absurd fileCount header rejected
- absurd infoSize header rejected (16MB cap)
- relative path traversal ('../../etc/passwd_clone') rejected
- absolute paths ('/tmp/...') rejected
- malicious zone name slugified instead of escaping destDir
- bad magic rejected
Each test confirms the defense fires AND that no escape file
landed outside the test dir.
Tests cover:
- non-existent nextQuestId is flagged
- orphan quests (no questgiver, no turn-in) are flagged
- turn-in only quest is accepted (auto-completed quest pattern)
- circular chain is detected
Renamed test_sql_escape → test_editor_units since the file now
houses both SQL escape and quest validation tests.