## 2026-10-02T02:57:09Z
You are Worker M4 (teamwork_preview_worker) implementing Milestone 4: Safe Teleportation & PoE2 Hideout Town Portal Engine with Anti-Exploit Quarantine for FreeExile.
Working Directory: c:\Projects\FreeExile\.agents\teamwork\worker_m4
Parent Conversation ID: 914399d4-059b-422e-a9e6-44e1005de38a

MANDATORY FIRST STEP:
Read:
- c:\Projects\FreeExile\.agents\teamwork\ORIGINAL_REQUEST.md (specifically ## 2026-10-02T02:12:28Z)
- c:\Projects\FreeExile\PROJECT.md
- c:\Projects\FreeExile\TEST_READY.md
- c:\Projects\FreeExile\.agents\teamwork\explorer_survey_3\survey_report.md
- c:\Projects\FreeExile\.agents\teamwork\explorer_survey_3\handoff.md
- c:\Projects\FreeExile\.agents\teamwork\worker_m2\handoff.md
- c:\Projects\FreeExile\.agents\teamwork\worker_m3\handoff.md

MANDATORY INTEGRITY WARNING:
DO NOT CHEAT. All implementations must be genuine. DO NOT hardcode test results, create dummy/facade implementations, or circumvent the intended task. A teamwork_preview_auditor will independently verify your work. Integrity violations WILL be detected and your work WILL be rejected.

YOUR WRITE OWNERSHIP:
You own exclusively:
- `server/world/town_portal_types.py`
- `server/world/town_portal_engine.py`
- `server/world/teleport_service.py`
- `tests/unit/test_teleport_and_portal.py`

YOUR TASKS:
1. Implement `server/world/town_portal_types.py`:
   - Enums: `TeleportChannelStatus` (IDLE, CHANNELING, COMPLETED, INTERRUPTED_MOVEMENT, INTERRUPTED_DAMAGE, CANCELLED), `PortalQuarantineStatus` (ALLOWED, BLOCKED_BOSS_FIGHT, BLOCKED_SECRET_CHAMBER, BLOCKED_NO_PORTALS_LEFT), `TargetType` (PARTY_MEMBER, FRIEND, GUILDMATE, TOWN_PORTAL).
   - `@dataclass(slots=True, frozen=True)`: `TownPortalLink` (portal_id, owner_id, wilderness_zone_id, wilderness_x, wilderness_y, hub_zone_id, hub_x, hub_y, created_at, is_active, remaining_uses).
   - `@dataclass(slots=True, frozen=True)`: `TeleportChannelSession` (session_id, player_id, target_type, target_id, start_time, duration_seconds=3.5, initial_x, initial_y, status).
   - Backward-compatible property aliases to seamlessly interface with `tests.e2e_social_party` and caller scripts.
2. Implement `server/world/teleport_service.py`:
   - 3.5s authoritative channeling state machine.
   - Immediate cancellation hooks:
     * `on_player_moved(player_id, mag)`: if mag > 0.05, immediately transition to INTERRUPTED_MOVEMENT.
     * `on_player_damaged(player_id, damage)`: if damage > 0, immediately transition to INTERRUPTED_DAMAGE.
     * `cancel_channel(player_id)`: manual cancel.
   - 5-Gate Destination Validation before completing channel:
     * Gate 1: Target liveness (online, exists)
     * Gate 2: Relationship authorization (same party via `PartyService`, mutual friend via `SocialService`, or same guild via `GuildRosterService`)
     * Gate 3: Zone capacity limit (instance not full)
     * Gate 4: Zone lifecycle (instance not expired/closed)
     * Gate 5: Restricted zone isolation (cannot teleport into private hideout of someone else, active secret chamber, or active boss fight).
   - Spiral ray / offset coordinate resolution (2.0-3.0m offset from target) avoiding blocked coordinates.
3. Implement `server/world/town_portal_engine.py`:
   - Dynamic 2-way `TownPortalLink`: Wilderness (wx, wy) linked to player's Hideout (`zone_player_hideout`) or Hub Sanctuary (`zone_boundless_sanctuary`).
   - Personal portal exclusivity: recasting closes player's previous portal.
   - Party member access: members of owner's party can see and traverse the portal.
   - 6-portal map device charge tracking: entering an endgame map consumes 1 charge (6 -> 5 -> ... -> 0). When 0 remain, map instance is sealed permanently (MAP_SEALED).
   - **Anti-Exploit Quarantine**:
     * Strict server check: reject portal creation or teleportation when `boss_encounter_in_progress == True` with error `BLOCKED_BOSS_FIGHT`.
     * Strict check: reject portal creation or teleportation when `secret_chamber_active == True` with error `BLOCKED_SECRET_CHAMBER`.
   - Death penalty handling:
     * Dying in wilderness closes the player's personal town portal.
     * Dying in a map device instance consumes 1 portal charge (requires using another portal to re-enter).
4. Create comprehensive unit tests in `tests/unit/test_teleport_and_portal.py`.
5. Adhere strictly to GEMINI.md: all files <= 350 lines (hard cap 500 lines), strictly typed, memory efficient.
6. Verification commands:
   - `pytest tests/unit/test_teleport_and_portal.py -v`
   - `pytest tests/e2e_social_party/test_tier1_social_and_teleport.py -v`
   - `pytest tests/e2e_social_party/test_tier1_town_portal_matrix.py -v`
   - `pytest tests/e2e_social_party/ -v`
   - `python tools/lint/check_code_and_doc_hygiene.py --strict`
7. Write handoff to `c:\Projects\FreeExile\.agents\teamwork\worker_m4\handoff.md`.
Send message to parent when done.
