# Log Analysis Design

## 概述

Log Node 是 FWAuto 的 AI 驅動日誌分析節點，透過 Claude Code SDK 自動解析 UART 日誌並回答使用者問題。

### 解決的核心問題

- **日誌分析耗時**：手動檢視數千行日誌尋找錯誤或特定事件
- **跨平台日誌存取**：遠端裝置（AM62X、Raspberry Pi）的日誌需要先手動下載
- **重複性工作**：每次都要重新指定日誌路徑

### 關鍵特性

- **AI 自動分析**：使用 Claude Code SDK 智能解析日誌內容
- **遠端日誌支援**：透過 SSH/SCP 自動下載遠端裝置日誌
- **自動路徑檢測**：自動檢測上次 deploy 的日誌路徑，無需手動指定
- **路徑記憶**：deploy_node 執行後自動儲存日誌路徑到 config，log_node 自動讀取
- **安全沙箱**：限制 AI 只能使用 Read 和 Grep 工具

## 架構設計

### 整體流程圖

```mermaid
flowchart TD
    START["使用者執行<br/>fwauto log '問題'"] --> GET_PARAMS["取得參數<br/>user_prompt<br/>log_file_path (optional)"]

    GET_PARAMS --> CHECK_PATH{log_file_path<br/>是否提供?}
    CHECK_PATH -->|否| FALLBACK["從 config 自動讀取<br/>last_log_file_path<br/>(v0.5.0 新功能)"]
    CHECK_PATH -->|是| DETECT

    FALLBACK --> HAS_SAVED{是否有<br/>儲存路徑?}
    HAS_SAVED -->|是| DETECT
    HAS_SAVED -->|否| ERROR["錯誤: 請提供日誌路徑<br/>或先執行 deploy"]

    DETECT{路徑類型?}
    DETECT -->|本地路徑| LOCAL["轉換為絕對路徑<br/>驗證檔案存在"]
    DETECT -->|遠端路徑| REMOTE["使用 SCP 下載<br/>到 .fwauto/logs/"]

    LOCAL --> LOAD_PROMPT
    REMOTE --> LOAD_PROMPT["載入 Prompt Template<br/>prompts/log.md"]

    LOAD_PROMPT --> CONFIG_SDK["配置 Claude SDK<br/>- 工具: Read, Grep<br/>- 權限: bypass<br/>- 目錄: log_dir"]

    CONFIG_SDK --> EXECUTE["執行 AI 分析<br/>asyncio.run()"]
    EXECUTE --> STREAM["串流接收回應<br/>即時顯示"]

    STREAM --> CLEANUP{是遠端下載?}
    CLEANUP -->|是| DELETE["刪除暫存檔案"]
    CLEANUP -->|否| SKIP["保留檔案"]

    DELETE --> RETURN
    SKIP --> RETURN["返回分析結果<br/>log_analysis_result"]
    ERROR --> END_ERROR["結束"]

    style START fill:#e1f5ff
    style FALLBACK fill:#90EE90
    style EXECUTE fill:#DDA0DD
    style RETURN fill:#90EE90
    style DELETE fill:#FFE4B5
    style ERROR fill:#FFB6C1
```

### 核心組件

```mermaid
graph TB
    subgraph CLI["CLI 層"]
        CMD["fwauto log '問題'<br/>--log-path 路徑"]
    end

    subgraph LogNode["Log Node (nodes/log.py)"]
        MAIN[log_node 函數]
        DETECT[_is_remote_path]
        PARSE[_parse_remote_path]
        FETCH[_fetch_remote_log]
        CLEANUP[_cleanup_temp_files]
    end

    subgraph SDK["Claude Code SDK"]
        QUERY[query 函數]
        READ[Read Tool]
        GREP[Grep Tool]
    end

    subgraph Storage["儲存層"]
        PROMPT["prompts/log.md<br/>Jinja2 Template"]
        CONFIG[".fwauto/config.toml<br/>last_log_file_path"]
        TEMP[".fwauto/logs/<br/>暫存目錄"]
    end

    CMD --> MAIN
    MAIN --> DETECT
    DETECT -->|遠端| PARSE
    PARSE --> FETCH
    FETCH --> TEMP

    MAIN --> PROMPT
    MAIN --> CONFIG
    MAIN --> QUERY

    QUERY --> READ
    QUERY --> GREP

    MAIN --> CLEANUP
    CLEANUP --> TEMP

    style CLI fill:#e1f5ff
    style LogNode fill:#fff3e0
    style SDK fill:#f3e5f5
    style Storage fill:#e8f5e9
```

