一句話:本卡屬 FR-105(母卡見卡尾「母卡」段),第 1 棒:
module_frame模組 81 檔/10,942 行逐檔分類——每一支判給「真業務/轉接殼/共用設施/死碼」四類之一並附依賴證據。只分析不動程式。
module_frame 是主專案裡最大的模組之一。裡面同時住著兩種完全不同的程式:一種是本產品自己的業務(例如把客戶上傳的 Word/Excel 解析成 OSCAL 資料、比對兩份文件差異),另一種是轉接殼(主專案自己不做事,只是把前端的請求轉給 jedi_oscal_v2 套件、再把套件回的資料換成前端要的欄位名)。這兩種混在同一個 service 目錄裡,看目錄分不出來。
決策者要開發新功能了,要的是「乾淨的 code」。乾淨不等於刪——真業務本來就該留在主專案;轉接殼是「主專案回答套件問題」的必要接線,也不是垃圾。但兩種混住,接手的人不知道哪支可以動、哪支動了會影響套件契約。 這一棒的產出是一張逐檔的分類表,讓之後要動刀的人有正確的圖。
FR-102 全模組地圖(docs/features/FR-102-2609-host-module-map/README.md)已把 26 個模組盤到「模組層級」,但明講 oscal 與 module_frame 兩支「單一標籤蓋不住內部差異」需另開卡逐檔判。兩支共 244 檔/30,938 行,佔主專案四層一半,一棒做不完,故按模組切兩棒。第 1 棒先做 module_frame:v2 子物件殼的欄位對應表在這邊定義,oscal 那邊是引用者。
98d756bb 實查,用 git ls-files)api/module_frame 25 檔 / 2,763 行 43 條 route
app/module_frame 31 檔 / 7,416 行
domain/module_frame 12 檔 / 348 行
infra/module_frame 13 檔 / 415 行 自持表 module_frames / module_frames_trans
合計 81 檔 / 10,942 行
另:di_containers/module_frame/module_frame_containers.py(不在四層內,但判 DI 註冊要看)
對外 route 43 條(AST 數 add_resource 得出,regex 會漏抓換行寫法)。開工先重跑一次確認數字沒變(指令見「怎麼做」步驟 0)。
app/module_frame 逐檔 jedi/主專案 import 數(grep -cE '^\s*(from|import) jedi_'):ssp_import_template_app_service.py 1,500 行 jedi=18/host=3;module_frame_template_import_service.py 1,008 行 jedi=4;excel_template/generator.py 652 行 jedi=0、sheet_definitions.py 617 行 jedi=0——Excel 範本這整包(generator/sheet_definitions/header_i18n/lookup_builder/data_validation_builder/styles 共 1,645 行)看起來是純主專案業務,請實查確認。module_frame_party_service.py(323 行,「寫入層換成套件 jedi_oscal_v2 SspService 子物件 CRUD,對外 API 不變」,主體是 FE 欄位 ↔ OSCAL props 對應表);components/inventory/leveraged/system_characteristic/ssp_resources 五支同型(186~220 行,jedi=2~4)。這六支殼帶不帶主專案獨有規則(例如 matched-user-id 這類產品擴充軟參照、審計欄位暱稱 enrich)是本棒要標清楚的。module_frame_service.py(304 行,jedi=11/host=8)是模組內依賴最雜的一支,被 app/flow_engine/service/workflow_execution_service.py 用(模組外唯一 import domain.module_frame 的地方之一)。app/module_frame:app/auth/service/user_import_template_app_service.py、core/plugins/evidence_classification.py、di_containers/flow_control/flow_control_containers.py(首腦 grep,要逐一確認用的是哪支、為什麼)。app/oscal/service/ssp_control_impl_import_service.py」的 module_frame_template_import_service.py(1,008 行)——與 oscal 那支(431 行)是不是重複實作,是「可以立刻收的」候選,本棒先標、第 2 棒(oscal)對照。README.md:101):「真業務與 v2 轉接殼約各半」是模組層級的粗估,本棒要給出實際比例。app/oscal/service/ssp_*_app_service.py 同名五支逐字相同(oscal 那邊檔頭自陳「完全相同」)。相同就是兩份真相,該進「可以立刻收的」或「要設計才能動的」。excel_template/ 整包零 jedi 引用——它是真業務沒錯,但要確認它讀的資料來源(sheet_definitions 定義的欄位)有沒有另一份在 oscal 的 excel_parser/ 重複定義。ssp_import_template_app_service.py 1,500 行、jedi=18:一支檔混了多少種事?若能拆成「殼段/業務段」各多少行,寫進第 ⑤ 節。