FR-056 人工手測中繼交接 — Context 已滿,接手繼續帶 user 手測

✓ ARC CLOSED — 2026-07-27 收尾,見 2026-07-27-fr056-manual-test-arc-SUMMARY.md。user 手測全數驗收通過,收尾工作包(CM-935:STG migration / 使用手冊正式化 / SPEC 更新 / 本 SUMMARY)已完成。本文件保留作歷史交接紀錄,行為描述請以 SUMMARY 與最新 SPEC/使用手冊為準。

項目 內容
緣由 主導 session(首腦角色:分析 + 派 case 給 runner + 跟 user 一起手動驗證)context 已滿,中繼交接
Branch(三 repo 同名) feature/scan-plugin-integration不可切 branch
角色 你是首腦:分析 + 派 case 給 runner + 跟 user 一起手動驗證全部功能,不自己實作
現況一句話 端到端掃描鏈路已跑通(多輪 bug 修復後),目前 6 張 case 等 user 手測驗收(927 主戰場 + 930/931/932/933/934 子修正),Notion 狀態有落差需先核實
push 狀態 三 repo 皆有未 push commits(push 永遠等 user 明示,尚未 push
預估時間 手測本身無法預估(等真實 OpenVAS 掃描,每輪 15~20 分鐘);交接閱讀 15 分鐘

🧭 原始需求 / WHY(先讀這段,別跳過)

FR-056 讓客戶「檢測工具掃描 → 報告自動變任務證據 → 通知 → 完成」全自動化。四子需求 56.1(工具設定)/ 56.2(任務類型)/ 56.3(Agent 執行)/ 56.4(執行編排+轉證據)程式碼審查已放行,但真實 OpenVAS 端到端掃描一直沒做過(CM-927)。本棒(一整天)就是在做這件事:跟 user 一起在 DEV 環境對真實 OpenVAS(部署在 123 = ubuntu-lab-03)跑真掃描,過程中連續挖出 10 個先前程式審查沒抓到的 bug(見下方「本棒完整戰史」),每個都開 Notion case 派給 runner 修、驗收、重部署、再測,滾動式推進。

現在的狀態:核心鏈路(測試連線 → 任務設定 → 開始執行 → agent 領工 → OpenVAS 真掃描 → 報告回收 → 證據入庫 → 通知信 → manual 手動完成)已經完整跑通一次成功(15:02~15:20,152 掃描 succeeded,PDF 證據 + summary 統計都有)。後續又追加了「取消機制」「命名撞名」「篩選連動」「UI 收合」等 4 個子修正(930/931/932/933/934),全部程式碼已 commit,但只有部分實測驗證過

你接手的任務

  1. 先核實 Notion 卡片狀態與 git commits 是否一致(見 §7,有落差)
  2. 帶 user 把剩下的手測項目跑完(PDF 證據、取消機制、命名撞名、auto 模式、失敗情境 — 見 §4 開工順位)
  3. 手測全過後,等 user 明確下收尾令才做 spec / SUMMARY / 母案收口 / memory(不要自己接著跑)

🧭 冷接自檢(讀完 §0~§3 後自問,答不出來回去讀)

  1. 為什麼要做這一整輪手測?(提示:56.1~56.4 只過了程式審查,從沒對真實 OpenVAS 跑過)
  2. 目前端到端鏈路的「已知良好基準」是哪一次掃描?(提示:exec id=5,15:02~15:20,succeeded)
  3. 現在還沒驗證過的是哪些?(提示:932 的 PDF/summary 實測、931 的取消確認框實測、934 的撞名修正實測、auto 模式、失敗情境)
  4. 為什麼 Notion 卡片狀態不能直接信?(提示:930/931/934 我已程式驗收但卡片還顯示 Not started,需要你重新核實或提醒 user)
  5. 為什麼「重新執行」按鈕現在會彈確認框?(提示:931 修正,掃描中重按會先真中斷 OpenVAS 側 stop_task 才派新工單,避免並行掃描疊出孤兒 task)

§0 接手讀序

🔒 先讀(懂 WHY,不可跳)

  1. 本文件全文(尤其 §1 現況戰況表 + §4 開工順位)
  2. docs/features/FR-056-2607-detection-tool-integration/handoff/2026-07-27-fr0565-probe-and-e2e-handoff.md — 更早一棒的交接,含 FR-056.5 probe 設計決策全文(案 1 雲端直推 vs 任務化的取捨)

接著讀(機械座標,開工前查): 3. §7「Notion 座標與狀態核實」— 六張卡的 page id + 當前落差 4. §5「三 repo 版號與部署現況」 5. §8「行為規範重要提醒」

冷接自檢:讀完能答出上面 5 題才開始碰任何操作。


§1 現況戰況表(本棒完整戰史,10 個 bug 修復鏈)

user 手測時我們(主導 session)連續發現、開 case、派 runner 修、驗收、重部署的完整鏈路,依發現順序

# Case 問題 修法 狀態
1 CM-929(FR-056.5) 測試連線用 BE httpx 直連 OpenVAS,架構死(BE 連不到客戶內網) 改「雲端直推」:BE mTLS POST agent /detection/probe,agent 用 python-gvm 探測 ✅ 已驗收,Notion=修正待驗證
2 (同案追加,未單開) 派工 tenant_config_id 從未寫入 → 憑證永遠解不到 fallback 用 (tenant_id, detection_tool_id) 反查 config ✅ 已驗收(commit a0d593ab)
3 (同案追加) 心跳 API log 記錄明文憑證,違反 D9 api_log middleware 對 secret 類 key 通用遮罩 ✅ 已驗收(commit e2eb1c2c)
4 (同案追加) 規劃頁「開始執行任務」不會自動派 detection 任務首次掃描 start_task_execution 尾端加自動派工(user 拍板:自動化是核心價值) ✅ 已驗收(commit 538d8da0)
5 (同案追加) agent 心跳解析錯信封層級,pending_tasks 永遠讀不到 body.get("data", body) 容錯(真根因,堵死真實掃描) ✅ 已驗收(agent commit f1b6629)
6 (同案追加) create_targetport_list_id,GVMd 400 補預設 port list UUID + params 可覆寫 ✅ 已驗收(agent commit 3515320)
7 (同案追加) hosts 是字串被當 list,逐字元拆解成垃圾 connector 邊界正規化為 list ✅ 已驗收(agent commit cdd76e8)
8 (同案追加) 心跳「先等滿一輪才第一跳」,升級部署要空等 改「先跳再等」 ✅ 已驗收(agent commit e8f667f)
端到端掃描第一次成功 exec id=5,15:02:09→15:20:25,152 掃描 succeeded,PDF 證據入庫 已達成,是後續驗收基準
9 CM-930 任務抽屜「執行紀錄」一律全展開,多筆時佔位 加可收合 toggle + 智慧預設展開(running/failed 才展開)+ 區塊滾動 + BE 排序移到 repo 層 ✅ 已驗收,Notion 卡仍顯示 Not started(落差,見 §7)
10 CM-931 「重新執行」無確認框,掃描中按會疊出並行掃描 user 拍板方案 C 真中斷:確認框 → agent /detection/cancelgmp.stop_task() 真停 → 才派新工單;競合防護(取消後舊掃描若仍回報,不轉證據/不通知/不觸發 auto) 程式已驗收尚未實測(見 §4)
11 CM-932 報告存 XML 使用者看不懂;summary 永遠空 同一 report_id 取 PDF(證據)+ XML(解析 <result_count> 填 summary,不上傳) ✅ 程式已驗收,Notion=修正待驗證,尚未實測(見 §4)
12 CM-933 /project/task-manage 輪次篩選與專案篩選不連動 未選專案 disabled;選定後改拉該專案完整輪次清單(改走既有 audit-rounds/list API) ✅ 已驗收,Notion=修正待驗證
13 CM-934 同批發佈多個同目標任務會撞名(Target exists already create_target/create_task 命名從秒級 timestamp 改用 agent task_uid(天然唯一) 程式已驗收Notion 卡仍顯示 Not started(落差)尚未實測(見 §4)

版號軌跡(evidence-agent,三輪疊加後最新):0.2.5(CM-929 鏈)→ 0.2.6(CM-932 PDF)→ 0.2.7(CM-931 取消)→ 0.2.8(CM-934 撞名,目前部署版本)。BE/FE 無版號概念,看 commit hash。

額外開的 case(尚未派工)

  • 檔案裡沒開卡,但 §1 之外還討論過「agent 對外暴露安全性」(弱掃背景雜訊打到 agent port,可能需要防火牆收緊)— 未開 case,未派工,交給下一棒判斷是否要開。

§2 前次教訓(別重蹈覆轍)

  1. agent 心跳間隔優先讀部署機 certs/agent.json 快取,不是環境變數 — 改 .env/compose 的 HEARTBEAT_INTERVAL_SEC 對已註冊的 agent 完全無效,已存 memory reference_agent_heartbeat_interval_cache.md。要改要嘛改快取檔(sed 後 restart),要嘛重新註冊。
  2. docker compose up -d 不帶 service 名會 recreate 整個 compose 的所有服務(含 DB)— 已存 memory feedback_compose_up_scope_service_name.md。永遠 docker compose --profile full up -d guidant-ai-agent,不要裸 up -d
  3. agent 版號 bump 有五處要同步pyproject.toml / config/config.py AGENT_VERSION 預設 / deploy/docker-compose.yml image tag + AGENT_VERSION env / deploy/.env.example / rebuild.sh 註解)— runner 連續三輪(0.2.6/0.2.7/0.2.8)都只改了 pyproject,其餘四處停在 0.2.5,我已手動補齊並 commit(e59c9fc)。下次 bump 版號要主動核對這五處,不要只信 runner commit message 說「已同步」
  4. docker compose restart 不會重讀 compose 檔變更,要用 up -d — restart 只是重開既有 container 的既有設定;改了 env 值要 up -d 才會偵測差異重建。
  5. 心跳 response 是標準信封 {"data": {...}, "status": true},agent 端解析容易忘記從 data 底下取值 — CM-929 鏈路裡的信封 bug 就是這樣來的,之後任何雲端→agent 回應解析都要留意這個模式。
  6. DDD 分層 + 命名唯一性這類 bug 都是「單元測試 mock 全綠、真機才炸」 — port_list_id 缺失、hosts 型別錯誤、target 撞名,三個都是這個模式。往後新 case 的驗收要求都要求「斷言實際呼叫參數」而非只驗 mock 回傳值。

§3 Notion 狀態核實結果(已驗證,可直接採信)

用 Notion query 對比 Case No 927/929/930/931/932/933/934 的狀態,與我親自審過的 git commits 交叉比對:

Case Notion 狀態(查詢當下) git commits 是否存在 我的程式驗收結論
927(主戰場) Not started N/A(這張本來就是手測 checklist,不是修 code) 尚有多項待手測,見 §4
929 修正待驗證 ✅ 存在且已驗收 一致
930 Not started ✅ 存在(FE f2ba9b7、BE 318b9625)且我已驗收放行 落差 — runner 可能沒做狀態更新,或 user 手測後才會轉
931 Not started ✅ 存在(BE 3a9a9c05、FE e986b88、agent a7bad25)且我已程式驗收放行 落差 — 尚未實測,狀態未轉「修正待驗證」正常,但也可能是 runner 漏更新
932 修正待驗證 ✅ 存在(agent 60ad41f、BE 5c0ba4da)且我已驗收放行 一致,等實測
933 修正待驗證 ✅ 存在(FE da4b422 + 6febb2b)且我已驗收放行 一致
934 Not started ✅ 存在(agent 703b59a)且我已程式驗收放行 落差 — runner 可能沒做狀態更新

下一棒動作:不要假設 Notion 狀態準確。930/934 你可以直接信我的驗收結論(已放行,等 user 實測),不用重查 diff。931 同樣已放行,只是還沒實測過(跟狀態落差無關,是正常流程)。建議接手後把 930/934 的 Notion 狀態手動改成「修正待驗證」(除非你重新核實後發現有問題)。


§4 開工順位(手測劇本,依優先序)

user 目前在「人工測試中」——這是你接手後要立刻帶 user 做的事,不是自己寫 code。

Step 1:核實環境活著(30 秒)

# BE 進程存活 + 是最新 commit 跑的(重啟時間需晚於 3a9a9c05 這個 commit 的時間)
ps aux | grep main_app.py | grep -v grep

# agent 版號(應為 0.2.8,last_seen 應在最近 5 分鐘內)
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
export PGPASSWORD=$(grep '^#DB_SECRET' .env | sed 's/^#DB_SECRET=//' | python3 -c "import json,sys; print(json.loads(sys.stdin.read())['rds_master_password'])")
psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev -t -A \
  -c "SELECT 'agent version=' || agent_version || ' last_seen=' || to_char(last_seen_at,'HH24:MI:SS') || ' now=' || to_char(now(),'HH24:MI:SS') FROM compliance.remote_agents WHERE id=8;"

若 agent last_seen 超過 5 分鐘沒動、或版號不是 0.2.8 → 先跟 user 確認 123 上的 container 是否還活著(docker compose --profile full ps),不要跳過這步直接測。

Step 2:CM-932 實測(PDF + summary)— 建議優先,因為順便驗證整條鏈路還通

帶 user 對已知的 detection 任務(job 13342 或 13362,兩個都是 manual 模式、hosts=151,目前都 PROCESSING)到抽屜按「重新執行」(此時無 running 執行,不會彈確認框,直接派工)。

驗收重點:

  • 掃完後證據列表出現的是 PDF(不是 XML),檔名格式 OpenVAS掃描報告_192.168.50.151_<日期>.pdf
  • 抽屜「發現 N 項」有真實數字(不是空白)
  • 下載 PDF 能直接開,內容是 Greenbone 排版報告

Step 3:CM-931 實測(取消機制)— 依賴 Step 2 的掃描還在跑時操作

這步要抓時機:Step 2 的掃描開始後(狀態變 running,約派工後 1~2 分鐘),趁它還在跑再按一次「重新執行」。

驗收重點:

  • 應彈出確認框(文案「上一次執行將被中止」類)
  • 確認後開 Greenbone UI(https://192.168.50.123:9392 → Scans → Tasks)看舊 task 變 Stopped新 task 開跑
  • 抽屜執行歷史:舊那筆狀態變「已取消」(cancelled,灰色 Tag)、新的一筆 running
  • 若不小心錯過時機(掃描已經 succeeded 才按)→ 不會彈框(無 running 執行),這是正常行為,重跑一次抓時機即可

若 agent 端 /detection/cancel 呼叫失敗(agent 離線等)→ 應該回 409,不能默默派出新工單,這是 §1 表格裡強調過的關鍵行為,務必驗證到。

Step 4:CM-934 實測(撞名)

到規劃頁,同一批發佈兩個以上同目標(hosts=151)的 detection_tool 任務(可以用不同 completion_mode,一個 manual 一個 auto,順便驗 Step 5)。

驗收重點:

  • 兩個任務都能成功派工、成功建立各自的 target/task(不再出現 Target exists already
  • Greenbone UI 上兩個 target 名稱不同(後綴應為各自的 task_uid 前 8 碼)

Step 5:auto 模式驗收(CM-927 原始 checklist 未勾項目)

Step 4 若有建 auto 模式的任務 → 掃完應自動變 COMPLETED(不用手動按完成)。若還沒測過,額外建一個 auto 任務單獨測。

Step 6:失敗情境驗收(CM-927 原始 checklist 未勾項目)

建一個 hosts 填不存在 IP(如 192.168.50.199)的任務 → 執行應標「失敗」、錯誤訊息可辨識(網路不可達類訊息,非籠統錯誤)、任務仍留 PROCESSING 可從抽屜重試。

Step 7:CM-933 快速複驗(純 FE,5 秒可驗)

/project/task-manage:專案篩選=全部時輪次應 disabled;選定專案後輪次只列該專案的;切換專案輪次自動 reset。


§5 三 repo 版號與部署現況

Repo 目前 commit(HEAD) 版本 部署狀態
compliance-manager-be 3a9a9c05 N/A 本機 python main_app.py 跑著(PID 34101,2026-07-27 17:41 起,含 CM-931 的取消機制)
compliance-manager-fe e986b88 N/A Vite dev server HMR,localhost:5180,改檔即生效
evidence-agent e59c9fc(含 CM-932/931/934 + 版號補齊) 0.2.8 已部署到 123(ubuntu-lab-03),雲端 DB 確認 agent_version=0.2.8status=active

working tree 全乾淨(三 repo 皆無未 commit 改動,git status --short 已核實)。

push 狀態:三 repo 都有一長串未 push commits,push 永遠等 user 明示,不要自動 push。


§6 DB 現況快照(供比對,勿當唯一真相,重新查一次更保險)

compliance.remote_agents (id=8):agent_version=0.2.8, status=active, last_seen=17:54:41

compliance.detection_executions(最新 5 筆):
  id=8  failed     job=89a11a15... (13342) started=15:52:43
  id=7  succeeded  job=7232a47e... (跟哪個 job 對應需查) started=15:47:46
  id=6  failed     job=89a11a15... (13342) started=15:47:46
  id=5  succeeded  job=d0dac9be... (13362) started=15:02:09  ← 端到端第一次成功基準
  id=4  failed     job=d0dac9be... (13362) started=14:52:50

compliance.job_executions:
  id=13342, uid=77a9079c-..., status=PROCESSING(detection_tool, manual)
  id=13362, uid=d0dac9be-..., status=PROCESSING(detection_tool, manual)

exec id=6/7/8 是後續(CM-932/CM-934 修正過程中)的測試紀錄,其中有失敗的(可能是撞名問題被抓到的證據,或 CM-934 修好前的殘留失敗)。不要假設這些是「新 bug」,先看 error_message 判斷是否是已知已修的問題。

SELECT id, status, error_message FROM compliance.detection_executions WHERE id IN (6,7,8);

§7 Notion 座標

  • 母案 CM-907:3a9346da-4cd0-81a5-be6f-f0ddd6d770c6
  • 任務清單 data source:collection://23c346da-4cd0-8041-955e-000bb6976dd2
  • CM-927(主戰場手測 checklist):3aa346da-4cd0-81f9-a029-deda20be47cd
  • CM-929(FR-056.5 probe):3aa346da-4cd0-8191-9fba-c4fb2474820f(狀態=修正待驗證)
  • CM-930(執行紀錄可收合):3aa346da-4cd0-81f6-bfa6-e890f17e0f60狀態顯示 Not started,實為已驗收
  • CM-931(取消機制):3aa346da-4cd0-81cc-934a-f1585aacf6f9(狀態=Not started,正常,尚未實測)
  • CM-932(PDF+summary):3aa346da-4cd0-8113-b184-d7596efc3602(狀態=修正待驗證)
  • CM-933(輪次篩選連動):3aa346da-4cd0-8149-a35a-cb7cbf94e715(狀態=修正待驗證)
  • CM-934(撞名):3aa346da-4cd0-8125-bcd4-e7333cc1bab8狀態顯示 Not started,實為已驗收

DEV DB:psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev(密碼查 BE .env 註解行 #DB_SECRET,用 cmmgr 帳號那組)

BE 起服務 python main_app.py(port 8000),改 service 要 kill -9 重啟;log 在 log/app.log

FE dev server 在 5180(HMR,改檔即生效)

Agent 部署機:jedi@192.168.50.123(ubuntu-lab-03),deploy 目錄 /opt/evidence-agent/deploy,SSH key 已加(雙方都可連)


§8 行為規範重要提醒

  • 不切 branch,三 repo 都在 feature/scan-plugin-integration 工作
  • push 永遠等 user 明示,不自動 push
  • 收尾(spec / SUMMARY / 母案收口 / memory)等 user 明確下令才做 — 手測全過不代表可以自動跑收尾流程
  • 派 subagent 一律用 1M context model(不帶 model override,繼承主 session)— 今天多次因用 sonnet 導致 context 爆炸重派,這條鐵律要嚴守
  • 繁體中文;Notion 先搜尋再開卡(今天開的 6 張新卡都先確認過無重複);Claude/runner 做的作業人員填「小弟」
  • BE 改 service 要 kill -9 重啟(ps aux | grep main_app.py 找 PID)
  • Agent 每次改完要 rebuild + docker save/load 出貨到 123,且 docker compose --profile full up -d guidant-ai-agent必須帶 service 名,見 §2 教訓 2)
  • 密碼/憑證類資訊絕不代打、絕不寫入任何會 commit 的檔案(今天 user 曾在對話中貼過 123 的 SSH 密碼,已提醒但沒代打,也沒有寫入任何檔案)

§9 不在本期 scope

  • OpenVAS target/task 的清理策略(每次掃描都新建,殘留物正在累積)— CM-934 卡內已提及但明確標「本次不實作」,若 user 想處理需另開 case
  • agent 對外暴露的安全性強化(防火牆規則、只放行雲端來源 IP)— 只在對話中口頭提過,未開 case,需要 user 決定優先度
  • Nessus / SonarQube 等其他檢測工具的 connector 實作 — 平台預留但本輪全程只測 OpenVAS
  • STG / POC 環境的 migration 套用(CM-932 的 param schema migration 2026-07-27-fr056-5-openvas-param-schema-port-list.sql 只套了 DEV)

§10 給下一棒的超短 Prompt(可直接複製貼開新 session)

請讀 docs/features/FR-056-2607-detection-tool-integration/handoff/2026-07-27-fr056-manual-test-mid-arc-handoff.md
接手 FR-056 主導 session。角色是首腦:分析 + 派 case 給 runner + 跟 user 一起手動驗證
全部功能,不自己實作。

先過交接文件的「🧭 原始需求 / WHY」+「冷接自檢」5 題(答不出來回去讀 §1 戰況表)。

現況一句話:端到端掃描鏈路已跑通(10 個 bug 修復鏈後),CM-930/931/932/933/934 五張
子修正 case 程式碼已驗收完成,正在等 user 手動實測。§4 開工順位是接下來要跟 user
一起做的手測劇本,照順序帶 user 測(PDF+summary → 取消機制 → 撞名 → auto 模式 →
失敗情境 → 篩選連動複驗)。

§3 有 Notion 卡狀態核實結果(930/934 卡片顯示 Not started 但實際已驗收,屬已知落差,
不用重查 diff,直接信這份交接文件)。

Pre-flight:先跑 §5 的 repo 狀態核對 + §6 的 DB 快照重查一次,確認環境沒有在你離開
期間被變動過,再開始帶手測。