本卡屬 FR-091(母卡 CM-1690),21 支套件卡之外的最後兩支。決策者 2026-09-13 裁:oscal-v2 要做(輕量版)、common 併進來只做註解與 logger。建議 model:Sonnet 5,effort:medium——規則已定、範圍已列,錯誤會被守衛與全量測試抓到。可與 CM-1730 平行。
FR-091 把 19 支有 plugin 的套件整理成同一種形狀。剩兩支沒有 plugin 的:jedi-oscal-v2(OSCAL 文件模型與解析,364 個檔,主專案 32 檔在用,純 library)與 jedi-common(工具箱,92 個檔,主專案 268 檔在用)。它們沒有 route、沒有 register,所以 plugin 五檔與 api 四件不適用,不要為了形狀開空目錄(SOP §4.3 明寫)。但 SOP §4.3 另外三條版面規則(port 只放 domain/ports.py、logger 掛 common.jedi_<pkg>、註解只留為什麼與陷阱)對它們一樣適用,這張卡把這幾條收齊。
jedi_oscal_v2/ports/ 三檔(__init__.py、oscal_parser_factory.py、oscal_parser_provider.py),domain/ 底下沒有 ports.py;from jedi_oscal_v2.ports 的 import 主專案+套件內共 4 處(runner 開工先 grep 列清單)。logger 兩種並存:common.jedi_oscal_v2 4 處、__name__ 12 檔。domain/entity/ 三個子目錄(ap/ar/base)共 90 個 entity 檔,grep @dataclass 全部有(0 檔缺),只需抽查確認不是空殼裝飾。施工日誌註解 0(CM-1679 清過)。tests 118 passed 124 skipped(skipped 是什麼 runner 看一眼寫進回寫)。主專案 pyproject.toml:126 是 pin 2.2.3、:256 有註解掉的 path 行——開工取消註解改 path、poetry update,不 commit。grep -rniE '第 ?[0-9]+ ?棒|CM-1[0-9]{3}' 可列)。logger 五種名:common.jedi_common 2、comment_generator 1、error_handler 2、middleware 1、__name__ 1。⚠️ error_handler/middleware 這兩個名字是主專案 dictConfig 掛 handler 的樹(見 CLAUDE.md 與主專案 test/test_jedi_package_logger_names.py),改了 log 就進不了 app.log——runner 先讀那支守衛測試,只把 comment_generator 與 __name__ 那兩處收成 common.jedi_common,error_handler/middleware 若守衛白名單有就不動,回寫寫明。common 已是 path dep(:228)。common 不動目錄結構、不動任何 public API。git mv 三檔內容併進 domain/ports.py(合起來超過 300 行就 domain/ports/ 子套件);頂層 ports/__init__.py 留 re-export 薄殼(4 處 import 靠它),其餘刪。照 CM-1732 file-upload 的做法。getLogger(__name__) 改 getLogger("common.jedi_oscal_v2")。@dataclass 真的在 class 上且沒有手寫 __init__ 疊在下面;有異常列表回寫不動。tests/test_plugin_layout.py(名字照其他套件,內容只有三條):頂層 ports/ 只允許 __init__.py 一檔;domain/ports.py(或子套件)存在且 4 處用到的符號 getattr 得到;AST 掃全套件 logger 名只有 common.jedi_oscal_v2。test/test_jedi_package_logger_names.py 看哪些名字在白名單;comment_generator(utils/gen_comment.py)與 __name__ 那處改 common.jedi_common;error_handler/middleware 依守衛結果決定,不確定就不動並回寫。oscal_parser_factory.py 放回頂層 ports/ → 紅;某檔 logger 改回 __name__ → 紅。還原後貼輸出。git stash。python -c "import jedi_oscal_v2,jedi_common;print(jedi_oscal_v2.__file__,jedi_common.__file__)" 都指工作樹。jedi_oscal_v2 import+268 檔 jedi_common import 用 AST 掃出目標逐一 importlib 實跑,貼數字。