FR-167 交接現況(STATE)

這份是 living 檔:每棒就地 Edit,只描述「此刻」。歷史脈絡看同資料夾的 fr167-LOG.md。

項目 值
最後更新 2026-11-01 15:5x(第 9 棒交接:七 repo feature/FR-139 已由決策者合回 main、ws-CM-3241 worktree 與 branch 全刪、母卡 Done;下一棒見 §4)
branch 七 repo 皆在 main、與 origin 同步、工作樹乾淨(決策者 11-01 15:xx 把 feature/FR-139 合回 main,首腦未切)。BE 4f9cc336d、FE 78e4f535、Agent 2b78d00、update-center f4d2cd0、LC 4cfa423、test 80e8087、jedi 7842c01b。版號 BE/FE 1.27.10、Agent 1.4.8、jedi-detection 1.7.2。主線含批 32 修正與重試 412 修正,未出包
母卡 CM-3241 https://app.notion.com/p/FR-167-Agent-35-8-408346da4cd0815eaf38ffbe607f448e (狀態 Not started,母卡狀態不代表進度) Done(2026-11-01 收口)
子卡 批 1~32 共 93 張:除 CM-3312(e2e 暫緩)、CM-3377(裁不做)、CM-3378(結案出包等 FR-171/172)外全部 Done
工作坊 工作坊 30 已跑完 95 張(含批 32),無在跑的卡;七 repo 的 .worktrees/CM-3241 與 ws-CM-3241 已刪(11-01,決策者令,branch -d 全放行=內容都在主線)
本棒角色 首腦(第 9 棒,2026-11-01 12:5x~15:5x):60.167 真因磁碟滿並清兩台磁碟、P12 收口卡與批 32 合回、技術文件站、重試 412 修、母卡收 Done、七 repo 雜檔整理、worktree 清除。細節 LOG 第 9 棒
接手前必讀 §0

🧭 原始需求 / WHY

  • 客戶主機升級要「絕不出事」:guidantai upgrade 在資料庫複本上做、每步有時限、寫進度檔,失敗/卡住/斷電自動退回,現用那份資料庫從頭到尾沒動。
  • 把搬檔與敲指令拿掉:主系統每天問更新站有沒有新版 → 管理員確認後才下載、驗簽 → 有權限的人按立即或排程 → 主系統只寫更新單、主機 systemd 呼叫 guidantai upgrade。離線客戶自己上傳。Agent 在主系統升完後跟進,先一台再其餘。
  • 版本只有一種、任何版本都不自動裝、授權管能用什麼不管能不能裝。更新站(Cloudflare Worker+D1+R2)沒有私鑰,只轉交決策者在自己電腦蓋章的清單。
  • 決策者 2026-10-29 裁:開發期無人值守(小弟只驗本機能驗的),測試期首腦操作 190、決策者看畫面;小弟可 push 自己的 ws branch、套件發 beta,正式版留結案卡。
  • 完整決策 D1~D31 在 ../design.md §3;為什麼這樣決定在 ../discussion.md。

§0 接手讀序

  1. 本檔 🧭、§1 當前狀態、待辦 56~60、§4、§5 最新兩條(不再用心跳帶訊息、push 常態授權)
  2. fr167-LOG.md 第 8 棒 兩個 block(推翻了什麼、教訓);docs/draft_requirement_spec/2026-11-01-agent-independent-update.md
  3. PM 簡報 https://claude.ai/artifact/1HqiRVDJkGsJCsKeGiEBfU 與機制報告 https://claude.ai/artifact/AmUhtjZVptzoqExGEUhjhx(repo 副本在 ../briefing/;機制問答已交給另一個 session,見 qa-session-handoff.md;決策者與 PM 的共識在這兩份;報告 Q5/Q20 備份、Q15 PG 大版是已知缺口)
  4. 雛形 v2:../prototype/update-center-v2.html
  5. ../design.md §5.1/§5.4/§5.8/§7(D16 原文已過時,以 §3「Agent 跟進可選」為準)
  6. 要看某張卡:python3 /Users/chouraymond/Projects/Jedicogy/agent-workshop/scripts/notion_case.py get CM-xxxx(BE repo 目錄跑;每張隔幾秒,連撈會 429)
  7. 發布工具:~/Projects/Billows/Audit-Manager/.fr167-dev/publish/publish-12710.sh <版>(改檔內 S= 為你的 scratchpad 路徑;要 notes-<版>.json);188 出包腳本 /home/jedi/fr167-build-12710.sh(Agent+主系統,先把主控台前端產物 scp 到 /tmp/fr167-fe-console/dist-console)

§1 當前狀態(2026-11-01 12:50,第 8 棒交接)

✅ 此刻:更新站最新 1.27.10(內含 Agent 1.4.8)。189 POC 已線上升到 1.27.10;190/188 仍 1.27.8,沒升。189 的 Agent:121(ubuntu-lab-01)1.4.8 成功、60.167(60-ubuntu-2604-lab-03)推送失敗仍 1.4.7。

主機 主系統 Agent
190 測試機 1.27.8 本機一台,未推
188 STG 1.27.8 —
189 POC 1.27.10(12:14:55~12:22:23 線上升級八步全成功,system_logs 已補寫) 121 1.4.8(12:31:50 主機升完、12:36:30 主系統收成功、12:37:07 回報更新站);60.167 1.4.7 失敗「無法讀取新映像」
  • 更新站:product_releases 1.27.8/1.27.9/1.27.10 皆 published;instance_version_reports 189 為 1.27.10;agent_version_reports 第一次有真資料(121 succeeded 1.4.7→1.4.8、60.167 failed)=P11-1/P11-6 真環境驗過。
  • 1.27.10 內容:jedi-detection 1.7.2(心跳 Profile 清單帶 tool、name)+隨包 Agent 1.4.8(容器版 Office 預覽修正:Agent 接上 jedi-file-upload 設定讀取 port+image LIBREOFFICE_CMD;主控台 CINC/GCB Profile 下拉,依工具過濾)。開包核過:Agent 映像 env、BE 執行檔 tool_code、主控台新字串、storage-seed 11 檔。
  • 60.167 失敗點:Agent 主機升級單第 0 步 docker create --network none guidant-ai-agent:1.4.8 失敗(映像已 load 且 inspect 得到)。121 同包同步驟過 → 疑該機 docker/核心(同 190 昨天的「核心裝了沒重開」)。首腦連不到該機,決策者在該機跑三行查(uname/reboot-required、手動 docker create、journalctl -u guidant-agent-upgrade-order)。包已在該機下載過,修好後 Agent 區勾 60.167 再推不必重下。
  • 121 手放的 dev-sec:/data/content/cache/manual/ 兩支(見待辦 61),CINC 在 Agent 主控台貼路徑用。
  • 121 的應急捷徑已消失:今早 10:4x 首腦在 121 容器 ln -s guidant-soffice soffice 讓 demo 能預覽 Word,12:31 換成 1.4.8 新容器後由正式修正接手。
  • 188 build 機:.build/bundle/ 刪了 1.27.5~1.27.7 本機副本(已在 R2),留 1.27.8/1.27.9/1.27.10;磁碟約 38G→(出 1.27.10 後)再查。build 腳本 /home/jedi/fr167-build-12710.sh(Agent+主系統一起出);主控台前端產物要從本機 build 後 scp 到 188 /tmp/fr167-fe-console/dist-console(188 沒 node)。
  • 發布工具:~/Projects/Billows/Audit-Manager/.fr167-dev/publish/publish-12710.sh(S= 指本棒 scratchpad,下一棒要改)+notes-1.27.10.json。
  • briefing/:PM 簡報原檔、機制問答第 9 版(加升級接力 sequence 圖)、handoff/qa-session-handoff.md(機制問答交給另一個 session)。

§1 歷史狀態(第 6 棒交接,2026-10-31 18:20)

✅ 此刻:更新站 1.27.3~1.27.7 五版 published;190 在 1.27.6、前端已熱換成含 e1849538 修正的 image、正在升 1.27.7(incoming 已有 .part)

  • 今天發版軌跡:1.27.3(P9 全部修正+bugsink 2.6.2)→ 1.27.4(只換版號,驗第 0 步秒級/維護頁當次換新)→ 1.27.5(FE 三修正:Agent 收合 a4126e2b、目標版號 13ef3ecc、遮罩 30addad1)→ 1.27.6(只換版號,驗遮罩)→ 1.27.7(FE e1849538:輪詢看「有沒有未結束的更新單」不看畫面狀態、Agent 區無本輪紀錄不畫格)。1.27.4/1.27.6 是 188 直出沒回主線版號;主線 BE f1d87a12b/FE d81b08a4 已是 1.27.7。
  • 為什麼要 1.27.7(根因,不要再補狀態格):access log 證明前端最後一次 status 在下載完成前 16 秒;pollMs 只在 ACTIVE_VIEWS 才輪詢,下載完後端先寫 ready(不在集合內)→ 前端停止輪詢 → 一秒後後端寫單、主機驗包 59 秒、開跑,前端全程沒再問。13/19/37 三次都在修「問到之後怎麼畫」,沒碰「要不要問」。修法 pollIntervalMs(status):latest_job 不在終態(succeeded/failed/rolled_back/cancelled/skipped)就 3 秒問;scheduled 且未到 30 秒;watch(status) 不是 watch(view)。
  • 190 前端熱換(決策者 18:00 令「直接去替換 190 的 docker」):188 用 FE e1849538 重 build guidant-ai-fe:1.27.6 同 tag、docker save 傳 190 load、compose -f /srv/guidant-ai/docker-compose.yml up -d --no-deps guidant-fe。現在跑的 image 8a89cef33901(舊 36f11968b0a4),用壓縮後仍在的字面值序列核過(rolled_back,cancelled,skipped 新 1/舊 0)。api/db 沒動。注意:190 的 bundles/guidant-ai-1.27.6/ 已被清理,compose 要用 /srv/guidant-ai/docker-compose.yml,不是容器標籤寫的 bundles 路徑;guidantai restart 不會重建容器。
  • update-center 已部署(8e6ea6e,Version 5dd8c372):蓋章帶 ops_sha256/ops_size、download-url 認 artifact: "ops"。正式 CLI publish 路徑(register-draft → D1 → guidant-release publish)還沒帶 ops 兩欄,測試期用 ~/Projects/Billows/Audit-Manager/.fr167-dev/publish/publish-1273.sh <版> 直接從 188 的 release.json 簽(含 ops),要另開 update-center 卡。
  • 發布工具:publish-1273.sh <版>(支援 STATUS=draft)、notes-<版>.json 三段說明;188 出包腳本範本 build1277.sh(be/init 沿用上一版 retag、FE 重 build、build_bundle、prune)。FE image 現在 20 秒(P9-11 分層快取生效);整包 ~11 分;R2 上傳 ~5 分。

✅ 188 STG/189 POC 都已升到 1.27.7(第 7 棒,2026-10-31)

  • 188:18:33 sudo ./install.sh --upgrade → 18:39 完成,七步全 ok,164 支 migration,清掉 1.27.5/1.27.6 殘留映像;磁碟 86%/54G。log /srv/guidant-ai/log/upgrade-20261031-183353.log。
  • 189:包從 188 scp 到 /home/jedi/(sha256 OK)→ 19:21 開跑 → 19:33 完成(約 12 分,比 188 慢,資料庫複製與弱點庫解開較久),七步全 ok,164 支 migration,api/worker/socketio/fe 1.27.7 healthy,版本 API 回 1.27.7,ui_routes 無幽靈列;磁碟 73%/52G。log /srv/guidant-ai/log/upgrade-20261031-192137.log。
  • 189 的兩台 Agent 已手動升 1.4.2 → 1.4.7(決策者 21:05 令「都是 POC,幫我升」):50.121(ubuntu-lab-01)21:22、60.167(60-ubuntu-2604-lab-03)21:34,各用 sudo guidant-agent-compose upgrade /home/jedi/guidant-agent-compose-1.4.7.tar.gz,兩台 agent+seaweedfs 皆 healthy,189 remote_agents 回報 1.4.7。為什麼手動:1.4.2 沒有遠端更新能力(1.4.4 才加),更新中心推不動;升到 1.4.7 後下一版起可從 189 推(但要 189 upgrade/bundles/guidant-ai-<版>/agent/ 有包,這次走 install.sh 升的沒有)。包怎麼搬:主機之間沒有免密 SSH(189↔︎121、188→121 都拒),經 mac 中轉兩趟 1.8G。順手發現:兩台的 SeaweedFS 升級前都 unhealthy、can't fork,PID 數 15,360/18,478(Agent 本體才 6),容器沒設 pids 上限、1.4.2 跑三週程序洩漏;升級重建容器後 PID 22/18 恢復。要盯 1.4.7 會不會再長(待辦 53)。兩台都提示「本機管理員密碼尚未設定」,屬既有狀態。
  • 188/189/190 bucket 已補灌 CRA PDF(決策者 21:50 令「你先做吧」):來源 venv jedi_oscal_v2/assets/CRA Regulation (EU) 2024-2847 OJ L EN.pdf(sha256 e3ecaabd… 與 009 migration 一致),照 install.sh load_storage_seed 同一條路(docker cp 進 seaweedfs 容器 → weed filer.copy … /buckets/guidant-ai/),key 20261014000000_b81c42ff-….pdf,三台 fs.ls 皆 1,782,351 bytes。不用重啟。待辦 47 的「當下補救」半做完,出包守門那半在 P10-4。
  • 兩台 compose 工作目錄現在都是 /home/jedi/guidant-ai-1.27.7/。/home/jedi/guidant-ai-1.26.0/ 已刪(決策者 21:55 令;刪前核 working_dir/bind mount/config_files/install.conf/symlink 皆 0 引用),各回收 6.1G;guidant-ai-1.26.0.tar.gz 留著。188 磁碟 85%/60G、189 69%/59G。
  • 兩台都還沒做 §4-1 第 6 步(guidant.env 加 UPDATE_SITE_URL,讓之後走線上更新)——改 STG/POC 設定,等決策者令。
  • 升級後決策者在 188 看到三件事,已記待辦 45~47(側欄幽靈選單=瀏覽器存檔,登出再登入即消失;product-update 能力點缺翻譯;CRA PDF 沒進包)。189 同樣會有待辦 47(bucket 沒有 CRA PDF)。
  • 簡報:決策者 19:00 要「給 PM 向資安背景老闆報告」的簡報,已產 12 張 https://claude.ai/artifact/1HqiRVDJkGsJCsKeGiEBfU (私人,要分享才能開)。