## 關鍵設計模式

### 1. 路徑處理：本地 vs 遠端

**遠端路徑偵測**：

```python
# 使用 Regex 匹配 user@host:path 格式
_is_remote_path("kent@192.168.50.1:/home/kent/uart.log")  # True
_is_remote_path("logs/uart.log")                           # False
```

**處理流程**：

```mermaid
flowchart TD
    INPUT["輸入路徑"] --> CHECK{"格式匹配<br/>user@host:path?"}

    CHECK -->|是| PARSE["解析 user/host/path"]
    CHECK -->|否| ABS["轉換絕對路徑"]

    PARSE --> SCP["SCP 下載<br/>timeout 30s"]
    SCP --> TEMP["儲存到<br/>.fwauto/logs/"]
    TEMP --> MARK["標記為暫存檔"]

    ABS --> VALIDATE["驗證檔案存在"]
    VALIDATE --> MARK2["標記為本地檔"]

    MARK --> ANALYSIS["AI 分析"]
    MARK2 --> ANALYSIS

    ANALYSIS --> CLEANUP{"是暫存檔?"}
    CLEANUP -->|是| DELETE["刪除檔案"]
    CLEANUP -->|否| KEEP["保留檔案"]

    DELETE --> END1["完成"]
    KEEP --> END1

    style PARSE fill:#FFE4B5
    style SCP fill:#FFE4B5
    style TEMP fill:#FFE4B5
    style MARK fill:#FFE4B5
    style ABS fill:#E1FFE4
    style VALIDATE fill:#E1FFE4
    style MARK2 fill:#E1FFE4
    style ANALYSIS fill:#DDA0DD
```

### 2. SDK 執行模式隔離

**問題**：Claude AI 預設行為是「諮詢模式」，會詢問澄清問題而非直接執行任務。

**解決方案**：覆寫 system prompt 強制執行模式

```python
system_override = (
    "CRITICAL: You are executing a specific automated task via SDK. "
    "This is NOT an interactive consultation. "
    "Execute the user's prompt instructions IMMEDIATELY and EXACTLY. "
    "DO NOT ask clarifying questions. DO NOT provide help menus. "
    "DO NOT explain what you can do. JUST DO THE TASK."
)
```

**SDK 配置**：

```mermaid
graph LR
    CONFIG["ClaudeAgentOptions"] --> TOOLS["allowed_tools<br/>['Read', 'Grep']"]
    CONFIG --> PERM["permission_mode<br/>'bypassPermissions'"]
    CONFIG --> DIR["add_dirs<br/>[log_dir]"]
    CONFIG --> SYS["system_prompt<br/>強制執行模式"]

    TOOLS --> LIMIT["限制工具權限<br/>只能讀取"]
    PERM --> AUTO["自動執行<br/>不詢問使用者"]
    DIR --> SANDBOX["沙箱限制<br/>只存取日誌目錄"]
    SYS --> FORCE["防止諮詢模式<br/>直接執行分析"]

    style CONFIG fill:#87CEEB
    style LIMIT fill:#FFB6C1
    style AUTO fill:#90EE90
    style SANDBOX fill:#FFE4B5
    style FORCE fill:#DDA0DD
```

### 3. 持久化配置與自動檢測（v0.5.0 新功能）

**設計目的**：簡化重複分析流程，使用者無需每次都指定日誌路徑。

**核心機制**：

1. **Deploy 時儲存路徑**：deploy_node 執行成功後，自動將 `remote_log_path` 儲存到 `.fwauto/config.toml` 的 `last_log_file_path` 欄位
2. **Log 時自動讀取**：log_node 執行時，若未提供 `--log-path` 參數，自動從 config 讀取上次儲存的路徑
3. **跨命令狀態共享**：透過持久化配置檔案，在不同命令執行之間保持狀態

**完整流程圖**：

