# FR-181 Agent 只出站通道 — 交接現況（STATE）

> **這份是 living 檔**：每棒就地 Edit，只描述「此刻」。歷史脈絡看同資料夾的 `fr181-LOG.md`。

| 項目 | 值 |
|------|-----|
| 最後更新 | 2026-11-07 21:40（第 2 棒，首腦） |
| branch | BE／FE／evidence-agent／jedi-python-package 皆 `feature/FR-172`，四 repo 與 origin 同步（第 2 棒的 Agent `1a47d90`／`24ee084`、FE `2a07071b` 已推） |
| 母案卡 | CM-3595 https://app.notion.com/p/FR-181-Agent-Agent-Agent-8443-13-7-410346da4cd081018321e4f28777e998 |
| 本棒角色 | 首腦（第 2 棒：接手、排除本機驗收前置——FR-182 主控台三個缺陷、123 更新） |
| 接手前必讀 | §0 讀序 |

## 🧭 原始需求 / WHY

- **決策者原話（2026-11-07）**：「這個會因為客戶網路的關係 沒辦法從外連入」「不能開 確定的 所以可能也要定時回來拿工作回去agent執行」「就都改輪詢的時候同步回去就好」「直推退役 開新 FR 寫討論稿」。後改判「8443 先不要退役 把 API 功能都先關掉就好 我怕未來又說要開」。
- **要解的問題**：FR-171（11-02 合回）把六種指令改成主系統直推 Agent 8443；FR-039 起證據檔、FR-178 遠端查日誌也是主系統直連。客戶防火牆不讓主系統連進 Agent，這些全部送不到；心跳補推也連 8443 救不了。
- **目標**：主系統不再主動連 Agent。Agent 常駐一條 `GET /agents/commands?wait=30` 長輪詢取指令（八種用途全走這條）；同步問答（測試連線、帳密、證據檔、查日誌、對帳）走「等回答插槽」（`agent_requests` 表＋Redis pub/sub 跨 gunicorn worker 喚醒）；證據檔經主系統暫存中轉。直推程式留著、兩個開關預設關；Agent 8443 照起只剩健檢；客戶不用開任何入站埠。心跳維持只表存活。
- **本棒在大圖的位置**：整案 19 張程式卡驗過合回推遠端；本機 Agent 已裝照、長輪詢與心跳實際跑通；123 已更新到主線待裝照。剩動態／真機驗收、C-2 文件、母卡 Done。

## §0 接手讀序

### 0.1 🔒 先懂需求 gate
1. 本檔 WHY ＋ §2 已定裁示
2. `../design-v1.1.md` §1 這案在做什麼、§3 決策定案表、§4 兩張時序圖（10 分鐘）
3. `../README.md` 結論五條＋需求討論紀錄（決策者每一句裁示都在）

### 0.2 現況與待辦：本檔 §1、§3

### 0.3 需要細節才開
- 各卡做了什麼／怎麼驗：Notion 子卡回寫（卡號見 §1 表）；拆卡底表 `cards.py`
- 為什麼這樣設計、被排除的選項：`../discussion.md`
- 撞號事故全貌：`fr181-LOG.md` 第 1 棒「教訓」

### 0.4 ✅ 冷接自檢
- 長輪詢和心跳是同一條連線嗎？（不是；心跳只表存活，長輪詢獨立端點，11-01 裁示不翻）
- 直推程式刪了嗎？（沒有；`AGENT_DIRECT_PUSH_ENABLED`／`data_plane_commands_enabled` 預設 false，守衛測試擋）
- 證據檔 bytes 經哪裡？（主系統 `/tmp/agent-outbound/` 暫存，取走即刪；D4 A 案）
- 主線契約／remote-agent 現在釘哪版？（0.5.3／1.17.5；0.5.2 被 FR-182 同號覆蓋，0.5.3 是合併版）

## §1 當前狀態

### 1.1 卡片（20 張）

| 批 | 卡 | 狀態 |
|---|---|---|
| 1～6 | P-0、F-1～F-3、E-1、A-1、A-2～A-4、B-1～B-5、C-1（CM-3596～3608、3619、3631） | 驗收通過待確認（決策者已在狀態頁收 Done 的以 Notion 為準） |
| 7 | C-2 文件收口 CM-3632 | 修正待驗證（第 2 棒首腦直接做，`5de3ae6cc`，決策者裁不等真機驗收） |
| 8～10 | B-6a～d 對帳改走插槽 CM-3634～3637 | 驗收通過待確認 |

