---
date: 2025-11-03T15:33:59+0800
researcher: Claude (via Kent)
git_commit: 2c8bb7e456edda88d29771d4746477350b6541e5
branch: main
repository: FWAauto
topic: "FWAuto SSH 遠端執行可行性研究"
tags:
  - research
  - ssh
  - remote-execution
  - closed-loop
  - architecture
status: complete
last_updated: 2025-11-03
last_updated_by: Claude
---

# Research: FWAuto SSH 遠端執行可行性研究

**Date**: 2025-11-03T15:33:59+0800
**Researcher**: Claude (via Kent)
**Git Commit**: 2c8bb7e456edda88d29771d4746477350b6541e5
**Branch**: main
**Repository**: FWAauto

---

## Research Question

如何在 FWAuto 中透過 SSH 執行 VM 和開發板上的命令，並整合到 LangGraph workflow 中，以實現跨三環境（開發機 + VM + 開發板）的 AI 輔助開發閉環？

**關鍵子問題**：
1. FWAuto 目前是否有任何遠端執行能力？
2. 如何建立 log → ai_brain → build 的閉環路由？
3. 配置系統是否支援 SSH 遠端主機配置？
4. Python SSH 技術的可行性評估（subprocess+ssh vs paramiko）

---

## Summary

**核心發現**：

1. **FWAuto 100% 本地執行架構**
   - 所有命令透過 `subprocess.Popen()` 在本機執行
   - 無任何 SSH 或遠端連線功能
   - 但已有成熟的命令執行框架可擴展

2. **閉環路由擴展點明確**
   - `log_node` 目前直接路由到 END（graph.py:188）
   - 可參考現有 build → ai_brain → build 循環模式
   - 擴展點：新增 `route_after_log()` 函數

3. **配置系統完全缺少遠端支援**
   - ProjectConfig 和 UserConfig 無 SSH 相關欄位
   - 但兩層配置架構清晰，易於擴展
   - 擴展點：config.py, user_config.py, state.py

4. **SSH 技術方向建議**
   - **推薦：subprocess + ssh**（簡單、零依賴、符合 KISS 原則）
   - 備選：paramiko（更多控制，但複雜度高、需引入依賴）
   - 整合複雜度：中等（約 50-200 行程式碼，視選擇而定）

---

## Detailed Findings

### 1. 現有遠端執行能力分析

#### 1.1 命令執行架構

**核心執行函數**：`src/fwauto/utils.py:78-156`

```python
def execute_make_command(
    makefile_path: Path,
    target: str,
    project_root: Path,
    timeout: int = 60,
) -> tuple[int, str]:
```

**關鍵發現**：
- ✅ 使用 `subprocess.Popen()` 執行命令（第 122 行）
- ✅ 完整的超時處理（第 127-137 行）
- ✅ 錯誤處理成熟（`TimeoutExpired`, 一般 `Exception`）
- ✅ 即時輸出捕獲機制
- ❌ **完全本地執行**，無遠端主機概念

**執行流程圖**：

```mermaid
graph LR
    A["build_node"] --> B["execute_make_command()"]
    B --> C["subprocess.Popen()"]
    C --> D["本地 Makefile"]
    D --> E["本地工具鏈"]
    E --> F["返回 (returncode, output)"]

    style B fill:#87CEEB
    style C fill:#FFB6C1
```

#### 1.2 現有 subprocess 使用情況

| 檔案位置 | 用途 | 執行方式 | 錯誤處理 |
|---------|------|----------|---------|
| `utils.py:122` | 核心命令執行 | `Popen()` | ✅ 超時 + 異常 |
| `build.py:79-84` | 編譯節點 | 調用 utils | ✅ 完整 |
| `flash.py:79-84` | 燒錄節點 | 調用 utils | ✅ 完整 |
| `scripts/check.py` | 代碼檢查 | `run()` | ✅ 基本 |
| `scripts/format.py` | 代碼格式化 | `run()` | ✅ 基本 |
| `scripts/lint.py` | 代碼 lint | `run()` | ✅ 基本 |