188 STG/189 POC 升級前現況(歷史,19:35 前)

  • 兩台都 1.26.0(沒有 guidantai upgrade、沒有更新中心、不會問更新站),compose 工作目錄 /home/jedi/guidant-ai-1.26.0/、資料目錄 /srv/guidant-ai、GUIDANT_VERSION=1.26.0,guidant.env 沒 UPDATE_SITE_URL,沒裝 Agent。
  • seccomp errno 524 已解(待辦 38 根因=apt 裝了新核心沒重開):兩台今天重開進 5.15.0-202,no-new-privileges 能起、exec 能進、全部容器 healthy。188 STG api 三容器(10-30 第 4 棒 smoke docker rm -f 掉的)已起回;188 /home/jedi/guidant-ai-1.26.0 是首腦 12:xx 誤刪後從同目錄 tar.gz 重建的(compose 與 /srv 那份 cmp 相同,資料庫 named volume 未動:58 專案/2 使用者/311 migration)。
  • 磁碟:188 82%/68G 可用;189 61%/75G 可用(今天各清 ~70G/~50G)。1.27.7 包 5.26G+解開 ~8G+資料庫複本(<1G)夠。
  • 189 升了 containerd.io 2.4.2(無效但無害);188 沒升。
  • 1.27.7 包只在 188 /opt/guidant-ai-be/.build/bundle/guidant-ai-1.27.7.tar.gz(+.sha256/.ops.tar.gz/.release.json),189 沒有。

§1 歷史狀態(第 5 棒)(2026-10-30 23:52)

測試期第一步(2026-10-30 17:40,進行中)

  • 測試章換新:原 DEV 公鑰 d6c8513a4ea604d9 的私鑰隨小弟暫存清掉、遺失。首腦在決策者 mac 用 openssl 產新測試章 b91819f86eb4b4f8,私鑰在 ~/.guidant-release-test/(600、無 passphrase、不入 repo,只供內部測試),公鑰換進 scripts/installer/release-keys/(BE daf3fa35b)。正式章仍待決策者 init-keys。
  • 簽章工具:測試期簽清單用首腦 scratchpad 的 sign-release.ts(import update-center cli/envelope.ts 的 buildPayload/signRelease/serializeEnvelope,不另寫簽章邏輯)+ BE scripts/build/make_offline_bundle.sh 產單一離線檔。端到端驗過:BE verify_manifest/verify_package_file 收下、竄改簽章被拒。scratchpad 會清,下一棒要用就照這段重寫(三十行)。
  • 出包漏洞:10/29 晚之後 pip-audit 新增 81 項 CVE,擋在 verify。已全清(本機 audit_deps.sh 0 項):
    • 發 Nexus:jedi-license-runtime 1.1.7(beta 轉正)、jedi-remote-agent 1.10.1(補事件碼 6230~6236)、jedi-common 1.3.8(opentelemetry 1.45.1)、jedi-ai-gateway 0.1.5(litellm 1.103.1;不取 1.104.0,它加 filelock<4 會把 filelock 壓回有洞的 3.32.7)、jedi-file-protect 0.2.2(pyzipper 0.4)、jedi-evidence-classification 1.6.9(沙箱 pillow 13/pypdf 6.21.4 等)。
    • BE 釘上述六支,Pillow 上限改 <14,升 aiohttp/brotli/certifi/dnspython/filelock/setuptools/opentelemetry 全家(BE 04889d086、43b3469c9)。
    • 分類沙箱 relock.sh 加參數 ./relock.sh <套件…> 轉 --upgrade-package(原版 pip-compile 不會自己升)。
  • 版號:BE pyproject.toml 1.27.0、FE package.json 1.27.0。這是內部測試包,release note/spec 快照/tag 等測完正式進版再做。
  • 188:/opt/jedi-python-package 由 main 切到 feature/FR-139(決策者 2026-10-30 授權)。原因:CI 只在當下 branch git pull,main 的分類沙箱停在 1.6.6,與 BE 鎖的版號不符會停在 build_classifier_image。BE/FE clone 本來就在 feature/FR-139。
  • pipeline 3007809601(e2e、rehearse_base 1.26.0):清 190 → 裝 1.26.0 → 灌 STG 唯讀 dump → 用 1.27.0 包升級比筆數。package 段預期紅(無 PROD 章、無更新站 CI 變數),不影響 190。
  • 剩下:190 升好後出 1.27.1(BE/FE 改版號、188 手動 build_all+build_bundle --skip-prod-key-check)→ 測試章簽清單 → 離線檔 → 決策者在 190 更新中心上傳、按更新。線上更新站要決策者 npx wrangler login(在 update-center 資料夾,先 npm install)+告知 Access 信箱,第二輪做。

🔴 190 上有一個測試期繞道(修好升級程式後要刪)

  • /etc/systemd/system/guidant-upgrade-order.service.d/fr167-self-replace-timeout.conf:Environment=UPG_LIMIT_SELF_REPLACE=600(2026-10-30 22:40 加、已 daemon-reload)。原因見下:第 0 步 60 秒讀不完 5.25GB 包,實測抽兩個小檔要 62 秒。正式修正在下一版升級程式;出新版後刪這個檔再 systemctl daemon-reload,否則會掩蓋升級程式有沒有真的修好。

✅ 此刻(2026-10-31 10:20):190 已線上升級 1.27.1 → 1.27.2 成功,繞道已刪

  • 決策者 10:04 按更新到 1.27.2 → 下載 5.25GB → 10:11:58 主機開始 → 10:19:41 完成(約 7 分 40 秒)。第 0 步 2 分 19 秒;第 4 步 post-migrate 的錯誤追蹤站與弱點庫兩關都過(正式包、非手補);redis 全程 healthy、/tls 5 檔在;健康檢查實打版本/登入/3 支 API 通過。
  • 結果:api/worker/socketio/fe 皆 1.27.2 healthy;清理刪 1.27.0 三顆映像與第一次升級留下的 named volume,資料庫快照只留 pgdata-prev-1.27.1;磁碟 38%→37%。role-manage 已被第三輪清掉;tool-plugin-manage 仍在(待辦 28 未修,1.27.3 才清)。
  • 190 的 systemd 繞道已刪(fr167-self-replace-timeout.conf+daemon-reload,Environment= 已空);190 現在跑 1.27.2 升級程式,第 0 步時限自己依包大小算(upg_self_replace_limit)。
  • 升級中畫面的修正(自動跳維護頁、維護頁白話步驟名、退回失敗終態)要 1.27.2 → 下一版 才看得到(升級過程由舊版前門顯示);平常畫面的修正這次即生效。
  • 下一步:Agent 區推 1.4.5,驗主系統主動通知(不等 5 分鐘心跳)。

✅ 此刻(2026-10-31 02:15):1.27.2 已發布,190 可直接測

  • 更新站:D1 有 1.27.1、1.27.2 兩列皆 published;1.27.2 kid=b91819f86eb4b4f8、size 5,251,570,709、r2_key v1/1.27.2/…。R2 三檔齊、大小與 188 包一致。依更新站 planPath,1.27.1 客戶端路徑=[1.27.2] 一跳(min_base 1.0.0)。
  • 驗章:用 BE 真實 verify_manifest+出貨公鑰,以 1.27.1 為基準驗過;190 /etc/guidant/release-keys/ 有此 kid。
  • 包內確認(188 解開目錄 grep+FE image 內 grep):待辦 1/7/17/18/20/21/23 的主機 lib 修正、install.sh ensure_bugsink_env 在 case 前、Agent compose 1.4.5、維護頁 self_replace/rollback_failed/?upgraded=1、更新中心 submitted 與白話步驟名,全在。
  • 沒驗到:190 從自己的身分實際「立即檢查」看到 1.27.2(產品 image 是 Nuitka 無 python,容器內無法直呼 client;要決策者登入按「立即檢查」)。
  • 決策者早上做:190 更新中心「立即檢查」→ 看到 1.27.2 →「更新到 1.27.2」。🔴 這次停服務那刻仍要手動重新整理一次(自動跳轉在新前端,1.27.2→下一版才生效);第 0 步跑的是 190 上手補的 lib(同一套修正),時限仍有 600 秒繞道。升過後 Agent 區推 1.4.5 可驗「主動通知、不等 5 分鐘」。
  • 之後首腦做:190 升過 → 刪 /etc/systemd/system/guidant-upgrade-order.service.d/fr167-self-replace-timeout.conf+daemon-reload。

🌙 夜間無人值守計畫(2026-10-31 00:50 起,決策者:「我希望早上來看到我是可以直接測試升級的」「交給你了」)

  • 工作坊 30 是 auto 模式(dispatch_mode=auto):每批全驗完+全合回 ws-CM-3241 就自己開下一批,不需人按。00:40 時批 18 五張 CM-3336~3340 全過驗全合回;批 19 CM-3341/3342 已派。之後批 20(CM-3343 文件)→ 批 21(CM-3344 P8-9 結案出包)自動接續。
  • P8-9(CM-3344)00:55 派工前補卡縮範圍:小弟只做本機驗新裝+驗升級+BE 版號 1.27.2,不去 188 出包(原因:188 pull 的是 feature/FR-139,修正此刻只在 ws-CM-3241,照原卡出的包不含修正)。首腦掛 Monitor 盯工作坊 log,看到 #CM-3344 合回 ws-CM-3241:merged 或「沒有下一批」即接手:
    1. 合回主線:BE/FE/agent feature/FR-139 ← ws-CM-3241(merge-tree 零衝突才 merge --no-ff);FE package.json → 1.27.2,並補 16 個 PRODUCT_UPDATE_* 錯誤碼翻譯;守衛測試;push(常態授權)。00:52 預檢:三 repo 試合皆零衝突(BE ws 領先 8/落後 5,落後的是首腦今晚推的文件與 lib 修正);主工作區各有一支別 session 的未提交檔(BE FR-170 parent-cards.json、agent CLAUDE.md),不在合回路徑、不 add。 1b. Agent 要升 1.4.5:P8-5 改了 Agent 程式但版號仍 1.4.4,與 190 現行同號,重出會被判「已是最新」而送不到。合回後 agent pyproject.toml → 1.4.5、RELEASE_NOTES.md 加 ## 1.4.5 兩條(主系統推送後立刻開始、升級解包有進度),commit+push,再出 compose 包。
    2. 188 出包:/opt/guidant-ai-be、/opt/guidant-ai-fe、/opt/guidant-ai-agent git pull 到剛推的 HEAD(先 pgrep -f 'nuitka|build_all');Agent compose 若有新版先 build_all.sh --with-compose;BE scripts/build/build_all.sh --all → build_bundle.sh --skip-prod-key-check(約一小時)。開包 grep dbc_restore_item、ensure_bugsink_env 在 case 前、維護頁 step_self_replace。
    3. 簽章:本 session scratchpad sign/sign-release.ts(從上一 session 複製、import update-center cli/envelope.ts,私鑰 ~/.guidant-release-test/),UC_ROOT=~/Projects/Billows/Audit-Manager/update-center node --experimental-strip-types sign-release.ts <unsigned> <out>。
    4. 上傳 R2:在 188 用 rclone(憑證 /home/jedi/.fr167-r2.env),key v1/1.27.2/ 三檔(tar.gz/.sha256/.release.json),照 scripts/build/publish_draft.sh 的 key 形狀。
    5. D1:照昨晚 insert.sql(範本在本 session scratchpad rel1271-reference/)寫 1.27.2 一列,status=published、kid=b91819f86eb4b4f8、三段說明沿用 1.27.1;npx wrangler d1 execute guidant-update-center --remote --file。
    6. 驗:curl https://guidantai-update.jedicotech.com 客戶端端點以 190 身分問得到 1.27.2;190 更新中心「立即檢查」看到 1.27.2(唯讀,不按更新)。
    7. 停:不在 190 按更新、不刪 190 繞道。STATE 寫結果、桌面通知。
  • 卡住或驗不過:寫進本段下方、不出半套、通知決策者。
  • 00:56 CM-3343 小弟停下問 → 工作坊暫停:問的是 FE error-code.json 翻譯不在它工作目錄(首腦開卡把 FE 檔塞進 BE 卡,違反一卡一 repo)。首腦裁:本卡縮成三份文件(6aed60bbf 已完成),卡上寫裁示、改「修正待驗證」、POST /api/workshops/30/resume(要帶 Content-Type: application/json),00:57 已送驗。FE 16 個 PRODUCT_UPDATE_* 翻譯改由首腦在合回 FE 時補(zh-tw+en error-code.json,中文取 common/code/product_update_error_code.py)。