### 1.2 Git
- 四 repo `ws-CM-3595` 全部 merge 進 `feature/FR-172`（BE `b61d9710c`＋`a577aec82`、jedi `7fa3d6f9`＋`3e8b8f1c`、agent `a2bdb28`＋`5d8e5f6`、fe `56ee950d`），已由 FR-182 首腦一併推遠端。
- 之後 FR-179（`ws-CM-3546`）、FR-182（`ws-CM-3609`）也合回主線；主線現含三案合併版，釘 `jedi-agent-protocol==0.5.3`／`jedi-remote-agent==1.17.5`／`jedi-detection==1.10.1`。
- 工作坊 42 狀態 `waiting_approval`；它的「合回」按鈕**不要按**（已手動合過）。

### 1.3 本機與 123
- 主系統 8000：pid 61066（主線）。FE 5180：pid 76746（主線）。
- 本機 Agent 8443／8444：pid 2550（外層 `start-agent.sh`），跑 evidence-agent 主線 `24ee084`。**已裝授權照**，sync 起來：心跳 200、`GET /agents/commands?wait=30` 每 30 秒循環（無指令回 204）。主控台主系統票登入（`blsadmin`）與本機管理員登入都通。
- **123（`ubuntu-lab-03`）是源碼跑法**：`/opt/evidence-agent`（git clone，主線 `24ee084`，契約 0.5.3）＋`~/guidant-agent-dev/start-agent-dev.sh`（pid 記在 `agent.pid`），透過 VPN 連 Mac 的 DEV 主系統 `10.8.0.6:8000`。已起、閘門 missing（**未裝照**）、主控台認得身分（agent_uid `1126d080…`）。
- 123 `git pull` 靠 GNOME keyring 存的 GitLab 帳密：**重開機後要有人登入桌面一次 keyring 才解鎖**，否則 ssh 進去 pull 會 `could not read Username`。長久解法是 123 的 ssh key 加 GitLab Deploy Key（未做）。
- BE venv 1.17.5／0.5.3／1.10.1、本機 Agent venv 與 123 venv 契約 0.5.3，與主線對齊。

### 1.4 驗收進度
- **靜態驗收完成**（母卡 CM-3595 第 1 段回寫）：直推只剩開關後一處、兩開關預設關、gunicorn gthread；BE 176～178 passed、Agent 173、jedi-detection 303、契約 73（補刀 `b20f85c5`）；remote-agent 接受 runner 540（打折）。
- **前置已排除**：第 2 棒修掉 FR-182 主控台三個缺陷（見 §4），本機 Agent 裝照後長輪詢實際跑通——這是新通道第一次在真實執行環境跑。
- **動態驗收未做**（design v1.1 §8 十五條＋B-6d 三情境：竄改／刪檔／停 Agent）：前置已解，可直接跑本機。
- **真機驗收未做**：123 已更新，待裝照；擋 8443 的 iptables 要 sudo（`sudo -n` 不行），決策者下或給免密方式。

## §2 已定裁示（不要重新討論）
D1 吊 30 秒｜D2 gthread 16＋配額 8＋每台一條（P-0 驗過走長輪詢）｜D3 `agent_requests` 5 分鐘過期｜D4 證據檔 A 案經主系統中轉｜D5 源碼包瀏覽器直傳擱置｜D6／D7 直推程式留著用開關關、8443 照起、客戶不用開埠｜D8 FR-170／171 檔頭加指路行（C-2）｜舊 Agent 全部重裝｜文件等真機驗收過後寫（C-2 暫緩）｜本案獨立母卡。全文 `../design-v1.1.md` §3。

## §3 下一步（每項單獨等決策者發令）
1. 動態驗收：本機跑 §8 十五條＋B-6d 三情境，回寫母卡第 3 段。
2. 真機驗收：決策者在 123 主控台（`https://192.168.50.123:8444`）裝照 → 首腦先確認長輪詢通 → 決策者下 `iptables -I INPUT -p tcp --dport 8443 ! -s 127.0.0.1 -j DROP` → 整張 §8 再跑。
3. 真機驗收若與文件描述不符 → 回頭修 C-2 的手冊／資安報告。
4. 決策者收母卡 Done。

## §4 待辦與風險
- **FR-182 主控台三個缺陷第 2 棒已直接修**（決策者裁示，三筆都回寫 FR-182 母卡 CM-3609）：
  - 閘門關時 `start_planes()` 不載 `holder.state` → 主系統票登入與授權分頁被當未註冊（Agent `1a47d90`，改從憑證目錄載身分）。
  - 8444 主控台拿到 files 子容器、看不到根容器的 `agent_license` → 總覽 license 恆 None、授權分頁 500（Agent `24ee084`，改經 `license.current_gate()`；原測試 fixture 自塞根容器所以沒抓到）。
  - 總覽沒照不提示、只顯示「斷線請網路除錯」（FE `2a07071b`，missing／invalid／mismatch 紅條＋沒照時隱藏斷線條）。
