本卡屬 FR-091(母卡 CM-1690),版面殘留回補。只動 jedi-integrity 一支,主專案不改(靠 re-export)。建議 model:Sonnet 5,effort:medium——搬檔+補 re-export+守衛,判斷點只有「哪個檔歸哪層」,卡上已分好。
決策者 2026-09-13 打開 jedi-integrity 看到一片亂:jedi_integrity/ 底下 plugin/ 五檔是照標準拆好了,旁邊卻還有 12 支 .py 平鋪在頂層(config、context、forensic、lc_report、lockdown、manifest、ports、runtime_check、startup_gate、tamper_marker、termination、unlock),總共 2248 行;app/ 與 infra/ 各只有一支檔,沒有 domain/。這是 FR-064 當初寫的形狀,CM-1693 整理時只做了清註解、拆 plugin、logger、版面守衛,沒動這 12 支的位置。21 支套件裡只有它這樣(iam 另有一支 security_policy.py 平鋪,在 CM-1725 收)。
這支套件特殊在:沒有 route、啟動閘門在 create_app() 之前跑、DB 未開 DI 未 wire,所以 README 專門有一節「為什麼沒有 api 層」。但「沒有 api 層」不等於「不分層」,其他層的規則對它一樣適用。這次把 12 支歸位,對外 import 路徑一字不改。
jedi_integrity.startup_gate.run_startup_gate、jedi_integrity.termination.register_gunicorn_master、jedi_integrity.config.IntegrityConfig、jedi_integrity.context.IntegrityContext,各 1 處;另 jedi_integrity.plugin(register/IntegrityAdapters/build_context/EXTENSION_KEY)與 jedi_integrity.infra.tamper_event_repo.TamperEventRepo 不動。搬檔後這四條舊路徑要留薄模組 re-export(保留原檔名,內容只剩 from jedi_integrity.domain.config import * 加 __all__),不改主專案。__init__.py docstring):啟動路徑只能 stdlib,不得 import flask/SQLAlchemy/jedi_common session。app/service/tamper_sync_service.py 與 infra/tamper_event_repo.py 是例外(服務起來後才跑)。搬檔不可破壞這條:放進 infra/ 的檔仍只能 stdlib,不能因為進了 infra 就順手 import jedi_common。tests/test_plugin_contract.py 或 layout 有沒有 AST 守這條,runner 查;沒有就補一條。tests/test_plugin_layout.py 已存在(凍結 jedi_integrity.plugin 公開符號)。harness 四情境(pass/tamper/unlock/lockdown)在 harness/dev_app.py。歸位表(首腦依 docstring 與 import 分的,runner 開檔確認,有異議先回寫再動):
domain/config.py ← config.py (IntegrityConfig 純參數值)
domain/context.py ← context.py (config+adapters 一束)
domain/ports.py ← ports.py (宿主要給的 port ABC)
domain/manifest.py ← manifest.py (manifest 載入/驗章/比對,純邏輯,hashlib+json)
domain/tamper_marker.py ← tamper_marker.py (標記檔格式;若含 pathlib 寫檔則改放 infra/)
app/startup_gate.py ← startup_gate.py (啟動閘門流程編排)
app/runtime_check.py ← runtime_check.py (抽查流程+埋點)
app/unlock.py ← unlock.py (token 核銷流程)
infra/lockdown.py ← lockdown.py (http.server 殼,碰網路)
infra/termination.py ← termination.py (os.kill/signal,碰 OS)
infra/forensic.py ← forensic.py (寫存證檔,碰檔案系統)
infra/lc_report.py ← lc_report.py (回報 License Center,碰網路)
git mv 逐檔搬(保留歷史),修套件內 import。jedi_integrity. import 確認,含 scripts/ 與 test/)。ls *.py 只允許 __init__.py 與那四支 re-export 薄模組(凍結集合);四支薄模組的公開符號可 getattr 到。domain/+app/+infra/lockdown|termination|forensic|lc_report 沒有 flask/sqlalchemy/jedi_common import(若已有等價測試就不重複)。__init__.py docstring 的模組名對照更新。domain/manifest.py 加 import flask → ④ 紅。還原後兩次紅的輸出貼回寫。