🌙 夜間執行進度(2026-10-31 01:20)

  • 工作坊 30 批 18~21 九張全過驗全合回 ws-CM-3241(01:09「64 張卡都做完了,沒有下一批」)。CM-3344 本機驗:新裝 186 支/升級 164 支皆 0 錯誤、終點 475、audit_deps 0、守衛 119 綠。
  • 首腦補:SPEC skipped 三處(638361333)、FE 14 個錯誤碼翻譯+版號(bc78ddf6;實數 14,卡寫 13、小弟報 16 皆不準)、Agent 1.4.5(99722ff)。
  • 已合回並 push(遠端=本地已核):BE abd6fe721、FE f908f7a2、Agent 99722ff。合回後 BE 測試 200 綠、FE vitest 58 綠+vite build 0、Agent 87 綠。
  • 🔴 Mac git 對 gitlab.com 憑證失效(keychain 空,could not read Username)。glab 仍登入,push 用一次性 helper:git -c credential.helper= -c 'credential.helper=!glab auth git-credential' push origin feature/FR-139(不改全域設定、不存新憑證)。188 用 SSH 不受影響。
  • 188:三 clone pull 到上述三個 commit。主控台前端暫存副本 /tmp/fr167-fe-console 是純檔案(非 git、188 的 /opt/guidant-ai-fe 無 node),用 git archive 從 f908f7a2 刷新後 npm run build:CONSOLE(nvm node 22),01:15 新產物——昨晚那份是 19:25 舊 FE,沿用會讓 Agent 1.4.5 帶舊主控台。
  • 01:15 Agent build_all.sh --with-compose(FE_CONSOLE_DIST=/tmp/fr167-fe-console/dist-console)背景跑,log /tmp/fr167-agent-145-build.log。
  • BE 出包已排在 188:/tmp/fr167-be-after-agent.sh 等 Agent EXIT=0 才跑 build_all.sh --all → AGENT_COMPOSE_BUNDLE=…1.4.5.tar.gz build_bundle.sh --skip-prod-key-check(明確指定,不靠 mtime 挑;Agent 失敗就不跑)。log /tmp/fr167-be-127-2-build.log。兩個 Nuitka 不並跑(188 會 linker crash)。
  • 188 磁碟 92%(32G 可用),估本次約 20G,未刪任何舊包(1.27.0 在 190、1.27.1 在更新站上)。
  • 01:35 Agent 1.4.5 完成 EXIT=0(Nuitka 8 分、smoke 六項、Trivy+Grype 弱點關卡過、compose 1.79GB,notes 帶兩條新說明)。
  • 🔴 01:35 BE 出包 3 秒就失敗在 ⓪b audit_deps:找不到 pip-audit——不是漏洞。audit_deps.sh 以裸名呼叫 pip-audit,它只在 /opt/guidant-ai-be/.venv/bin/;昨晚是互動 shell(venv 已 activate)所以過,nohup setsid 的非互動 shell 沒有。無人值守出包一律先 export PATH=/opt/guidant-ai-be/.venv/bin:$PATH(同理 FE 主控台要 source nvm)。01:37 用 /tmp/fr167-be-build.sh 重排,log /tmp/fr167-be-127-2-build.log(失敗那次留在 .fail1.log)。
  • 🔴 01:38 第二次又停在 ⓪ DB 前置斷言(STG 落後 116+48 支)——這是常態不是錯(memory feedback_release_smoke_db_assert_use_pipeline_tempdb_not_stg):build_all.sh 沒有「斷言 exit 3 → smoke_tempdb.sh」分流,那段只寫在 .gitlab-ci.yml build-be job,所以在 188 手跑 build_all.sh 永遠出不了正式包。絕不為了出包去升 STG schema。01:39 改用 /tmp/fr167-be-build.sh 照 CI 順序手跑:sbom→audit_deps→build_release→build_prompt_guard_onnx→assert_db_current(rc 3 走 smoke_tempdb:STG 唯讀 pg_dump→188:25432 臨時庫→migrate→smoke→刪庫)→build_image→build_fe_image→build_init_image→build_classifier_image→build_bundle --skip-prod-key-check(CI 的 internal_test 路徑才准這個旗標;正式 package 段禁止)。失敗 log 留 .fail1.log(pip-audit)、.fail2.log(DB 斷言)。
  • 01:39~01:57 照 CI 順序跑完:build_release 12 分、smoke_tempdb PASS 9/FAIL 0(臨時庫 guidant_ai_smoke_1272 已刪)、BE/FE/init 三顆 1.27.2 image+classifier 沿用 1.6.9。
  • 🔴 01:57 第三次停在 build_bundle:GUIDANT_BUGSINK_ADMIN_PASSWORD 未設——CI 是遮罩變數,手跑要自己 export。值取 188 /home/jedi/fr167-test-bugsink-admin.txt(雜湊與 1.27.1 包內 bugsink-admin.secret 相同,即 190 錯誤追蹤站建站那組)。01:58 只重跑打包 /tmp/fr167-be-bundle-only.sh(image 不重建;密碼經環境變數帶入、不上命令列不入 log),log /tmp/fr167-be-127-2-bundle.log。
  • 188 手跑出包的三道 CI 專屬前提(下次照抄,都寫在 /tmp/fr167-be-build.sh 與 -bundle-only.sh):①PATH 加 /opt/guidant-ai-be/.venv/bin(pip-audit);②DB 斷言 rc 3 走 smoke_tempdb.sh(只在 .gitlab-ci.yml);③export GUIDANT_BUGSINK_ADMIN_PASSWORD。另 Agent 要 FE_CONSOLE_DIST 指新建的主控台產物、FE 主控台要 source nvm。
  • 發布腳本已備:本 session scratchpad publish-1272.sh(188 取未簽清單→Mac 測試章簽→188 rclone 用 env 臨時遠端上傳 v1/1.27.2/ 三檔,不寫 rclone.conf→wrangler 寫 D1 一列)。已驗:wrangler 仍登入正確帳號、D1 只有 1.27.1、R2 憑證能列出 1.27.1 三檔、簽章模組可載入。

✅ 此刻(2026-10-30 23:32):190 線上更新第四次實測成功,1.27.0 → 1.27.1

  • 全程 4 分 30 秒(23:27:36 收單 → 23:32:03 前門重建):第 0 步 skipped(已裝維運指令=目標版)、1~7 全 ok;健康檢查實打版本/登入/3 支 API;換接後 .env 版號 1.27.1、GUIDANT_PGDATA_DIR=/srv/guidant-ai/pgdata,升級前那份留在 named volume guidant_guidant-pgdata(prev_kind=volume,第一次升級的既定契約)。容器 api/worker/socketio/fe 1.27.1 healthy,redis/seaweedfs/bugsink 全程沒停。Agent 這次沒勾跟進(with_agents=false),仍 1.4.3。
  • 跑的是手補 lib(待辦 16/18/20/21/23 的修正直接套在 190 /usr/local/lib/guidant/ 與解開的包;備份 /home/jedi/fr167-lib-bak-20261030-232552/、/home/jedi/fr167-install.sh.bak-20261030-230145)。正式包出來後 190 要再升一次才算驗過出貨品。
  • 今晚四次實測軌跡:①22:30 第 0 步 60 秒逾時(繞道 600 秒)②22:51 第 4 步 bugsink 變數未設、自動退回成功 ③23:04 第 4 步 vulndb 因 redis unhealthy、自動退回也失敗、guidantai recover 救回 ④23:27 成功。每次的根因與修法在待辦 1/16/21。
  • Agent 手動推送 1.4.3→1.4.4 成功(23:34 按推送 → 23:38 心跳下發 → 23:38:50 下載驗過寫單 → 23:42:5x 容器 1.4.4 healthy):Agent 側六步全過。中間兩段空窗要修:心跳等待 4 分(待辦 26)、解包無進度 3 分(待辦 27)。
  • 未驗:真重開機的開機檢查、跨版兩段、排程模式、Agent 自動跟進(勾「接著更新 Agent」那條)。
  • 190 的 systemd 繞道(UPG_LIMIT_SELF_REPLACE=600)仍在;待辦 1 修正進包後刪。