- **總覽中間卡與狀態燈**沒照時仍顯示「所有檢查都正常，這台可以接工作」、主系統連線綠勾——判斷在 Agent 後端，建議開 FR-182 卡（決策者未裁）。
- **FR-182 收尾前要用真 Agent 走一次上傳照**：它的授權分頁在真實執行環境從沒正常過。
- **8443 上 `/blob`、`/detection` 仍無條件掛著**（只有 FR-171 六支 cmd_* 受開關）：主系統預設不呼叫、mTLS＋短效 JWT 守門，資安報告 C21 記為殘留；要關需改 Agent（未開卡、決策者未裁）。
- **手冊兩處是 install.sh 印出的原文**（第三章完成畫面、第四章 status「本機需開放 8443/tcp 供雲端連入」）：要先改 evidence-agent `deploy/install.sh:1006／2377`，手冊再跟。手冊第三章「安裝問六題」是 FR-179 的文件債。
- **首次設定頁仍問「本機位址」**：FR-181 後主系統不連回，該值只剩寫進憑證 SAN；要不要拿掉併 C-2 盤點。
- **FR-179 S5（Agent .env 加密）／A3／D1** 還在工作坊 40。
- **出貨基線**：已於 2026-11-07 重產到含 FR-178／181（memory `project_baseline_regen_before_next_bundle`），封包前照該檔一行指令查差集。

## §5 Pre-flight（接手必跑，唯讀）
```bash
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be && git status --short | grep -v '^??' ; git log --oneline -3
for r in ~/Projects/Jedicogy/module/jedi-python-package ~/Projects/Billows/Audit-Manager/evidence-agent ~/Projects/Billows/Audit-Manager/compliance-manager-fe; do echo "$(basename $r): $(git -C $r log --oneline -1 | cut -c1-60)"; done
grep -o 'jedi-remote-agent==[0-9.]*\|jedi-agent-protocol==[0-9.]*' pyproject.toml
echo "8000 $(lsof -nP -iTCP:8000 -sTCP:LISTEN -t | head -1) / 5180 $(lsof -nP -iTCP:5180 -sTCP:LISTEN -t | head -1) / 8444 $(lsof -nP -iTCP:8444 -sTCP:LISTEN -t | head -1)"
grep "license gate\|agents/commands" ~/guidant-agent-local/agent.log | tail -2
curl -s --max-time 5 http://localhost:7777/api/status | python3 -c "import json,sys; d=json.load(sys.stdin); [print(w['id'],w['status'],w['summary']['text']) for p in d['projects'] for w in p['workshops'] if w['id']==42]"
```

## §6 環境座標
- 工作坊狀態頁 `http://localhost:7777`；工作坊 42＝本案；Notion 讀寫用 `python3 /Users/chouraymond/Projects/Jedicogy/agent-workshop/scripts/notion_case.py get|append|status <卡號>`。
- 本機 Agent 目錄 `~/guidant-agent-local/`（`start-agent.sh`、`data/`、`agent.log`）；DB 的 Agent 列 `compliance.remote_agents` base_url `https://127.0.0.1:8443`。
- 123 Agent（`ubuntu-lab-03`，`192.168.50.123`）是真機驗收用；重啟前查有無掃描在跑。
- DEV DB 本機 5432，`agent_requests` 表已建、migration 已登記。

## §7 行為規範提醒
- 首腦不開 subagent；不碰 STG／POC；重啟 BE 只 kill 核過的 PID；`poetry update` 指名套件；Agent 側 poetry 用 `env -u VIRTUAL_ENV`。
- 發 jedi 套件前先查 Nexus 最新號（撞號教訓，memory `feedback_nexus_allows_same_version_republish_coordinate_before_publish`）。
- 工作坊 42 的「合回」不要按。

## §8 不在本期 scope
WebSocket／gRPC 長連線（反悔條件 Agent > 100 台）；SaaS 暫存不落磁碟；D5 源碼包直傳改中轉；FR-182 閘門與主控台登入縫（它的卡）。

## §9 給 fresh session 的短 prompt
```
接手 FR-181 首腦。讀 docs/features/FR-181-2611-agent-outbound-only-channel/handoff/fr181-STATE.md，答 §0.4 自檢，跑 §5 pre-flight，回報現況後停下等我發令。
```
