本卡屬 FR-181(母卡 FR-181 母案(同清單上一張)),卡 F-2,批 2。只改 evidence-agent。依賴:無。

這張卡做什麼(白話)

Agent 這邊的核心:一條背景執行緒,註冊成功後就不停地打主系統 GET /agents/commands?wait=30——主系統有事立刻回一串指令、沒事 30 秒回 204,Agent 收到就馬上再打下一次,所以任何時刻都有一條請求掛在主系統那邊等。拿到指令逐條交給「既有的處理函式」(派工進既有佇列、重啟叫既有 ops.request_restart、升級叫既有 update_sync.trigger、設定變了叫既有 config_pull),不重寫邏輯,只是觸發點從「主系統打進來」換成「自己拉到」。連不上主系統就退避(5→10→20→40→60 秒)再試。另外兩件事一起做:①回覆主系統的小工具 reply_sender(之後 A-3 回答類指令要用),送不到進既有的 outbox 補送;②8443 上原本給主系統直推用的六個端點,加一個設定開關預設不掛(決策者裁「API 功能先關掉、程式留著怕未來要開」),8443 照起只剩 health。照 config_pull.py 的骨架寫,那支就是「背景拉東西」的現成範本。

reuse/extend/new

new:guidant_agent/sync/app/command_pull.py(照 config_pull.py 的 WorkerComponent 骨架)——註冊成功後起背景執行緒無限迴圈 GET /agents/commands?wait=30(通行證+DPoP 同心跳);204 立刻再掛、2xx 逐條分派、連線錯退避 5→10→…→60 秒;分派表是模組內一張 dict[kind -> handler],本卡先接四個既有函式:task→cmd_tasks 的 _parse+task_queue.submit(把 _parse 從 route 檔抽到 app 層 task_intake.py,route 改呼叫它)、restart→ops.request_restart(mode, REASON_CLOUD, ACTOR_MAIN)、update→update_sync.trigger、config_changed→config_pull.request();其他九個 kind 先登記 no-op(A-3 填)。new:guidant_agent/sync/app/reply_sender.py——reply(request_id, status, result=None, reason=None, file=None) 打 POST /agents/replies/<id>,送不到走 event_sender 同一條 outbox(新 kind reply)。extend:registry.py 登記本元件(登記型檔,本卡 owner,一次把 A-3 要的 handler 槽也留好);data_plane_server.register_command_blueprints 加開關 cfg.data_plane_commands_enabled(預設 False)才掛六個 cmd_*(D7,本卡一併做,避免 C-2 再碰登記型檔)。🔴 升級中/重啟已排定拿到 task → 不進佇列、回 failed reason=upgrading(現況 409 語意搬過來)

在哪裡

repo:~/Projects/Billows/Audit-Manager/evidence-agent
改既有:guidant_agent/platform/registry.py
改既有:guidant_agent/sync/api/data_plane_server.py 61(register_command_blueprints 加開關)
改既有:guidant_agent/sync/api/cmd_tasks.py(_parse 抽到 app 層)
改既有:guidant_agent/sync/app/outbox.py(加 kind reply)
改既有:config/config.py(AgentAuthConfig 加 data_plane_commands_enabled 預設 False)
新開:guidant_agent/sync/app/command_pull.py
新開:guidant_agent/sync/app/task_intake.py
新開:guidant_agent/sync/app/reply_sender.py
新開:tests/sync/test_command_pull.py

怎麼做

驗收(首腦照這個驗)

pytest:假主系統回 204 → 立刻再掛(兩次請求間隔 < 100 ms);回一條 task → task_queue.submit 被叫一次且 ack 走既有路徑;回一條未知 kind → log warning、其餘照分派;連線錯三次 → 間隔 5/10/20 秒;升級旗標起時拿到 task → reply failed upgrading、佇列不變;data_plane_commands_enabled=False 時 8443 上 POST /tasks 回 404。本機對 DEV 主系統(F-3 工作區起的)實跑:主系統 DB 插一張 pending 單 → Agent 3 秒內 ack

必讀