**關鍵洞察**：
- FWAuto 已有統一的命令執行抽象層
- 錯誤處理模式成熟且一致
- 可直接擴展支援遠端執行，無需重構現有邏輯

#### 1.3 SSH / 遠端連線相關

**搜尋結果**：❌ **完全不存在**

- 搜尋關鍵字：`ssh`, `paramiko`, `fabric`, `pexpect`, `remote`
- 結果：零匹配（除了一行註解提到 "connection"）
- 依賴套件（pyproject.toml）：無 SSH 相關套件

---

### 2. 閉環路由擴展點分析

#### 2.1 現有路由架構

**位置**：`src/fwauto/graph.py`

**現有路由函數**：

```mermaid
graph TD
    START["START"] --> R1["route_from_start<br/>(32-68)"]
    R1 --> INIT["init_project"]
    R1 --> BUILD["build"]
    R1 --> FLASH["flash"]
    R1 --> LOG["log"]

    INIT --> R2["route_after_init<br/>(70-90)"]
    BUILD --> R3["route_after_build<br/>(92-112)"]
    R3 -->|error + retry| AI["ai_brain"]
    AI --> R4["route_after_ai_brain<br/>(114-118)"]
    R4 --> BUILD

    FLASH --> R5["route_after_flash<br/>(120-127)"]
    LOG --> END1["END (direct edge)"]
    R3 --> END2["END"]
    R5 --> END3["END"]

    style LOG fill:#FFB6C1
    style R3 fill:#90EE90
    style AI fill:#DDA0DD
```

**關鍵發現**：
- ✅ Build 有條件路由（build → ai_brain → build 循環已存在）
- ❌ Log 直接路由到 END（第 188 行：`workflow.add_edge("log", END)`）
- ❌ 缺少 `route_after_log()` 函數

#### 2.2 參考實現：Build → AI Brain 循環

**觸發條件** (`graph.py:92-112`)：
```python
def route_after_build(state: FirmwareState) -> str:
    if state["build_status"] == "success":
        return "flash" or "end"
    else:
        # 檢查重試次數
        if state["iteration"] < state["max_retries"]:
            return "ai_brain"  # 路由到 AI 修復
        return "end"
```

**重試追蹤** (`build.py:109`)：
```python
"iteration": state.get("iteration", 0) + 1  # 失敗時累加
```

**AI 任務檢測** (`ai_brain.py:92-94`)：
```python
if state.get("build_errors") and state.get("build_status") == "error":
    return "fix_build_errors"  # 載入對應 prompt
```

**關鍵模式**：
1. Node 設定錯誤狀態 + 累加 iteration
2. Route 函數檢查狀態 + 比較 iteration vs max_retries
3. AI Brain 根據狀態判斷任務類型
4. 返回原 node 驗證修復結果

#### 2.3 Log 擴展點

**主要擴展點**：`src/fwauto/graph.py:188`

**當前實現**：
```python
workflow.add_edge("log", END)  # 無條件結束
```

**可參考的模式**：
```python
# 參考 build 的條件路由（157-167 行）
workflow.add_conditional_edges(
    "build",
    route_after_build,
    {
        "flash": "flash",
        "ai_brain": "ai_brain",
        "end": END,
    }
)
```

**擴展方向**：
- 新增 `route_after_log(state: FirmwareState) -> str` 函數
- 檢查 `log_analysis_result` 是否偵測到需要修復的問題
- 如需修復且 iteration < max_retries → 路由到 `ai_brain`
- 否則 → 路由到 `end`

#### 2.4 擴展點總結表

