FR-172 · 需求討論稿 v1 · 2026-11-01(與 FR-171 同週期拍板)
安裝包、CI、R2 路徑、更新站版本線全部分家;主系統更新中心與 Agent 主控台都能發動 Agent 更新;進度與結果當下回報
今天修一個 Agent 的小 bug,要重出一包 1.7 GB 的主系統、客戶停機 7 分鐘升主系統,再等心跳推 Agent,升完又等 5 分鐘才知道結果,畫面上的八格進度還停在第一格。原因只有一個:Agent 的包、版本線、推送、回報全部掛在主系統身上。本稿把它們一件件拆開——Agent 自己出包上傳、更新站多一條版本線、主系統更新中心能單獨抓 Agent 新版、Agent 主控台多一頁「更新」、進度與結果走 FR-171 定的專用通道。四個決策者已先裁的題目直接寫進設計,其餘 D1~D12 等拍板。
整案一句話:Agent 的「貨」(安裝包、版本線、下載、推送畫面)從主系統身上拆下來自己走,「線」(主系統叫 Agent 升級、Agent 回報進度)用 FR-171 定的通道,不再借心跳。
| 階段 | 做什麼 | 產出 | 完成怎麼判定(決策者檢查法) |
|---|---|---|---|
| P1 出貨分家 | Agent repo 自己 CI 出包、登記更新站、上 R2 自己的路徑;主系統包不再帶 agent/;更新站多一條 Agent 版本線;蓋章 CLI 多 --product agent |
Agent .gitlab-ci.yml、更新站 D1 加欄+後台 Agent 分頁、CLI |
更新站後台看到「主系統」「Agent」兩個版本分頁,各自列各自的版號;R2 多一個 agent/v1/ 資料夾;主系統包解開沒有 agent/ 目錄、小了 1.7 GB |
| P2 主系統側 Agent 區 | 更新中心 Agent 區改成自己查 Agent 新版、先下載再推、相容兩向檢查、移到 agent-bundles/<Agent 版>/ |
BE product_update Agent 線、FE Agent 區 v3(照雛形第 1~5 頁) | 主系統不升版,Agent 區按「立即檢查」看到 Agent 新版、按「預先下載」、按「更新選取的台」,整段不碰主系統版本 |
| P3 進度與結果即時 | Agent 升級每一步當下送事件給主系統;畫面八格跟著走;失敗能看到主機端的原因 | Agent 事件推送元件(用 FR-171 專用端點)、BE 收事件寫表、FE 八格改讀表 | 推一台,八格在 3 秒內開始往前走;拔網路線再插回,事件補送、最後一格仍會亮;故意塞滿磁碟推一次,「看原因」顯示 no space left on device |
| P4 Agent 主控台更新頁 | 主控台新增「更新」頁:看版本、看主系統上有沒有新版、按「請主系統更新這一台」、離線上傳更新包 | 主控台 Update.vue(照雛形第 6~9 頁)、Agent 兩支端點、主系統一支端點 |
登入 Agent 主控台按更新,主系統更新中心同時出現這一台的進度;拔掉主系統、在主控台上傳離線包,Agent 自己升上去 |
| P5 收尾 | 更新站後台 Agent 三欄改比 Agent 版本線;舊客戶過渡;相容矩陣四格測試;文件 | 後台修正、過渡文件、e2e | 後台「Agent 在版」數字等於 Agent 區實際台數 |
依賴一句:P1 與 P2 不依賴 FR-171,可立刻開;P3 與 P4 的「主系統→Agent 叫升級」「Agent→主系統送事件」兩條線用 FR-171 批 1~2 定的通道與契約,等它合回才開。決策者功課:裁 D1~D12;其中 D1(更新站存法)與 D2(章怎麼分)影響 P1 第一張卡。
這邊之後要改成主系統跟 agent 要分開更新。主系統跟 Agent 要分開來,不要像現在都包在同一包裡面;要可以各別分開更新;Agent 那邊也要有更新中心,可以做離線更新,或是跟主系統發動更新需求;R2 上面的安裝包要分開來;不要再用心跳帶資料。 — 決策者原話(2026-11-01,189 推 Agent 1.4.8 時)
2026-11-01 為修兩個 Agent 問題實際走一次的帳:
20 分出 Agent 1.4.8
36 分只為帶 Agent 而重出主系統 1.27.10
7 分客戶停機升主系統(主系統本身沒事)
5 分升完等下一跳心跳才知道結果
Agent 包 1.8 GB 被塞進主系統包 agent/ 底下一起簽、一起上 R2 v1/<主系統版>/。更新站只有一條版本線。Agent 改一行就得重出主系統、客戶就得停機。Agent 包還占主系統包一半以上的下載量。
推送後最長等 5 分鐘 Agent 才來拿;FR-167 補了「叫醒心跳」等於再疊一層。結果只隨心跳上報,容器一換狀態就丟。八格進度是主系統畫面刷新時去拉 Agent,結果一到就清掉,失敗時常常看不到卡在哪一步。60.167 那次真因是磁碟滿,主系統只拿到「無法讀取新映像」一句。
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
flowchart LR
subgraph build["188 build 機(人手跑)"]
A1["evidence-agent<br/>build_all.sh --with-compose<br/>→ guidant-agent-compose-1.4.8.tar.gz"]
B1["compliance-manager-be CI package<br/>build_bundle.sh 去抓最新一支 Agent 包<br/>塞進 guidant-ai-1.27.10/agent/"]
end
subgraph site["更新站(一條版本線)"]
S1["product_releases 1.27.10<br/>min_agent_version"]
R1["R2 v1/1.27.10/guidant-ai-1.27.10.tar.gz<br/>(內含 agent/,1.7 GB)"]
end
subgraph host["客戶主系統"]
H1["升級主系統 → 解到<br/>upgrade/bundles/guidant-ai-1.27.10/agent/"]
H2["更新中心 Agent 區<br/>只能推『這版主系統附的那個 Agent』"]
end
subgraph agent["客戶 Agent"]
G1["心跳回應 update 鍵 → 下載 → 寫升級單"]
G2["主機 systemd 升級 → 結果等下一跳心跳帶回"]
end
A1 --> B1 --> S1 --> R1 --> H1 --> H2 --> G1 --> G2
| 環節 | 現況 | 掛在主系統的哪裡 |
|---|---|---|
| 出包 | Agent repo 沒有 CI,人在 188 手跑;主系統 CI package 段去 /opt/guidant-ai-agent/.build/compose/ 抓最新一支 |
build_bundle.sh ⑧ |
| 簽章 | Agent 包沒有自己的發布章;靠主系統 release.json 的 sha256 間接涵蓋 |
payload_type=release_manifest 只有一種 |
| 上傳 | 只有主系統三個檔上 R2 v1/<主系統版>/ |
publish_draft.sh |
| 更新站 | product_releases 一條版本線;min_agent_version 只有「主系統要求 Agent 最低版」一向;後台 Agent 三欄拿 Agent 版號 1.4.x 比主系統版號 1.27.x 永遠 0 |
releases.ts |
| 主系統本機 | upgrade/bundles/guidant-ai-<主系統版>/agent/,host_version 不得比現行主系統新;刪掉就沒有復原路徑 |
agent_rollout_service.py |
| 推送 | 寫 rollout → /update/notify 叫醒心跳 → 心跳回應 update 鍵下發 |
_agent_update.py、update_sync.py |
| 進度 | 畫面刷新時主系統去拉 GET /update/progress,快取在 worker 行程各一份 |
_PROGRESS_CACHE |
| 結果 | 心跳 payload upgrade_result,最晚一個心跳週期 |
record_upgrade_result |
| Agent 主控台 | 沒有更新頁;能力點只有 configure/files/run-local-scan/net-diag/restart/download-files |
CONSOLE_SCOPES |
| 離線 | 只有主系統的離線單一檔;Agent 離線只能人到主機跑 install.sh --upgrade |
— |
v<主版>/<版>/+release_manifest;Agent agent/v<主版>/<版>/+agent_release_manifest。POST /update 直推;Agent 升級每一步 POST /agents/update/events 當下送,送不到進 outbox。心跳回到只表存活。min_agent_version、Agent 清單 min_host_version;不相容在畫面擋。%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
flowchart LR
subgraph ci["兩條 CI"]
C1["BE CI → guidant-ai-1.28.0.tar.gz<br/>(不含 agent/)"]
C2["Agent CI(新)→ guidant-agent-compose-1.5.0.tar.gz<br/>register-draft --product agent"]
end
subgraph site["更新站(兩條版本線)"]
S1["product_releases (host, 1.28.0)<br/>min_agent_version"]
S2["product_releases (agent, 1.5.0)<br/>min_host_version"]
R1["R2 v1/1.28.0/"]
R2["R2 agent/v1/1.5.0/"]
end
subgraph mac["決策者電腦"]
K["guidant-release publish --product host|agent<br/>兩種 payload_type,各驗各的"]
end
subgraph host["客戶主系統"]
H1["更新中心:主系統卡(不變)"]
H2["更新中心:Agent 卡<br/>立即檢查 → 預先下載 → 相容檢查 → 推選定的台<br/>upgrade/agent-bundles/1.5.0/"]
H3["收事件表 agent_update_events<br/>八格進度、失敗原因"]
end
subgraph agent["客戶 Agent"]
G1["POST /update(FR-171 直推)→ 下載 → 寫升級單"]
G2["主機 systemd 升級每步 → 事件當下送 POST /agents/update/events"]
G3["主控台「更新」頁<br/>請主系統更新這一台/離線上傳"]
end
C1 --> S1 --> R1
C2 --> S2 --> R2
K -.蓋章.-> S1
K -.蓋章.-> S2
R1 --> H1
R2 --> H2
H2 --> G1 --> G2 --> H3
G3 -- "請主系統更新這一台" --> H2
| 項 | 現況 | 改成 | repo |
|---|---|---|---|
| Agent CI | 無,人手在 188 跑 | 新增 .gitlab-ci.yml,同 guidantai-build runner:build_all.sh --with-compose → smoke → register-draft --product agent → 上 R2 三檔(包、.sha256、未簽 release.json)。主控台前端在 node 容器內 build,不靠 188 裝 node(D4) |
evidence-agent |
| 主系統包 | build_bundle.sh ⑧ 收 Agent 包進 agent/ |
拿掉 ⑧ 與「正式包必須帶 Agent」守門;--skip-prod-key-check 不再有 Agent 那半邊 |
BE |
| 更新站資料 | product_releases 一條線 |
加 product 欄(host/agent),主鍵改 (product, version);Agent 列多 min_host_version(D1) |
update-center |
| R2 路徑 | v<主版>/<版>/ |
主系統不動;Agent agent/v<主版>/<版>/<檔>,一樣只由 r2Key() 拼(主版號資料夾仍是授權邊界) |
update-center |
| 章 | payload_type=release_manifest |
Agent 用 agent_release_manifest,payload 多 min_host_version;主系統端驗 Agent 包只認 agent_release_manifest、驗主系統包只認 release_manifest(D2) |
update-center CLI、BE、evidence-agent |
| 客戶端端點 | /v1/check、/v1/download-url、/v1/report |
三支加 product 參數,不帶=host(舊主系統不用改);/v1/report target=agent 已有,改對 Agent 版本線比 |
update-center |
| 後台 | 一張版本表 | 分「主系統」「Agent」兩個分頁;Agent 三欄改比 Agent 版本線(FR-167 待辦 63) | update-center |
| 版本說明 | Agent notes.json 隨包 |
改與主系統一樣:發布前貼更新站後台的 Agent 列 | update-center |
| 離線單一檔 | 只有主系統 | guidant-agent-<版>.offline.tar.gz(包+簽好的 release.json),publish --product agent 順帶產 |
update-center CLI |
雛形第 1~5 頁。規則:
product=host 與 product=agent;「立即檢查」兩個都問。upgrade/agent-bundles/<Agent 版>/,驗章(agent_release_manifest)、驗 sha256;下載人寫稽核。保留現行版與最新版兩份,其餘清掉(D7)。min_host_version 高於主系統現行版 → Agent 卡顯示「需要先把主系統升到 X」,推送鈕灰。min_agent_version 高於某台 Agent 現行版 → 主系統卡標「必須更新 Agent」(FR-167 D16 既有行為),該台在 Agent 卡標「必須更新」。agent_update_rollouts(先 1 台、再其餘、任一失敗其餘暫停、暫停/繼續/稍後提醒),只換兩件事:包從 agent-bundles/<Agent 版>/ 拿、下發改 FR-171 的 POST /update 直推(打不通退回心跳備援一個版本,之後拔)。agent-bundles/ 已有相容的 Agent 新版就照舊自動建列。host_version 欄位退役:Agent 包不再綁主系統版,改記 agent_bundle_version。依 FR-171「心跳只表存活」:
| 事件 | 誰送 | 送到哪 | 內容 |
|---|---|---|---|
| 下載進度 | Agent 容器(每 5% 或每 10 秒) | POST /agents/update/events |
{job_id, kind:"download", bytes_done, bytes_total} |
| 主機每一步開始/結束 | Agent 容器監看 upgrade-progress.json 變動即送 |
同上 | {job_id, kind:"step", n, name, status, started, ended, detail} |
| 最終結果 | 新容器啟動時讀升級單結果即送(容器換掉那幾步由新容器補) | 同上 | {job_id, kind:"result", status, version, error, detail} |
| 送不到 | 進 Agent 既有 outbox(新 kind update_event),連上就補送、順序照 created_at |
— | — |
agent_update_events(每台每 job 一列 upsert,存最後進度與全部步驟),畫面 3 秒輪詢改讀這張表,不再去拉 Agent;_PROGRESS_CACHE 與 GET /update/progress 退役。upgrade_order.sh 不再丟 stderr,每步失敗把 stderr 最後 20 行寫進進度檔 detail(≤ 4 KB);主系統存、畫面「看原因」顯示;仍過濾不可列印字元(D8)。upgrade_result 與回應的 update 鍵:主系統接受但不再依賴,留一個版本給舊 Agent,下一 minor 拔(跟 FR-171 的 /update/notify 同節奏)。雛形第 6~9 頁。決策者已裁「按一下=主系統幫這一台更新」。
| 畫面元素 | 資料從哪來 | 動作 |
|---|---|---|
| 目前版本、上次更新時間與結果 | Agent 本機(升級單結果檔) | — |
| 「主系統上有 Agent 新版 X」/「已是最新」/「主系統不相容,要先升主系統」 | Agent 向主系統 GET /agents/update/available(控制面通行證),主系統回 agent-bundles/ 裡相容的最新版與版本說明 |
按「請主系統更新這一台」→ Agent 打主系統 POST /agents/update/request → 主系統建一張 manual rollout 只含這台(按更新的人記 agent-console:<操作者>)→ 走 P2/P3 同一條路 |
| 進度八格、失敗原因 | Agent 本機進度檔(與送給主系統的是同一份) | — |
| 離線上傳 | 上傳 guidant-agent-<版>.offline.tar.gz → Agent 驗章(agent_release_manifest,公鑰隨 Agent 包帶 release-keys/)、驗 sha256、寫升級單 → 主機 systemd 照舊接手 |
要先過「主系統不相容」檢查:Agent 端拿不到主系統版本時只提示不擋(D5) |
| 權限 | 新能力點 update(D6) |
預設 local-admin 有;離線操作者可由主系統勾給 |
Agent 主控台事件(誰按了更新、上傳了什麼)照既有 console_events 送主系統稽核。
| FR-171 管「線」 | FR-172 管「貨」 | |
|---|---|---|
| 做什麼 | 主系統→Agent 指令直推(派工/重啟/升級/換證/取消)、Agent→主系統事件專用端點、心跳只表存活、憑證自動換、守門與 client 收一份 | 出包/CI/R2/更新站版本線分家、相容兩向、主系統 Agent 區改版、進度事件的內容與畫面、Agent 主控台更新頁、離線上傳 |
| 172 直接用 171 的 | POST /update 指令端點與 AgentDataPlaneClient;Agent→主系統事件端點的簽章與守門規則;契約套件 jedi-agent-protocol 的版號 |
— |
| 172 自己定的 | — | agent_release_manifest 章、min_host_version、agent_update_events 表與事件形狀、GET /agents/update/available、POST /agents/update/request、主控台頁與能力點 |
| 順序 | 批 1 守門與 client 收斂 → 批 2 指令通道與事件端點 | P1、P2 立刻開(不等 171);P3、P4 等 171 批 2 合回 |
| 不互踩 | 171 不動 agent_rollout_service 的包來源與畫面 |
172 不另開第二條直推 client、不自己定事件簽章 |
兩案同一個討論週期拍板、各自一棵卡樹(兩張母卡)、工作坊可同時跑兩個;172 的 P3/P4 卡在 Stage 排在 171 批 2 之後。
已裁(2026-11-01 決策者)
D1 — 更新站怎麼存 Agent 版本線:加 product 欄,還是另開一張表?
建議:加欄。product_releases 加 product TEXT NOT NULL DEFAULT 'host',主鍵改 (product, version),Agent 列多 min_host_version。visibleReleases、releaseAdoption、後台、CLI 全部多一個 product 條件。另開表會讓發布流程、撤回、保留期、下載紀錄每支都寫兩份。
D2 — Agent 的章怎麼分:同 payload_type 加 product 欄,還是另一個 payload_type?
建議:另一個 agent_release_manifest。理由:已出貨的主系統 1.27.x 驗章只認 release_manifest,拿到 Agent 清單會直接 bad_signature 拒收;若共用型別只加欄位,舊主系統會把 Agent 1.5.0 當成「主系統 1.5.0」走到版號比較才擋,差一道門。同一把發布私鑰簽兩種型別,不用多一把章。
D3 — 相容矩陣兩向的擋法
Agent 新版 min_host_version > 主系統現行版 → 擋推送(灰鈕+說明);主系統新版 min_agent_version > 某台 Agent → 標「必須更新」但不擋主系統升級(FR-167 D16 既有)。
建議:照此。Agent 比主系統新是允許的(兩條線不綁版,FR-171 相容矩陣同一精神),只擋「Agent 要求的主系統最低版沒到」。min_host_version 由 Agent repo scripts/build/min_host_version 一行檔決定,沒有=不限。
D4 — Agent CI 跑在哪、主控台前端怎麼 build
188 runner 沒有 node,主控台前端現在在 Mac build 再傳過去(runbook 2.2)。
建議:Agent CI 跑同一台 188 runner(guidantai-build tag),主控台前端在 node:20 容器內 build(跟 BE CI 的 build_fe_image.sh 同手法),FE repo 以 submodule 或 CI 變數指定 commit 拉進來。188 不裝 node。
D5 — Agent 主控台離線上傳的驗證與相容檢查
Agent 端要能驗 agent_release_manifest 的章,公鑰要隨 Agent 包帶(現在只在主系統包 release-keys/)。相容檢查需要主系統版本,離線時拿不到。
建議:Agent compose 包加 release-keys/(與主系統同一批公鑰與 PROD_KIDS),升級時換新;離線上傳時 Agent 拿不到主系統版本就只提示「無法確認相容性,請確認主系統 ≥ X」不擋——離線場景本來就是人在現場。
D6 — 主控台權限:新能力點 update,還是沿用 restart?
建議:新 update。重啟是分鐘級可逆、更新是換版本不可逆,給離線操作者的授權面不同;CONSOLE_SCOPES 加一項、主系統 Agent 管理頁勾選清單多一格、local-admin 預設有。
D7 — 主系統本機 Agent 包目錄與保留
upgrade/bundles/guidant-ai-<主系統版>/agent/ → upgrade/agent-bundles/<Agent 版>/。
建議:保留「各台現行版中最舊的那版」與「最新版」兩份,其餘清;升級到 1.28 時把舊 bundles/<版>/agent/ 裡的那支搬過去當第一份。這同時解掉 FR-167 待辦 42(被刪就重下載)。
D8 — 失敗原因回多少
建議:每步 detail ≤ 4 KB、只收 stderr 最後 20 行、過濾不可列印字元、主系統再截一次;畫面預設收起、「看原因」展開;診斷包照舊收全量 journal。不送整段 journal(主機路徑與帳號會進主系統稽核表)。
D9 — Agent 區「預先下載」要不要獨立成一步
主系統卡現在是「預先下載 → 更新」兩步(FR-167 已裁名稱不改)。Agent 卡現況是「推送」一步,包早就在主系統包裡。
建議:對齊成兩步。Agent 包 1.8 GB 不小,下載誰按、何時下載要有紀錄;且離線客戶走上傳到主系統這條路時本來就分兩步。雛形第 1~2 頁照這樣畫。
D10 — 舊客戶怎麼過渡
現場 1.27.10 的主系統包裡還有 agent/;下一版主系統 1.28.0 不帶。
建議:1.28.0 主系統升級第 7 步把 bundles/1.27.10/agent/ 那支搬到 agent-bundles/1.4.8/;更新站 Agent 版本線第一筆登 1.4.8(補登既有包,不重出);1.5.0 起走新 CI。舊主系統 1.27.x 問 /v1/check 不帶 product 照舊拿主系統線,不受影響。
D11 — FR-167 搬過來的小待辦哪些併入本案
| 待辦 | 內容 | 建議 |
|---|---|---|
| 60 | 八格讀錯欄位(FE 已修未出包)、結果晚 5 分 | 併入 P3,整段重做 |
| 63 | 更新站後台 Agent 三欄永遠 0 | 併入 P1 |
| 42 | 刪掉 bundles/<版>/agent/ 沒復原路徑 |
D7 順帶解 |
| 58 | Agent 主控台檔案頁把 PDF 快取列成證據 | 併入本案當一張 Agent repo 小卡(同 repo、不撞檔) |
| 61 | 主控台 CINC 網址型 Profile 下拉空 | 不併:B 方向要改主系統 Profile 匯入(解析時留檔),屬檢測 Profile 功能,另開小 FR 或掛 FR-060 續作 |
| 62 | 升級換接後 compose 標籤指舊目錄 | 不併:主系統自升級的事,留 FR-167 下一版 |
建議:照表。
D12 — 拆卡順序與批(約 18 張、5 repo)
P1:更新站 D1 加欄+端點 product 參數(1)→ CLI --product+agent_release_manifest+離線檔(1)→ 後台兩分頁+三欄(1)→ Agent CI+min_host_version+release-keys/(1)→ BE 拿掉 ⑧(1)。 P2:BE Agent 線(檢查/下載/相容/agent-bundles//host_version 退役)(2)→ FE Agent 區 v3(1)→ 主系統升級第 7 步搬包(1)。 P3(等 171 批 2):契約加事件形狀(1)→ Agent 事件推送元件+outbox kind+upgrade_order.sh detail(2)→ BE 收事件表+退役拉進度(1)→ FE 八格改讀表+看原因(1)。 P4(等 171 批 2):主系統 available/request 兩支(1)→ Agent 兩支端點+能力點(1)→ 主控台 Update.vue(1)。 P5:e2e+文件+結案出包(1~2)。
建議:照此。釘版套件 jedi-agent-protocol 有改動,P3 批 1 前要環境卡(可與 171 共用同一張)。詳細拆卡表等裁完在 design.md 用 cards.py 驗過再寫。
| 不做 | 理由 |
|---|---|
| Agent 直接連更新站 | 決策者裁;Agent 是客戶內網掃描機,不出網是賣點也是資安前提 |
| Agent 差異包、只換單顆容器 | FR-167 已裁不做;Agent 包本來就是整組映像 |
| Agent 自動裝新版 | 與主系統同原則:任何版本都不自動裝,要人按 |
| 主系統版本線改名或搬 R2 資料夾 | 已有 10 版在 v1/,搬了舊主系統找不到 |
| 第二把發布私鑰專給 Agent | 一把章兩種 payload_type 已能防互相冒充;多一把章多一個保管問題 |
| 心跳備援長期並存 | 心跳的 update/upgrade_result 只留一個版本給舊 Agent,與 FR-171 /update/notify 同節奏拔 |
| 風險 | 怎麼防 |
|---|---|
| 兩條版本線被互相冒充(拿 Agent 1.5.0 清單餵給主系統) | 兩種 payload_type 各驗各的;R2 路徑不同;更新站 product 欄進主鍵 |
| 171 通道卡延後,172 的 P3/P4 跟著卡 | P1、P2 先跑;P3/P4 卡在 Stage 排 171 批 2 之後,工作坊自己等 |
| 容器換掉那幾步事件沒人送 | 新容器啟動時讀進度檔補送「步驟+結果」;主系統按 job_id upsert 不怕重送 |
| 事件送到但主系統多 worker 各寫各的 | 寫 DB 不寫行程快取;畫面只讀 DB |
| Agent CI 跟 BE CI 同時在 188 build 互撞(Nuitka linker crash) | CI 設 resource_group: build-188,兩條 CI 串行 |
| 1.28 主系統沒帶 Agent,客戶以為「Agent 不見了」 | 第 7 步搬包+更新站補登 1.4.8;Agent 卡文案「隨主系統附帶」改「由主系統下載」 |
| 離線上傳的包被人塞假的 | Agent 端驗章+sha256,公鑰隨包帶;PROD_KIDS 同一批 |
登記型共用檔(CONSOLE_SCOPES、result_outbox kind、contract pyproject、BE 路由表、FE console router.js)同批撞 |
拆卡時各自不同批,或最早那張卡一次掛完 |
docs/claude/memory/feedback_no_heartbeat_piggyback_messaging.md