建議 model:opus/effort:medium — 跨 repo 搬檔+改容器契約+改 image 名,牽動 build 線與出貨包。
本卡屬 FR-107(母卡 CM-1843)第 .2 棒(子需求卡 CM-1845),子任務 T-2.3:把分類容器從主專案搬進套件 repo,並把它「自己連資料庫、自己連 Google Drive」的能力全部拿掉。
分類容器是一個獨立的 Docker 程式,負責真正呼叫 AI 把每份檔判成「對應哪幾個檢查點」。
現在這個容器自己連資料庫、自己解密 Google Drive 的憑證、自己下載檔案——等於把資料庫密碼與 Drive 權限交給一個外部容器,而且落地版客戶沒有 Drive 根本跑不動。
這張卡把它改成只認一個掛進來的目錄:主專案先把整批檔拉到 /job/files/,再起容器,容器讀目錄、算完把結果寫回目錄。改完之後容器的環境變數只剩一個 AI 金鑰,網路可以完全關掉(除了打 AI API)。
同時做兩件搬家:① 整個容器目錄從主專案搬進套件 repo(版本跟套件連動);② image 改名——原本叫 cmmc-classifier(名字綁死 CMMC 這個框架),改成 evidence-classifier。
主專案 → 套件(整包 git mv)
scripts/evidence/classify/docker/ → 套件 repo jedi-evidence-classification/docker/
主專案 scripts/evidence/classify/ 只留一支 README 指路
容器程式(搬過去之後改)
container_entrypoint.py
:123 DB_HOST ← 🔴 刪(整段連資料庫的邏輯)
:160 DRIVE_TOKEN_ENCRYPTION_KEY ← 🔴 刪(整段解密 Drive token 與下載檔案)
:742 ANTHROPIC_API_KEY ← 保留,這是唯一留下的環境變數
service-classify 子命令 ← 改吃 --input-dir,讀 manifest.json
:504 build_system_block() ← 本卡不動(T-5.3 才改成讀 prompt.json)
:109 ao_id = f"{ctrl['id']}[{ao['letter']}]" ← 本卡不動(T-5.3 改)
Dockerfile ← 拿掉 DB/Drive 相關依賴
rebuild.sh ← 改 image 名與 tag
套件
.../infra/classifier_container_runner.py
:58 ClassifierContainerRunner
:63 jobs_base_dir 預設 ~/.cm-jobs
:119 docker run 指令 ← 拿掉 --evidence-folder-id/--tenant-id,
加 --network none(或可配的代理參數)
:206 回讀 /job/_report-original.json ← 保持
.../plugin/contract.py:50 classifier_image 預設值
cmmc-classifier:latest → evidence-classifier:<套件版號>
宿主起容器前把 jobs_base_dir/<batch_uid>-<run_uid>/ 準備成:
/job/
files/<file_uid>.<ext> ← IEvidenceStorage.stage_to_dir 拉下來的實體檔
manifest.json ← [{file_uid, original_name, mimetype, size}]
catalog.json ← 目標集(含 part_id/group_id/group_title/ao_letter/prose)
prompt.json ← {persona, guidance, hints_by_part_id}(T-5.3 才有內容,
本卡先接受它存在或不存在都不炸)
容器指令:
docker run --rm --network none \
-v <job_dir>:/job \
-e ANTHROPIC_API_KEY=... \
evidence-classifier:<tag> \
service-classify --input-dir /job --output-dir /job \
--model ... --min-confidence ... --workers ...
🔴 沒有 --tenant-id、沒有 --evidence-folder-id、沒有任何 DB/Drive 環境變數
容器回:
/job/
_report-original.json ← {"files":[{"file_uid","matches":[{"part_id","confidence"}],
"primary":part_id|null,"error":null}],
"usage":{...}, "estimated_cost_usd":...}
_container.log
宿主讀回 _report-original.json 之後會寫進分類結果表,然後刪掉 files/(工作目錄不留實體檔,避免出現第二份真相);log 與 json 留 7 天供排查。這段宿主邏輯在 T-3.2 做,本卡只要讓容器契約成立。
git mv 搬,不要複製貼上——git mv 保留檔案歷史,複製會讓 git log 斷掉。跨 repo 搬沒有 git mv,所以:在套件 repo 新增目錄並 commit,主專案 repo git rm 舊目錄並 commit,兩邊的 commit message 都要說明「從哪搬到哪」。--network none 要可配:完全斷網時容器連 AI API 也打不了,所以實務上要嘛用只允許 AI API 的 network、要嘛走主機代理。把它做成可配參數,預設值選一個能跑的,並在 README 說明兩種模式。這是本卡唯一需要 runner 判斷的地方,選了哪個要在回寫說明。evidence-classifier:<套件版號>),plugin/contract.py:50 的預設值同步改。開發期用 evidence-classifier:dev 驗證即可,正式 tag 在 T-6.2 發版時才定。scripts/evidence/classify/ 留一支 README,寫明「容器已搬到 jedi-evidence-classification 套件的 docker/,版本與套件連動」。只寫現況,不寫「本來在這裡、CM-xxxx 搬走的」——沿革進 commit message。docker run --network none -v <dir>:/job -e ANTHROPIC_API_KEY=... evidence-classifier:dev service-classify --input-dir /job --output-dir /job → 跑出 _report-original.json(網路模式若不是 none,用實際選的模式跑並在回寫說明)。