一句話:本卡屬 FR-105(母卡見卡尾「母卡」段),第 2 棒:
oscal模組 163 檔/19,996 行逐檔分類——每一支判給「真業務/轉接殼/共用設施/死碼」四類之一並附依賴證據。只分析不動程式。
oscal 是主專案裡最大的模組之一。裡面同時住著兩種完全不同的程式:一種是本產品自己的業務(例如把客戶上傳的 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 行,佔主專案四層一半,一棒做不完,故按模組切兩棒。第 2 棒接在 module_frame 之後,對照第 1 棒結果標兩模組的鏡像與重複實作。開工先讀第 1 棒產出 module-frame-classification.md。
98d756bb 實查,用 git ls-files)api/oscal 67 檔 / 3,984 行 59 條 route(routes/framework/ssp/module_frame_template_ssp_route/oscal_export_route/resource_library_route)
app/oscal 46 檔 / 10,964 行 子目錄 import_diff/import_adapter/excel_parser/export
domain/oscal 36 檔 / 4,549 行 parser/adapter/import_pipeline/service(resolver/reconciliation)
infra/oscal 14 檔 / 499 行 自持表 framework_parse_jobs / ssp_docx_parse_jobs / ssp_excel_parse_jobs
合計 163 檔 / 19,996 行
另:di_containers/oscal/oscal_containers.py
對外 route 59 條(AST 數 add_resource 得出,regex 會漏抓換行寫法)。開工先重跑一次確認數字沒變(指令見「怎麼做」步驟 0)。
import_diff/ssp_diff_service.py 751 行、import_adapter/_common.py 620 行、excel_parser/sheet_handlers.py 428 行、import_diff/decision_merge.py 318、snapshot_views.py 315、export/ssp_docx_generator.py 258、excel_parser/v2_bundle.py 217、export/ssp_export_model.py 169;domain/oscal/parser/ 三支共 1,816 行、adapter/cmmc_ssp_adapter.py 860 行。framework_app_service.py 247 行 jedi=7(檔頭自陳「補套件沒有的主專案職責——分頁、filter、main_version 字串解析」);framework_version_edit_service.py 351 行 jedi=14/host=0;resource_library_app_service.py 541 行 jedi=11/host=0;framework_version_app_service.py 229 行 jedi=5。541 行的殼太厚,要看裡面有沒有主專案業務。ssp_control_implementation_service.py 1,004 行 jedi=20/host=3;framework_parse_job_service.py 674 行 jedi=14;ssp_excel_import_app_service.py 937 行、ssp_docx_import_app_service.py 787 行(兩支檔頭都有「殼/委派」字眼)。這幾支是第 ⑤ 節「要設計才能動的」主要來源。ssp_party/components/inventory_items/leveraged/system_characteristic_app_service.py(68~194 行):ssp_leveraged_app_service.py 檔頭自陳「欄位 mapping 與資源庫範本版 ModuleFrameLeveragedService 完全相同」——第 1 棒(module_frame)已標另一半,本棒要對照確認是否逐字相同、兩份能不能收成一份。ssp_control_impl_import_service.py(431 行)與 module_frame 的 module_frame_template_import_service.py(1,008 行,檔頭自陳「格式對齊」前者)疑似重複實作,第 1 棒已標,本棒對照。domain/oscal/service/ssp_project_resolver.py(184 行)與 ssp_context_resolver.py(158 行)——前者被 common/authz/ssp/SspPermissionChecker 用(守門軸),屬跨模組共用;reconciliation/ 兩支 person reconciler。app/flow_control/service/assessment_plan_app_service.py、app/flow_control/service/project_service.py、app/flow_engine/service/workflow_execution_service.py、di_containers/flow_control/flow_control_containers.py(首腦 grep,要逐一確認用哪支)。README.md:100)與「需另開卡深挖」段(README.md:139)。api.js 的 OSCAL_* 15 個+SSP_* 37 個常數確認模組活著,沒有逐條對,有沒有常數存在但無頁面呼叫的死端點。