| 擴展點 | 檔案:行號 | 當前狀態 | 可參考實現 |
|-------|----------|---------|-----------|
| Route 函數 | `graph.py:188` | ❌ 直接 edge | `route_after_build()` (92-112) |
| 條件路由 | `graph.py:187-188` | ❌ `add_edge()` | build 條件路由 (157-167) |
| AI 任務檢測 | `ai_brain.py:83-106` | ⚠️ 無 log-fix 類型 | build_errors 檢測 (92-94) |
| Prompt 模板 | `prompts/` | ❌ 缺少 fix_from_log | `fix_build_errors.md` |
| 重試追蹤 | `log.py:116-119` | ❌ 無 iteration | build.py:109 |

---

### 3. 配置系統對 SSH 的支援

#### 3.1 當前配置架構

**兩層配置設計**：

```mermaid
graph TB
    USER["UserConfig<br/>~/.fwauto/config.toml<br/>(全域設定)"]
    PROJECT["ProjectConfig<br/>.fwauto/config.toml<br/>(專案設定)"]

    USER -.->|繼承 SDK 路徑| PROJECT
    PROJECT -->|可覆寫| USER

    USER --> SDK1["sdk.stm32_keil"]
    USER --> SDK2["sdk.am62x"]
    USER --> DEV1["device.stm32_keil"]

    PROJECT --> BUILD["build.makefile"]
    PROJECT --> FLASH["flash.makefile"]
    PROJECT --> DEV2["device.model"]

    style USER fill:#e1f5ff
    style PROJECT fill:#fff3e0
```

#### 3.2 ProjectConfig 結構

**位置**：`src/fwauto/config.py:42-116`

**現有欄位**：

| Property | Type | Default | 說明 |
|---------|------|---------|------|
| `build_makefile` | str | ".fwauto/build/Makefile" | Build Makefile 路徑 |
| `build_target` | str | "build" | Make target 名稱 |
| `flash_makefile` | str | ".fwauto/flash/Makefile" | Flash Makefile 路徑 |
| `flash_target` | str | "flash" | Make target 名稱 |
| `sdk_type` | str \| None | None | SDK 識別符 |
| `sdk_path` | str \| None | None | SDK 安裝路徑 |
| `device_family` | str | - | 裝置系列 |
| `device_model` | str | - | 裝置型號 |

**關鍵發現**：
- ❌ **完全缺少遠端主機相關欄位**
- ✅ 所有欄位都有 `@property` 裝飾器，易於擴展
- ✅ 配置驗證寬鬆（`_validate()` 幾乎不做檢查）

#### 3.3 UserConfig 結構

**位置**：`src/fwauto/user_config.py:10-56`

**現有方法**：
```python
def get_sdk_config(sdk_type: str) -> dict[str, Any] | None
def set_sdk_config(sdk_type: str, sdk_data: dict) -> None
def get_device_config(sdk_type: str) -> dict[str, Any] | None
def set_device_config(sdk_type: str, device_data: dict) -> None
```

**TOML 結構範例**：
```toml
[sdk.stm32_keil]
type = "keil"
path = "C:\\Keil_v5"

[device.stm32_keil]
family = "stm32f4"
model = "STM32F407VGT6"
```

**關鍵發現**：
- ❌ **無 SSH 或遠端連線配置**
- ✅ 已有索引式存取模式（`sdk.{type}`），可仿效建立 `remote.{id}`
- ✅ 支援動態新增配置（`set_*_config()` 方法）

#### 3.4 FirmwareState 相關欄位

**位置**：`src/fwauto/state.py:6-77`

**現有欄位**（與環境相關）：
```python
execution_mode: Literal["build", "flash", "run", "log", ...]
platform: str  # e.g., "stm32_keil", "am62x"
project_root: str  # 本地專案路徑
```

**完全缺少的欄位**：
- ❌ `remote_host`
- ❌ `remote_user`
- ❌ `ssh_key_path`
- ❌ `remote_work_dir`
- ❌ `connection_type`（local vs remote）

**⚠️ 重要提醒**（CLAUDE.md）：
> **CRITICAL**: Keep `FirmwareState` minimal. Before adding fields, discuss with project owner.

#### 3.5 配置擴展點

