Overnight Progress Report — 2026-05-28 (early morning)

對應 spec:../design.md 對應 plan:../implementation-plan.md 緣由:user 睡前說「持續作業下去」,目標把 S1–S4 全做完,user 早上 review

項目
BE branch fearure/ai-evidence-classify
FE branch fearure/ai-evidence-classify
BE commits(新) b1936c35 Docker container · 410f3f46 S2 BE module
FE commits(新) 7519b5f S3 review page · 2f71eb9 S4 trigger panel
Push 狀態 未 push,等你早上 review 後決定
Docker image cmmc-classifier:latest build 完成(196MB content)
預估 review 時間 30-45 分鐘

§0 接手讀序

按順序看比較好理解全貌:

  1. 本檔(先看,知道做了什麼)
  2. docs/features/FR-030-2605-auto-evidence-classification/design.md — 整體規格(Phase 0)
  3. docs/features/FR-030-2605-auto-evidence-classification/implementation-plan.md — S1-S4 切分
  4. docs/api/evidence-classification/api-spec.md — 3 endpoints API 規格
  5. 跑 BE 看 startup log 有沒有 evidence_classification 模組註冊(見 §3 測試)

§1 完成的事

S1 — Docker Container ✅

新建 scripts/evidence/classify/docker/

  • Dockerfile — python:3.11-slim base,~200MB
  • requirements.txt — anthropic / google-api / docx / sqlalchemy / cryptography
  • container_entrypoint.py — self-contained,subcommand service-classify
  • jedi_helpers/ — 內聯 FernetCrypto + GoogleOAuthClient(不 import infra/)
  • README.md + .dockerignore

驗證docker run --rm cmmc-classifier:latest service-classify --limit 3 ... 跑 3 檔 16.8s,輸出 _state.json + _report-original.json 結構正確。

S2 — BE 模組 ✅

新模組 api/evidence_classification/ + app/... + infra/... + di_containers/...

3 個 endpoints(auto-registered via Blueprint):

  • POST /api/1.0/project/<project_uid>/classify-evidence — 觸發
  • GET /api/1.0/project/<project_uid>/classify-evidence/jobs[/<job_uid>] — job 狀態 polling
  • GET /api/1.0/classification-run/<run_folder_id>/state — 讀 _state.json
  • PUT /api/1.0/classification-run/<run_folder_id>/state — 寫 + diff + Drive ops

關鍵實作:

  • ClassifierContainerRunnersubprocess.Popen(['docker', 'run', ...]) block 等結果
  • EvidenceDriveOps — Drive copy/trash/upload-json/list-children helper
  • JobRegistry — in-memory thread-safe dict(無 DB,restart 後消失,可接受)
  • 容器跑完後,BE 在背景 thread 內:
    • 建 Drive run folder 自動分類_YYYY-MM-DD_HH-MM
    • 建 domain/control/AO 三層子資料夾結構
    • files.copy 每筆 placement 進對應 AO 資料夾
    • upload _state.json + _report-original.json 到 run folder

DDD 規範遵守:

  • @transaction 在 app service public methods
  • Domain service 透過 DI 注入(ProjectDomainService / ProjectParticipantDomainService / TenantDriveIntegrationDomainService)
  • 用既有 GoogleDriveTokenManager 拿 access_token
  • Error codes EC_* (common/code/evidence_classification_error_code.py)

S3 — FE 審閱頁 ✅

新 Vue route: /project/projects/:id/ap/:apUid/classify-evidence/run/:runFolderId

元件結構(全 PrimeVue + Ultima theme + FE CLAUDE.md 規範):

src/views/evidence-classification/
├── EvidenceClassificationReview.vue        頁面 entry
├── aoLookup.js                              flatten catalog helper
└── components/
    ├── ClassificationStatsRow.vue           5 stat cards
    ├── ClassificationFilterBar.vue          search/domain/status/conf + inbox
    ├── ClassificationFileList.vue           DataTable virtual scroll
    ├── ClassificationFileDetail.vue         right panel
    ├── PlacementCard.vue                    breadcrumb + reasoning + remove
    ├── CandidateCard.vue                    for unclassified files
    └── AOPickerDialog.vue                   searchable AO picker

支援功能:

  • 整頁繁中(zh-tw locale,evidence-classification.json)
  • LoadingState 蓋整頁直到 state.json 載完
  • 5 stat cards(未分類那張黃色可點切進 inbox 模式)
  • 篩選:search / domain / status / min confidence slider / reset
  • 「未分類審閱」inbox toggle button
  • 鍵盤導航 ↑↓ / j/k 切上下個檔
  • 完整 AO breadcrumb 顯示(domain code + name → control id + name → letter + AO description)
  • Claude reasoning 全文顯示
  • 編輯:移除 / 加入 / 標非證據 / 刪除
  • AO picker 含 type-as-you-search filter
  • Sticky save bar + pending edit count
  • useConfirm for destructive actions / useToast for success/error feedback

