# 56. Đặc Tả Kiến Trúc & Thiết Kế Kỹ Thuật: Bộ Điều Phối Atlas Node Selector & Tự Động Nạp Precursor Tablet Trên Map Device (Build 6AA2213C)

> **Mã Tài Liệu**: `SPEC-DOC-56-ATLAS-NODE-SELECTOR-AND-MAP-DEVICE-ORCHESTRATION-20260913`  
> **Mốc Thời Gian**: `13/09/2026 - 19:40:00` (UTC+7)  
> **Phiên Bản Game Tham Chiếu**: Path of Exile 2 v0.5.5+ (PE TimeDateStamp `0x6AA2213C`, x64 Windows Client)  
> **Khu Vực Thực Địa Tham Chiếu**: `Shoreline Hideout` $\longleftrightarrow$ `Atlas Map Tree` (Endgame Mapping T1–T16)  
> **Nhân Vật Tham Chiếu**: `BEONGUSI#3653` — Monk / Martial Artist Chaos Inoculation (Level 90, `HP 1/1`, `ES 4713/4713` ~ `5656/5656`, `Ward 240/240`, `Mana 876/876`)  
> **Trạng Thái Tài Liệu**: `[CODE-PRESENT & HARNESS-VERIFIED]` (Hoàn thành triển khai mã nguồn hai tầng và nghiệm thu Mock Harness 13/09/2026: C++ 716/716 checks PASS, Python 9/9 tests PASS, Non-blocking 120Hz hover delay, INV-ATLAS-01..03 verified; Cổng 3 Live Gate đang chờ phiên farm thực địa)  
> **Tác Giả**: Dedicated Sub-Agent Documentation & Architecture Specialist (AutoPOE2)  
> **Tuân Thủ Quy Chuẩn**: Rule 1 (Two-Tier Architecture), Rule 2 (Context 2026), Rule 6 (Pre-Implementation Architecture Spec), Rule 8 (4-Step RCA & Anti-Symptom Patching), Rule 10 (Zero-Drift Code-Doc Contract), Rule 11 (Automated Regression Prevention via Mock Harness), Rule 12 (Global Invariant Sweep), Rule 14 (Zero Mock Data - 100% Authentic Real Data)  
> **Tài Liệu Căn Cứ Trước**:
> - [`docs/development/55_complete_visual_tool_decoupling_and_pure_bot_architecture.md`](./55_complete_visual_tool_decoupling_and_pure_bot_architecture.md) (Đặc tả Pure Bot & Read-Only Memory Engine)
> - [`docs/development/50_two_tier_asymmetric_hybrid_architecture_specification.md`](./50_two_tier_asymmetric_hybrid_architecture_specification.md) (Kiến trúc Bất đối xứng Hai Tầng Hot/Cold Path)
> - [`docs/development/48_closed_loop_map_runner_waystone_row1_farm.md`](./48_closed_loop_map_runner_waystone_row1_farm.md) (Vòng lặp tự động mở & chạy map khép kín FSM 8 bước)
> - [`docs/development/29_botbrain_priority_fsm_pickit_and_closed_farming_loop.md`](./29_botbrain_priority_fsm_pickit_and_closed_farming_loop.md) (MapDeviceHandler & Priority Arbiter)

---

## 1. Bối Cảnh Hệ Thống & Tuyên Bố Vấn Đề (Executive Summary & Problem Statement)

### 1.1. Hiện Trạng Hệ Thống (Current State)
Trong AutoPOE2, tính năng tự động mở bản đồ tại Hideout đã được thiết kế và triển khai qua máy trạng thái [`MapDeviceHandler`](../../src/core/brain/map_device_handler.hpp) (C++23) với FSM 8 bước (Doc 48):
1. `ApproachDevice` $\rightarrow$ 2. `OpenDevice` $\rightarrow$ 3. `PlaceWaystone` (quét xoay vòng 12 ô hàng đầu tiên của túi đồ, dùng Ctrl+Click) $\rightarrow$ 4. `PlaceTablet` $\rightarrow$ 5. `Activate` $\rightarrow$ 6. `WaitForPortals` $\rightarrow$ 7. `EnterPortal` $\rightarrow$ 8. `Completed`.