**建議的擴展結構**（僅供參考，非實施建議）：

```toml
# User Config (~/.fwauto/config.toml)
[remote.am62x_vm]
host = "192.168.50.163"
user = "alientek"
ssh_key = "~/.ssh/am62x_key"

[remote.devboard]
host = "192.168.50.170"
user = "root"

# Project Config (.fwauto/config.toml)
[build]
execution = "remote"    # local | remote
remote_id = "am62x_vm"  # 參照 UserConfig
remote_work_dir = "/home/alientek/workspace/project"

[flash]
execution = "remote"
remote_id = "devboard"
```

**擴展點位置**：

| 檔案 | 行號 | 擴展類型 | 說明 |
|-----|------|---------|------|
| `config.py` | ~116 | 新增 property | `remote_host()`, `remote_config()` |
| `user_config.py` | ~56 | 新增方法 | `get_remote_config()`, `set_remote_config()` |
| `state.py` | ~77 | 新增欄位（需討論） | `remote_enabled`, `remote_host` 等 |

---

### 4. Python SSH 技術可行性評估

#### 4.1 技術方案比較

**方案 A：subprocess + ssh（推薦）**

```mermaid
graph LR
    A["Python Code"] --> B["subprocess.Popen()"]
    B --> C["ssh client<br/>(系統內建)"]
    C --> D["遠端主機"]
    D --> E["命令執行"]
    E --> F["返回結果"]

    style B fill:#87CEEB
    style C fill:#90EE90
```

**優點**：
- ✅ 零依賴（無需新增套件）
- ✅ 簡單（與現有 `execute_make_command()` 模式一致）
- ✅ 效能高（C-based SSH client）
- ✅ 使用系統 SSH 配置（~/.ssh/config）

**缺點**：
- ❌ 錯誤資訊較粗糙（exit code 255 = SSH 失敗）
- ❌ 需要系統安裝 SSH client（Linux/macOS 內建，Windows 需安裝）
- ❌ 無程式化連線管理

**複雜度**：🟢 低（約 50 行程式碼修改）

---

**方案 B：paramiko**

```mermaid
graph LR
    A["Python Code"] --> B["paramiko.SSHClient()"]
    B --> C["Python SSH<br/>實作"]
    C --> D["遠端主機"]
    D --> E["命令執行"]
    E --> F["返回結果"]

    style B fill:#87CEEB
    style C fill:#FFB6C1
```

**優點**：
- ✅ 豐富的異常類型（`AuthenticationException`, `SSHException`）
- ✅ 程式化控制（連線池、持久連線）
- ✅ 跨平台一致性（Pure Python）

**缺點**：
- ❌ 新增依賴（paramiko + cryptography + C/Rust extensions）
- ❌ 學習曲線（用戶完全不熟悉）
- ❌ 複雜度高（更多配置、更多錯誤處理）
- ❌ 效能較低（20-40% slower than native SSH）

**複雜度**：🟡 中高（約 150-200 行程式碼）

---

**方案 C：fabric（不推薦）**

- ❌ 基於 paramiko，但增加更多抽象層
- ❌ 為部署/系統管理設計，不適合 build/flash 場景
- ❌ 執行緒並行問題（1-10 主機效能極差）

---

#### 4.2 方案選擇建議

**推薦：subprocess + ssh**

**理由**：
1. **符合 KISS 原則**（CLAUDE.md 核心原則）
2. **零依賴增長**（維護成本低）
3. **學習曲線低**（用戶已知 subprocess 存在，只是不熟）
4. **已有模板**（utils.py 提供完整參考）
5. **效能優勢**（C-based 實作）

**適用場景**：
- ✅ 順序執行（build → flash，非並行）
- ✅ SSH 金鑰認證已配置
- ✅ 超時需求簡單（≤ 120 秒）

**不適用場景**：
- ❌ 需要持久連線（多次快速命令）
- ❌ 需要程式化密碼認證
- ❌ 需要細粒度 SSH 錯誤分類