```mermaid
sequenceDiagram
    participant User
    participant DeployNode
    participant Config as ".fwauto/config.toml"
    participant RemoteBoard as "AM62X 開發板"
    participant LogNode
    participant AI as "Claude AI"

    Note over User,AI: === 步驟 1: Deploy 並儲存路徑 ===

    User->>DeployNode: fwauto run
    DeployNode->>DeployNode: 渲染 remote_log_path<br/>→ /home/root/led_2025-11-24.log
    DeployNode->>RemoteBoard: SSH 部署二進制 + 啟動
    RemoteBoard->>RemoteBoard: nohup ./led >> log 2>&1 &<br/>（背景執行 + 日誌重定向）
    DeployNode->>Config: 儲存 last_log_file_path<br/>= "kent@192.168.50.1:/home/root/led_2025-11-24.log"
    DeployNode-->>User: ✓ Deploy 成功<br/>📊 Remote log: kent@192.168.50.1:/home/root/led_2025-11-24.log

    Note over User,AI: === 步驟 2: Log 自動檢測路徑 ===

    User->>LogNode: fwauto log "分析 LED"<br/>(未提供 --log-path)
    LogNode->>Config: 讀取 last_log_file_path
    Config-->>LogNode: "kent@192.168.50.1:/home/root/led_2025-11-24.log"
    LogNode->>LogNode: _is_remote_path() → True
    LogNode->>RemoteBoard: SCP 下載日誌
    RemoteBoard-->>LogNode: 保存到 .fwauto/logs/
    LogNode->>AI: Claude Code SDK<br/>Read + Grep tools
    AI-->>LogNode: 分析結果
    LogNode-->>User: 顯示分析結果
```

**使用範例**：

```bash
# 步驟 1: 執行 deploy（會自動儲存日誌路徑）
fwauto run
# 輸出:
# ✓ Deploy succeeded
# 📊 Remote log: kent@192.168.50.1:/home/root/led_2025-11-24.log

# 步驟 2: 後續分析無需指定路徑（自動檢測）
fwauto log "有任何 error 嗎?"  # 自動使用上次的路徑
fwauto log "LED 閃爍頻率是多少?"  # 依然自動使用

# 步驟 3: 需要時仍可手動指定覆蓋
fwauto log "分析其他日誌" --log-path /local/path/other.log
```

### 4. 錯誤處理與分類

**SCP 下載錯誤處理**：

```mermaid
flowchart TD
    SCP_START["執行 SCP 命令"] --> MONITOR{執行結果}

    MONITOR -->|timeout| ERR_TIMEOUT["TimeoutError<br/>30 秒超時"]
    MONITOR -->|exit code != 0| ERR_PROCESS["CalledProcessError<br/>分析 stderr"]
    MONITOR -->|success| SUCCESS["下載成功<br/>返回本地路徑"]

    ERR_TIMEOUT --> MSG_TIMEOUT["Remote host did not<br/>respond within 30s"]

    ERR_PROCESS --> ANALYZE{stderr 內容}
    ANALYZE -->|connection refused| MSG_CONN["Cannot connect to<br/>remote host"]
    ANALYZE -->|permission denied| MSG_AUTH["SSH authentication<br/>failed"]
    ANALYZE -->|no such file| MSG_FILE["Remote log file<br/>not found"]
    ANALYZE -->|其他| MSG_OTHER["SCP download failed"]

    MSG_TIMEOUT --> RETURN_ERR["RuntimeError"]
    MSG_CONN --> RETURN_ERR
    MSG_AUTH --> RETURN_ERR
    MSG_FILE --> RETURN_ERR
    MSG_OTHER --> RETURN_ERR

    SUCCESS --> RETURN_OK["返回本地路徑"]

    style SCP_START fill:#87CEEB
    style SUCCESS fill:#90EE90
    style ERR_TIMEOUT fill:#FFB6C1
    style ERR_PROCESS fill:#FFB6C1
    style RETURN_ERR fill:#FF6347
```

## State 管理

### 輸入/輸出

**State 輸入**：

| Field           | Type          | 說明                       |
| --------------- | ------------- | -------------------------- |
| `user_prompt`   | `str`         | 使用者的分析問題           |
| `log_file_path` | `str \| None` | 日誌檔案路徑（本地或遠端） |
| `project_root`  | `str`         | 專案根目錄（用於暫存目錄） |

**State 輸出**：

| Field                 | Type  | 說明                  |
| --------------------- | ----- | --------------------- |
| `log_analysis_result` | `str` | AI 分析結果或錯誤訊息 |

### 完整執行流程