🔴 第一次實測(2026-10-30 22:35):失敗在第 0 步,系統未動

  • 決策者在 190 更新中心「檢查更新 → 預先下載 → 更新到 1.27.1(勾接著更新 Agent、立即)」。下載 5.25GB 與驗章都成功(22:28),主機收單、驗包通過、22:30:14 開始升級。
  • 第 0 步 self_replace 60 秒逾時(退出碼 124)→「升級未進行,系統沒有任何變動」。190 仍 1.27.0 照常;product_update_jobs id 1 = failed。
  • 根因:lib/upgrade_runner.sh:36 UPG_LIMIT_SELF_REPLACE 預設 60 秒;lib/self_replace.sh sr_extract 用 tar -xzf 從整包抽 VERSION/guidantai/lib/release-keys 幾個小檔,gzip 無法隨機存取、必須讀完整包。1.27.1 包 5.25GB(含 Agent compose 1.79GB)讀不完 60 秒。下一棒第一件事:時限改依包大小(或改 60→300),或 self_replace 改讀包外已解好的檔/先把小檔放在包最前面並抽到即停。修完重出 1.27.1、重放更新站(D1 列與 R2 物件換新、版號可不變,見下)。
  • 更新站現況:https://guidantai-update.jedicotech.com(Cloudflare Worker,帳號 Raymond.jedicotech、D1 guidant-update-center id 219dbab7…)。Access 守後台(team curly-water-b543.cloudflareaccess.com、AUD 在 update-center .env);Worker secret 五個(ACCESS_×3、R2_×2)。已發布 1.27.1(直接寫 D1,略過 Access/內部先裝,決策者裁示僅測試用)、R2 v1/1.27.1/ 三檔。測試章 b91819f86eb4b4f8,私鑰 ~/.guidant-release-test/。簽章工具在首腦 scratchpad sign/sign-release.ts(import update-center cli/envelope.ts),scratchpad 會清,要用就重寫。
  • 190 現況:1.27.0 全新安裝(/srv/guidant-ai),Agent 1.4.3 已裝已核准、心跳正常(/srv/guidant-ai-agent,名 guidant-190-agent)。guidant.env 加了 UPDATE_SITE_URL(有 .bak-fr167-* 備份)。授權由 189 LC 開通(無身分票,開通早於 189 LC 更新,送原文+warning)。安裝設定碼 c3ca9258…;Bugsink 測試密碼在 188 /home/jedi/fr167-test-bugsink-admin.txt;Agent 本機管理員密碼在 190 /home/jedi/fr167-agent-local-admin.txt。
  • 188 磁碟(第 6 棒 12:40):79%、83G 可用。已刪自家舊包/舊映像/兩個 home 殘留目錄;build cache 60G 全是被現存 image 引用的 shared 層(builder prune --filter until 清不掉),只能等刪舊 image 或 P9-2 的 --keep-storage 收;第三方映像、dist、Prompt Guard 模型一律不清(決策者 10/31 明示)。FR-133 留下的兩個 until pgrep build_all 等待迴圈已 kill。
  • 188 現況:BE/FE/jedi/agent clone 皆 feature/FR-139(jedi、agent 本棒由 main 切過來,決策者授權)。.build/bundle/ 有 1.27.0、1.27.1(含 Agent 1.4.4);舊 1.27.1(含 1.4.2)在 /home/jedi/fr167-bundle-old/。Agent compose 1.4.3、1.4.4 在 /opt/guidant-ai-agent/.build/compose/。主控台前端暫存 build 在 /tmp/fr167-fe-console/dist-console(FE_CONSOLE_DIST 指它)。R2 憑證 /home/jedi/.fr167-r2.env(600,用完可刪)。
  • 189 LC:已更新到 feature/FR-139 14fc8eb(product_major+update_ticket,alembic a7c3e19d52b0),決策者授權;備份 /home/jedi/lc-poc-before-fr167-20261030-195811.dump。189 現在跑 feature 分支,合回 main 前要記得。
  • 本棒修掉、已 commit 已 push:IEC 62443 migration 空操作(升級擋)、fr144 選單驗證只驗自己六項(新裝擋)、六支套件發版(license-runtime 1.1.7/remote-agent 1.10.1/common 1.3.8/ai-gateway 0.1.5/file-protect 0.2.2/evidence-classification 1.6.9)+12 支第三方升版清 81 CVE、測試章換新、CI internal_test input、更新站部署+改公司網域、Agent SeaweedFS 加密、Agent build 三個過時檢查(LDAP 路徑/smoke https/就緒判定)、Agent 四支掃描工具升版+兩條 Go CVE 進白名單(agent 限定、至 2026-12-31)、Agent 1.4.4 版本說明、檢查更新改每 6 小時+啟動先問一次。
  • 本棒發現、未修(交給下一棒或第二期):
    1. self_replace 60 秒逾時(上面,擋線上更新,最優先)。🔴 第 0 步跑的是主機上已裝的舊版升級程式(/usr/local/lib/guidant/upgrade_runner.sh),不是新包裡的——所以這個 bug 在「被升級的那一版」,新包不必重打。修法擇一或並用:① 時限依包大小算(例:每 GB 60 秒、下限 300);② self_replace 不從整包抽檔:出包時把 VERSION/guidantai/lib//release-keys/ 另放包外一份(或放在 tar 最前面、抽到即停);③ 第 0 步改讀已解好的 bundles 目錄。注意:修好的升級程式要先裝到舊版主機上才生效——客戶從 1.27.0 升時跑的仍是 1.27.0 的程式,所以 1.27.0 已出貨的客戶仍會撞這個逾時,要評估是否要靠更新單帶時限參數、或 1.27.x 補一版只換升級程式。
    2. FE「立即」文案錯:mode_now_hint「先提醒在線使用者 5 分鐘再開始」、apply_now_done「5 分鐘後開始更新」,後端與 design 都是立刻開始(not_before=now)。使用者會以為有 5 分鐘存檔。改文案或真的做 5 分鐘緩衝,要決策者裁。
    3. 全新安裝多一個沒翻譯的選單 lang.menu.role-manage(jedi-iam 001 在第二輪插回 FR-132 刪掉的選單)。
    4. 全新安裝角色詳細頁 500(ui-routes capability 缺 license_module)。
    5. 1.26.0 舊包在全新機器裝不起來(fr114 backfill 在能力點建立前查),CI 排練從零重灌 1.26.0 必紅;排練基底要換或改流程。
    6. Agent 單獨更新(不下載 5G 整包)未做,design 寫第一版不做;Agent 修正頻繁,建議第二期。
    7. 預檢要按更新才跑,預先下載後卡片仍「還沒跑過」。
    8. SPEC system-admin/product-update.md:242 仍寫 cron 03:00(已改每 6 小時+啟動)。
    9. 13 個 PRODUCT_UPDATE_* 錯誤碼 FE 沒翻譯(舊待辦)。
    10. 升級失敗後前端一直轉圈:第 0 步逾時、主機放棄(系統未動),但更新中心頁卡在「更新中」輪詢、使用者以為整站壞了(決策者 22:35 實測,重新整理即恢復;伺服器全程正常、無 500)。失敗要正確顯示「失敗、系統未變動」並停止輪詢;查 product_update_order_sync 寫回 failed 後 FE deriveView 是否仍判 running。
    11. 第 0 步逾時被記成 failed,該記 skipped:failed 的語意是「驗證失敗、包已刪、要重下載」,但第 0 步逾時時包還在 incoming/、系統未動。後果:「重試」只收 rolled_back/skipped 用不了;畫面退回「有新版可更新」且預先下載鈕重新出現,使用者以為包被刪了(決策者 22:49 實測)。不會重下載:下載程式開跑前看 incoming 有包就重驗雜湊與簽章、驗過直接 ready(第 5 棒核程式碼+190 實測 26 秒),第 4 棒寫「會重新下載 5.25GB」是錯的。修 host 寫進度檔時,第 0~2 步(系統未動)逾時一律寫 skipped。
    12. 出新版前要做的事(決策者 2026-10-30:晚點修正後出一版新的):上面 1、2、3、4、7、10、11、13~27 修完一次打包(16、18、20、21、23 第 5 棒已修已 commit、待進包;其餘未動),不要修一項打一次(一包約 1 小時)。出包前在本機先驗:新裝用出貨 init image 空庫 init+migrate、升級用 STG 唯讀 dump+migrate.sh(本棒做法,見 LOG)。出新版後刪 190 的 systemd 繞道(上面)。「檢查更新每 6 小時+啟動先問」(7774e7345)已 commit,下一版才生效。
    13. 按「更新到 X」後畫面跳回起始畫面(決策者 22:50 實測):沒包時 apply 走「先下載、就緒後寫單」,從下載驗證完(22:50:07)到主機寫回 running(22:51:45)約 1 分半,更新單狀態是「已送單等主機」,FE deriveView 不認這個狀態就退回 available(只是最近一筆不再 failed 所以少了預先下載鈕)。使用者以為沒送出會再按一次。修:按下到主機接手的每個中間狀態(下載中/驗證中/已送單/主機已收單)都要有對應畫面,不可退回起始畫面;順便核 status 端點有沒有把「已送單」這個狀態露出來。
    14. 預檢結果排版(決策者 22:54 實測):預檢通過的 detail 是用分號串成一行的長字串,更新中心「更新前檢查」區整段擠成一行。修:主機寫 detail 時一項一列(或用固定分隔符),FE 拆成清單一列一項(設定檔/版本/簽章/路徑/docker/資料庫/空間/停機預估)。
    15. 停服務那一刻更新中心跳「網路無法回應」(決策者 22:54 實測):第 3 步停 api 容器到前門切 503 維護頁之間,原頁面輪詢 status 失敗,SPA 當一般網路錯誤彈訊息。維護頁本身有進度條與步驟清單(每 3 秒讀 /upgrade-progress.json),決策者手動重新整理後就看到了(22:57),缺的只是自動跳轉。修:更新中心在 view=running 時輪詢遇 503/連線失敗不彈錯,直接 location.reload() 讓前門送維護頁;維護頁完成後已會自動回原頁。決策者 23:03 按「重試更新」再次點名「一樣沒有跳轉」——立即、排程、重試三條路都要跳。
    16. 🔴 190 第二次線上更新失敗在第 4 步 post-migrate:bugsink.sh: line 101: BUGSINK_DB_PASSWORD: unbound variable(22:57,自動退回成功、1.27.0 以原資料庫起來、前門 200)。第 0~3 步全過(self_replace 2 分 22 秒、migrate 0 支待套+能力點 243 筆)。根因:升級的設定補齊分四段各自 bash install.sh --upgrade-phase <段>(lib/upgrade_apply_on_copy.sh:39 aoc_phase),config 段 ensure_bugsink_env 把密碼讀進 shell 變數,post-migrate 段是新行程、setup_bugsink → bugsink_create_db 直接用 $BUGSINK_DB_PASSWORD,set -u 炸。手動 install.sh --upgrade 同一行程跑完所以 CI 排練與 STG 升級都沒撞到。修:run_upgrade_phase 每段開頭都先 bugsink_load_env(或 setup_bugsink 自己從 $ENV_FILE 讀),並盤 post-migrate/post-switch/ops-cli 段其他「靠前一段 shell 變數」的函式(seed_ai_provider_keys、upgrade_backfill_storage_snapshot、install_vulndb)。這支在新包裡(第 4 步跑的是解開的新包 install.sh),所以要重打包才會好;驗法=本機用 --upgrade-phase 四段分四個行程跑,不是跑一次 --upgrade。 第 5 棒已修 repo(run_upgrade_phase case 前統一 ensure_bugsink_env,冪等)並把同一 patch 套到 190 解開的包(備份 /home/jedi/fr167-install.sh.bak-20261030-230145),決策者按「重試更新」驗第 5~7 步;190 跑的是手補包,正式包出來後 190 要再升一次。
    17. 失敗訊息裡的步驟名是程式代號(決策者 22:59 實測):「第 4 步 apply_on_copy 未通過,已退回 1.27.0」「第 0 步 self_replace 未通過」——使用者看不懂。修:主機 upgrade_runner.sh 寫進度檔 error 時用白話步驟名(0 換成新版維運指令/1 預檢/2 停接新工作/3 複製資料庫/4 在複本上升級/5 健康檢查/6 換接/7 清理/8 退回),FE 與維護頁顯示步驟也走同一份對照。維護頁的步驟對照表漏了第 0 步,畫面直接印 self_replace(決策者 23:07 截圖,其餘 1~7 步都有白話名);維護頁與更新中心的預檢 detail 同樣一行擠在一起(待辦 14 兩邊都要修)。
    18. 自動退回後 guidant-bugsink 容器停在 Exited(22:58 退回完 docker ps -a 看到,升級前是 Up):退回第 8 步「以升級前那份資料庫啟動 1.27.0」只起主服務清單,沒含 bugsink。修:upgrade_rollback.sh 起服務時加 $(bugsink_services) 或照 install.sh 2139 行同一份清單;順便核換接(第 6 步)起服務的清單有沒有同樣漏。
    19. 按下更新/重試後到主機開跑之間畫面沒反應(決策者 23:04:「看起來都沒反應,user 會覺得有問題」):按下到第 1 步開始約 2 分鐘(後端重驗包 26 秒 → 寫單 → systemd 收單 → 主機再驗包 50 秒),期間畫面沒有任何變化。修:按下後立即切成「已送出」卡片,依序顯示「驗證更新包中」「已交給主機」「主機驗包中」「開始升級(即將看到維護頁)」,每個中間狀態都有字與轉圈;主機收單與驗包階段要寫進度檔或更新單讓 status 端點看得到。與 13、15 合併成一條「從按下到維護頁的完整狀態鏈」一起修。
    20. 重試仍從第 0 步 self_replace 跑(23:04 實測,又花 2 分多抽檔):設計與 upgrade_order.py:330 註解都說重試「從預檢重跑」,但主機 runner 收單一律從第 0 步。第 0 步是把包內維運指令裝到主機,重試時已裝過(/usr/local/lib/guidant/VERSION 已是目標版)。修:runner 第 0 步前比對已裝維運指令版本=目標版就記 skipped 直接進第 1 步;或更新單帶 retry=1 讓 runner 跳過。
    21. 🔴 第三次實測:第 4 步 vulndb 匯入「guidant-redis unhealthy」失敗 → 自動退回也失敗,190 服務停擺(23:08~23:09,guidantai recover 待跑)。bugsink 修正已生效(④-2 過)。根因:第 3 步 dbc_config_snapshot 把 DBC_CONFIG_ITEMS=(.env guidant.env docker-compose.yml certs pki …) 整個目錄留快照、第 4 步 config 段 internal_tls.sh 重寫 certs/internal、退回 dbc_config_restore 整個目錄換回——目錄 inode 變了,但 redis/seaweedfs 容器升級期間沒停、bind mount 仍指舊 inode,容器內 /tls 變空(實查 docker exec guidant-redis ls /tls 為空),healthcheck 讀不到 CA 變 unhealthy,之後任何 compose up 都因依賴不健康起不來:第 4 步 vulndb-import 炸、退回起舊版 api 也炸。第二次實測沒撞到是因為那次退回前 config 段沒換過目錄。修(擇一或並用):① certs/pki 這類被容器 bind mount 的目錄,快照與換回改目錄內逐檔 rsync 覆寫,不搬目錄;② 第 3 步停服務把 redis/seaweedfs 一起停、退回與換接時一起 recreate;③ 退回起服務用 --force-recreate。第 5 棒已修(repo commit 見 LOG):dbc_config_restore 目錄改 dbc_restore_item 在原目錄內 rsync -a --delete(無 rsync 退 find+cp);190 以拋棄式容器實證舊法掛載變空、新法仍看得到檔;bats 87 綠。同一批一起修了 18(bugsink 偵測改先存變數再 grep,避開 pipefail)、20(第 0 步已裝版本=目標版就記 skipped,UPG_FORCE_SELF_REPLACE=1 可強制)、23(診斷包 chmod 644)。四支檔已套 190 主機 lib(備份 /home/jedi/fr167-lib-bak-20261030-232552/)與解開的包。仍要進正式包;1.27.0 已裝的客戶主機跑舊 lib 同待辦 1 問題。
    22. 維護頁在「退回失敗」終態顯示錯(決策者 23:10 截圖):進度檔 status=failed, result=rollback_failed 時,頁面仍標「更新中」、進度條卡一半、底下「更新進行中,請勿關閉主機」;步驟列 rollback 沒翻譯(併待辦 17);第 4 步失敗 detail 把最後一條 migration 進度與錯誤串成一行(「設定補齊失敗 · migration 2/2 …」)。修:維護頁 renderProgress 的 state 要多一個 rollback_failed(紅色、標題「升級失敗,自動退回也失敗」、顯示 sudo guidantai recover 指引、停掉「勿關機」提示);失敗步驟 detail 只顯示錯誤、不接前一條進度;更新中心同一終態也要對應(待辦 10 一起)。
    23. 下載診斷包 500(決策者 23:17 實測):主機 guidantai diag 以 root 產出 upgrade/diag/<job>/guidant-diag-*.tar.gz(0.3MB 產出成功),api 容器輪詢到檔案存在後讀檔 PermissionError: [Errno 13](容器內非 root、檔案 root 600 類權限)。修:upgrade_order.sh 產完診斷包 chmod 644(目錄 755)或 chown 給容器使用者;api 端讀不到時回 4xx 帶原因而非 500。
    24. 升級成功後更新中心仍顯示「1.27.1 → 1.27.1 有新版本」+「已排程在 23:27 更新/取消這次更新」(決策者 23:32 截圖)。兩個來源:①更新單同步排程一分鐘一次,前門重建(23:32:03)到紀錄同步 succeeded(23:32:50)之間畫面拿到的仍是 scheduled;②升級後 session 失效(status 23:33:04 回 401),頁面留著升級前那份回應在畫,而 last_check 仍是「以 1.27.0 身分問到 1.27.1」那筆(BE available_from 與 FE latestRelease 都有擋 latest=current,所以不是判定漏、是舊 payload)。修:換接完成時主機或後端把 last_check 清掉或立刻重查一次;維護頁偵測後端回來跳回時要帶 ?upgraded=1 讓更新中心強制重載並處理 401 導登入;更新單同步在換接後要立刻觸發一次而非等排程。
    25. Agent 推送後最長要等一個心跳週期(5 分鐘)才開始動(決策者 23:34 按推送、23:38 心跳才下發):rollout 建了但 Agent 要下一次心跳才拿到更新單,期間畫面無變化、使用者以為沒反應(與待辦 19 同一類)。修:①畫面在 dispatched 狀態明示「已推送,Agent 最晚 N 分鐘內(下次心跳)開始」並倒數;②評估主系統推送時主動通知 Agent(Agent 有 8xxx 本機 API 可敲、或 socketio)讓它立刻心跳一次,不改 5 分鐘預設。
    26. 🔴 推送 Agent 要主動通知,不等心跳(決策者 23:36 裁:「這太蠢了,後來是有通道可以進去的」,取代待辦 25 的「畫面倒數」方案)。通道就是 FR-039 的主系統→Agent 資料面(mTLS+短效 JWT,infra/remote_agent/agent_credential_client.py 的 _send 是先例、RemoteAgentAdapter._request 是 canonical),Agent 端守門 core/data_plane_auth.py 的 _PROTECTED_PREFIXES。做法:①Agent 加 POST /update/notify(前綴加進 _PROTECTED_PREFIXES,與 /detection 同級守門),handler 只呼叫既有 core/heartbeat_wake.request()(vulndb/profile 立即檢查已在用的原語)讓心跳迴圈立刻跳一次;②主系統 agent_rollout_service.push() 與自動跟進 _rebatch 寫完 rollout 後,對每台照 credential_client 的 auth 打一次 notify,連不到一律靜默降級回等心跳(Agent 離線、客戶沒開入站埠都還能用),不報錯。190 的 AGENT_AUTH_MODE=full,Agent 8443 對主機開;api 容器要能連到 agent 的 base_url(同機時是主機 IP,先驗)。Agent 側改動屬 evidence-agent repo,要另開卡(Repo 欄)。
    27. Agent 升級解包階段沒進度(23:38:46~23:4x,主機單元 activating 一分多鐘、進度檔還沒建、畫面與 journal 都無變化):guidant-agent-compose upgrade-host order 先從 1.79GB 包 tar -xzf 抽 install.sh/compose/映像再寫進度檔,抽檔分鐘級。修:收單後先寫進度檔「第 0 步 解開更新包」再抽,與主系統第 0 步同一個問題(待辦 1)。
    28. 全新安裝多一個沒翻譯的選單 lang.menu.tool-plugin-manage(決策者 2026-10-31 10:02 截圖,190「合規與稽核」底下,在「Agent 掃描工具設定」下面)。與待辦 3(role-manage,P8-7 已修)同一類病、換一個選單:主線 2026-10-29-fr166-1-tool-page-agent-credentials.sql 把 tool-plugin-manage 改名成 agent-tool-credentials;但 jedi-detection 套件 005-detection-ui-routes.sql 是「WHERE NOT EXISTS name='tool-plugin-manage' 就插」——改名後舊名不在了,套件在第二輪(主線之後跑)又插回一列舊名,enable=1,FE 沒有這個 key 的翻譯就印原文。實證 190(全新安裝 1.27.0):ui_routes id 20=agent-tool-credentials、id 120=tool-plugin-manage(兩列並存);schema_migrations 套用順序 fr166-1 19:48:41 → hide 19:48:46(此時舊名已不存在,空跑)→ 套件 005 19:48:50(插回)。DEV 只有改名後那一列,因為 DEV 從沒重放套件 005——只有全新安裝會中,CM-3344 驗新裝時抽查的是 role-manage 沒查這列所以沒抓到。1.27.2 包也會帶這個 bug(套件 005 沒改),190 從 1.27.1 升上去不會清掉既有那列。修法(擇一,照 P8-7 先例):①改套件 jedi-detection 005 的插入條件,改名後的 agent-tool-credentials 存在也不插(根治、要發套件版);②在 scripts/init/migrate-capability-grants.sql (e) 段(第三輪,唯一排在套件之後的掛點,P8-7 清 role-manage 就放這裡)加一行冪等 DELETE FROM ui_routes WHERE name='tool-plugin-manage' AND EXISTS(SELECT 1 FROM ui_routes WHERE name='agent-tool-credentials');第三輪每次升級都跑,190 升級時就會清掉。建議①+②都做:①防新裝、②清已裝客戶(190、及任何從 1.27.x 全新裝起來的)。順手掃一次「主線改名或刪除過、但某支套件仍以舊名 NOT EXISTS 插入」的所有 ui_routes 列,一次收乾淨。
    29. role-manage 幽靈選單(另一個 session 2026-10-31 轉來,請出版首腦統一處理)——1.27.2 已處理,剩根治與 190 現存一列。另一 session 查實:jedi-iam 001-iam-ui-routes.sql(第 25~26 行插、第 51 行起綁 route_capabilities)以 WHERE NOT EXISTS 在全新安裝的套件那輪插回;只有全新安裝會中,188/189 舊版升上來的順序剛好對。此根因第 4 棒已記為待辦 3,P8-7(CM-3342,ee697bab8)已修:scripts/init/migrate-capability-grants.sql (e) 段在第三輪(唯一排在套件之後的掛點)DELETE FROM ui_routes WHERE name='role-manage' AND url='/auth/role-manage';首腦 10:15 實查 1.27.2 init image 的模板與實際執行的 packages/_capability_grants.sql 都已含這行,所以 1.27.2 全新安裝不會再長出來,190 從 1.27.1 升 1.27.2 時第三輪也會清掉它現存那列(id 121,route_capabilities 隨刪)。剩下要做的:①根治套件——改 jedi-iam 001 拿掉 role-manage 的 INSERT 與綁定(另四個選單不動),發新版、主專案改釘、重跑 flatten_pkg_migrations.sh;第三輪那行 DELETE 留著當保險(已套環境改內容不重跑,靠它清)。②與待辦 28 一起盤:所有「主線改名/刪除過、套件仍以舊名 NOT EXISTS 插回」的 ui_routes 列(另一 session 點名 user-manage、tenant-manage、department-manage、ldap-config 待查;待辦 28 的 tool-plugin-manage 已是一例),第三輪 (e) 段一次補齊清理。③驗收:修好的包在乾淨環境全新安裝,ui_routes 無 role-manage/tool-plugin-manage,側欄只有「存取管理 → 角色/指派」與「Agent 掃描工具設定」。
    30. 「更新前檢查」顯示上一次升級的舊結果,看起來像這次的(決策者 2026-10-31 10:12 截圖:要升 1.27.1→1.27.2,區塊卻打勾「現行版本 1.27.0」「出貨包雜湊相符(1.27.1)」「1.27.0 → 1.27.1」,底下小字「2026-10-30 23:28 跑的結果」)。根因:FE preflightResult(progress) 只找進度檔裡的 preflight 步,沒比對進度檔的 from/to 是不是這次要升的版本,進度檔留的是上一次升級那份就照樣顯示成「通過」。決策者另點出:預檢要按更新才跑、放在開頭像是一進來就有資料,問為什麼不跟進度放一起或改彈窗。建議:①FE 判定加「progress.from==現行版 且 progress.to==目標版」,對不上一律當「還沒跑過」;②平常畫面不放這個展開區,改到「更新到 X」確認視窗裡顯示(P8-2 已做「下載完自動先跑一次只讀預檢」,確認視窗開啟時就有這次的結果;沒有就顯示「按下更新時第一步會跑」);③升級中預檢就是步驟清單第 1 步,不另列。理由:預檢的意義是「按下去之前告訴你會不會過」,放在決定要不要按的那個視窗才對得上;放在頁面上常駐,不是空的就是過期的。同一張截圖還有:「預計停機 約 3 秒」(拿資料庫複製秒數當停機,實際 190 這次停機約 4 分半,要改成依步驟加總估,或照既有規範「不寫數字、寫會看到維護頁」);「已排程在 10:10 更新」但其實已在跑(待辦 13/19,1.27.2 前端已修,這次看到的是 1.27.1 前端)。
    31. 按下更新後畫面停 3 分多鐘才開始「預檢」轉圈(決策者 2026-10-31 10:15,190 升 1.27.2 實測)。時間線:10:10:57 收單 → 10:11:58 重驗 4.9G 包通過(1 分)→ 10:11:58~10:14:17 第 0 步 self_replace(2 分 19 秒)→ 10:14:18 第 1 步預檢才開始。畫面在前 3 分多鐘完全不動。1.27.2 只修了維護頁一半:維護頁 KNOWN_STEPS 已含 self_replace(待辦 17),但更新中心頁 productUpdateState.js:14 STEP_NAMES 仍從 preflight 開始、漏第 0 步,進度檔寫了第 0 步 running、畫面沒有對應列就像卡住(第 5 棒先前回報「待辦 17 已修」只對維護頁成立,更正)。修:①STEP_NAMES 第一列加 self_replace(白話「準備新版升級程式」),running 時顯示已經過秒數;②收單後重驗包那 1 分鐘也露出來(併待辦 19 狀態鏈);③根治=縮短第 0 步本身:2 分 19 秒全花在 gzip 要讀完 5G 才抽得出幾個小檔,出包時把 guidantai/lib//release-keys/VERSION 另放一份在包外(或 tar 最前面、抽到即停),第 0 步改讀那份,秒級完成——即待辦 1 修法②,這次要真做,不只靠時限放寬。
    32. Agent 區要有每台的逐步進度(step)(決策者 2026-10-31 10:25:「至少要讓 user 知道現在跑去哪了,不然他等很久很白痴」)。現況 1.27.2 每台只一個標籤(排隊中→下發中→成功/失敗),升級那幾分鐘一直「下發中」。Agent 主機進度檔(/srv/guidant-ai-agent/upgrade/upgrade-progress.json)已有 steps[](n/name/status/started/ended/limit_s),只是心跳只帶最終 upgrade_result。定案做法:每台 Agent 下展開 8 格,重用 UpgradeStepList(不另刻):0 等 Agent 接手(已推、等心跳領單)→1 下載更新包(1.8G,帶已下載量)→2 解開更新包(P8-5 的 extract)→3 預檢→4 停接新工作→5 換上新版→6 啟動新版、健康檢查→7 清理;running 轉圈+已經過秒數、ok 打勾、failed 打叉+原因。0、1 兩格最久最像當掉(等心跳最多 5 分、下載 1.8G),一定要列,不能只列 Agent 本機那 6 步。改三處:①Agent core/update_sync.py 心跳多帶 upgrade_progress(讀既有進度檔+下載 .part 大小),升級期間心跳加快到 5 秒;②BE agent_update_rollouts 加 progress jsonb,心跳收進來寫入,agent_rollout_service.overview() 的 _agent_item 回傳;③FE AgentRolloutPanel.vue 每列可展開、下發中那台預設展開。限制:回報進度的是 Agent 自己,要 Agent 先升到有此功能的版本,下一次推送才看得到。
    33. 維護頁只有暗色(決策者 2026-10-31 10:20):public/maintenance/maintenance.css 只照抄 src/assets/_theme-overrides.scss 的暗色 :root token,主系統選亮色、升級時跳到維護頁仍是黑底。修:①maintenance.js 最前面讀 localStorage['cm_color_scheme'](主系統 layout.js 存的鍵,同源可讀)設 document.documentElement.dataset.theme,沒有值就跟 prefers-color-scheme;②maintenance.css 補 :root[data-theme="light"] 一套 token,值照抄 _theme-overrides.scss 的 light 段(兩邊改 token 要一起改,檔頭已註明);③程式放既有外掛 js(CSP 不放行 inline script)。
    34. 證據上傳要有類型白名單(決策者 2026-10-31 10:55):實查 BE 沒任何類型關卡、FE input 無 accept;預覽只有 pdf/html/png/jpg/gif/webp 直開+十種 Office 轉 PDF;影片完全沒預覽。白名單與擋下清單寫在 P9-9(CM-3354)。決策者 11:15 裁:eml/msg 收(只下載不預覽),已回寫 CM-3354。影片播放器留第二期。
    35. Agent 區跑成功後 8 格仍常駐展開(決策者 10-31 16:28):✅ 已修 FE a4126e2b(成功自動收起、失敗保留),進 1.27.5。
    36. 更新中心目標版號被上一張已成功的更新單蓋住(決策者 10-31 16:38:查到 1.27.4 畫面與按鈕仍 1.27.3):✅ 已修 FE 13ef3ecc(targetVersionOf:單還在走才以單為準),進 1.27.5。
    37. 下載完畫面退回起始、按下到主機開跑之間沒反應(決策者 10-31 16:47):✅ 已修 FE 30addad1(scheduled 且時間已到=submitted;整張卡蓋遮罩+五格狀態鏈),進 1.27.5;升級前那版前端顯示,1.27.5→1.27.6 才看得到。
    38. 🔴 客戶主機 apt 裝了新核心沒重開 → docker 29 預設 seccomp 在舊核心 errno 524:帶 no-new-privileges 的容器起不來、exec 全炸、exec 式健康檢查全 unhealthy。188 STG(跑 -187)/189 POC(跑 -171)都中、已裝 -202、reboot-required 亮著;190 跑 -198 正常是對照組。升 containerd.io/runc 無效(189 實升 2.4.2/runc 1.5.2 無效),重開機即解(189 17:31 重開後 9 容器全 healthy;188 17:36 重開)。要進:①升級預檢加「reboot-required 存在或跑的核心 < 已裝核心 → 擋並指路先重開」+「實測 docker run --security-opt no-new-privileges --entrypoint true <base>」;②手冊主機層依賴與升級章加「安裝/升級前 apt 更新到底並重開一次」;③check_environment 同一條。memory feedback_seccomp_errno524_is_stale_kernel_reboot_not_runc。開卡時機:P9 收尾後另開。
    39. Bugsink 管理員密碼全客戶同一組(FR-133 D5 刻意取捨;決策者 10-31 17:0x 問起):出包時從 CI 變數烙進包內 bugsink-admin.secret,每台裝同一組,任何一台外洩等於全部外洩。建議改每台隨機產生、原廠取得走不印明文的路(一次性重設或 LC 通道)。屬方案取捨,另開卡,不擋本輪。
    40. 誤刪 188 /home/jedi/guidant-ai-1.26.0(首腦 10-31 12:xx 清磁碟時,以為是解開的舊包,實為 STG compose 工作目錄):已從同目錄 1.26.0 tar.gz 重建(compose 與 /srv 那份 cmp 相同),資料庫未受影響。教訓入 memory:刪目錄前先 docker inspect 全部容器的 working_dir/bind mount。
    41. Agent 列 expander 箭頭在沒東西可展開時仍顯示(決策者 10-31 18:05):PrimeVue expander 欄整欄固定畫箭頭;rows 空時要用 #body slot 依 stepRowsOf(data).length 決定畫不畫(BodyCell 的 rowtogglericon slot 可參考)。決策者裁「先不要動」,demo 後再修。
    42. 【第二期】使用者刪掉 bundles/<版>/agent/ 後推 Agent(決策者 10-31 18:10 問,裁併第二期):現況安全——overview bundle_ready=false、按鈕全灰、412008;下載途中被刪 Agent 拿 404 記失敗。不夠好:①文案「這一版的更新包沒有附 Agent 安裝包」把「被刪」說成「沒附」,要分兩句;②沒有復原路徑(同版重下被擋),要讓現行版能單獨重抓 Agent 包——與待辦 6「Agent 單獨更新」同一件事,第二期一起做。
    43. Agent 升級 cleanup 沒清舊映像:190 留 guidant-ai-agent 1.4.3~1.4.7 五顆各 4.23G(第 7 棒 18:30 docker images 核實)。demo 後收。
    44. 🔴 下載 100% 到遮罩之間 37 秒空窗,「更新到 X」按鈕仍是活的(決策者 10-31 18:25:「為什麼不能 100% 就直接開遮蔽」「中間還是會被 user 到處按、可以再按一次升級」「停了很長一段時間我以為你又沒做好」)。第 7 棒用 190 的檔案 mtime+DB 列+journal 對出時間軸(1.27.6→1.27.7):18:17:00 下載完 → 18:17:17 worker 算完第 1 次整包 sha256 寫 ready(畫面退回就緒卡、按鈕亮)→ 18:17:37 apply_after_download 寫單前再算一次整包 sha256(_enqueue→verify_ready_path→verify_package_file)才寫單變 scheduled/submitted(遮罩才出現)→ 18:18:33 主機撿單驗包第 3 次 → 18:18:59 預檢第 4 次。輪詢沒斷(第 6 棒修正有效),洞在後端把 ready 當中途狀態寫 DB、前端照字面畫就緒卡,沒看這張單是「更新到 X」建的(applied_by 有值)。修法三處:①FE deriveView:ready 且 applied_by 有值、無 error、無 cancelled_at → 視為 submitted,遮罩從 100% 那刻蓋上(可熱換 190 驗);②BE apply:同條件再按回 412「已在處理」,不寫第二張單;③BE run_download:下載完剛驗過,寫單前不重算雜湊(把驗過結果傳給 _enqueue),主機撿單與預檢兩次也可併一次,「按下到開跑」約 80 秒可縮到約 30 秒。決策者 18:35 裁「記錄或開卡」→ 先記這裡,demo 後開卡。
    45. 側欄殘留 lang.menu.tool-plugin-manage(決策者 10-31 18:50,188 升 1.27.7 後截圖):伺服器端乾淨——第 7 棒用 blsadmin 實打 188/190 /user/web-menu,都只回 agent-tool-credentials,ui_routes 也沒有舊列(P9-5/P9-7 有效)。殘留在瀏覽器:FE userStore.permissions(側欄樹)隨 cm_store 進 localStorage,只在登入/OTP/切租戶/開通授權時重抓 API.WEB_MENU,F5 與升級後 ?upgraded=1 重載都拿存檔那份。修法:頁面載入時比照 ensureCapabilities 重抓一次 WEB_MENU(或把 permissions 排除在 persist 外)。當下解法:登出再登入。
    46. 角色頁能力點顯示 system.product-update.read/update 原始 key(決策者 10-31 18:52):FE permission-tree.json(zh-tw/en)的 capability.system/permission_resource.system/capability_how.system 三段都沒有 product-update,capabilityLabel 查不到就回 name。補三段各兩筆(中文取 core/host_capabilities.py:214-215)。
    47. 🔴 CRA 框架頁「原始 PDF 檔已遺失」(決策者 10-31 18:55):1.27.7 包 storage-seed/ 只有 10 檔(兩支 CMMC PDF+八支 TWGCB),少 20261014000000_b81c42ff-….pdf。根因:188 /opt/guidant-ai-be/.build/storage-seed/ 是 8 月 21 日的舊殘留(10 檔),build_bundle.sh ⑥ 段「已存在且非空時不動」讓它贏過 10 月 30 日攤平的 .build/pkg-assets/(11 檔、含 CRA)。套件 jedi-oscal-v2 2.9.0 的 assets/storage-seed.map 三行都對,問題只在 build 機殘留。188/190 bucket 都沒有這支(188 升級補灌 10 個、190 同)。修法:①188 刪 .build/storage-seed/ 讓它從 pkg-assets 重建,build_bundle.sh 改成「pkg-assets 比 storage-seed 新就覆蓋」或乾脆每次重建(守門改 fail-fast:map 列數 ≠ 攤平檔數就擋);②188/189/190 當下補救=把那支 PDF 丟進 bucket(對 STG/POC 是寫入,等令);③下一包 1.27.8 帶齊。
    48. 🔴 拿掉發布清單 90 天有效期檢查(決策者 10-31 20:00 裁「就 1」):現況 package_verifier.py MANIFEST_VALID_DAYS=90,簽發超過 90 天的清單主機拒收;客戶拖三個月或離線檔放著就裝不了,原廠得每 90 天重蓋章。決策者裁拿掉,理由:重放舊版已由「版號只能往上+主版號相同+主機公鑰目錄」三道擋住,要廢某版走更新站 withdraw 或輪換公鑰。改兩處要一起:主系統 verify_manifest 的有效期分支(含 EXPIRED 錯誤碼與測試)+主機 scripts/installer/lib/release_keys.sh/預檢第 1 步若有同一條檢查;update-center planPath 若有看 issued_at 也查。issued_at 欄位保留(紀錄用)。demo 後開卡。
    49. 主系統沒打更新站 POST /v1/report(第 7 棒 20:10 grep 證實,決策者裁記待辦):更新站 handleReport 與 instance_version_reports.last_upgrade_* 欄位都做好了,後台版本頁也用它算「幾台退回/失敗」,但 BE update_site_client.py 只有 check/download_url/ops_download_url,沒有 report。現況原廠只能從 check 看到客戶「現在幾版」(每 6 小時),看不到「升級成功還是退回」。補法:update_site_client.report(license_text, fingerprint, ticket, result, from, to, at),在 upgrade_order.after_switch/sync_from_progress 寫回終態那一刻打一次(成功、rolled_back、failed、skipped 都報),連不到只 warning 不擋。demo 後開卡。
    50. PM 簡報收進 FR 資料夾(決策者 10-31 20:45:「這個簡報到時候也把它放到我們的 FR 裡面」):簡報 https://claude.ai/artifact/1HqiRVDJkGsJCsKeGiEBfU 10 張(封面、做了什麼、架構、出版流程圖、簽章圖、五件確認、升級八步圖、狀態、資料不掉、服務架構圖;第 11 安全對照與第 12 待補已拿掉,內部知道就好)。原始檔在本 session scratchpad artifact-files/0259ebe7-…/project/(scratchpad 會清,要收時從 artifact read 回來)。落點建議 docs/features/FR-167-2610-online-update-channel/briefing/,照 doc-site-build skill 進需求站;收尾一併做,等令。
    51. 🔴 Agent 區落後三版仍顯示「已是最新」(決策者 10-31 20:48,189 截圖:兩台 Agent 1.4.2、包是 1.4.7):根因=走 install.sh --upgrade 時包解在 /home/jedi/guidant-ai-1.27.7/,<資料目錄>/upgrade/bundles/ 不存在,agent_rollout_service._bundle 找不到 → target_version=None → is_lagging 看到目標空回 False → 畫面全「已是最新」(§3 契約早寫「install.sh --upgrade 時 Agent 不會跟進」,但畫面不該說最新)。修法:目標版未知時 lagging 回 null、bundle_ready=false 時畫面顯示「無法比對(這一版的 Agent 安裝包不在升級目錄)」並說明怎麼補;順手修待辦 42 ①文案(「被刪」≠「沒附」)。188/189 當下要能推 Agent:把 /home/jedi/guidant-ai-1.27.7 搬或 symlink 到 /srv/guidant-ai/upgrade/bundles/guidant-ai-1.27.7(改 STG/POC,等令)。
    52. CRA 繁中舊版本列 2024/2847-zh-TW 出現在框架清單(決策者 10-31 20:46):全新安裝沒有(基線庫、DEV、init seed 都只有英文版);升級路徑有——jedi_oscal_v2 007(10/13 建繁中版)→ 011(10/15 併進英文版翻譯表、繁中版標 deprecated 不刪)→ 188/189/190 三台都留一列 deprecated,前端清單沒濾。修法:①migration 驗無資源庫/專案 catalog 掛在那列(011 已改掛英文版)後刪 framework_version+catalog;②API/FE 清單一律濾 deprecated 當保險。
    53. Agent 1.4.2 的 SeaweedFS 程序洩漏(第 7 棒 21:15 升 189 兩台 Agent 時發現):跑三週後 seaweedfs 容器 PID 15,360/18,478、健康檢查 can't fork: Resource temporarily unavailable,容器 PidsLimit 未設。升 1.4.7 重建後 PID 22/18。要查:①是 seaweedfs 4.48 本身還是 Agent 打它的方式(心跳每次開連線不關?);②compose 加 pids_limit;③一週後回看 121/167 的 PID 有沒有再長。屬 Agent repo,另開卡。
    54. 三台主機指紋相同(第 7 棒 23:21 看更新站回報表):188/189/190 授權編號各異,fingerprint 都是 ff793254d00c…。三台是同一範本複製的 VM,指紋若取 machine-id/MAC 之類會撞(memory feedback_container_machine_id_empty_fallback_mac_drifts 相關)。影響:更新站統計與封鎖名單按指紋會誤殺;授權檔本身綁指紋也會互通。要查指紋算法與這三台的來源欄位,屬 jedi-license-runtime,另開卡。
    55. PM 會議 2026-10-31 機制問答報告:https://claude.ai/artifact/AmUhtjZVptzoqExGEUhjhx (Q6/7/8/9/11~19、Q5+20 備份現況、待討論四條;私人,分享給 PM 要從 Share)。與簡報(待辦 50)一起收進 FR 資料夾 briefing/,收尾做。PM 會議 B 類(私鑰保管、本體與 Agent 分開更新、Agent 主控台更新中心、PG 引擎大版升級)決策者裁「先不討論」,報告末段已列。
    56. Agent 升級結果回報更新站(P11-1/P11-6)本輪驗不到真環境(第 8 棒 02:20):三台 Agent 都是 1.4.7、1.27.9 包內 Agent 也是 1.4.7,更新中心沒有新版可推(同版 412 擋)。要驗 agent_version_reports 得等下一版 Agent 包(或出一個 1.4.8 只改版號)。程式面已核:欄位名、指紋 regex、終態值兩邊一致;BE test_fr167_agent_rollout.py 97 行含送達才寫 reported_at。
    57. Agent 主控台「檔案」頁把預覽 PDF 快取當證據列出、名稱只顯示一串 ID(決策者 2026-11-01 11:2x 在 121 看到兩列 45a7b531-…、89fc9235-…):根因在 jedi-file-upload minio_adapter.convert_to_pdf——轉好的 PDF 另寫一列 upload_files,file_name 填存檔名去掉 .pdf(=原檔存檔 ID,不是原檔名)、storage_scope 走預設 customer,只有 ref_id 指回原檔。Agent 主控台檔案清單(guidant_agent/files/adapters/customer_files_repo.py 只濾 storage_scope=customer)照列,總數與佔用量也多算。原檔都還在(121 實查 20261101011429_<id>.docx 兩個 + 兩個 .pdf 快取)。主系統證據畫面走關聯表、不受影響。修:①Agent 三個查詢(清單、數量、佔用)加 ref_id IS NULL,Agent 一處即可;②(選)套件把 file_name 改「原檔名.pdf」,牽動主系統共用套件,另發版。決策者裁「先不用,記錄下來」。
    58. 🔴 主系統與 Agent 要分開更新(決策者 2026-11-01 12:2x 裁:「這邊之後要改成主系統跟 agent 要分開更新」,在 189 推 Agent 1.4.8 時說):現況 Agent 包只能隨主系統包出,修一個 Agent bug(本日 1.4.8 Office 預覽)也得出整包主系統 1.27.10、客戶要先停機升主系統才推得到 Agent。原本列在 PM 會議 B 類「先不討論」、design 標第二期,決策者已改判要做,待開討論稿/開卡。要碰的:更新站多一類成品(Agent 版本線、R2 agent/ 路徑、清單簽章 payload_type)、主系統更新中心 Agent 區「檢查 Agent 新版/下載 Agent 包」不經主系統升級、bundles/<主系統版>/agent/ 改成獨立的 agent-bundles/<Agent 版>/、min_agent_version/相容矩陣兩向檢查、離線單一檔也要能單出 Agent。決策者 2026-11-01 12:4x 補需求五點並裁「下階段要討論,也要開始做」:①主系統與 Agent 不再包在同一包 ②各別更新 ③Agent 也要有更新中心(離線上傳、或向主系統發動更新需求)④R2 安裝包分開 ⑤不再用心跳帶資料。需求紀錄:docs/draft_requirement_spec/2026-11-01-agent-independent-update.md(現況、心跳夾帶 8 種盤點、每條要碰的地方)。
    59. Agent 區升級途中 8 格永遠停在第 1 格「等 Agent 接手」(決策者 2026-11-01 12:28 在 189 推 1.4.8 時看到):BE P9-6(180b30904)把拉到的進度放在 overview 每台 agent 的 item["progress"],FE P9-10(fc08e549)讀 agent.rollout?.progress,兩張同批平行做、欄位位置從一開始就沒對上;成功時 FE 直接全打勾不看進度,所以 10-31 在 190 看結果時沒發現。升級、結果、回報不受影響(121 成功、60.167 失敗都正確記錄並回報)。修:FE agentRolloutState.js 改讀 agent.progress(一行),或 BE 把 progress 放進 rollout;加一條契約測試讓兩邊對同一份形狀。順帶:60.167 失敗「無法讀取新映像」=主機升級單第 0 步 docker create --network none guidant-ai-agent:1.4.8 失敗(映像已 load、121 同包同步驟過),疑主機 docker/核心問題,決策者在該機查。
    60. Agent 主控台 CINC 的 Profile 下拉是空的(決策者 2026-11-01 12:5x,121 實測):主系統只同步「檔案型」Profile 給 Agent;CINC 兩支 dev-sec 在 189 登記為「網址型」(GitHub),沒有檔可同步,121 本機只有 GCB 8 支 TWGCB。GCB 下拉正常、CINC 退回文字框(文案「這台還沒收到同步的 Profile」對 CINC 是準的)。兩條路:A 主控台也列網址型(心跳/新通道帶名稱與網址,要出版);B 網址型改由主系統先下載再同步(封閉網路也能跑,但主系統要連外,改設計)。決策者裁「先不動,要 demo」,併入 Agent 獨立更新那輪討論。補查(12:5x):①189 主系統登記網址型時有下載過(解析出控制項 Linux 59/Windows 431,extraction_status=succeeded),但解析完不留檔(file_id 空),所以不同步——合理修法是網址型解析時順便存檔、當檔案型同步給 Agent(B 方向,不需主系統常態連外)。②決策者記得「以前可以下拉」:查 FE 歷史,Agent 主控台這欄從 FR-166 P2-3(10-27 6c608601)出生就是文字框,下拉一直只在主系統檢測頁(FR-059 08-01 78f8e073),不是 FR-170 重構弄壞的。③demo 應急:首腦把 dev-sec 兩支放到 121 Agent /data/content/cache/manual/{linux,windows}-baseline(/data/content 唯讀、cache 可寫、為資料卷,重建容器不掉),cinc-auditor check Valid;主控台 CINC 欄貼該路徑可跑,不進下拉。這兩個目錄是手放的、不在同步清單,日後修好待辦 61 後可刪。
    61. 升級換接後 redis/seaweedfs/bugsink 的 compose 標籤仍指舊目錄(第 9 棒 11-01 清 188 時發現):線上升級不重建這三個,working_dir/config_files 標籤留在升級前的解包目錄(188 現指 /home/jedi/guidant-ai-1.27.7),舊目錄一刪下次 compose 操作就變孤兒。修:第 6 步換接或第 7 步清理對不重建的服務也 compose -f <新目錄> up -d --no-deps(不重啟、只換標籤),或清理時把舊目錄留到下一次升級。併下一版。
    62. 更新站後台「Agent 在版/Agent 退回/Agent 失敗」三欄永遠 0(文件棒 11-01 查到,首腦核過 update-center/src/releases.ts:378-380):拿 Agent 版號(1.4.x)比主系統版號(1.27.x),兩條版本線永遠不相等。回報本身正確,只有後台三格不準。決策者裁:記待辦、等 FR-172(Agent 獨立版本線)一併處理,不另開卡。
    63. 收尾小碎片(文件棒 11-01 核對時查到,收尾一起做):①BE PUT /system/product-update/auto-check 與 status 的 auto_check_enabled FE 沒接,留或拔待裁;②FE i18n product_update.intro(寫「每天一次」,實際每 6 小時)與 offline_hint(舊兩檔說法)兩個鍵已無人引用,可刪;③錯誤碼 PRODUCT_UPDATE_400002(清單過期)驗證已不拋,BE 與 FE 翻譯可一起拿掉;④onprem/README.md、agent/README.md 手冊變更紀錄各補一行(這次只改章節頁);⑤正式 publish 路徑不帶 ops_sha256/ops_size(CI register-draft 丟掉、D1 無欄)且 publish 完仍印「90 天到期」提示,正式出版前要補。
    64. 更新單 failed+進度檔 result=unchanged 時前端有重試鈕、後端回 412(文件棒 11-01 查到):FE canRetry 對這組合顯示重試,BE retry 只收 rolled_back/skipped。會落到這組合的是開機檢查或 recover 判「斷在第 3 步之前」(upgrade_rollback.sh:306-311)。修:BE retry 放行 failed 且 result=unchanged(系統沒動過、包還在)或 FE 這組合改顯示「重新下載」。併下一版。
    65. (本棒即時回饋收集區:決策者 2026-10-30 指示「聽到回饋先記錄、晚點一起修」,新回饋往下加編號,不單獨修。)