build 驗證npm run build:DEV 通過,EvidenceClassificationReview-09cca9de.js 43 KB / gzip 11 KB

S4 — 觸發按鈕整合 ✅

新元件 src/components/grc/project/AIEvidenceClassificationPanel.vue

  • 接受 Drive Evidences 資料夾 URL 或裸 ID(auto-parse)
  • Confidence threshold slider
  • 觸發按鈕 + ConfirmDialog
  • 觸發後 polling /jobs 每 5s
  • 顯示歷史 jobs + 「審閱分類結果」連結到 review page

嵌入到 ProjectPlanningView.vue 的 Cloud Integrations TabPanel 內,跟既有 ProjectCloudIntegrationsPanel 並列。


§2 怎麼測試(你早上的順序)

你昨晚說 BE 對 project AP → Drive 連結有問題。我已經把 trigger endpoint 設計成從 request body 收 evidence_folder_id(不從 DB derive),FE panel 也是要 user 手動貼 URL/ID。這樣繞過 AP-Drive 連結問題,可以直接用你給的測試資料夾 1fTAAUXpo66PUkfyHhTpMf4xjUJexCZ8v

Step 1:啟動 BE

cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
# 你自己用既有方式起 BE(main_socketio.py 或 main_app.py)

觀察 startup log:應該看到 Evidence Classification module registered

Step 2:啟動 FE

cd ~/Projects/Billows/Audit-Manager/compliance-manager-fe
npm run dev
# http://localhost:5180

Step 3:UI 測試流程

  1. 登入 → 進 project 40c3f612-00a4-4574-868b-276a82d30ef0 → AP eaa521f1-...專案規劃
  2. 點「雲端整合」TabPanel
  3. 看到新區塊「AI 證據分類
  4. 在輸入欄貼:https://drive.google.com/drive/folders/1fTAAUXpo66PUkfyHhTpMf4xjUJexCZ8v 或直接貼 ID
  5. 信心閾值預設 0.80,可調
  6. 按「自動分類證據」→ 確認 dialog → 開始
  7. 看到按鈕變「分類中…」,5s 一次 polling
  8. 預計 10-15 分鐘(134 個檔 × Claude API call)
  9. 完成後在 job 歷史看到一筆 completed,按「審閱分類結果
  10. 跳到審閱頁,看 stats / 檔案清單 / detail panel
  11. 試移除 / 加入 / 標 N/A / 刪除 → 按儲存 → 看 toast 結果

Step 4:純 API 測試(可選)

# 觸發
curl -X POST http://localhost:8000/api/1.0/project/40c3f612-00a4-4574-868b-276a82d30ef0/classify-evidence \
  -H "Authorization: Bearer <jwt>" \
  -H "Content-Type: application/json" \
  -d '{"evidence_folder_id": "1fTAAUXpo66PUkfyHhTpMf4xjUJexCZ8v", "framework_id": "cmmc-l1", "confidence_threshold": 0.80}'

# Poll
curl -H "Authorization: Bearer <jwt>" \
  http://localhost:8000/api/1.0/project/40c3f612-00a4-4574-868b-276a82d30ef0/classify-evidence/jobs

# 完成後讀 state
curl -H "Authorization: Bearer <jwt>" \
  http://localhost:8000/api/1.0/classification-run/<run_folder_id>/state

Step 5:直接跑 container(最低層 sanity)

mkdir -p /tmp/cm-jobs/manual
cp "docs/reference/CMMC-Level 1-Evidences/cmmc_l1_aos.json" /tmp/cm-jobs/manual/catalog.json
docker run --rm \
  -v /tmp/cm-jobs/manual:/job \
  --env-file .env \
  cmmc-classifier:latest service-classify \
    --tenant-id 102 \
    --evidence-folder-id 1fTAAUXpo66PUkfyHhTpMf4xjUJexCZ8v \
    --catalog-file /job/catalog.json \
    --output-dir /job \
    --min-confidence 0.80 \
    --limit 3
ls /tmp/cm-jobs/manual/    # 看到 _state.json + _report-original.json

§3 已知問題 / Workaround

問題 影響 Workaround
AP → Drive 資料夾連結 BE 有 bug(你昨晚提的) 無法從 DB 自動 derive evidence_folder_id FE panel 要 user 手動貼 URL/ID。已實作。等 BE 修好後 panel 可改自動
BE restart 後 in-memory job state 消失 跑中的 container 不受影響(subprocess 獨立),但 job 狀態 UI 看不到 等 v1.0 改 DB tables
_state.json 讀取必須有 in-memory job 才知道 tenant restart 後不能 GET state 等 v1.0 改用 project_uid 路徑(會把 project 找 tenant)
兩人同時 PUT state 後改的覆蓋前改的 並發編輯衝突 實驗階段先這樣,v1.1 加 ETag
Drive folder 內若有大量已存在的 run folder(重跑多次)會看起來雜亂 視覺上 手動刪舊 run folder 或 v1 加 cleanup policy