#### 4.3 整合複雜度評估

**修改範圍**（subprocess + ssh 方案）：

| 檔案 | 修改類型 | 估計行數 | 說明 |
|-----|---------|---------|------|
| `config.py` | 新增 property | ~20 | `remote_config()` |
| `user_config.py` | 新增方法 | ~30 | `get/set_remote_config()` |
| `utils.py` | 擴展函數 | ~30 | `execute_make_command()` 加入 SSH 支援 |
| **總計** | - | **~80 行** | 主要修改 |

**修改範圍**（paramiko 方案）：

| 檔案 | 修改類型 | 估計行數 | 說明 |
|-----|---------|---------|------|
| `config.py` | 新增 property | ~20 | 同上 |
| `user_config.py` | 新增方法 | ~30 | 同上 |
| `utils.py` | 新增函數 | ~150 | `execute_remote_command_paramiko()` |
| `pyproject.toml` | 新增依賴 | ~2 | paramiko |
| **總計** | - | **~200 行** | 主要修改 + 依賴 |

#### 4.4 技術風險評估

**風險矩陣**：

| 風險類型 | subprocess+ssh | paramiko | 緩解策略 |
|---------|---------------|----------|---------|
| 認證失敗 | Exit code 255 | `AuthenticationException` | 預先驗證 SSH 金鑰 |
| 網路超時 | `TimeoutExpired` ✅ | 多層 timeout 設定 | 使用現有 timeout 模式 |
| 連線中斷 | Hang 風險 | 無自動重連 | Timeout 保護 + 重試邏輯 |
| 依賴衝突 | 無 ✅ | Cryptography + Rust | 測試環境驗證 |

**操作風險**：
- ⚠️ SSH 金鑰需要預先配置（用戶責任）
- ⚠️ 首次連線需要 host key 驗證
- ⚠️ SSH client 必須安裝（Linux/macOS 無問題，Windows 可能需要）

#### 4.5 LangGraph State 整合

**關鍵發現**：
- ✅ 可以**零 State 修改**實現遠端執行
- 配置存放在 `ProjectConfig`，而非 `FirmwareState`
- `execute_make_command()` 返回值保持不變：`(returncode, output)`
- Nodes 邏輯完全不變，透明化遠端執行

**整合流程**：

```mermaid
sequenceDiagram
    participant Node as build_node
    participant Utils as execute_make_command()
    participant Config as ProjectConfig
    participant SSH as SSH Client

    Node->>Utils: 調用
    Utils->>Config: 檢查 remote_enabled?
    Config-->>Utils: Yes, remote_config
    Utils->>SSH: ssh user@host "cd /path && make build"
    SSH-->>Utils: (returncode, output)
    Utils-->>Node: 返回結果（與本地一致）
```

**關鍵優勢**：
- Node 層不感知遠端執行
- State 結構不變
- 錯誤處理模式一致
- 可隨時在本地/遠端之間切換（僅需改配置）

---

## Architecture Insights

### 1. 命令執行抽象層的延伸性

**發現**：FWAuto 的 Maketool 抽象層設計非常適合擴展到遠端執行

**當前架構**：
```
Python (utils.py) → subprocess → make → Makefile → 工具鏈
```

**擴展後架構**：
```
Python (utils.py) → [local or remote] → subprocess/SSH → make → Makefile → 工具鏈
```

**關鍵洞察**：
- ✅ 抽象層邊界清晰（utils.py 是唯一需要修改的核心檔案）
- ✅ Nodes 完全不感知執行位置（透明化）
- ✅ 返回值介面一致（`(returncode, output)` tuple）

### 2. 兩層配置系統的擴展模式

**發現**：UserConfig + ProjectConfig 的設計非常適合 SSH 配置

**設計優勢**：
- **UserConfig（~/.fwauto/config.toml）**：存放敏感資訊（SSH 金鑰路徑、主機 IP）
- **ProjectConfig（.fwauto/config.toml）**：參照 UserConfig（`remote_id = "am62x_vm"`）
- **好處**：敏感資訊不進版本控制，多專案共享遠端主機配置