190 全新安裝 1.27.0 後看到的問題(決策者裁:先測更新,功能問題晚點處理)

  • 多一個沒翻譯的選單 lang.menu.role-manage(租戶與組織 → 存取管理旁)。根因:主線 2026-10-07-fr132-access-management-menu.sql 刪掉舊 role-manage,但 jedi-iam 套件 001-iam-ui-routes.sql 以「不存在才插」在第二輪又插回來;全新安裝才會出現,DEV 與既有安裝沒重放 001 所以看不到。修法待定:套件那支不再插 role-manage,或主線補一支空操作刪除在套件之後。
  • 角色詳細頁打開就錯(/access/roles/<uid>):GET /api/1.0/ui-routes 500,ValueError: capability 缺 license_module,宣告漏填(不可退回 resource_type)。全新安裝有能力點的 license_module 是空的;同屬「全新安裝才有」的資料缺口。角色本身資料正確(role_capability_patterns 與範本一致;role_capabilities 是退役表,0 筆正常)。
  • 這兩件與 1.27.0/1.27.1 的更新流程無關,第二輪換版後一起查。

開發期全部收完,已合回 feature 分支

  • 批 14~17 十張功能卡(含工作坊首腦-3 補開的 CM-3316 更新站 min_agent_version、CM-3317 Agent compose 包旁 .notes.json)全過驗、全合回;決策者 16:10 按完 Done。四 repo merge --no-ff 零衝突。
  • CM-3312(test e2e 綁 v2)暫緩:程式已寫完 commit,只差「對 v2 版面實跑 @product-update」,留 190 測試期。
  • BE 守衛 test_module_boundaries 兩紅(jedi_password 無層號/未接 plugins)是 FR-170 合回帶進來的既有紅(合回前同 commit 一樣紅),屬 FR-170 CM-3315 範圍,不是本案。
  • 新 migration 2026-10-30-fr167-agent-follow-optional.sql(CM-3306)DEV 已套已登記;出貨基線待重產清單再加這一支。