```mermaid
stateDiagram-v2
    [*] --> ValidateInput

    ValidateInput --> FallbackConfig
    ValidateInput --> DetectPathType

    FallbackConfig --> LoadFromConfig
    LoadFromConfig --> DetectPathType
    LoadFromConfig --> ErrorNoPath

    DetectPathType --> LocalPath
    DetectPathType --> RemotePath

    LocalPath --> ValidateFile
    ValidateFile --> LoadPrompt
    ValidateFile --> ErrorNotFound

    RemotePath --> ParseRemote
    ParseRemote --> SCPDownload
    SCPDownload --> LoadPrompt
    SCPDownload --> ErrorDownload

    LoadPrompt --> ConfigureSDK
    ConfigureSDK --> ExecuteAnalysis
    ExecuteAnalysis --> StreamResponse
    StreamResponse --> CleanupCheck

    CleanupCheck --> DeleteTemp
    CleanupCheck --> KeepFile

    DeleteTemp --> ReturnResult
    KeepFile --> ReturnResult

    ErrorNoPath --> ReturnError
    ErrorNotFound --> ReturnError
    ErrorDownload --> ReturnError

    ReturnResult --> [*]
    ReturnError --> [*]

    note right of ConfigureSDK
        工具限制：Read, Grep
        權限：bypassPermissions
        沙箱：僅 log_dir
    end note

    note right of CleanupCheck
        遠端下載的檔案
        會被自動清理
    end note
```

## Prompt Template 設計

**prompts/log.md** 結構：

```markdown
You are analyzing UART log files for firmware development.

**Task**: Analyze the log file and answer the user's question.

**Log File**: `{{log_file_path}}`
**User Question**: {{user_prompt}}
**Working Directory**: {{cwd}}

**Instructions**:

- Use the Read tool to read the log file
- For large log files, use the Grep tool to search for specific patterns
- Provide a clear analysis based on the log content
- Answer the user's question directly

Do this NOW. No explanations about the task itself, just read and answer.
```

**Template 變數**：

- `log_file_path`: 日誌檔案絕對路徑
- `user_prompt`: 使用者問題
- `cwd`: 當前工作目錄（由 PromptManager 自動注入）

**設計原則**：

- **明確指令**：清楚告訴 AI 使用哪些工具
- **直接執行**：強制立即執行，避免詢問澄清
- **簡潔明瞭**：保持 template 簡短易懂

## 使用範例

### 本地日誌分析

```bash
# 相對路徑
fwauto log "有任何 error 嗎?" --log-path logs/uart.log

# 絕對路徑
fwauto log "LED 閃爍頻率" --log-path /home/user/project/logs/uart.log
```

### 遠端日誌分析

```bash
# 遠端路徑（自動下載）
fwauto log "boot 流程正常嗎?" --log-path kent@192.168.50.1:/tmp/uart.log
```

### 自動檢測路徑（v0.5.0 推薦方式）

```bash
# 第一次執行 deploy（會自動儲存路徑）
fwauto run
# 輸出: 📊 Remote log: kent@192.168.50.1:/home/root/led_2025-11-24.log

# 後續分析無需指定路徑（自動檢測上次 deploy 的路徑）
fwauto log "系統初始化時間"
fwauto log "有沒有 memory leak"
fwauto log "LED 閃爍頻率是多少?"
```

### 獨立測試

```bash
# 直接執行 log node（開發/測試用）
python -m src.fwauto.nodes.log "分析 LED 閃爍頻率" logs/uart.log
```

## 技術特點總結

| 特點                       | 說明                                         | 實作位置                             |
| -------------------------- | -------------------------------------------- | ------------------------------------ |
| **跨平台遠端存取**         | 透過 SSH/SCP 支援遠端裝置日誌                | `_fetch_remote_log()`                |
| **自動路徑檢測（v0.5.0）** | 自動檢測上次 deploy 的日誌路徑，無需手動指定 | `config.last_log_file_path` 讀取     |
| **路徑持久化**             | deploy_node 自動儲存路徑到 config            | `config.update_last_log_path()`      |
| **安全沙箱**               | 限制 AI 只能使用 Read/Grep，僅存取日誌目錄   | `ClaudeAgentOptions`                 |
| **錯誤處理完善**           | 網路超時、認證失敗、檔案不存在等場景         | `_fetch_remote_log()` error handling |
| **暫存清理**               | 自動清理遠端下載的暫存檔案                   | `_cleanup_temp_files()`              |
| **執行模式隔離**           | 強制 AI 直接執行任務，不詢問澄清             | `system_override` prompt             |
| **串流輸出**               | 即時顯示 AI 分析過程                         | `async for message in query()`       |