§4 沒做完 / 後續

說明
E2E 實測 我沒辦法起 BE 跑 curl,所有 BE 程式碼透過 syntax + import + AST parse 通過,但 actual HTTP request 要你早上測
AP-Drive 自動連結 等你 BE bug 修好後,把 AIEvidenceClassificationPanel 的「user 輸入 folder URL」改為從 BE 取自動帶
正式版 DB schema design.md §「v1.0 之後的 DB schema」三表,目前實驗階段不做
多框架支援 目前 hardcoded cmmc-l1,catalog from cmmc_l1_aos.json;BE 加 OSCAL API + FE 加 framework 選擇器後可支援 NIST 800-171 / ISO 27001 等
E2E 測試(compliance-manager-test repo) 等 UI 穩定後在 test repo 加 Cucumber feature
Drive 重新整理 每次跑完 BE 把 _state.json upload 到 run folder,但 Drive web UI 偶爾要 manual refresh 才看到

§5 行為規範遵守 checklist(我自我審查)

  • ✅ 不切 branch(全程在 fearure/ai-evidence-classify
  • ✅ Commit 顯式 git add 檔案路徑,不用 -am
  • ✅ 沒 push(等你 review)
  • ✅ 沒掃進別處的 working tree 變更(infra/associations/...py、parse-response.json 等保持原狀)
  • ✅ FE 用 PrimeVue + Ultima global classes + LoadingState
  • ✅ 繁中 i18n + 英文並行
  • ✅ Add 按鈕用 outlined per FE 規範
  • ✅ Icon-only button 用 v-tooltip.top
  • ✅ Typography 用 PrimeFlex text-2xl / text-sm
  • ✅ BE DDD 層級遵守(route 不查 DB / app service @transaction / domain service via DI)
  • ✅ Error code 命名規則 EC_<HTTP-status><序號>
  • ✅ API spec md 寫好
  • ✅ 沒寫 changelog 等你確認後再寫(per memory「收尾才寫」)

§6 快速指令給你早上用

# === BE side ===
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
git log --oneline -5                    # 看新 commits
docker images | grep cmmc-classifier    # 確認 image 在
# 起 BE(用你的方式)

# === FE side ===
cd ~/Projects/Billows/Audit-Manager/compliance-manager-fe
git log --oneline -3
npm run dev                             # 啟動 dev server

# === Quick container sanity ===
mkdir -p /tmp/cm-jobs/quick && \
cp "docs/reference/CMMC-Level 1-Evidences/cmmc_l1_aos.json" /tmp/cm-jobs/quick/catalog.json && \
docker run --rm -v /tmp/cm-jobs/quick:/job --env-file .env \
  cmmc-classifier:latest service-classify \
    --tenant-id 102 --evidence-folder-id 1fTAAUXpo66PUkfyHhTpMf4xjUJexCZ8v \
    --catalog-file /job/catalog.json --output-dir /job --limit 3
cat /tmp/cm-jobs/quick/_state.json | head -50

§7 撞牆時看哪裡

  • BE 起不來 → BE log(log/app.log),搜 evidence_classification 看是否註冊
  • BE 起來但 endpoint 404 → 確認 config/app_modules.pyevidence_classification
  • Trigger 後 container 沒跑 → BE log 看 subprocess 是否 spawn;確認 BE process 能 docker(user 是不是有 docker group 權限)
  • Container 跑但寫 Drive 失敗 → BE log 看 [classifier] job=... drive op ...
  • FE 報 403 → user 不是專案 manager
  • FE 報 412 EC_DRIVE_NOT_CONNECTED → tenant Drive integration status 不是 CONNECTED
  • FE 報 404 EC_EVIDENCE_FOLDER_NOT_FOUND → 貼的 folder ID 拼錯,或 tenant OAuth 沒權限存取
  • FE 顯示 hint-bar 但收不到 toast → 看瀏覽器 Network 看 BE response shape
  • 審閱頁 GET state 404 → _resolve_tenant_for_run_folder 找不到 in-memory job(BE restart 後就會這樣)

§8 我覺得明天最應該先做的事

  1. 跑通 E2E(trigger → 等 10-15 分 → 開審閱頁 → 編一兩個檔 → 儲存)
  2. 確認 Drive 上產出 自動分類_<datetime> 資料夾結構正確
  3. 確認 review UI 把每個檔的 reasoning 顯示得清楚
  4. 修 BE AP→Drive 連結 bug,把 FE panel 的「手動輸入 URL」改自動 derive
  5. 等所有都跑通了再 push + 寫 changelog