DEV 測試環境(首腦起在背景,下一棒沿用即可)

  • DEV 授權是落地版(config.tenant_licenses id 5087,本機 LC DEV 簽、綁本機 Mac 指紋、帶身分票),決策者裁維持,不改回 SaaS(§5)。原 SaaS 照 id 43 停用。
  • BE 8000 與 worker 16:15 已重啟到合回後的程式,都帶 UPDATE_SITE_URL=http://127.0.0.1:8788、GUIDANT_RELEASE_KEYS_DIR=~/Projects/Billows/Audit-Manager/.fr167-dev/release-keys、GUIDANT_UPGRADE_DIR=~/Projects/Billows/Audit-Manager/.fr167-dev/upgrade。測試資料夾已從 scratchpad 複製到 ~/Projects/Billows/Audit-Manager/.fr167-dev/(不會被清;含假站 log、授權換照 SQL、公鑰 7fa0a0746b2f8327.pub)。重啟任何一支都要帶這三個變數,worker 漏帶會讓下載驗章失敗。stdout 在 BE log/fr167-api.out/log/fr167-worker.out。
  • 假更新站:test repo site-regression/support/update-site-stub.js 在 8788(每次重啟換一把臨時章,要清舊 .pub 再重塞版本);目前塞 1.27.0。License Center DEV 在 5062(PYTHONPATH=src 才起得來)。
  • DEV product_update_jobs 現在最新一筆是 ready(1.27.0 包在 fr167-dev/upgrade/incoming/),決策者可直接按「更新到 1.27.0」試排程與立即;立即後畫面會停在已送出,mac 沒有主機升級程式,正常。