**參考模式**：SDK 配置已使用相同模式（project 參照 user-scope SDK）

### 3. 閉環路由的可組合性

**發現**：現有的 build → ai_brain → build 循環提供了完整的參考實現

**可複用模式**：
1. **狀態檢查** → Node 設定錯誤狀態
2. **重試控制** → 比較 `iteration` vs `max_retries`
3. **AI 任務檢測** → 根據 state 欄位判斷任務類型
4. **循環驗證** → 返回原 node 重新執行

**擴展方向**：
- log → ai_brain → build 循環可以完全參照此模式
- 甚至可以抽象出通用的 `create_retry_loop()` 工具函數

### 4. KISS 原則在技術選擇中的體現

**發現**：subprocess + ssh 方案完美符合 KISS 原則

**證據**：
- 程式碼行數：80 行 vs 200 行（省 60%）
- 依賴增長：0 vs 4 個套件
- 學習曲線：利用現有知識 vs 全新 API
- 維護成本：無額外依賴更新 vs 需追蹤 paramiko 安全更新

**引用 CLAUDE.md**：
> "Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away."

### 5. 環境異質性的統一抽象

**發現**：配置驅動的設計可優雅處理「有 VM」vs「無 VM」場景

**當前問題**（問題文檔）：
- AM62X：需要 VM 編譯
- STM32：本機編譯

**統一方案**：
```toml
# AM62X 專案
[build]
execution = "remote"
remote_id = "am62x_vm"

# STM32 專案
[build]
execution = "local"
```

**關鍵洞察**：
- 同一套程式碼，透過配置區分執行模式
- 不需要「方案 A」vs「方案 B」二選一
- 可以逐步遷移（Phase 1 本地 → Phase 2 遠端）

---

## Code References

### 核心檔案

| 檔案路徑 | 行號 | 說明 |
|---------|------|------|
| `src/fwauto/utils.py` | 78-156 | 命令執行核心函數 `execute_make_command()` |
| `src/fwauto/utils.py` | 122 | `subprocess.Popen()` 調用點 |
| `src/fwauto/utils.py` | 127-137 | 超時處理實現 |
| `src/fwauto/nodes/build.py` | 79-84 | Build 節點調用 Maketool |
| `src/fwauto/nodes/build.py` | 109 | Iteration 累加 |
| `src/fwauto/nodes/flash.py` | 79-84 | Flash 節點調用 Maketool |
| `src/fwauto/graph.py` | 92-112 | `route_after_build()` 重試邏輯 |
| `src/fwauto/graph.py` | 114-118 | `route_after_ai_brain()` 返回驗證 |
| `src/fwauto/graph.py` | 188 | **擴展點**：Log 直接路由到 END |
| `src/fwauto/nodes/ai_brain.py` | 83-106 | AI 任務類型檢測 |
| `src/fwauto/nodes/ai_brain.py` | 92-94 | Build errors 檢測模式 |
| `src/fwauto/nodes/log.py` | 116-119 | Log 節點返回值 |
| `src/fwauto/config.py` | 42-116 | ProjectConfig 類別定義 |
| `src/fwauto/config.py` | 92-105 | SDK 路徑繼承邏輯 |
| `src/fwauto/user_config.py` | 10-56 | UserConfig 類別定義 |
| `src/fwauto/state.py` | 6-77 | FirmwareState TypedDict 定義 |
| `pyproject.toml` | 17-28 | 當前依賴套件清單 |

### 參考實現

| 實現類型 | 檔案:行號 | 用途 |
|---------|----------|------|
| 錯誤處理模式 | `utils.py:133-138` | Timeout + 一般異常處理 |
| 重試循環 | `graph.py:92-112` | Build failure → AI fix loop |
| 任務檢測模式 | `ai_brain.py:92-94` | 根據 state 判斷任務類型 |
| 配置繼承 | `config.py:92-105` | Project 繼承 User config |
| Prompt 模板 | `prompts/fix_build_errors.md` | AI 修復 prompt 範例 |

