本卡為 FR-091 母案,是 FR-089(套件結構統一,母卡 CM-1688)的第三段。FR-089 第一段已用 jedi-asset 定出標準形狀(CM-1676/1677/1678),第二段 FR-090 正在收主專案側殘留。本案把那個形狀套到其餘 18 支有 plugin.py 的套件。子卡清單在末段;第一批 5 張先開,第二批起等 FR-090 第 5 棒(CM-1689)落地後再開。
後端有 21 支 jedi-* 套件,是不同時期、不同人抽出來的,同一件事各有寫法:有的一個 plugin.py 塞 400 行、有的守門函式叫 ctx() 有的叫別的、logger 名字五花八門、註解裡塞滿「第幾棒做了什麼」。jedi-asset 已經整理成一種形狀並寫進 SOP,本案把其餘 18 支整成一樣。整完之後任何人打開任何一支套件,看到的目錄、檔名、函式名都一樣。
決策者 2026-09-12 裁「全部做法都統一」。FR-069 D8(2026-08-30)就定了「第三階段:既有套件升級插件模式」,但當時只做輕量升級(補殼不搬 API)。FR-089 第一段用 jedi-asset 把「標準形狀」定死了,現在有範例可抄。首腦盤過 20 支:19 支 plugin.py 都是同型(240~620 行、5~7 個 dataclass 擠一檔),13 支 logger 名不對,16 支 api/init 有 ctx(),8 支有空的 tests/integration 骨架。
plugin/ 五檔(init/contract/runtime/assembly/migrations);api/ 拆 guards.py(runtime()+三個 lazy decorator)與 routing.py;取用執行期組件叫 runtime() 不叫 ctx();logger 掛 common.jedi_<pkg>;entity 一律 dataclass 並用 inspect.signature 逐欄對照;註解只留「為什麼」與「陷阱」。SOP 全文在 extraction-sop.md §4.3;範例看 jedi-asset/jedi_asset/;說明頁 docs/features/FR-089-2609-package-shape-unification/plugin-anatomy.md。created_user_name 的套件才開 identity port(survey/detection/task-platform/compliance-audit/log 五支),沒吐的不開,不塞用不到的欄位。iam 由 FR-090 CM-1686 做。core/plugins/<pkg>.py。本案子卡只動套件 repo;若套件改動迫使主專案 import 路徑要變,回寫問首腦,不自己動主專案。test_plugin_contract.py 若有 URL 集合/能力點字串/error code 字串守衛,整理前後必須同綠;沒有的先補再整理。建議順序:第一批 5 張可並行派(各自獨立目錄,不撞);一批做完首腦驗收、修 SOP 缺漏,再開下一批。
pytest tests/ 全綠(含新加的 test_plugin_layout.py);harness --smoke 全綠;主專案 pytest test/test_module_boundaries.py 全綠;主專案對該套件的每一處 import 逐一實跑。