證據分類誤判報表(Classification Adjudication Report)
功能群:證據管理|AI 分類生命週期、兩種「證據」區分、EC_ 錯誤碼、核心資料模型先讀 功能群總覽|姊妹頁:驗證報表(同一 run 的另一份下游報表,算「量化準確度」)
事實基準:2026-07-05 從 FE / BE code 掃出(FR-031);API 欄位逐條對照
adjudication_report_builder.py組裝碼(本模組報表無 marshmallow serializer,route 直接回傳 builder dict,此 dict 即線上契約)。2026-07-06 自「證據分類報表」單頁拆分成 validation / adjudication 兩頁(各自對應獨立 FE route 與 view)。變更紀錄:2026-07-09 FR-047 U-2 —— 報表載入失敗(404)補 FE error state(error ref + catch +
v-else錯誤畫面 + 重試 + i18n key),不再留純空白
1. 功能描述
誤判報表是 AI 證據分類 run
的唯讀下游報表,回答「這個檔案該不該放這裡、User
和 AI 誰對誰錯」:以固定的 CANON
正解基準(cmmc_l1_canon.json,程式碼內附資源檔,非資料庫表)同標準檢視
User 與 AI 的放置,找出 User 誤放、AI
多放、超出框架範圍的檔案。不寫入任何資料——每次開啟都即時運算,以
report_original(AI 首次輸出,immutable)與
state(覆核頁 User 修正後的 placements)分別對 CANON
判定(見 _overview §2)。
量化的召回率/精確率是姊妹頁驗證報表的職責,兩頁 Header 有互跳按鈕。
主要使用者:專案參與者(v1 實驗階段僅檢查 JWT 登入,未鎖角色,見 §3);用於盤點分類覆核成效、裁決 User 與 AI 的分歧。
角色速覽(完整定義與本群角色基調見 _overview §5;本頁 v1 為實驗階段檢視,未鎖角色):
| 角色 | 一句話 |
|---|---|
| 專案參與者 | 任何通過 JWT 登入且能存取此 run URL 的使用者,皆可檢視 |
1.1 功能總覽(本頁全部功能)
| # | 功能 | 說明 | 位置 | 詳述 |
|---|---|---|---|---|
| 1 | Header:模型與門檻資訊 | 顯示本 run 使用的分類模型、confidence threshold | Header | §5 |
| 2 | 報表互跳按鈕 | 「查看驗證報表」+「返回覆核頁」導覽按鈕 | Header | §5 |
| 3 | 無 CANON 提示 | available=false
時只顯示提示訊息,其餘區塊全部不顯示 |
頁面頂部 | UC-ECR-02 |
| 4 | 判定基準圖例 | 說明 CANON 判定規則(放在 CANON 列出=對、放別的=錯、CANON 空集合=超範圍) | 頁面頂部 | §5 |
| 5 | User 未審閱警示 | note_user_equals_ai=true 時提示:本 run 尚未審閱,User
端等同 AI 端 |
頁面頂部 | UC-ECR-02 |
| 6 | User 標錯表 | 檔案 / User 誤放控制項 / CANON 正解 / AI 是否放對 / 理由;空清單顯示「(無)」 | 「一、User 標錯」 | UC-ECR-02 |
| 7 | AI 多放表 | 檔案 / AI 誤放控制項 / CANON 正解 / 理由;空清單顯示「(無)」 | 「二、AI 多放」 | UC-ECR-02 |
| 8 | 超出框架範圍表 | 檔案 / User 放置 / AI 放置 / 理由(CANON 該檔為空集合,兩邊只要有放就列) | 「三、超出範圍」 | UC-ECR-02 |
| 9 | 逐 AO 比對明細(依控制項摺疊) | <details> 巢狀:每控制項 has_issue
徽章(有放錯的預設展開),展開見每檔 User/AI verdict 著色 + 結論句 |
「四、逐 AO 明細」 | UC-ECR-02 |
UC(§2)展開本頁具實質後端邏輯的路徑:誤判報表整體檢視(UC-ECR-02,含功能 3、5~9)。功能 1(Header 資訊)、2(互跳按鈕)、4(判定基準圖例)為純顯示/導覽,見 §5。正解基準匯入(UC-ECR-03)影響本頁「User 未審閱警示」的判定,規格見驗證報表 §6.3。
2. Use Case
角色速覽(完整定義與本群角色基調見 _overview §5;本頁 v1 為實驗階段檢視,未鎖角色):
| 角色 | 一句話 |
|---|---|
| 專案參與者 | 任何通過 JWT 登入且能存取此 run URL 的使用者,皆可檢視 |
流程圖視覺慣例:菱形 = 判斷、橘底 = 例外/擋下、紅框 = 錯誤(標 error code)、綠框 = 成功終點、虛線 = 可選路徑。
UC-ECR-02 開啟誤判報表
| 項目 | 內容 |
|---|---|
| 角色 | 已登入使用者(無角色限制) |
| 前置條件 | run 已存在(DB 有列或 Drive 可回填);_state.json /
_report-original.json 可讀取;另需
cmmc_l1_canon.json 資源檔存在才能產出完整內容 |
| 產出 / 後置條件 | 純讀取;CANON 缺檔時回傳 available=false
精簡殼,不視為錯誤(HTTP 200) |
3. 權限矩陣
本群角色基調見 _overview §5。本頁實際檢查點:
| 操作 | FE 判定 | BE 強制 | BE 檢查位置 |
|---|---|---|---|
| 開啟誤判報表 | 無(路由可直接進入) | 僅 @jwt_required(),無角色守門 |
api/evidence_classification/routes/evidence_classification_route.py::ClassificationRunAdjudicationReportRoute.get |
⚠️ 已知不一致:報表 GET 無專案角色(manager/auditor)檢查,僅要求登入——與觸發分類本身(鎖 manager,
EC_NOT_MANAGER)不對稱。屬 v1 實驗階段已知邊界(見 _overview §7 坑 7),非資安定案,收斂鎖權限前不要假設此頁已受保護。
4. 狀態機與前置條件
本報表不受輪次 / AP 狀態機影響(無
assert_round_phase 或類似 phase guard);只要 run
存在即可檢視,即使專案已推進到後續階段。
| 條件 | 效果 | 出處 |
|---|---|---|
DB 無此 run_folder_id 且 Drive 也找不到
_state.json |
NotFound(EC_STATE_FILE_NOT_FOUND)(404) |
evidence_classification_service.py:997(_ensure_run_persisted_for_read) |
| DB / Drive 回填後仍拿不到 run 實體 | NotFound(EC_RUN_NOT_PERSISTED)(404,EC_404008:「分類結果尚未保存,無法產生報表」) |
同檔 :1094 |
cmmc_l1_canon.json 資源檔缺失 |
available=false,其餘欄位回空陣列/預設值(HTTP
200,非錯誤) |
adjudication_report_builder.py:30-33 |
| 無匯入正解 且未審閱 | note_user_equals_ai=true(User 端等同 AI
端,比對意義有限) |
同檔 :47-52 |
5. UI 設計
📸 實際畫面截圖待補(一律亮色模式拍攝):以 playwright 對 STG 擷取,預計補以下兩張到
assets/img/: ① 誤判報表整頁(Header + 判定基準圖例 + User 標錯/AI 多放表)ecr-adjudication-overview.png② 誤判報表逐 AO 明細摺疊區塊(<details>展開狀態,User/AI verdict 著色)ecr-adjudication-ao-detail.png
版面骨架與區塊職責(單欄長頁、無 tab、無
dialog,<details> 摺疊承載逐 AO
明細;彩色區塊可點跳本頁小節錨點,API 僅標代表性):
狀態呈現:共用元件
LoadingState(size="page")顯示載入中;無
per-item spinner(一次性整頁載入)。verdict
用固定色碼(correct=綠、wrong/out=紅、over=橘、undecided/none=灰)。無
socket,一次性 onMounted 載入,無輪詢或手動重載按鈕。
6. API 規格
Envelope:成功 {"status": true, "data": …}、失敗
{"status": false, "data": "<錯誤訊息>"}(common/util/response_util.py:4-16)。本模組無
marshmallow serializer——route 直接把 builder 回傳的 dict 交給
return_response,故下列欄位表即線上契約(來源是 builder
組裝碼,非 schema class)。
6.1 總清單(本頁呼叫的全部 endpoint)
| 分類 | Method + Path | 說明 | 完整規格 |
|---|---|---|---|
| 誤判報表 | GET
/classification-run/{run_folder_id}/report/adjudication |
質化誰對誰錯報表(CANON 為準) | §6.2 |
正解基準匯入 POST
/classification-ground-truth(背景操作)影響本頁note_user_equals_ai判定,完整規格見驗證報表 §6.3。
6.2 [GET] /classification-run/{run_folder_id}/report/adjudication
無 query 參數。Response data:
| 欄位 | 型別 | 說明 |
|---|---|---|
| available | bool | false = CANON 資源檔缺失,其餘欄位皆為空/預設值(FE
顯示「無 CANON」提示,不再渲染其他區塊) |
| run | object | available=true
時才有:{run_folder_id, model, confidence_threshold} |
| note_user_equals_ai | bool | true = 無匯入正解且 run 未審閱,User 端等同 AI
端(比對意義有限,FE 顯示警示) |
| user_wrong[] | array | {file, placed_control, placed_control_name, canon: [control_id...], ai_has_canon: bool, reason}——User
放置的控制項不在 CANON 內 |
| ai_wrong[] | array | {file, placed_control, placed_control_name, canon: [control_id...], reason}——AI
放置的控制項不在 CANON 內 |
| out_scope[] | array | {file, user: [control_id...], ai: [control_id...], reason}——CANON
判定該檔超出框架範圍(空集合)但雙方仍有放置 |
| undecided[] | array | {file}——該檔不在 CANON 規則內,不判對錯 |
| by_control[] | array | {control_id, control_name, has_issue: bool, aos: [{ao_id, ao_text, files: [{file, user_verdict, ai_verdict, canon: [control_id...], conclusion}]}]} |
user_verdict / ai_verdict
enum:correct(放對)/wrong(User 放錯,僅
User 側用此值)/over(AI 多放,僅 AI
側用此值)/out(超出範圍卻放了)/undecided(未裁定卻放了)/none(該
AO 未放)。
出處:app/evidence_classification/service/report/adjudication_report_builder.py:26-172(build_adjudication_report)、evidence_classification_service.py:1089-1101(get_adjudication_report,@transaction);CANON
讀取 report_common.py:196-212(load_canon,讀
app/evidence_classification/resources/cmmc_l1_canon.json)。錯誤:run
不存在 →
NotFound(EC_RUN_NOT_PERSISTED)(404,EC_404008)。
7. 前端檔案地圖(compliance-manager-fe/)
| 檔案 | 角色 |
|---|---|
src/views/evidence-classification/EvidenceClassificationAdjudicationReport.vue |
誤判報表主檢視(165 行) |
src/config/router/index.js:870-875 |
route
evidence-classification-report-adjudication,breadcrumb
parent 為 evidence-classification-review |
src/service/EvidenceClassificationService.js:56-59 |
getAdjudicationReport(),單參數
runFolderId 的 GET |
src/config/api/api.js:397 |
端點常數 CLASSIFICATION_RUN_REPORT_ADJUDICATION |
src/components/common/LoadingState.vue |
整頁 loading 元件(size="page") |
src/config/locales/i18n/{zh-tw,en}/evidence-classification.json |
頁面 i18n,namespace
evidence_classification.report.* |
本頁無專屬子元件(verdict chip、表格皆為手刻
<div>/<span>+ scoped CSS,非共用元件庫)。
8. 後端檔案地圖(本頁核心鏈路)
| 鏈路 | Route | App Service | 底層 |
|---|---|---|---|
| 誤判報表 | api/evidence_classification/routes/evidence_classification_route.py::ClassificationRunAdjudicationReportRoute |
app/evidence_classification/service/evidence_classification_service.py::get_adjudication_report(@transaction) |
report/adjudication_report_builder.py::build_adjudication_report
+ report_common.py::load_canon |
| run 讀取 / 惰性回填 | 同上共用 | _ensure_run_persisted_for_read(DB 優先,缺列則從 Drive
三檔案回填並 upsert) |
ClassificationRunRepoImpl(self._run_ds)+
Drive 讀檔(self._drive_ops) |
匯入正解查詢(note_user_equals_ai 判定用) |
— | _load_ground_truth_aomap |
ClassificationGroundTruthRepoImpl(self._gt_ds) |
DDD 提醒:report route 遵守「route 不碰 DB、app
service
@transaction」的層級規範;唯一偏離常規之處是無角色檢查(見
§3 已知不一致),新增類似報表 API 時不要照抄「無角色守門」這點。
9. DB
9.1 資料表總清單(本頁讀寫的全部表)
| 表 | 讀/寫 | 說明 | 欄位詳述 |
|---|---|---|---|
| compliance.evidence_classification_runs | 讀(惰性回填時寫,見 §12 坑 2) | 分類 run 記錄;report_original / state
JSONB 是判定的兩側輸入 |
驗證報表 §9.3(欄位定義同源,不重複) |
| compliance.evidence_classification_ground_truth | 讀 | 匯入正解基準;有值時 note_user_equals_ai 不成立 |
同上 |
本頁的判定基準另讀檔案資源
app/evidence_classification/resources/cmmc_l1_canon.json(非資料庫表,程式碼隨版本內附的固定 CANON 規則檔,全租戶共用)。
9.2 ER 圖(本頁讀取範圍)
10. 頁面邏輯與資料對應
載入時序:單次載入,onMounted 直接呼叫
report API,無並行請求、無分階段渲染。
關鍵欄位對應(畫面 ↔︎ API):
| 畫面元素 | FE state | API 欄位 |
|---|---|---|
| 無 CANON 提示 | !report.available |
available |
| User 未審閱警示 | report.note_user_equals_ai |
同名欄位 |
| User 標錯 / AI 多放 / 超出範圍三表 | report.user_wrong / .ai_wrong /
.out_scope |
同名欄位(皆空陣列時顯示「(無)」段落) |
| 逐 AO 摺疊 verdict 著色 | vCls(f.user_verdict) /
vCls(f.ai_verdict) |
by_control[].aos[].files[].user_verdict/ai_verdict |
儲存流程:無——本頁純讀取,無任何表單或儲存動作。
錯誤對應:BE
404(EC_STATE_FILE_NOT_FOUND /
EC_RUN_NOT_PERSISTED)目前無 FE
專屬錯誤畫面——load() 只用 try/finally
控制 loading,沒有 catch 顯示錯誤訊息;若 API
拋錯,report 維持
null,畫面停在空白狀態,使用者只看到 Header
而無任何內容區塊(見 §12 坑 1)。
11. 背景行為與外部依賴
| 類型 | 內容 |
|---|---|
| 通知 | 本頁無站內通知 |
| 背景 job | 本頁不觸發任何 job;分類本身(觸發 / 容器執行)屬覆核前置頁的背景行為,見 _overview §2 |
| Socket | 本頁無 socket / 輪詢;一次性載入,無重新整理機制(需重新整理瀏覽器才會重算) |
| jedi-* 套件 | jedi-auth(JWT);報表運算本身是純 Python
邏輯(app/evidence_classification/service/report/),不依賴
jedi-oscal 等領域套件 |
| 系統參數 / 資源檔 | app/evidence_classification/resources/cmmc_l1_canon.json(本頁
CANON 正解基準,隨程式碼版本內附,非資料庫、非可透過 UI 編輯) |
12. 邊界情況與已知坑
- API 錯誤已有 FE 錯誤畫面(2026-07-08 FR-047
U-2):原本
load()只有try/finally、無catch,run 不存在(404EC_RUN_NOT_PERSISTED)或狀態檔遺失(404EC_STATE_FILE_NOT_FOUND)時report保持null、頁面留純空白(僅 Header 渲染)。已補errorref +catch,模板加最終v-elseerror state(含重試)+ 1 個 i18n key。注意這跟available=false(HTTP 200,有明確「無 CANON」提示)是不同的空畫面 _ensure_run_persisted_for_read會惰性寫入 DB:本頁雖是「讀」頁,但若 run 尚未持久化(本期前的舊 run),BE 會從 Drive 回填三個檔案並upsert進evidence_classification_runs——屬一次性遷移行為,非常態- 兩個「正解基準」概念不同源:本頁的
canon(程式碼內附資源檔cmmc_l1_canon.json,全租戶共用固定規則,改動需改資源檔並隨版本部署)與驗證報表的ground_truth(DB 表,per-tenant×framework 可透過 API 匯入覆寫)是兩套不同機制,不要混為一談 - CANON
判定是精確控制項比對,不看同家族:
user_wrong/ai_wrong判斷是「放的控制項是否精確在 CANON 列出的集合內」,即使放到同一家族的相鄰控制項也算錯——比對邏輯比驗證報表的「AO選錯(已分到同控制項)」寬容度更嚴格,兩份報表對同一份錯誤分類可能給出不同嚴重度評價 - 無角色守門(v1 實驗階段):報表 GET 只檢查 JWT 登入,未限定專案角色(見 §3)
- 無重新整理機制:分類覆核頁修改 placements 後儲存進
_state.json(同步回 DBstate欄位),若使用者已開著本頁分頁,資料不會自動更新,需手動重新整理瀏覽器
13. 開發與驗證
- 跑起來:BE
python main_socketio.py(port 8000,log 在log/app.log);FE 在compliance-manager-fe/起 Vite dev server。BE 改 service / builder code 後必須重啟(無 hot reload) - 測試帳號:dev
環境一般登入帳號即可(無角色限制,密碼見
.env/ 部署文件) - 導航路徑:登入 → 專案 → AP → 證據分類覆核頁 → Header 進入「查看誤判報表」
- 前置資料:需已有一個分類
run(
run_folder_id)且 DB 或 Drive 可讀到_state.json/_report-original.json;若要看完整內容需確認cmmc_l1_canon.json資源檔存在於部署環境 - E2E:
compliance-manager-test/repo(Cucumber + Playwright);以分類報表/evidence-classification-report/adjudication搜尋 - 相關文件:FR-031(
docs/features/FR-031-2605-evidence-classify-reports/,設計背景,非行為真相來源);覆核前置頁見 evidence-classification-review.md;姊妹頁驗證報表;DB / API 全量見 GAI-SD-02/03