FE:已接新契約(CM-3311),ProductUpdateService.apply 直接送 with_agents/agent_uids,SEND_AGENT_FOLLOW 旗標已拆掉。決策者 FE dev 要自己重啟才吃到。

未 push:BE 領先 origin 29、FE 4、update-center 3、evidence-agent 6(含 FR-170 的)、jedi 18(FR-170 的)、test 1。

已知紅燈:test_module_boundaries.py 在另一 session 重產基線後已全綠(2abba2b3d)。BE 13 個 PRODUCT_UPDATE_* 錯誤碼 FE 仍沒翻譯。

雜項:BE repo stash@{0}(CM-3273 security-report 產物)仍在,確認不需要可 drop(stash@{1} 是 FR-075 的,別動)。Agent 側卡的 venv 改用 evidence-agent-knWYPLiu-py3.13(FR-170 P0 後,舊 7jojxvJC import 會失敗);FR-170 的 CM-3314 會把 FR-167 的 core/update_sync.py 改成 WorkerComponent,本案不再碰那支與 core/enroll.py 心跳迴圈。

§2 批次總表

批 卡 repo 做什麼 狀態
1 CM-3242 P1-1 BE 升級骨架:guidantai upgrade/recover、先換成新版的自己、lib 空殼、進度檔 Done
1 CM-3243 P1-9a BE 出包產未簽的 release.json Done
1 CM-3244 P1-3a jedi jedi-remote-agent 心跳契約(dispatch_gate、update、upgrade_result);發 1.10.0b1 Done
1 CM-3245 P3-1 BE 能力點、更新中心選單路由、預設角色授權(migration) Done
1 CM-3246 P1-8 FE 前門維護頁(nginx 503 → maintenance.html 讀進度檔) Done
1 CM-3247 P2-1 update-center TS Worker 骨架、D1 六表、客戶端三端點、WebCrypto 驗授權檔 Done
1 CM-3248 P2-5 license-center 授權檔 payload 加 product_major Done
2 CM-3249 E-1 BE 主 repo 釘 jedi-remote-agent==1.10.0b1 Done
2 CM-3250 P1-2 BE 預檢:空間、版本路徑、DB、驗清單簽章 Done
2 CM-3251 P1-3c BE draining 旗標、輪詢進行中數、時段結束放棄 Done
2 CM-3252 P3-2a BE product_update_jobs 表、模組骨架、DI Done
2 CM-3253 P2-2 update-center Access 守門後台端點、CI token 只能登記草稿、後台頁 Done
2 CM-3254 P2-3 update-center CLI guidant-release:init-keys 一正一備、publish、withdraw、rotate-key Done
3 CM-3255 P1-3b BE 主系統接 draining:worker 不撿單、心跳不派任務 Done
3 CM-3256 P1-4 BE 停服務、複製資料庫到 pgdata-next、compose 卷吃變數 Done
3 CM-3257 P1-5 BE 在複本上升級:載映像驗雜湊、migrate 進度轉寫 Done
3 CM-3258 P2-4 BE CI 出包後 register-draft、傳 R2 Done
3 CM-3259 P2-6 BE DEV 公鑰隨包、裝到 /etc/guidant/release-keys/ Done
3 CM-3260 P3-2b BE 發現新版與下載:更新站 client、每日排程、五道驗章、離線上傳 Done
3 CM-3261 P3-3 FE 更新中心頁 Done
4 CM-3262 P1-6 BE 健康檢查、換接(複本轉正、原份留快照、前門最後重建) Done
4 CM-3263 P3-2c BE 更新單端點、systemd path+service、排程、全站提醒端點 Done
4 CM-3264 P3-4 FE 有新版橫幅、更新前 30/5 分提醒 Done
5 CM-3265 P1-7 BE 自動退回、開機檢查、guidantai recover Done
5 CM-3266 P1-10 BE 收尾清理、診斷包 Done
5 CM-3267 P3-2d BE 跨版兩段 Done
5 CM-3268 P4-5 agent Agent 升級每步時限、進度檔、自動退回;邏輯進 install-lib/ Done
6 CM-3269 P1-9b BE CI 跨版排練(190 裝舊版+STG dump 再升級) Done
6 CM-3270 P4-2 BE Agent 跟進主系統側:agent_update_rollouts、先推 1 台、心跳下發 Done
7 CM-3271 P4-3 agent Agent 跟進 Agent 側:下載驗 sha、升級單、開機退回 Done
7 CM-3272 P4-4 FE 更新中心 Agent 跟進區;notice 全站提醒、診斷包 gzip、錯誤碼翻譯 Done
8 CM-3273 P5-1 BE 手冊升級章、防火牆放行、資安例外登記、預檢補 python3 Done(已合回)
8 CM-3274 P5-2 BE SPEC system-admin/product-update.md Done
8 CM-3275 P5-3 test e2e 更新中心頁(離線上傳標 @known-bug) Done
8 CM-3276 P5-5 BE 結案:發正式版、釘正式版、PROD 印樣守門、網域 Done
9~13 CM-3293~3302 多 repo 開發期收完後的修正(更新站身分票 A 案等,見 LOG 第 3 棒) Done
14 CM-3306 P7-1 BE Agent 跟進可選(apply 多 with_agents/agent_uids)、手動推送可排程、稍後提醒 7 天;migration agent-follow-optional Done
14 CM-3307 P7-2 BE 「更新到 X」沒包也能送:apply 先下載、就緒後才寫更新單;下載中/排程中再按回 412005 Done
14 CM-3308 P7-3 BE release.json 加 min_agent_version;make_offline_bundle.sh 產單一離線檔 Done
14 CM-3309 P7-4 agent gen_agent_manifest 讀 RELEASE_NOTES.md 寫 manifest notes Done
15 CM-3310 P7-5 BE 上傳收單一離線檔、status 帶最近成功升級時間、Agent 概覽帶最低相容版/說明/提醒、紀錄合併 Done
16 CM-3311 P7-6 FE 接新契約:必須更新紅色路徑、Agent 排程與稍後提醒改後端、離線單一檔、紀錄合併 Done
16 CM-3313 P7-8 BE design D16 改可選、SPEC 更新中心頁照 v2、手冊離線改單一檔 Done
17 CM-3312 P7-7 test e2e 頁物件改綁 v2(程式已 commit 0f292b9,差實跑) 暫緩
17 CM-3316 P7-9 update-center min_agent_version 進 register-draft/D1 0003/publish 蓋章 Done
17 CM-3317 P7-10 agent compose 包旁產 guidant-agent-compose-<版>.notes.json Done
18 CM-3336 P8-1 BE 主機升級程式:第 0 步時限依包大小、0~2 步失敗記 skipped、步驟白話名、預檢分列、換接後寫 last-switch.json Done
18 CM-3337 P8-2 BE 後端:status 露出 submitted、換接立即同步+重查新版清 last_check、診斷包讀不到 412、預先下載後先跑預檢 Done
18 CM-3338 P8-3 FE 更新中心頁:按下到維護頁狀態鏈、輪詢失敗自動跳維護頁、失敗終態停輪詢、步驟白話、預檢分列、?upgraded=1 重載、「立即」文案問決策者 Done
18 CM-3339 P8-4 FE 維護頁:rollback_failed 終態、self_replace/rollback 白話、detail 分列、跳回帶 ?upgraded=1 Done
18 CM-3340 P8-5 agent POST /update/notify(guidant_agent/sync/,守門同 /detection)+升級解包先寫進度 Done
19 CM-3341 P8-6 BE rollout 轉 dispatched 時走 FR-039 mTLS 主動打 Agent notify,連不到靜默回等心跳 Done
19 CM-3342 P8-7 BE 全新安裝缺口:role-manage 幽靈選單、能力點 license_module 回填、排練基底 1.26.0→1.27.0(問決策者) Done
20 CM-3343 P8-8 BE 文件同步:SPEC/手冊/design §5、13 個錯誤碼 FE 翻譯 Not started
21 CM-3344 P8-9 BE 結案:本機驗新裝+升級 → 版號 1.27.2 → 188 出包(簽清單/發布/190 升級/刪繞道由首腦做) Done
22 CM-3346 P9-1 BE B:出包另產 ops.tar(維運指令+維護頁),第 0 步秒級抽、維護頁隨第 0 步換新(A 主機半) 驗收通過待確認(已合回 feature、已 push)
22 CM-3347 P9-2 BE D:build_all --reuse-images 快速出包、三道 CI 前提進腳本、版號不烙 C 碼 驗收通過待確認(已合回 feature、已 push)
22 CM-3348 P9-3 FE A FE 半+30/31/33:步驟補第 0 步、預檢進確認視窗比對版本、停機不寫秒、維護頁亮色+nginx try_files 驗收通過待確認(已合回 feature、已 push)
22 CM-3349 P9-4 agent Agent 開唯讀 GET /update/progress 回升級逐步進度與下載量(守門同 notify);心跳不改(決策者 10/31 裁改拉) 驗收通過待確認(已合回 feature、已 push)
22 CM-3350 P9-5 jedi jedi-iam 001 不插 role-manage、jedi-detection 005 不插 tool-plugin-manage;發 1.11.1/1.7.1 驗收通過待確認(已合回 feature、已 push)
22 CM-3356 P9-11 FE Dockerfile 分層:npm install 獨立一層在 COPY . . 前、加 .dockerignore(不排 .git);只改程式不重裝套件(第 6 棒補開,另一 session 清 188 時發現) 驗收通過待確認(已合回 feature、已 push)
22 CM-3354 P9-9 BE 證據上傳只收文件與圖片:副檔名+檔頭白名單(zip/影片/執行檔擋),清單放 jedi-file-upload port,FE 讀端點 驗收通過待確認(已合回 feature、已 push)
23 CM-3351 P9-6 BE overview 對下發中那幾台並行拉 GET /update/progress 回 progress(記憶體快取、不加表不加 migration);FE 8 格另開 fe 卡 驗收通過待確認(已合回 feature、已 push)
23 CM-3355 P9-10 FE Agent 區每台展開 8 格(重用 UpgradeStepList,吃 P9-6 progress);五個證據上傳入口 accept 讀 P9-9 端點、新錯誤碼翻譯(第 6 棒補開) 驗收通過待確認(已合回 feature、已 push)
23 CM-3352 P9-7 BE 改釘兩套件重攤平、第三輪刪 tool-plugin-manage、出包前幽靈選單比對、升級後只留安裝包;build_all 出包成功後 builder prune --keep-storage 20G(從 P9-2 移來) 驗收通過待確認(已合回 feature、已 push)
24 CM-3353 P9-8 BE 結案:本機驗 → 1.27.3/1.4.6 正式包 → --reuse-images 出 1.27.4/1.4.7 第二包 Done(決策者 10-31 15:45)
25 CM-3358 P10-1 BE 待辦 44 BE 半:寫單前不重算整包雜湊、「更新到 X」建的單就緒後再按回 412 Done
25 CM-3359 P10-2 FE 待辦 44 FE 半+45+46+51 FE 半:下載 100% 即蓋遮罩、側欄每次載入重抓、product-update 能力點翻譯、Agent 目標版未知顯示「無法比對」 Done
25 CM-3361 P10-4 BE 待辦 47:出包 storage-seed 每次從套件 assets 重建+筆數守門 Done
25 CM-3362 P10-5 jedi 待辦 52:jedi-oscal-v2 027 刪 CRA 繁中 deprecated 列(驗無掛載)+清單濾 deprecated;發 2.9.1 Done
26 CM-3360 P10-3 BE 待辦 48+38:拿掉清單 90 天有效期;預檢加核心沒重開檢查+手冊(與 P10-1 同改 error_code 檔,故下一批) Done
27 CM-3363 P10-6 BE 待辦 49+51 BE 半:補打更新站 /v1/report;目標版未知 lagging 回 null Done
27 CM-3364 P10-7 BE 主專案改釘 jedi-oscal-v2 2.9.1、重攤平帶進 027、DEV 套 Done
28 CM-3365 P10-8 BE 結案:本機驗 → 1.27.8 → 188 出包(開包驗 storage-seed 11 檔含 CRA PDF);簽發/三台升級/補灌 PDF 由首腦做 Done(決策者 01:11)
29 CM-3366 P11-1 update-center PM #2 更新站半:report 收 target=agent+agent_fingerprint、新表 agent_version_reports、後台 Agent 統計 Done(2026-11-01)
29 CM-3367 P11-2 FE PM #10 文案「這一版更新了什麼」→「更新內容」 Done(2026-11-01)
29 CM-3368 P11-3 FE PM #21 支援頁文案精簡、內容清單收進 Accordion Done(2026-11-01)
29 CM-3369 P11-4 BE PM #17 升級進度檔每步回寫 system_logs(新事件碼段、只寫一次) Done(2026-11-01)
29 CM-3370 P11-5 BE PM #22 診斷包收 upgrade/install log 最近三支+last-switch.json Done(2026-11-01)
30 CM-3371 P11-6 BE PM #2 主系統半:Agent 升級結果打 report(target=agent,reported_at 防重送) Done(2026-11-01)
31 CM-3372 P11-7 BE 結案:本機驗 → 1.27.9 → 188 出包;UC 部署/簽發/三台升級由首腦做 Done(2026-11-01)