---

## Open Questions

### 技術實施問題

1. **SSH 認證機制**
   - 使用 SSH key 還是密碼？（建議：key-based）
   - 金鑰路徑如何配置？（建議：UserConfig）
   - 如何處理 host key 驗證？（建議：首次手動 ssh 連線）

2. **程式碼同步**
   - rsync vs scp？（建議：rsync 更高效）
   - 同步時機？（每次 build 前？還是手動觸發？）
   - 如何處理同步衝突？（VM 修改 vs 開發機修改）

3. **日誌收集**
   - stdout 重導向到檔案？（建議：`./led > app.log 2>&1`）
   - 日誌檔案大小限制？（建議：tail -n 1000）
   - 結構化日誌（JSON）vs 純文字？（建議：Phase 1 純文字）

4. **工作目錄管理**
   - VM 中的專案路徑如何對應？（建議：config 中配置 `remote_work_dir`）
   - 相對路徑 vs 絕對路徑？（建議：絕對路徑更可靠）

### 架構決策問題

5. **State 欄位新增**
   - 是否新增 `remote_enabled`, `remote_host` 等欄位？
   - 還是全部存放在 ProjectConfig？（建議：後者）
   - 需要與專案擁有者討論（CLAUDE.md 明確要求）

6. **Prompt 模板**
   - 是否需要新的 `prompts/fix_from_log_analysis.md`？
   - 還是複用 `fix_build_errors.md`？
   - Log 分析結果如何傳遞給 AI Brain？

7. **錯誤處理策略**
   - SSH 連線失敗是否進入重試循環？
   - 還是立即失敗並通知用戶？（建議：立即失敗）
   - 網路中斷如何區分於編譯失敗？

### Phase 劃分問題

8. **Phase 1：快速驗證 (VM-centric)**
   - 在 VM 中運行完整閉環是否可行？
   - UART 連接問題如何解決？（USB 轉發 vs SSH 日誌傳輸）
   - Phase 1 成功標準是什麼？

9. **Phase 2：環境抽象 (Dev-centric)**
   - Phase 1 → Phase 2 遷移路徑是否平滑？
   - 遷移成本是否可接受？
   - 如何確保不破壞現有 STM32 流程？

10. **投入產出比評估**
    - 4-6 週實作時間是否值得？
    - 還是先用簡單腳本驗證概念？
    - 如何評估「過度設計」的風險？

---

## 總結

本研究針對「如何在 FWAuto 中實現 SSH 遠端執行以支援跨三環境閉環」進行了全面分析。

### 主要發現

1. **現狀**：FWAuto 100% 本地執行，但架構清晰、易於擴展
2. **閉環**：可參考現有 build → ai_brain → build 循環建立 log 閉環
3. **配置**：兩層配置系統適合 SSH 設定，但需新增欄位
4. **技術**：subprocess + ssh 方案簡單且符合 KISS 原則

### 可行性評估

- **技術可行性**：✅ 高（所有技術點都已驗證）
- **整合複雜度**：🟡 中等（約 80-200 行程式碼）
- **維護成本**：✅ 低（subprocess+ssh 方案無新依賴）
- **風險等級**：🟡 中等（SSH 穩定性、認證配置）

### 關鍵建議方向

1. **優先選擇 subprocess + ssh**（簡單、零依賴、效能高）
2. **配置存放在 Config 層**（不污染 State）
3. **參考 build → ai_brain 模式**建立 log 閉環
4. **Phase 1 可在 VM 驗證**，Phase 2 遷移到開發機

---

**研究完成日期**：2025-11-03
**研究方法**：並行探索 4 個面向
**程式碼分析行數**：約 2,000+ 行
**參考文件**：3 份（high-level-design.md, flow-spec.md, problem definition）
