FR-058 協調者中繼交接(第四棒)— FR-058.6 主動掃描雙模式端到端通過(2026-08-01 上午)

這是中繼交接不是收尾。八款工具全數上線;FR-058.6 SonarQube 主動掃描模式(scan) 與既有拉取模式(pull)已雙雙端到端驗收通過——detection_executions 內 sonarqube 從 0 筆變 2 筆、皆 succeeded,且 SonarQube server 上實際長出 Guidant-AI-soybean-ui 專案。

⚠️ 交接當下有另一條線正在 agent repo 動 sonarqube.py(未 commit,mtime 就是此刻), 處理 §4.1 的品質門檻條件顯示問題。接手第一件事是確認那條線收工了沒,未收工完全不碰 agent repo。而且它的調查結論推翻了本文原先的根因推測(見 §4.1)。

前三棒交接文件(§1 狀態盤點全部已過期,只讀教訓 / 決策脈絡 / 裁示):

  • 2026-07-31-fr058-coordinator-handoff-3.md(第三棒)
  • 2026-07-31-fr058-coordinator-handoff-2.md(第二棒)
  • 2026-07-31-fr058-coordinator-midarc-handoff.md(第一棒)
項目 內容
本棒角色 協調、決策、派工、抽查。不寫 code、不跑測試、不寫文件——全部派 subagent(不帶 model 參數)
Branch 三 repo 皆 feature/FR-058不切 branch
接手第一件事 §4.1——確認 agent repo 那條線是否收工(git status 有無未 commit 的 sonarqube.py
下一個動作 收工後驗收該修正 → 等決策者驗收 FR-058.6 → 等決策者下令才收尾
預估時間 驗收 0.5h;全案收尾(若獲令)2~3h

🧭 原始需求 / WHY(不讀會誤解範圍,也會把 FR-058.6 誤判成「推翻前面的決策」)

決策者原話:「目前的檢測工具管理 /plugin/tool-plugin-manage 還需要增加下面工具——OpenSCAP for Windows 解決方案 / Nmap / GCB / SonarQube。請幫我分析跟規劃,開成新的需求放到 Notion。」

工具清單的演變(不讀會搞不清楚為何最終清單跟原話對不上)

階段 發生什麼
起點 四項:OpenSCAP for Windows / Nmap / GCB / SonarQube
中途 追加 ZAP(第五個)
裁示① SonarQube 本期不做(D10 成 tombstone)
調研 「OpenSCAP for Windows」證實不可行(官方已放棄 Windows 支援),改由 InSpec / CINC Auditor 承擔
裁示② ZAP 優先上線,其餘分批
裁示③(07-31 晚) SonarQube 重新納入,立為 FR-058.5(pull 拉取快照,D13–D16)
裁示④(07-31 深夜) 決策者看到實際畫面後指出「流程不對」——要平台真的發動掃描 → FR-058.6 主動掃描模式(D17–D24)

本案要解決兩件事:① 接入工具(現已八款);② 補平台結構性缺口(任務層敏感參數——原本 只有租戶層憑證有加密,任務層是明文且 FE 執行紀錄會顯示)。

🔑 FR-058.6 的關鍵認知(下一棒最容易誤解的點,務必讀懂)

FR-058.5(pull 拉取快照)不是做錯了。 D13 當時裁示「connector 不觸發掃描、只讀 CI 已推上去 的結果」,在當時的前提下是正確的——那時的輸入模型裡根本沒有「使用者提供源碼」這個東西, SonarQube Server 又確實沒有任何觸發掃描的 API,所以除了讀既有結果別無選擇。

FR-058.6 是前提變了,不是反覆。 決策者補上了新輸入(使用者提供 repo URL),平台才得以 在 agent 端打包 sonar-scanner 主動跑一次分析、把結果推上客戶 server 再讀回來。

兩模式並存(D17),同一張工具卡靠 scan_mode 參數分流,理由有二:

  1. 對「已有成熟 CI 的客戶」,pull 仍是正確且更輕量的答案——他們的 CI 本來就會推分析結果, 平台再跑一次是重複做工、浪費資源,還可能因為掃描環境不同產生跟 CI 不一致的數字
  2. C# / VB.NET 技術上永遠只能走 pull——這兩種語言的 SonarQube 分析器必須依附 MSBuild(SonarScanner.MSBuild.exe 要在 build 前後各插一段、吃編譯器輸出)。 agent 端的通用 sonar-scanner CLI 拿不到編譯期資訊,不是排程或資源問題,是架構限制

所以「未來把 pull 收掉、統一走 scan」這個方向不成立,不要往那邊想。


§0 接手讀序

  1. 本文「🧭 原始需求 / WHY」+ §1 現況 + §4 下一步(必讀,這是硬 gate)
  2. 本文 §3 裁示 + §5 教訓(必讀,避免重蹈與重開已定案的討論)
  3. 第三棒 2026-07-31-fr058-coordinator-handoff-3.md§2(教訓)——⚠️ 其 §1 狀態盤點已過期
  4. 第一 / 二棒的 教訓 / 決策脈絡 / 裁示 三節——同樣不讀其 §1
  5. design.md §2 決策表 D1–D24(D13–D16=FR-058.5 pull;D17–D24=FR-058.6 scan
    • §4.7(主動掃描流程)+ §5.9
  6. 全案 SUMMARY2026-07-31-fr058-arc-SUMMARY.md(⚠️ 尚未涵蓋 FR-058.6,收尾時要補)
  7. 需細節才開:handoff/2026-07-31-t63-gate-blocked.md(gate 停下的紀錄,見 §5.1 教訓)

冷接自檢(答不出來回去讀,不要碰任何東西)

  1. 同一張 SonarQube 工具卡上的 pull 與 scan 兩個模式,「誰跑掃描」這件事差在哪? 為什麼平台不能乾脆統一成 scan? 提示:SonarQube Server 有沒有觸發掃描的 API?pull 模式的資料是誰產生的? 統一成 scan 會對哪一類客戶造成什麼負面影響?

  2. 為什麼 C# / VB.NET 的專案在這個平台上永遠只能用 pull 模式,而 JavaScript 可以用 scan? 這是排程限制、授權限制,還是架構限制? 提示:想一下這兩類語言的分析器分別在什麼時間點介入、需要拿到什麼東西。

  3. DEV 已套 19 支 fr058 migration,STG / POC 只有 13 支。這是待修的落差還是正常狀態? 如果現在有人給你一張派工單寫「三環境都套上去」,你該怎麼做? 提示:本 arc 有一條血淚換來的鐵律,出事的案例就在 FR-058 自己身上。


§1 當前狀態(2026-08-01 10:26 協調者實查)

1.1 三 repo

Repo HEAD 時間 相對 main 未推 working tree
BE 298fef57 T-6.3 階段一檢查未通過紀錄 07-31 23:16 43+ 4 .claude/skills/big-feature-workflow/SKILL.md modified + 一批與本案無關的 untracked docs(別的 arc 留的)——都不要 commit、不要清理
FE c167f26 T-6.3 FE 微調 08-01 10:02 14 1 乾淨
agent 074f3b8 bump 0.2.22(已部署 DEV) 08-01 10:22 28 2 ⚠️ core/task_executor_connectors/sonarqube.py 有未 commit 修改(另一條線正在動,見 §4.1)

裁示不變:push 永遠等決策者明示。 origin 上已有的 FR-058 commits 是決策者自己推的, 不要因為「origin 已經有了」就自己補推剩下的。

1.2 三環境

環境 fr058 migration sonarqube 狀態 agent image
DEV 19 available 0.2.22(Up 22 分鐘)
STG 13 coming_soon 0.2.18(Up 17 小時)
POC 13 coming_soon 0.2.18(Up 17 小時)

DEV 領先 6 支(1419)屬正常狀態,不是待修落差

檔名 內容
2026-07-31-fr058-14-twgcb-server2022-profile-option.sql TWGCB Server 2022 profile 選項
2026-07-31-fr058-15-detection-tools-description-v2.sql 工具描述 v2
2026-07-31-fr058-16-gcb-profile-option-cleanup.sql GCB 下拉清理
2026-07-31-fr058-17-sonarqube-seed.sql SonarQube seed(FR-058.5,param_schema v1)
2026-07-31-fr058-18-twgcb-os-profiles-8-options.sql TWGCB 8 支 OS profile 上架(本棒)
2026-07-31-fr058-19-sonarqube-scan-mode.sql param_schema v2 雙模式(FR-058.6,本棒)

皆刻意只套 DEV(見 §3 鐵律 2)。上版時才依序補 STG / POC。

1.3 🎉 FR-058.6 兩模式端到端驗收已通過(本棒最大進展)

compliance.detection_executions 內 sonarqube 從 0 筆變 2 筆,皆 succeeded

execution id agent_task_uid 模式 內容 started_at
58 57b1c937-…78e5 scan repo https://github.com/soybeanjs/soybean-ui.git、suffix soybean-ui 08-01 10:18
57 5a523a72-…9d34 pull project_key=guidant-ai-backend 08-01 10:12

scan 模式的硬證據:171 上實際出現 Guidant-AI-soybean-ui 專案 (打 api/projects/search 實查到),證明 D21 的 Guidant-AI- 前綴生效、 且掃描結果真的推上客戶 server 了。

⚠️ 這也一併補完了 FR-058.5 尚未做的 UI 驗收(pull 模式從畫面發任務跑通), 該項原掛在 CM-997。

1.4 T-6.1 / T-6.2 的欄位 key 契約(協調者已交叉驗證,一致

A(BE param_schema)/ B(agent connector)並行實作時,唯一的風險點是兩邊各自取名。實查對得上:

BE param_schema v2 欄位 agent connector 讀取
scan_mode(select, required, 預設 scan params.get("scan_mode")_DEFAULT_SCAN_MODE = _SCAN_MODE_SCAN
repo_url(text, required, condition=scan) params.get("repo_url")
project_key_suffix(text, required, condition=scan) params.get("project_key_suffix")
project_key(text, required, condition=pull) params.get("project_key")
branch(text, 選填, condition=pull) params.get("branch")

param_schema 版本策略也正確(實查 config.detection_tool_param_schemas):

id=8  version=1  is_current=f    ← 保留,沒有原地 UPDATE
id=9  version=2  is_current=t

非法 scan_mode 值會 raise,已實作(sonarqube.py:327 _resolve_scan_mode

  • :109 _VALID_SCAN_MODES)。前綴防重複(避免 Guidant-AI-Guidant-AI-x)在 :371-379

1.5 八款工具現況

id code 名稱 status 驗收
1 openvas OpenVAS available 既有
2 nessus Nessus coming_soon 佔位
3 sonarqube SonarQube available(僅 DEV) pull + scan 雙模式端到端通過(本棒,見 §1.3)
4 openscap OpenSCAP available 既有(FR-057)
5 zap ZAP available ✅ 被動/主動通過;登入後對 SPA ❌(會打掛共用 ZAP,D12)
6 inspec CINC Auditor available ✅ 雙 transport 實跑:151 pass 131/fail 60、160 pass 300/fail 472
7 nmap Nmap available ✅ 實跑通過,HTML 證據
8 gcb 政府組態基準(GCB) available ✅ TWGCB 實跑;2026-07-31 晚上架 8 支 TWGCB 作業系統類基準(profile 下拉由 1 個擴為 8 個,只套 DEV

1.6 Notion

母案 CM-957(修正待驗證)。相關卡:

卡號 內容
CM-986~991 平台能力與 InSpec 線
CM-992 GCB content 產製後續案——本棒大幅更新(見 §2.4)
CM-993 收尾追蹤
CM-994~997 FR-058.5 SonarQube(pull)
CM-998~1001 FR-058.6 SonarQube 主動掃描(本棒開卡)
CM-984 ZAP SPA 後續案
CM-985 報告呈現優化(全案驗收後才做,不納入 SonarQube,見裁示 12)

Notion free plan 不支援 SQL 查資料源,用 notion-search + notion-fetch


§2 本棒(第四棒)完成的事

2.1 TWGCB 8 支 OS profile 上架(commit a8046a1e

決策者自製的 twgcb2inspec.py 轉換器產出 23 支 TWGCB profile,本棒從中挑 8 支上架 (Windows 4 + Linux 4),排除 15 支(macOS + browser / application / network / cloud)。

排除理由不是「還沒做」而是「做了也沒用」

排除類別 原因
browser / application 可自動檢查項數為 0——全是人工訪談題,上架只會給出一份全 skipped 的報告
network / cloud 除了自動檢查項少,目標形態根本接不上現有 transport——SSH / WinRM 是打「一台有 OS 的主機」,網通設備與雲端租戶不是這個形狀
macOS 同上,自動檢查覆蓋率不足

同批另含兩件事

  1. twgcb-01-011升級不是新增(pending 225→150、自動檢查 483→558)
  2. 修掉 system_services.rb實質 bug——原本用中文顯示名比對服務,實際 Windows 服務比對要用服務名(顯示名會因語系不同而失配)
  3. 轉換器 tools/ 一併進版控

2.2 agent bump 0.2.21(commit 2aa95ec

清掉第三棒留下的驗證用臨時 tag 0.2.20-fr0585-verify,走正式版號。 (後續 FR-058.6 再 bump 到 0.2.22,commit 074f3b8,已部署 DEV。)

2.3 FR-058.6 全流程走完

討論稿(Artifact)→ design.md D17–D24 + §4.7 + §5.9 → Notion CM-998~1001 → T-6.1(BE param_schema v2)/ T-6.2(agent scan 分支)並行 → T-6.3 驗收通過。

2.4 Notion CM-992 大幅更新

原卡的核心假設是「Linux / macOS 幾乎零自動化,GCB content 得從頭產製」。 決策者自製的 twgcb2inspec.py 直接推翻了它——實際產出 23 支 profile / 4,351 控制項 / 45% 可自動檢查

更新後 CM-992 的剩餘範圍:

  1. 待補對照 2,384 項
  2. 後台 content 管理機制
  3. 新浮現的 network / cloud / browser transport 形態(現有 SSH / WinRM 接不上, 要接得先想清楚「連到哪裡、用什麼協定」)

§3 已定裁示(不要重新討論)

沿用第三棒的裁示 1–9:

# 裁示
1 push 永遠等決策者明示
2 🔴 開發只動 DEV,STG / POC 需當次明確指示(含 DB 與部署)
3 commit 標籤不一致不回頭修——rebase 改寫歷史風險大於整齊
4 GCB content 產製 + 後台 content 管理機制列後續案 CM-992,不在 FR-058
5 config.detection_tools 沒有 i18n 機制——先不動(平台級缺口,FR-056 建表時就有)
6 CM-985(報告呈現優化)全案驗收後才做
7 SonarQube 為 FR-058.5(D13–D16);主動掃描為 FR-058.6(D17–D24)
8 GCB 報告內的 Cinc Auditor Report 標題不處理——html2 reporter 寫死的,要動 reporter 層
9 SonarQube 不換報表方案——免費方案都是同樣的「打 API 自組」路線

本棒新增 10–14

# 裁示
10 _credentials at-rest 明文 → 發 58 版時一起改。⚠️ 不是舊資料、仍在持續產生(最新一筆 07-31 22:10,59 筆全明文、is_encrypted=f)。修法:複用 common/util/detection_secret_params.py 現成的 envelope(不要新造輪子),改存加密、心跳組裝時才解。會動派工路徑,四款工具都要回歸
11 121 / 122 的 AGENT_VERSION 舊 pin → 跟發版一起處理(屬顯示用版本字串,不影響功能)
12 CM-985 不納入 SonarQube
13 TWGCB 其餘 15 支不上架——等補完對照;network / cloud / browser 另需先解決 transport 形態
14 GCB profile 下拉不依連線方式過濾——選 SSH 也會列出 Windows profile,選錯會派工失敗。決策者裁示「先不動」,屬體驗問題非功能缺陷

§4 下一步

4.1 🔴 立即:品質門檻條件顯示問題(已派工,交接當下正在進行

症狀:SonarQube 報告的「品質門檻條件」區塊顯示「此專案未設定品質門檻條件。」, 但同一份報告上方「品質門檻結果」卻正確顯示 OK

⚠️ 交接當下 agent repo 有未 commit 的 sonarqube.py 修改(mtime 就是此刻), 那條線正在處理這件事。接手第一件事:

git -C ~/Projects/Billows/Audit-Manager/evidence-agent status --short
git -C ~/Projects/Billows/Audit-Manager/evidence-agent log --oneline -3
  • 有未 commit 檔案 → 那條線還在跑,完全不碰 agent repo(唯讀查看可以)
  • 已 commit 且乾淨 → 進驗收(見下方「驗收要點」)

🔴 本文原先的根因推測已被推翻(這段一定要讀完再動手)

協調者派工時給的推測是「conditionsprojectStatus 底下一層, _render_gate_conditions 少剝一層」。這個推測是錯的。 實查 sonarqube.py:_fetch_quality_gate 的最後一行:

return payload.get("projectStatus") or {}

一直都有剝殼,取用端讀 gate["conditions"] 是對的。

實際成因(該條線對 SonarQube 26.7 實測的結論,協調者已核對程式碼一致)

SonarQube 內建與常見自訂 gate 的條件幾乎全是 new_* 指標new_violations / new_coverage / …),只評「新程式碼」。而「新程式碼」需要一個比較基準期(period—— 專案第一次分析時沒有前一版可比,於是 api/qualitygates/project_statusconditions: []period 鍵都不出現,同時 status 仍給 OK (沒有條件可判定=沒有條件不通過)。

這正是「狀態有值、條件卻空」的來源。

實測對照(可自行複現):

專案 分析次數 conditions 實際 gate 定義
guidant-ai-backend 第 10 次(有 period) 1 條
Guidant-AI-soybean-ui scan 模式首次(無 period) 0 條 套用的 Sonar way 實際定義了 4 條

複現指令(token 查本機 ~/.zshrcSONAR_USER_TOKEN絕不寫進任何檔案):

curl -s -u "$SONAR_USER_TOKEN:" \
  "http://192.168.50.171:9000/api/qualitygates/project_status?projectKey=guidant-ai-backend"
curl -s -u "$SONAR_USER_TOKEN:" \
  "http://192.168.50.171:9000/api/qualitygates/project_status?projectKey=Guidant-AI-soybean-ui"

派工時給的三項要求(驗收對照用)

決策者原話是「沒有的話就不要顯示這塊」,但協調者判斷這不只是顯示偏好—— 若客戶明明設了門檻卻被告知「未設定」,比空白更糟(稽核員會認為受稽單位沒有把關機制)。故要求:

  1. 先查清楚真相,不要直接照「藏起來」執行
  2. 空狀態改低調處理(真的空時整塊不輸出,不要留空表也不要寫死一句錯的話)
  3. 「品質門檻結果」那一格一律保留(在「基本資訊」區)——那是客戶自己 server 的判定結果, 藏掉等於隱瞞

驗收要點(該線收工後)

4.2 待決策者驗收 FR-058.6

兩模式已跑通(§1.3),但決策者尚未親自看過報告與 UI。等他驗收。

4.3 全案收尾(等決策者下令,一項都還沒做

# 項目
1 SPEC 三頁補 SonarQube 雙模式 + GCB 8 支 profilewriting-feature-specs skill,只改 docs/specs/current/
2 使用手冊補對應段
3 design.md §11 對應段標 closed
4 全案 SUMMARY 更新——⚠️ 兩件事:① 補進 FR-058.6;② 「任務層敏感參數已修」必須補範圍界定(見 §5.3),否則下一棒會誤判 _credentials 明文為迴歸
5 Notion:CM-994~1001 標 Done(FR-058.5 的 994~997 + FR-058.6 的 998~1001)+ 母案 CM-957 更新
6 memory:本 arc 教訓濃縮(候選:gate 型 prompt 要寫重試、「沒資料就藏起來」前先驗資料源、多 session 併發 pre-flight 紀律)
7 commit 收尾文件(顯式 git add

4.4 發版時一併處理(已裁示,形成一組上版清單)

# 項目 來源
1 _credentials at-rest 明文改加密(複用 common/util/detection_secret_params.py,四款工具都要回歸) 裁示 10
2 121 / 122 的 AGENT_VERSION 舊 pin 裁示 11
3 STG / POC 補 migration 14–19(6 支) + agent 0.2.180.2.22 §1.2
4 ⚠️ STG / POC 的 sonarqube 仍是 coming_soon,上版時要一起改 §1.2

🔴 以上四項全部要等決策者當次明確指示才能碰 STG / POC(環境異動鐵律)。


§5 教訓

5.1 gate 型 prompt 要寫「重試」,只寫「停」等於把持續監控做成一次性快照

發生什麼:昨晚安排一個 session「半夜 4 點檢查 A(T-6.1)/ B(T-6.2)是否完成, 通過才跑 C(T-6.3 驗收)」。實際上該 session 23:16 就執行了檢查,當時 T-6.2 尚未 commit (23:25 才完成,差 9 分鐘),於是停在 gate、留下 commit 298fef57 記錄, 之後沒有再重試,整晚空轉。

停下是正確行為——協調者明確要求「不通過就停、不准硬跑」,它照做了。 問題出在 prompt 只寫了「停」,沒寫「等一段時間再檢查一次」

紀律:寫 gate 型 prompt(「檢查 X 是否完成,通過才做 Y」)時, 必須同時指定重試策略——間隔多久、重試幾次、最終仍不通過才停下回報。 只寫「停」,等於把一次性快照當成持續監控用。

5.2 「沒資料就藏起來」之前,先確認是不是我們沒讀到

發生什麼:決策者看到報告顯示「此專案未設定品質門檻條件」, 直覺反應是「沒有的話就不要顯示這塊」——這個要求本身完全合理。 但實際打 API 查證後發現,guidant-ai-backend 確實設了條件(回傳 1 條), 是我們這邊沒有正確呈現。

若直接照「藏起來」執行,這個問題會被永久掩蓋,客戶會持續收到錯誤資訊。 (後續查證更發現真相比想像複雜——見 §4.1,空與非空取決於有沒有比較基準期, 不是單純的「有設 / 沒設」。)

紀律:收到「這塊沒東西,藏掉吧」這類要求時,先問「是真的沒有,還是我們沒讀到」。 用最短路徑驗證資料源(打一次 API / 查一次 DB),再決定是改顯示還是修解析。 顯示層的要求,不能免除對資料層的查證。

5.3 承襲前三棒仍然有效的教訓(不要重蹈)

# 教訓
1 多 session 併發是本 arc 常態——pre-flight 一律實查 git log / DB / 容器,不要憑交接文件。交接文件的狀態盤點寫下當刻就開始過期(本文也不例外)。發現另一條線在同一 repo 作業 → 完全不碰該 repo(唯讀可以)
2 log 裡的 ERROR 不一定是缺陷——先問「這筆資料是走哪條路徑產生的」,再問「程式有沒有 bug」。判別法:compliance.agent_tasks.created_user IS NULL 只可能來自手工 INSERT(API 路徑必填 curr_user
3 「已修」的宣稱要問清楚範圍——FR-058 修的是 job_execution_detection_tools.tool_paramssecret:true 欄位,不含 _credentials(那是 FR-056 既有的租戶憑證派工快照)。第三棒就因此一度誤判為迴歸
4 錯誤分類要問「這個錯誤最早能在哪裡被發現?現在是在那裡被發現的嗎?」——本 arc 兩次把真因(image 缺 git、Ruby 3.4 訊息截斷)誤報成「檢測引擎連線失敗」,兩次都把查修方向帶去憑證與網路
5 協調者的假設要標明是假設、容許被實測推翻——本棒 §4.1 的根因推測就被推翻了;Ruby 3.4 那次協調者給的三個初始假設全錯
6 subagent 自報完成不等於正確——驗收要獨立抽查(開檔 / 查 DB / fetch Notion)

§6 Pre-flight(接手必跑)

# ① 三 repo 狀態(期望:BE 未推 4 / FE 未推 1 / agent 未推 2)
for d in ~/Projects/Billows/Audit-Manager/compliance-manager-be \
         ~/Projects/Billows/Audit-Manager/compliance-manager-fe \
         ~/Projects/Billows/Audit-Manager/evidence-agent; do
  echo "=== $(basename $d) ==="; git -C "$d" branch --show-current; git -C "$d" log --oneline -1
  echo "ahead-main=$(git -C "$d" rev-list --count main..HEAD) unpushed=$(git -C "$d" rev-list --count origin/feature/FR-058..HEAD 2>/dev/null)"
  git -C "$d" status --short | head -5
done
# ⚠️ agent repo 若 sonarqube.py 仍 modified → §4.1 那條線還在跑,不要碰該 repo

# ② 三環境 DB(密碼查 .env 的 DB_SECRET,勿寫進任何檔案)
export PGPASSWORD=$(python3 -c "import json;from dotenv import dotenv_values;print(json.loads(dotenv_values('$HOME/Projects/Billows/Audit-Manager/compliance-manager-be/.env')['DB_SECRET'])['rds_master_password'])")
for db in "192.168.50.188|guidant_ai_dev" "192.168.50.188|guidant_ai_stg" "192.168.50.189|guidant_ai_poc"; do
  h=${db%%|*}; n=${db##*|}; echo "=== $n ==="
  psql -h $h -p 25432 -U cmmgr -d $n -tAc \
    "SELECT code||'='||status FROM config.detection_tools ORDER BY id" | tr '\n' ' '; echo ""
  psql -h $h -p 25432 -U cmmgr -d $n -tAc \
    "SELECT count(*) FROM public.schema_migrations WHERE filename LIKE '%fr058%'"
done
# 期望:DEV 19 支 + sonarqube=available;STG/POC 13 支 + sonarqube=coming_soon(正常,非落差)

# ③ SonarQube 端到端執行紀錄(期望 2 筆,皆 succeeded;⚠️ 欄位是 agent_task_uid 不是 agent_task_id)
psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev -c \
  "SELECT e.id, e.agent_task_uid, e.status, e.started_at FROM compliance.detection_executions e
   JOIN config.detection_tools d ON d.id=e.detection_tool_id WHERE d.code='sonarqube'
   ORDER BY e.id DESC LIMIT 6"

# ④ param_schema 版本(期望 v1 is_current=f 保留、v2 is_current=t)
psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev -tAc \
  "SELECT ps.id||' v'||ps.version||' current='||ps.is_current FROM config.detection_tool_param_schemas ps
   JOIN config.detection_tools d ON d.id=ps.detection_tool_id WHERE d.code='sonarqube' ORDER BY ps.id"

# ⑤ 三台 agent(期望 DEV=0.2.22、STG/POC=0.2.18)
for h in 192.168.50.121 192.168.50.122 192.168.50.123; do
  echo -n "$h: "; ssh -o ConnectTimeout=8 jedi@$h \
    "docker ps --filter name=guidant-ai-agent --format '{{.Image}}|{{.Status}}'"
done

# ⑥ BE 服務(port 8000;main_socketio.py 是 socket 8002 不是 API 入口,重啟必先 kill -9)
lsof -i :8000 | head -3
tail -200 ~/Projects/Billows/Audit-Manager/compliance-manager-be/log/app.log | grep -i 'Traceback\|ERROR' | tail -10

# ⑦ agent 測試(必帶 PYTHONPATH=.,repo 缺 conftest.py)
# ⚠️ working tree 有未 commit 檔案時不要跑(另一條線在動)
cd ~/Projects/Billows/Audit-Manager/evidence-agent && PYTHONPATH=. poetry run pytest test/ -q | tail -3
# 基線:0.2.21 當下為 487 passed / 1 skipped;T-6.2(scan 分支)加入後會更高,請實跑確認

§7 環境座標

項目
DEV agent 192.168.50.123,容器 deploy-guidant-ai-agent-1,deploy 目錄 /opt/evidence-agent/deploy(⚠️ 不是 ~/deploy),ssh jedi,目前 image 0.2.22
STG / POC agent 192.168.50.122 / 192.168.50.121,皆 0.2.18
測試目標 192.168.50.151(Linux/SSH,audit-scan 已設 NOPASSWD sudo)、192.168.50.160(Windows Server 2025/WinRM)
SonarQube http://192.168.50.171:9000(實查版本 26.7.0.124771)。token 在本機 ~/.zshrcSONAR_USER_TOKEN——⚠️ 只用變數名,絕不把值寫進任何檔案
scan 模式驗證用公開 repo https://github.com/soybeanjs/soybean-ui.git(suffix soybean-ui → server 上專案 Guidant-AI-soybean-ui
DB DEV / STG 192.168.50.188、POC 192.168.50.189,port 25432,帳號 cmmgr(密碼查 .envDB_SECRET
content 投放 主機 /opt/evidence-agent/deploy/content/ → 容器 /data/content/(唯讀掛載)
profile 版控 BE repo content/detection-profiles/不放 agent repo——Dockerfile 最後一行 COPY . . 會讓它進 image,違反 D7)

§8 行為規範

  • 不切 branch——永遠在 feature/FR-058;branch 不對停下問決策者
  • push 永遠等明示——即使 origin 上已有部分 commits
  • 顯式 git add 檔名,禁 -am——BE working tree 有一批無關的 untracked docs 與 .claude/skills/big-feature-workflow/SKILL.md 的既有修改,都不要 commit、不要清理
  • 收尾等命令——plan approve ≠ 自動收尾
  • 憑證禁入版控——SonarQube token / DB 密碼 / SSH key 一律只寫變數名或「查 .env / ~/.zshrc
  • BE 出錯先看 logtail -200 log/app.log | grep -A 30 -i 'Traceback\|ERROR'
  • 改 service / serializer 後 BE 必重啟kill -9 舊 pid,use_reloader=False 不會自動重載)
  • subagent 一律不帶 model 參數(繼承 1M context);文件類派工必寫「分段寫檔
  • 測試一律 headless
  • 任務發佈後最長等 30 秒才開跑(心跳週期,正常行為不是故障。⚠️ 第三棒文件寫 300 秒是錯的
  • agent image 重建必帶 --platform linux/amd64,build 完 docker inspect 確認
  • docker compose up 必指定 service 名guidant-ai-agent),否則連帶 recreate agent-db / nginx
  • 已知現象:本機 docker image inspect <tag> 對新 tag 可能報 No such image,用 image ID 可以 (Docker Desktop containerd 多平台索引行為,非損壞)
  • 另一條線在同一 repo 作業時,完全不碰該 repo(唯讀查看可以)
  • 🆕 Notion 卡的厚度要對齊任務規模——大型 arc 才需要「卡片自足」;小批次(≤5 張、雛形) 卡寫薄 + 留 design.md 段落座標即可。本棒開 CM-998~1001 時套了母 arc 的厚規格, 開卡耗時與產出價值不成比例(決策者當場提出質疑)

§9 收尾流程(全案驗收通過、決策者下令才做

  1. SPEC 三頁writing-feature-specs skill,只改 docs/specs/current/)—— 補 SonarQube 雙模式(pull / scan 差異、各自參數、適用情境)+ GCB 8 支 profile
  2. 使用手冊補 SonarQube 雙模式段 + GCB profile 段
  3. design.md §11 對應段標 closed
  4. 全案 SUMMARY 更新2026-07-31-fr058-arc-SUMMARY.md)—— ⚠️ ① 補進 FR-058.6;② 「任務層敏感參數已修」補範圍界定(見 §5.3 第 3 條)
  5. Notion:CM-994~1001 標 Done(FR-058.5 的 994~997 + FR-058.6 的 998~1001)+ 母案 CM-957 更新
  6. memory:本 arc 教訓濃縮
  7. commit 收尾文件(顯式 git add

§10 不在本期 scope

  • GCB content 產製 + 後台 content 管理機制(CM-992)
  • TWGCB 其餘 15 支 profile(裁示 13)
  • ZAP 對 SPA 的登入後掃描(CM-984)
  • 報告呈現優化(CM-985,全案驗收後;不納入 SonarQube
  • detection_tools i18n(已裁示不動)
  • GCB 報告內的 Cinc Auditor Report 標題(裁示 8)
  • SonarQube 換報表方案(裁示 9)
  • GCB profile 下拉依連線方式過濾(裁示 14)
  • 🆕 SonarQube scan 模式的下列能力(皆已裁示不在本期):
    • 檔案上傳取源碼(目前只支援公開 repo URL)
    • 私有 repo 認證
    • Java / C-C++ / Scala 主動掃描
    • C# / VB.NET——⚠️ 不是「本期不做」而是技術上永遠只能走 pull(見 WHY 段)
    • 資源控管(並行掃描數、逾時策略)
    • coverage 紅燈的處理

§11 給 fresh session 的短 prompt

接手 FR-058(檢測工具擴充)的協調與決策工作。

交接文件:
docs/features/FR-058-2607-detection-tools-expansion/handoff/2026-08-01-fr058-coordinator-handoff-4.md

先讀該文的「🧭 原始需求 / WHY」+ §0 讀序,讀完回答 §0 的冷接自檢三問,再跑 §6 pre-flight。
⚠️ 前三棒交接文件的 §1 狀態盤點全部已過期,只讀它們的教訓 / 決策脈絡 / 裁示三節。

現況:八款工具全數上線。FR-058.6 SonarQube 主動掃描(scan)與既有拉取(pull)
兩模式已端到端驗收通過——detection_executions 內 sonarqube 2 筆皆 succeeded,
且 171 上實際長出 Guidant-AI-soybean-ui 專案。這也一併補完了 FR-058.5 的 UI 驗收。
三 repo 未推:BE 4 / FE 1 / agent 2——但 push 仍永遠等我明示。

你的下一個動作是 §4.1——確認 agent repo 有沒有未 commit 的 sonarqube.py
(品質門檻條件顯示問題,交接當下另一條線正在處理)。還在跑就完全不碰 agent repo;
已收工則照 §4.1 的驗收要點抽查。
⚠️ §4.1 我原先給的根因推測(少剝一層 projectStatus)**已被實測推翻**,
真因是「新程式碼無比較基準期」,讀完那段再動手,別照舊推測去改。

你的角色是協調、決策、派工、抽查。不寫 code、不跑測試、不寫文件——全部派 subagent
(不帶 model 參數)。收尾類動作等我下令。
🔴 開發只動 DEV,STG/POC 要我當次明確指示才能碰(含 DB 與部署)。