| 32 | CM-3374 P12-1 | agent | 升級解包前磁碟預檢、docker 失敗帶真正原因、升級成功清舊映像 | Done(合回 2b78d00) | | 32 | CM-3375 P12-2 | agent | SeaweedFS pids 1024/mem 2g 上限 | Done(合回 2b78d00) | | 32 | CM-3376 P12-3 | FE | 8 格讀 agent.progress、無紀錄不畫箭頭 | Done(合回 d18e98a2) | | 32 | CM-3377 P12-4 | BE | Bugsink 密碼每台隨機 | 裁不做(Done 跳過) | | 33 | CM-3378 P12-5 | BE | 結案出 1.27.11/Agent 1.4.9 | 裁等 FR-171/172 後再出 |

§3 已落地的契約(與 design 原文不同處,後面一律照這裡)

  • 資料庫位置:第一次升級前資料庫在 docker named volume guidant_guidant-pgdata,mv 改不了名;換接是把 pgdata-next 改名成 <資料目錄>/pgdata 並在 .env 寫 GUIDANT_PGDATA_DIR,named volume 原封留作快照(進度檔 db.prev_kind=volume)。之後的升級快照才是 pgdata-prev-<舊版> 資料夾(prev_kind=dir)。路徑一律走 lib/upgrade_common.sh 的 upg_pgdata_dir/upg_pgdata_copy_dir/upg_pgdata_main_dir。P1-10 清理看 prev_kind 決定刪 volume 還是刪資料夾。
  • 簽好的清單:v2 信封存在包旁 guidant-ai-<版>.release.json;shell 端只能透過 release_keys_canonical 讀驗過章的 canonical,不准讀信封外層。主機要有 python3,或含 JSON::PP/Compress::Zlib/MIME::Base64 的 perl;缺了升級預檢會擋。
  • beta 版號:jedi-remote-agent 開發期是 1.10.0b1(不是文件原寫的 1.9.0b1,1.9.0 已被 FR-166.1 占用);正式版應為 1.10.0。
  • R2 物件 key:v<主版號>/<完整版號>/<檔名>,只在 Worker src/releases.ts 拼;P2-4 卡上 releases/<版>/ 是筆誤。
  • status 契約(FE 用):頂層 available、download、last_check(含 last_success_at、error_code)、scheduled_at、draining/in_flight、progress.segment;失敗記 failed(包已刪),skipped 只給包還在的情況。全站提醒 GET /system/product-update/notice 只驗登入。
  • 容器掛載:api/worker 掛 upgrade:ro,orders:rw、incoming:rw 疊在上面,/etc/guidant/release-keys:ro;fe 只掛 upgrade:ro。更新單上限 8KB;orders/ 730、incoming/ 750。
  • 送給更新站的身分:授權檔原文(含 issued_to 客戶名稱)+指紋+現行版號+最近一次升級結果;更新站只記授權編號、指紋、版號、結果。手冊已照實寫。
  • Agent 跟進限制:只支援 docker compose 形態;從沒有自動跟進能力的舊版要先手動升一次;主機要有 systemd;用 install.sh --upgrade 指向 IT 自己解開的目錄升級時 Agent 不會跟進、更新中心也推不了(412008),要改用 guidantai upgrade <包>。
  • Agent 跟進可選(決策者 2026-10-30 定案,取代 D16「一律自動」):「更新到 X」確認視窗勾「主系統更新完成後,接著更新 Agent」(預設勾,可選哪幾台)=主系統升完先 1 台再其餘;不勾=主系統升完 Agent 不動,之後在 Agent 區自己勾、立即或排程,另有「稍後提醒」7 天。apply 多 with_agents/agent_uids(CM-3306)。
  • 更新中心顯示文字:「這一版更新了什麼/影響範圍/建議動作」來自更新站後台三欄(CM-3295),來源是 release note 檔尾「更新中心顯示文字」段(version-bump skill Step 1),3~5 條白話、停機不寫分鐘數,發布前照貼。
  • 離線包由原廠提供:主機連不到外網時更新中心拿不到包;原廠交付,客戶上傳。目前要兩個檔(包+簽好的清單),CM-3308/3310 改成單一離線檔。
  • 停機時間一律不寫死:畫面與文案寫「升級期間將看到維護頁」,有預檢估算才顯示估算值。
  • wrangler.toml 的 database_id 是全 0 佔位、Access 信箱未填,首腦部署時 wrangler d1 create 後填;UPDATE_SITE_URL 預設空字串、客戶端預設網址等網域定了才填。

§4 下一棒要做什麼(第 10 棒)

4-1 FR-167 本案已收口:母卡 Done、批 32 合回主線、文件站上線、main 已含全部。留在本案的只有:CM-3378 結案出包(等 FR-171/172 一起出 1.27.11)、CM-3312 e2e 暫緩、待辦 62~64(換接後 compose 標籤、後台 Agent 三欄、收尾小碎片)、正式出版路徑(出貨前另開卡)。沒有要接手的進行中工作。

4-2 60.167 重推 1.4.8:磁碟已清到 31G,決策者在 189 Agent 區勾 60.167 重推即可,包在 189 bundles/guidant-ai-1.27.10/agent/ 不必重下;推完核更新站 agent_version_reports 該指紋變 succeeded(查法 §6)。

4-3 Agent 獨立更新=新 FR(建議 FR-172),與 FR-171 同一討論週期:決策者 11-01 裁「171 先,172 可能一起」。分工:FR-171 管主系統↔︎Agent 的線(指令直推、心跳只表存活、憑證自動換、守門收斂),FR-172 管 Agent 的貨(包分開出、更新站多一類成品、R2 分路徑、Agent 主控台更新頁、相容矩陣兩向)。重疊只有三處,172 直接用 171 定的通道:主系統叫 Agent 升級、Agent 回報結果與進度、契約版號。實作順序:172 的出包/更新站/主控台頁與 171 平行,172「結果與進度回報」那一兩張等 171 通道卡做完。需求紀錄 docs/draft_requirement_spec/2026-11-01-agent-independent-update.md;要搬過去的舊待辦:6、42、58、61、60 的「結果晚 5 分」半邊。

4-4 本棒查到、沒開卡的事實

  • 60.167 推 1.4.8 失敗真因=磁碟滿,不是 docker 或核心:dockerd journal 04:27 failed to extract layer … no space left on device;升級同時要放下載包 1.7G+解開 1.7G+載入映像 4.3G+快照 4.3G,該機當時剩 13G;upgrade_order.sh:305 把 stderr 丟掉只印「無法讀取新映像」。已清:舊 1.4.2 映像、1.4.7 包副本、舊 compose 專案 guidant-agent-compose-0230 三個 volume(15G 舊實驗證據,決策者裁刪)→ 可用 31G。決策者可去 189 Agent 區勾 60.167 重推,包在 189 bundles/guidant-ai-1.27.10/agent/ 不必重下。該機核心 7.0.0-30、已裝 -38 未重開(reboot-required 在),這次不是它害的。
  • SeaweedFS 洩漏在 1.4.7 仍在:121/60.167 跑 24 小時 PID 5,665/5,594(agent 本體 12);CM-3375 加上限是止血,根因未查。
  • 188 磁碟 6.7G→100G(決策者逐項裁):刪 24 個無容器引用的舊 tag、build cache 74G→36G(留 20G)、解開的 1.27.8/1.27.9 目錄、Agent 舊包 1.4.1~1.4.6、/home/jedi/seaweedfs 獨立 3.99 實驗組(含兩容器)、0.2.28 Agent 孤兒 seaweedfs+四 volume。沒刪 /home/jedi/guidant-ai-1.27.7(8.4G):redis/seaweedfs/bugsink 三容器的 compose working_dir/config_files 標籤仍指它(線上升級不重建這三個),刪了下次 compose 操作變孤兒=10-31 誤刪 1.26.0 同款。升級程式缺口:換接時應把不重建的服務也 up -d 一次讓標籤指到新目錄(或第 7 步清理改指),記為待辦 62,可併 171/172 後的下一版。
  • 三台主機指紋相同(待辦 54)更正:更新站 instance_version_reports 主鍵=(license_id, fingerprint),三台授權各異所以三列都在、統計沒混算,第 7 棒「會算成一台」判斷錯。真正會撞的是 License Center(範本複製 VM 的 /etc/machine-id 相同,188/189 實查同值 d478e208…,product_uuid 不同);屬 LC 不屬本案,轉記 LC。
  • 待辦 2「立即」文案已修(P8-3 933aa083,現為「按下後立刻開始更新」),不開卡。
  • Bugsink 登入不會強制改密碼(官方映像 CREATE_SUPERUSER 建帳號,無首次改密機制),每台客戶同組密碼直到有人跑 guidantai bugsink-set-password——待辦 39 的疑慮屬實,決策者裁先不處理。
  • FE 主線多一個 STATE 沒記的 commit:85753fdb 12:41 主控台 favicon,在 1.27.10 出包後才進,下一版才帶到。
  • Notion P8 批 18~21、P10 批 25~28 實際全 Done(§2 表仍寫 Not started,收尾時改)。

4-5 舊清單照舊:待辦 41(併入 CM-3376)、43(併入 CM-3374)、53(CM-3375 止血)、62(新);PM 會議 B 類(私鑰保管、PG 大版);Q20 備份;正式出版路徑;e2e CM-3312 暫緩;189 LC 跑 feature 分支。今天下午 Office 預覽/Profile 下拉那批沒卡,要不要補事後紀錄卡仍待決策者。

§5 已定裁示(不要重問)

  • 開發期小弟只驗本機;測試期首腦操作 190。CRA 兩題先不管。
  • 小弟可 push 自己的 ws branch;套件需要發版就直接發(2026-10-31 決策者改判,不再先確認清單),發後卡上留版號與 consumer 清單。
  • 更新站用 TypeScript、R2 既有 bucket guidant-ai-release 分主版號資料夾、Access 只放行決策者信箱、網域出貨前再定、先用免費方案。
  • 不自動裝、不分安全版與功能版、只維護最新版、授權過期仍可升同主版號、換主版號重新授權。
  • 救援頁、常駐助手、頻道、取消鈕(服務停掉後)、強制中斷進行中工作、差異包、只換單顆容器都不做。
  • push 自 2026-10-31 起為常態授權(決策者 00:35「這是常態,不鎖定了」):首腦可直接推自己當下的 branch(feature/FR-139),不推 main、不 force;母卡與子卡 Done 一律決策者。
  • 目前以落地版為主;DEV 授權維持落地版,不改回 SaaS(2026-10-30)。
  • 更新中心版面=雛形 v2;Agent 跟進可選(預設勾、可選台);「預先下載」名稱不改(=先下載到主機再決定要不要更新);按鈕說明用 hover 不常駐;停機不寫分鐘數。
  • 版本說明三段不是 release note,是 release note 檔尾抽出的 3~5 條白話,發布前貼更新站後台。
  • 🔴 不再用心跳帶訊息(決策者 2026-11-01 12:3x,189 推 Agent 1.4.8 時:「之後不要再用心跳帶訊息了,這機制真的雷到一個不行」)。心跳只回答「我還活著」,不承載任何狀態或指令。實測暴露的問題:①結果最晚 5 分鐘才回主系統(121 升完 12:31:39,新容器 12:31:29 已先心跳一次,要等 12:36 下一跳);②下發要等下一跳(推送後最長 5 分才開始,待辦 25/26 已補主動通知);③容器換掉時心跳中的狀態跟著丟;④升級途中畫面沒有即時資料。改法方向:Agent→主系統的結果與進度走專用端點、事件發生當下就送(Agent 已有 outbox 可重送);主系統→Agent 的指令走既有 FR-039 資料面(mTLS+短效 JWT,/update/notify、/update/progress 已是這條)。併入待辦 59「主系統與 Agent 分開更新」一起設計,既有靠心跳的欄位(update、upgrade_result、profiles、profiles_check、vulndb)逐一盤點改走專用通道。
  • 發布印章私鑰在決策者 mac;開發、CI、STG、POC 都不用蓋章,只有「給客戶」那一刻 publish 打一次 passphrase。章放哪台(是否與 LC 同機)決策者「流程面後續再了解」,未裁。

§6 pre-flight(接手先跑,唯讀)

cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
git status --short; git log --oneline -3
for r in . ../compliance-manager-fe ../update-center ../evidence-agent ~/Projects/Jedicogy/module/jedi-python-package ../license_center ../compliance-manager-test; do echo "$(basename $(cd $r; pwd)) ahead=$(git -C $r rev-list --count origin/$(git -C $r rev-parse --abbrev-ref HEAD)..HEAD) ws_ahead=$(git -C $r log --oneline HEAD..ws-CM-3241 2>/dev/null | wc -l)"; done
grep -n "工作坊 3[0-9]" ~/Projects/Jedicogy/agent-workshop/.workshop/logs/workshop.log | tail -15
for n in 3374 3375 3376 3378 3366 3372; do echo -n "CM-$n "; python3 ~/Projects/Jedicogy/agent-workshop/scripts/notion_case.py get CM-$n | grep "^狀態"; sleep 3; done
lsof -nP -iTCP:8000 -iTCP:8788 -iTCP:5062 -iTCP:5180 -sTCP:LISTEN | awk 'NR>1{print $1,$2,$9}'
.venv/bin/pip show jedi-remote-agent jedi-license-runtime jedi-detection | grep -E "^Name|^Version"   # 1.11.0/1.1.7/1.7.2
for h in 190 188 189; do echo -n "$h: "; ssh jedi@192.168.50.$h "curl -sk https://127.0.0.1/api/1.0/version"; echo; done   # 1.27.8/1.27.8/1.27.10
ssh jedi@192.168.50.189 "docker exec guidant-db psql -U cmmgr -d guidant_ai -At -c \"SELECT name, agent_version FROM compliance.remote_agents\""   # 121=1.4.8、60.167=1.4.7(重推後應 1.4.8)
ssh jedi@192.168.50.188 "df -h / | tail -1"   # 11-01 清到 100G

§7 行為規範(本案特有)

  • 首腦不開 subagent;改卡內文先改 cards.py/gen_notion_cards.py 再重產。
  • 驗收 shell 卡一律在 Linux 容器跑 bats(docker run --rm -v <樹>:/w -w /w ubuntu:24.04,裝 bats、jq、openssl、rsync、python3);mac 上會有假紅,小弟說「乾淨 HEAD 也紅」不能信。
  • 測合併後的樹不只測小弟 branch:git merge-tree --write-tree HEAD ws-CM-3241 → commit-tree → worktree add --detach 到暫存目錄測,測完 worktree remove --force。
  • 簽章相關驗收用 P2-3 CLI 真簽出來的信封(node --experimental-strip-types 直接 import update-center cli/envelope.ts),不用小弟自組的 fixture。
  • Notion 一次撈多張卡要隔幾秒,連撈 35 張會 429。
  • 只動 DEV;190 是測試期專用;STG/POC 唯讀。