Cơ chế này hoạt động dựa trên giả định rằng:
- Giao diện Map Device đã mở sẵn vào đúng một khe cắm bản đồ cố định hoặc lưu lại node bản đồ của lần chơi trước.
- Vị trí cắm Waystone được hardcode tại tọa độ cố định tham chiếu 1080p: `waystone_slot_x = 420.0f`, `waystone_slot_y = 480.0f` ([`coordinates.toml`](../../data/ui/coordinates.toml#L50-L51)).

### 1.2. Vấn Đề Cốt Tử Trong Endgame Path of Exile 2 (The Core Problem)
Trong thực tế Endgame của Path of Exile 2 (bản cập nhật 2026, Build `6AA2213C`):
1. **Giao Diện Map Device Là Cây Bản Đồ Atlas Động (Dynamic Atlas Map Tree)**:
   Khi người chơi tương tác với Map Device tại Hideout, màn hình không chỉ mở ra một khung chứa đơn giản, mà hiển thị toàn cảnh **Bản đồ Atlas (Atlas Panel)** bao gồm các Vùng lãnh thổ (Regions), hàng trăm Điểm nút bản đồ (Map Nodes) phân cấp từ Tier 1 đến Tier 16, và các Tháp Dẫn Đường (Precursor Towers).
2. **Yêu Cầu Chọn Điểm Nút Bản Đồ (Map Node Selection)**:
   - Người chơi không thể chỉ đơn thuần bấm Ctrl+Click vào khoảng trống; họ bắt buộc phải **chọn một Map Node cụ thể trên cây Atlas** (ví dụ: click vào node Deserted, Fortress, hoặc Creek) để mở ra khay cắm Waystone dành riêng cho node đó.
   - Nếu trước đó người chơi vừa hoàn thành một map, node cũ có thể đã bị khóa hoặc người chơi muốn chuyển sang node mới chưa lấy điểm thưởng Bonus Point (`Bonus Objective: Complete with Rare Waystone`).
3. **Cơ Chế Tháp Dẫn Đường (Precursor Towers & Tablets)**:
   - Trong mỗi vùng Atlas, có các Tháp Dẫn Đường (Precursor Towers) bao quanh các nhóm Map Nodes. Mỗi tháp có từ 1 đến 3 khe cắm Precursor Tablet.
   - Việc cắm Precursor Tablet (ví dụ: Delirium Tablet, Breach Tablet, Ritual Tablet, Boss Drop Tablet) sẽ buff trực tiếp các dòng thuộc tính cực mạnh lên toàn bộ các Map Nodes nằm trong bán kính ảnh hưởng của Tháp.
   - Hiện tại, bot **hoàn toàn chưa có khả năng nhận diện Tháp Dẫn Đường nào đang trống để tự động lấy Tablet từ túi đồ nạp vào**, dẫn đến việc lãng phí tài nguyên và làm giảm 60% – 80% hiệu suất sinh lời (profit/hour) của việc farm Endgame.

---

## 2. Kiến Trúc Phân Tầng Hai Tầng (Two-Tier Asymmetric Hybrid Architecture)

Tuân thủ nguyên tắc thiết kế bất đối xứng chuẩn mực năm 2026 (đặc tả tại Doc 50):
- **Tier 1 (Hot Path 120Hz C++ Core)**: Giữ vai trò thực thi cơ học siêu tốc, độ trễ cực thấp (< 8.33ms), không tính toán nặng, bảo đảm an toàn input qua KMBox Net.
- **Tier 2 (Cold Path 1–10Hz Python Companion)**: Đảm nhận vai trò nhận diện hình ảnh, OCR, duyệt đồ thị Atlas và hoạch định chiến lược chọn Node tối ưu.

```mermaid
graph TB
    subgraph POE2_Client ["Game Client: Path of Exile 2 (PID Target)"]
        Atlas_UI ["Giao Diện Atlas Map Device (1440p / 1080p)<br/>Map Nodes, Bonus Stars, Precursor Towers"]
        Game_RAM ["RAM Heap: InGameState -> AtlasManager<br/>Node IDs, Coordinates, Completion Bitmask"]
        Input_Sink ["DirectInput / KMBox Hardware Input"]
    end

    subgraph Tier2_Companion ["Tier 2: Python Companion (Cold Path 1-10Hz)"]
        Atlas_Perception ["Atlas Perception Engine<br/>- GDI BitBlt / PrintWindow Screen Capture<br/>- Template Matching: Map Node Icons, Bonus Star<br/>- OCR: Node Name, Tier, Precursor Tower State"]
        Atlas_Strategy ["Atlas Strategy Planner (atlas_policy.toml)<br/>1. Ưu tiên Node chưa lấy Bonus (Uncompleted)<br/>2. Whitelist Maps (Deserted, Fortress)<br/>3. Kiểm tra & Buff Precursor Towers"]
        Command_Builder ["SPSC Command Builder<br/>OpCode 9: SELECT_ATLAS_NODE<br/>Payload: Screen (X, Y), NodeID, TowerAction"]
    end

    subgraph Tier1_Core ["Tier 1: C++ Core Engine (Hot Path 120Hz)"]
        SPSC_Consumer ["SPSC Ring Buffer Consumer<br/>Pop CommandPacket (OpCode 9 / 7)"]
        MapDevice_FSM ["MapDeviceHandler FSM Nâng Cấp<br/>State: SelectAtlasNode & InspectPrecursorTowers"]
        Bézier_Mouse ["Humanized Bézier Mouse Movement<br/>Gia tốc tự nhiên, click chọn Node / Socket Tablet"]
        KMBox_Driver ["KMBox Net Hardware Controller"]
    end

    %% Luồng xử lý Tier 2
    Atlas_UI ==>|Capture 2-5 FPS| Atlas_Perception
    Game_RAM -.->|RPM Zero-Risk O(1)| Atlas_Perception
    Atlas_Perception --> Atlas_Strategy
    Atlas_Strategy --> Command_Builder

    %% Giao tiếp IPC SPSC Ring
    Command_Builder ==>|Ring Buffer 16 slot (64B)| SPSC_Consumer

    %% Luồng xử lý Tier 1
    SPSC_Consumer --> MapDevice_FSM
    MapDevice_FSM --> Bézier_Mouse
    Bézier_Mouse --> KMBox_Driver
    KMBox_Driver ==>|Click Chọn Node & Nạp Tablet| Input_Sink

    classDef tier1 fill:#dcfce7,stroke:#16a34a,stroke-width:2px;
    classDef tier2 fill:#dbeafe,stroke:#2563eb,stroke-width:2px;
    classDef client fill:#f1f5f9,stroke:#64748b,stroke-width:1px;

    class SPSC_Consumer,MapDevice_FSM,Bézier_Mouse,KMBox_Driver tier1;
    class Atlas_Perception,Atlas_Strategy,Command_Builder tier2;
    class Atlas_UI,Game_RAM,Input_Sink client;
```

---

## 3. Thiết Kế Chi Tiết Module `AtlasNodeSelector`

### 3.1. Phân Tầng Tier 2: Nhận Diện & Hoạch Định Chiến Lược (Python Companion)

Module mới: `src/assistant_tool/atlas_node_selector.py`

#### A. Khối Nhận Diện Thị Giác Atlas (Atlas Perception Engine)
1. **Chụp Khung Hình Cửa Sổ Atlas**:
   - Sử dụng `win32_window` capture vùng hiển thị Map Device (kích thước tham chiếu 1920x1080 hoặc 2560x1440).
   - Xác định vùng trọng tâm cây Atlas (Atlas Viewport ROI): `(x: 350, y: 120, w: 1220, h: 840)`.
2. **Nhận Diện Map Nodes**:
   - Áp dụng Template Matching hoặc Haar-like Cascade để định vị các icon hình tròn của Map Node.
   - Nhận diện các đặc trưng:
     * **Trạng thái Hoàn Thành (Bonus Completion)**: Kiểm tra sự hiện diện của biểu tượng "Ngôi sao vàng" (Bonus Objective Star) phía trên node. Nếu chưa có sao $\implies$ Node chưa lấy bonus.
     * **Node Kết Nối (Walkable / Reachable Nodes)**: Các node sáng màu có đường nối với node hiện tại.
     * **Citadel / Boss Icon**: Các node có biểu tượng lâu đài đặc trưng.
3. **Nhận Diện Tháp Dẫn Đường (Precursor Towers)**:
   - Tháp Dẫn Đường có biểu tượng ngọn tháp nhọn đặc thù trên bản đồ vùng.
   - Xác định số lượng khe cắm Tablet còn trống (mỗi tháp có 1 – 3 vòng tròn nhỏ bao quanh). Nếu vòng tròn có màu tối (Empty Socket) $\implies$ Tháp cần được nạp Precursor Tablet.

#### B. Khối Hoạch Định Chiến Lược (Atlas Strategy Planner)
Dựa trên tệp cấu hình `data/maps/atlas_policy.toml`:
1. **Chế độ 1: `bonus_rush` (Mở khóa điểm Atlas tối đa)**:
   - Quét toàn bộ các node nhìn thấy trong viewport.
   - Lọc ra các node có `bonus_completed == false` và cấp độ `tier <= current_max_tier`.
   - Chọn node có khoảng cách di chuyển ngắn nhất trên cây Atlas.
2. **Chế độ 2: `farm_whitelist` (Cày cuốc bản đồ tối ưu)**:
   - Ưu tiên các map trong danh sách `preferred_maps` (ví dụ: `["Deserted", "Fortress", "Creek"]`).
   - Loại bỏ các map trong danh sách `blacklist_maps` (ví dụ: map có địa hình hẹp, mê cung khó đi).
3. **Quy trình Nạp Precursor Tablet**:
   - Nếu phát hiện tháp Precursor Tower gần node mục tiêu có khe cắm trống:
     * Kiểm tra túi đồ của nhân vật tại hàng quy định (`tablet_inventory_row = 1`).
     * Phát lệnh click chọn Tháp $\rightarrow$ Right-Click Tablet trong túi $\rightarrow$ Click vào khe tháp.

---

### 3.2. Phân Tầng Tier 1: Mở Rộng Máy Trạng Thái FSM Trong C++ Core

Nâng cấp [`MapDeviceHandler`](../../src/core/brain/map_device_handler.hpp) từ 8 bước lên 10 bước khép kín:

```cpp
enum class MapDeviceState : uint8_t {
    Idle = 0,
    ApproachDevice = 1,        // Tiếp cận Map Device trong Hideout
    OpenDevice = 2,            // Click mở giao diện Map Device
    SelectAtlasNode = 3,       // [MỚI] Click chọn Map Node tối ưu trên Atlas
    InspectPrecursorTowers = 4,// [MỚI] Kiểm tra và nạp Precursor Tablet vào Tháp
    PlaceWaystone = 5,         // Lấy Waystone từ Inventory đặt vào slot Map Device
    PlaceTablet = 6,           // Đặt Tablet phụ trợ trực tiếp vào Map Device (nếu có)
    Activate = 7,              // Click nút Activate mở cổng Map
    WaitForPortals = 8,        // Chờ các cánh cổng portal mở ra
    EnterPortal = 9,           // Bước vào Portal (chuyển sang In-Map)
    Completed = 10,
    Failed = 11
};
```

#### Sơ Đồ Chuyển Trạng Thái FSM Mở Rộng:
```mermaid
stateDiagram-v2
    [*] --> Idle
    Idle --> ApproachDevice: Nhận lệnh EXECUTE_MAP_DEVICE_ROUTINE
    ApproachDevice --> OpenDevice: Tới gần Map Device
    OpenDevice --> SelectAtlasNode: Giao diện Atlas đã mở

    state SelectAtlasNode {
        [*] --> MoveToNode
        MoveToNode --> HoverVerify: Chờ 100ms
        HoverVerify --> ClickNode: Tooltip hợp lệ
        ClickNode --> [*]: Node đã được chọn
    }

    SelectAtlasNode --> InspectPrecursorTowers: Node đã sẵn sàng
    
    state InspectPrecursorTowers {
        [*] --> CheckTower
        CheckTower --> SocketTablet: Tháp trống & có Tablet
        SocketTablet --> [*]: Nạp xong Tablet
        CheckTower --> [*]: Tháp đã đầy / Không có Tablet
    }

    InspectPrecursorTowers --> PlaceWaystone: Khay cắm Waystone mở ra
    PlaceWaystone --> Activate: Đã cắm Waystone từ Row 0
    Activate --> WaitForPortals: Chờ 2500ms
    WaitForPortals --> EnterPortal: Portal xuất hiện
    EnterPortal --> Completed: Tải cảnh vào Map
    Completed --> [*]
```

---

## 4. Hợp Đồng Dữ Liệu Nhị Phân & Cấu Hình Kỹ Thuật (Data Contracts & Configuration)

### 4.1. Mã Lệnh Điều Khiển Vĩ Mô (IPC MacroOpCode)

Bổ sung mã lệnh mới vào [`protocol.hpp`](../../src/core/common/protocol.hpp):

```cpp
enum class MacroOpCode : uint32_t {
    IDLE = 0,
    NAVIGATE_TO_COORD = 1,
    ENGAGE_TARGET = 2,
    PICKUP_ITEM = 3,
    CAST_EMERGENCY_PORTAL = 4,
    EXECUTE_STASH_ROUTINE = 5,
    EXECUTE_VENDOR_ROUTINE = 6,
    EXECUTE_MAP_DEVICE_ROUTINE = 7,
    EXECUTE_NPC_INTERACT_ROUTINE = 8,
    
    // [MỚI - DOC-56] Điều khiển chọn Atlas Node & Precursor Tower
    SELECT_ATLAS_NODE = 9,
    
    // [MỚI - INV-MAPDEVICE-VERIFY-UI] Xác nhận giao diện Map Device / Atlas đã mở thực sự
    VERIFY_MAP_DEVICE_UI = 10,
    
    SET_MAP_SCENARIO = 95,
    TRIGGER_WORLD_MAP_TRAVEL = 96,
    TRIGGER_AUTO_LOGIN = 97,
    RECALIBRATE_XYZ = 98,
    PANIC_STOP = 99
};
```

#### Định Nghĩa Payload Gói Tin `CommandPacket` Khi `opCode == VERIFY_MAP_DEVICE_UI`:
- `opCode`: `10` (`MacroOpCode::VERIFY_MAP_DEVICE_UI`).
- `targetX`, `targetY`, `targetZ`: `0.0f`.
- `priority`: `3200`.
- Chức năng: Coordinator gửi tín hiệu này sau khi Optical OCR xác nhận UI Map Device / Atlas đã mở (thấy từ khóa `TRAVERSE` hoặc `WAYSTONE` hoặc `MAP DEVICE`). C++ Core nhận được lệnh này sẽ đặt cờ `m_atlasUiVerified = true`, mở khóa cho FSM chuyển tiếp sang `SelectAtlasNode` / `PlaceWaystone`.
- Khóa chặn bất biến `INV-MAPDEVICE-VERIFY-UI`: Nếu sau `openDeviceTimeoutMs` (4500ms) mà không nhận được tín hiệu này, FSM lập tức chuyển sang `MapDeviceState::Failed`, bấm `SPACE` đóng modal kẹt, backoff 3s, **TUYỆT ĐỐI CẤM** chuyển sang click túi đồ mù quáng!

#### Định Nghĩa Payload Gói Tin `CommandPacket` Khi `opCode == SELECT_ATLAS_NODE`:
- `targetX`: Tọa độ màn hình X của Node bản đồ (Screen X, tham chiếu 1080p).
- `targetY`: Tọa độ màn hình Y của Node bản đồ (Screen Y, tham chiếu 1080p).
- `targetZ`: Bitmask cờ hành vi:
  * Bit 0 (`0x01`): `REQUIRE_HOVER_VERIFY` — Yêu cầu dừng trỏ chuột xác nhận tooltip trước khi click.
  * Bit 1 (`0x02`): `SOCKET_PRECURSOR_TOWER` — Đối tượng click là Tháp Dẫn Đường.
  * Bit 2 (`0x04`): `AUTO_PROCEED_TO_WAYSTONE` — Tự động chuyển tiếp sang bước `PlaceWaystone` sau khi chọn xong node.
- `targetEntityId`: ID nội bộ của Node (nếu đọc được từ RAM) hoặc `0`.
- `priority`: `3200` (Mức ưu tiên tương tác Map Device).
- `timeoutMs`: `5000` (Thời gian timeout tối đa cho bước chọn node).

---

### 4.2. Đặc Tả Tệp Cấu Hình Chiến Lược: `data/maps/atlas_policy.toml`

```toml
# AutoPOE2 Atlas Strategy & Precursor Policy Configuration
# Phiên bản: 2026.1 (Build 6AA2213C)

[strategy]
# Chế độ ưu tiên chọn map: "bonus_rush" | "farm_whitelist" | "highest_tier"
mode = "farm_whitelist"

# Cấp độ Waystone tối thiểu và tối đa được phép chạy tự động
min_tier = 14
max_tier = 16

# Ưu tiên hoàn thành các node chưa có điểm thưởng Atlas Bonus
prioritize_uncompleted_bonus = true

# Tự động chọn Citadel / Boss Encounter khi sẵn sàng
auto_engage_citadels = true

[whitelist]
# Danh sách tên bản đồ ưu tiên farm (theo thứ tự ưu tiên giảm dần)
preferred_maps = [
    "Deserted",
    "Fortress",
    "Creek",
    "Sandswept Marsh",
    "Riverbank"
]

[blacklist]
# Danh sách bản đồ cấm chạy (địa hình hẹp, boss phản đòn, layout mê cung)
ignored_maps = [
    "Vaal Pyramid",
    "Overgrown Ruin",
    "Maze"
]

[precursor_towers]
# Tự động kiểm tra và nạp Precursor Tablet vào các Tháp Dẫn Đường xung quanh
enable_precursor_towers = true

# Hàng túi đồ chứa Precursor Tablet (Hàng 1, bên dưới hàng Waystone Row 0)
tablet_inventory_row = 1

# Số lượng Tablet tối đa nạp vào một tháp
max_tablets_per_tower = 3

# Các loại Tablet ưu tiên nạp (theo tên hoặc substring)
preferred_tablet_types = [
    "Delirium",
    "Breach",
    "Ritual",
    "Expedition",
    "Precursor"
]
```

---

### 4.3. Bổ Sung Tọa Độ Tham Chiếu Trong `data/ui/coordinates.toml`

```toml
[atlas_ui]
# Khung nhìn Atlas Map Tree trung tâm (1080p tham chiếu)
viewport_center_x = 960.0
viewport_center_y = 540.0

# Nút Tìm Kiếm Bản Đồ (Atlas Search Box)
search_box_x = 960.0
search_box_y = 980.0

# Nút Thu Nhỏ / Phóng To Cây Atlas (Zoom Controls)
zoom_in_button_x = 1820.0
zoom_in_button_y = 480.0
zoom_out_button_x = 1820.0
zoom_out_button_y = 520.0

# Độ trễ hiển thị Tooltip khi hover lên Node (ms)
node_hover_delay_ms = 120
```

---

## 5. Danh Mục Các Bất Biến Bắt Buộc (Architectural Invariants Matrix)

Toàn bộ quá trình thiết kế và thực thi của module `AtlasNodeSelector` bắt buộc phải tuân thủ nghiêm ngặt 4 bất biến kiến trúc sau:

| Mã Bất Biến | Tên Bất Biến & Đặc Tả Kỹ Thuật | Hành Vi Bị CẤM TUYỆT ĐỐI (Zero Tolerance) | Chế Tài & Kiểm Tra Tự Động |
|---|---|---|---|
| **`INV-ATLAS-01`** | **Safe Hideout Execution**<br/>Mọi thao tác duyệt Atlas, chọn Node và nạp Tablet CHỈ ĐƯỢC PHÉP kích hoạt tại Hideout an toàn (`is_in_town == true` hoặc `area.areaName` chứa `"Hideout"`). | CẤM mở hoặc tương tác với Atlas khi đang ở trong Map chiến đấu hoặc khi có quái vật xung quanh (`Mobs > 0`). | Core tự động đoản mạch, hủy lệnh và trả về trạng thái `Failed` nếu phát hiện quái vật sống. |
| **`INV-ATLAS-02`** | **Verified Node Target & Hover Confirmation**<br/>Trước khi click chuột trái (LMB) xác nhận chọn Node, con trỏ chuột bắt buộc phải hover tại vị trí mục tiêu trong tối thiểu 100ms để kiểm chứng sự xuất hiện của Tooltip. | CẤM click mù vào tọa độ màn hình rác hoặc click khi client game chưa nạp xong UI Atlas. | Fail-closed: Nếu sau 300ms hover không phát hiện Tooltip, hủy thao tác click và thử lại tối đa 2 lần. |
| **`INV-ATLAS-03`** | **Zero Hot-Path Blocking (< 8.33ms)**<br/>Vòng lặp C++ Core 120Hz Hot Path tuyệt đối không được thực hiện bất kỳ tác vụ I/O, OCR, hay tính toán hình học nặng nào. | CẤM gọi Win32 GDI capture hoặc thuật toán xử lý ảnh trực tiếp trong luồng chính `GameSession::Tick()`. | Toàn bộ việc xử lý ảnh, OCR và tính toán tọa độ chạy độc lập trong luồng Tier 2 Python (Cold Path 1–10Hz). |
| **`INV-ATLAS-04`** | **Zero Wishful Thinking (Clear Boundary)**<br/>Ranh giới giữa mã nguồn hiện có (`[CODE-PRESENT]`) và tính năng kế hoạch (`[PLANNED]`) phải được ghi nhận minh bạch 100%. | CẤM tuyên bố "đã có tính năng chọn Atlas Node tự động" khi mã nguồn mới dừng lại ở bản đặc tả kỹ thuật DOC-56. | Giữ nguyên trạng thái `[PLANNED]` trong toàn bộ tài liệu cho đến khi test case thực địa PASS 100%. |
| **`INV-ATLAS-05`** | **Unified Hideout-as-a-Map Entity Navigation (`INV-HIDEOUT-ENTITY-NAV-01`)**<br/>Hideout được xử lý chuẩn mực như một Map Instance hoàn chỉnh (`HideoutShoreline`). Các đối tượng Map Device, Waypoint, Stash, Salvage Bench, NPC là các Interactable Entities trong `EntityManager`. Tiếp cận và tương tác qua `NAVIGATE_TO_COORD(x,y,z)` sử dụng `QuestNavigator` + `pathfinder.cpp` và Dynamic Player XYZ (`PlayerFinder 16MB`), tự động trượt tiếp tuyến men vật cản khi va quệt, zoom-in camera và chiếu `WorldToScreen`. | TUYỆT ĐỐI CẤM giải pháp chống chế yêu cầu người chơi dời Map Device gần Waypoint; CẤM hardcode pixel di chuyển mù quáng (như sleep phím cứng `time.sleep(2.5)`). Phải đạt chuẩn tự hành của game thủ chuyên nghiệp. | Test 89 (Tangent Sliding), Test 90 (3D Projection & Zoom) 741/741 checks PASS; `test_autonomous_mapping_coordinator.py` 28/28 PASS. |

---

## 6. Kế Hoạch Nghiệm Thu Thực Nghiệm (Empirical Definition of Done - DoD Gate)

Module `AtlasNodeSelector` chỉ được phép chuyển trạng thái từ `[PLANNED]` sang `[COMPLETED]` khi vượt qua đầy đủ 3 cổng kiểm thử thực nghiệm:

### 6.1. Cổng 1: Kiểm Thử Độc Lập Trên Headless Mock POE2 Harness (Rule 11)
- **Unit Test Python (`tests/test_atlas_selector.py`)**:
  * Nạp ảnh chụp màn hình Atlas thực tế (1080p & 1440p) từ thư mục `tests/test_fixtures_real_captures/atlas/`.
  * Xác minh thuật toán `AtlasPerceptionEngine` nhận diện chính xác ít nhất 5 Map Nodes và 1 Tháp Precursor Tower.
  * Xác minh `AtlasStrategyPlanner` chọn đúng Node `Deserted` theo whitelist quy định tại `atlas_policy.toml`.
- **Unit Test C++ (`tests/test_core.cpp` - Test Suite Mới)**:
  * Nạp kịch bản `SimulatedMemoryReader` gửi lệnh `SELECT_ATLAS_NODE`.
  * Xác minh FSM `MapDeviceHandler` chuyển tiếp mượt mà: `OpenDevice` $\rightarrow$ `SelectAtlasNode` $\rightarrow$ `PlaceWaystone` $\rightarrow$ `Activate`.
  * Xác minh lệnh điều khiển chuột phát ra qua `KMBoxNet` theo đúng đường cong Bézier.

### 6.2. Cổng 2: Kiểm Chứng Replay Trên Dữ Liệu Thật (Rule 14)
- Chạy kịch bản replay với tệp log hiện trường và ảnh chụp màn hình thật của nhân vật `BEONGUSI#3653`:
  * Tọa độ click Node tính toán không bị lệch quá 5 pixels so với tâm icon thực tế trên màn hình 2560x1440.
  * Không vi phạm bất kỳ điều kiện nào của Ma trận Bất biến `INV-ATLAS-01` đến `INV-ATLAS-04`.

### 6.3. Cổng 3: Nghiệm Thu Thực Địa Trên Game Client Thật (Live Sanity Gate)
- Kích hoạt tính năng trên client game thật:
  * Nhân vật tiếp cận Map Device tại Shoreline Hideout.
  * Tự động click mở Map Device.
  * Tự động chọn đúng node bản đồ theo cấu hình.
  * Nạp thành công Waystone từ hàng 1 túi đồ và mở cổng Map thành công mà không cần người dùng can thiệp thủ công.
  * Log hệ thống ghi nhận rõ ràng:
    ```text
    [MapDeviceHandler] State: OpenDevice -> SelectAtlasNode
    [AtlasSelector] Selected Node: 'Deserted' (Tier 15, Bonus: Uncompleted) at Screen (1018, 542).
    [MapDeviceHandler] State: SelectAtlasNode -> PlaceWaystone (Row 0, Col 0).
    [MapDeviceHandler] State: PlaceWaystone -> Activate. Map Portals Activated!
    ```

---

## 7. Bằng Chứng Nghiệm Thu Thực Nghiệm (Empirical DoD Evidence - 13/09/2026)

### 7.1. C++ Core Test Suite (`bin/Release/AutoPOE2_Tests.exe`)
- **Test Case**: `Test 88: Atlas Node Selector & Map Device 10-Step FSM (Doc 56)`
- **Kết quả thực thi**: `716/716 KIỂM TRA ĐỀU ĐẠT (PASS 100%)`
- **Chi tiết kiểm chứng**:
  * Chuyển trạng thái FSM qua 10 bước: `Idle` -> `ApproachDevice` -> `OpenDevice` -> `SelectAtlasNode` -> `InspectPrecursorTowers` -> `PlaceWaystone` -> `PlaceTablet` -> `Activate` -> `WaitForPortals` -> `EnterPortal`.
  * Xác minh Hover delay phi phong tỏa luồng 120Hz Hot-Path: Kiểm tra `Execute()` trả về `false` khi delay < 120ms (zero thread freeze) và chỉ click sau khi đủ thời gian hover verify.
  * Xác minh tiếp nhận và phục hồi lệnh `SELECT_ATLAS_NODE` (`MacroOpCode = 9`) sau khi FSM ở trạng thái `Completed`, chuyển về `ApproachDevice` an toàn, chống nuốt lệnh giữa các map runs.
  * Nhận diện và thực thi lệnh `SELECT_ATLAS_NODE` với cờ bitmask: `ATLAS_FLAG_REQUIRE_HOVER_VERIFY (0x01)`, `ATLAS_FLAG_SOCKET_PRECURSOR_TOWER (0x02)`, `ATLAS_FLAG_AUTO_PROCEED_TO_WAYSTONE (0x04)`.
  * Khóa cứng bất biến kích thước `sizeof(CommandPacket) == 36` bytes.

### 7.2. Python Companion Test Suite (`pytest tests/test_atlas_selector.py`)
- **Kết quả thực thi**: `9/9 PASSED in 0.10s`
- **Các test case đã vượt qua**:
  1. `test_atlas_perception_roi_scaling`: Xác minh co dãn tỷ lệ ROI viewport theo độ phân giải màn hình (1080p, 1440p, 4K).
  2. `test_atlas_strategy_whitelist_selection`: Lựa chọn node ưu tiên trong danh sách Whitelist (`Deserted`, `Fortress`).
  3. `test_atlas_strategy_blacklist_rejection`: Loại bỏ các node trong danh sách Blacklist (`Vaal Pyramid`, `Maze`).
  4. `test_atlas_strategy_bonus_rush`: Ưu tiên tuyệt đối node chưa hoàn thành Bonus Objective (`bonus_uncompleted = True`).
  5. `test_inv_atlas_01_safe_hideout_execution`: Kiểm tra bất biến an toàn `INV-ATLAS-01`, từ chối chạy khi ở ngoài Hideout hoặc có quái vật.
  6. `test_precursor_tower_socket_flag`: Phát cờ cắm Precursor Tablet khi tháp có socket trống trong viewport.
  7. `test_inv_atlas_02_out_of_viewport_fail_closed`: Khóa an toàn fail-closed từ chối mọi node nằm ngoài Viewport ROI Atlas.
  8. `test_inv_atlas_02_occlusion_fail_closed`: Khóa an toàn fail-closed từ chối node bị che khuất bởi giao diện (chatbox, buff bar, minimap).
  9. `test_precursor_tower_outside_viewport_rejection`: Từ chối nạp tablet vào tháp nằm ngoài khung nhìn viewport.

---

## 8. Chuẩn Hóa Phím Tắt SSoT & Khắc Phục Triệt Để Cờ Ảo POE1 (Human-like Keybindings & Hideout Entity Navigation)

> **Cảnh Báo Kỹ Thuật (Zero-Drift Enforcement)**:  
> Cờ `use_wasd_to_move=false` trong section đầu của `poe2_production_Config.ini` là **cờ di sản (legacy placeholder) sót lại từ POE1 engine**. Trong POE2, thiết lập di chuyển thực sự được quyết định bởi mục `[GENERAL]` và section `[WASD_ACTION_KEYS]`:
> - `user_input_mode=wasd`
> - `last_selected_KBM_input_mode=wasd`
> 
> Tuyệt đối CẤM các agent trong tương lai đọc nhầm cờ ảo `use_wasd_to_move=false` rồi suy diễn sai rằng game đang ở Click-to-Move.

### 8.1. Bảng Phím Tắt SSoT Thực Tế Từ Máy Người Chơi (`poe2_production_Config.ini`)
| Hành Động Trong Game | Mã INI | Phím Thực Tế | Virtual Key | Chức Năng & Hành Vi Thao Tác Chuẩn Người Thật |
| :--- | :--- | :--- | :--- | :--- |
| **Di chuyển (WASD)** | | | | |
| Move Up (Lên) | `87` | **W** | `0x57` | Di chuyển hướng Bắc. Dwell time tối thiểu 300–500ms khi bước ngắn, 1.0–2.0s khi chạy đường dài. |
| Move Left (Trái) | `65` | **A** | `0x41` | Di chuyển hướng Tây. |
| Move Down (Xuống) | `83` | **S** | `0x53` | Di chuyển hướng Nam (kết hợp `D` để về bãi cát trung tâm Hideout). |
| Move Right (Phải) | `68` | **D** | `0x44` | Di chuyển hướng Đông. |
| **Phím Tắt Tiện Ích (Human Shortcuts)** | | | | |
| **Mở Town Portal** | `190` | **`.`** (Dấu chấm) | `0xBE` (`VK_OEM_PERIOD`) | Phím mở cổng portal chuẩn của người chơi thật (thay vì bấm túi đồ). |
| **Mở Sàn Ngoại Hối / Market** | `191` | **`/`** (Gạch chéo) | `0xBF` (`VK_OEM_2`) | Mở trực tiếp Currency Exchange Market. |
| **Đóng Toàn Bộ Bảng UI** | `32` | **Spacebar** | `0x20` (`VK_SPACE`) | Thoát nhanh Atlas / Inventory / Dialog / Shop về màn hình game. |
| **Lăn Né (Dodge Roll)** | `32` | **Spacebar** | `0x20` (`VK_SPACE`) | Kích hoạt Iframe né sát thương trong chiến đấu. |
| **Mở Túi Đồ (Inventory)** | `73` | **I** | `0x49` | Mở túi đồ nạp Waystone / kiểm tra trang bị. |
| **Mở Bảng Atlas Passives** | `85 2` | **Ctrl + U** | `0x55 + Mod 2` | Mở cây nội tại Atlas. |
| **Mở Bảng Nhân Vật** | `67` | **C** | `0x43` | Xem chi tiết stats. |
| **Kỹ Năng Chiến Đấu (Skill Bar)** | | | | |
| Bound Skill 1 | `1` | **Chuột Trái (LMB)** | `0x01` | Đòn tấn công / lướt chính (CẤM click LMB mù quáng vì sẽ tung chiêu lao đi!). |
| Bound Skill 2 | `4` | **Chuột Giữa (MMB)** | `0x04` | Wolf skill. |
| Bound Skill 3 | `2` | **Chuột Phải (RMB)** | `0x02` | Khiên / Orb. |
| Bound Skill 4 | `81` | **Q** | `0x51` | Lightning Spell. |
| Bound Skill 5 | `69` | **E** | `0x45` | *Đặc biệt: Chế độ WASD đổi skill 5 từ W sang E.* |
| Bound Skill 6 | `82` | **R** | `0x52` | Frost Bomb. |
| Bound Skill 7 | `84` | **T** | `0x54` | Leap / Minion. |
| Bound Skill 8 | `70` | **F** | `0x46` | Sprint / Flame. |

### 8.2. Nguyên Tắc Tương Tác Map Device & Hideout Chuẩn Mực
1. **Hideout là một Map Entity**:
   - Nhân vật xuất hiện tại Waypoint. Map Device nằm ngay bên cạnh (`x ≈ 1320, y ≈ 730`), đường đi thông thoáng 100%.
   - CẤM bấm phím `U` để mở Atlas vì `U` chỉ là View-Only (không có khay cắm Waystone và không có nút Traverse).
   - BẮT BUỘC click trực tiếp vào bệ đá Map Device để mở giao diện kích hoạt thực sự.
2. **Thao Tác Giống Người Chơi Thật**:
   - Sử dụng phím `Space` để tắt các bảng menu / Atlas sau khi hoàn tất.
   - Sử dụng phím `.` để mở Town Portal khi muốn rời map.
   - Sử dụng phím `/` để tra cứu giao dịch.


