---
title: "稽核計畫：左側選單直達入口 — 設計定案 (FR-144)"
brand: "Guidant AI · **FR-144** 稽核計畫入口"
eyebrow: "FR-144 · 設計定案 v1 · 2026-10-17"
h1: "稽核計畫直達入口：設計定案"
subtitle: "左側選單「稽核計畫」、一個稽核次一列的表格、後端分頁、整列直達 FR-141 填寫頁"
lede: "左側選單「待辦任務」底下多一項「稽核計畫」，旁邊帶「待填寫」筆數。進去是一張表格：一個稽核次一列，狀態分段鈕帶筆數、一個搜尋框、欄頭排序、後端分頁、整列可點直達該份稽核計畫。版式與 FR-142「我的稽核」、FR-143「改善計畫」入口同一套。不加表、不動套件：一支清單讀模型＋端點、一筆選單登記、一支 FE 頁。本文件寫定案規則、為什麼這樣定、踩到會怎樣。"
chips: [
  {text: "D1～D3 定案（2026-10-17）", kind: ok},
  {text: "兩張卡，端點先、頁面後", kind: accent},
  {text: "不動套件、不加表", kind: plain},
  {text: "陷阱：目前稽核次不帶 pass、分母數 include-objectives", kind: crit}
]
footer: "FR-144 · 設計文件 · 2026-10-17 · 討論稿：[discussion.md](discussion.md)　雛形：[prototype/my-audit-plans.html](prototype/my-audit-plans.html) · 沿革見討論稿與 git log"
---

> 🔴 **這份是設計決策，不是現況。** 內文停在 2026-10-17 定稿當時，實作改動不回頭改寫這裡。

> 狀態：**設計定案，待開卡派工**｜討論稿：[`discussion.md`](discussion.md)｜雛形：[`prototype/my-audit-plans.html`](prototype/my-audit-plans.html)

> 檔案路徑與行號以 2026-10-17 為準，查不到時以函式名重新定位。路徑慣例：BE 路徑相對 `compliance-manager-be/`；FE 路徑相對 `compliance-manager-fe/`；三個 repo 都在 `feature/FR-139`。

名詞：**稽核次**＝`compliance.audit_round_passes` 一筆，一輪裡每做一次稽核一筆、各自一份稽核計畫；**稽核計畫（AP）**＝FR-141 的計畫概要＋查核項目規劃；**評估目標（AO）**＝控制項底下的檢查項目，鍵是 part_id；**填寫站**＝流程範本「稽核計畫填寫」站，稽核次狀態 `audit_planning`，對應 job 的 `template_job_id` 是 `UserTask_ap_authoring`／`UserTask_internal_ap_authoring`／`UserTask_external_ap_authoring`；**參與者**＝`compliance.project_participants`。

## 變更紀錄 {#changelog nav="變更紀錄"}

| 日期 | 變更 | 對應 |
|---|---|---|
| 2026-10-17 | v1：D1～D3 定案；資料模型、清單查詢、端點契約、FE 頁面、兩張卡、端到端驗收 | 討論稿定案 |

---

## 分工概述（30 秒版） {#overview nav="概述"}

整案一句話：**左側選單多一項「稽核計畫」，點進去一張表格列跟我有關的每一份稽核計畫，點列直達 FR-141 的填寫頁。**

| 卡 | 做什麼 | 產出 | 完成怎麼判定（決策者親手做什麼、看到什麼） |
|---|---|---|---|
| **1** | 清單端點＋選單登記 | 讀模型、app service、route、schema、`ui_routes` seed migration、count 端點 | Swagger 用顧問帳號打 `POST /audit-plans/my/list`，回的列數＝DEV 裡該人是 auditor／manager／reviewer、且稽核次到填寫站以後的筆數，每列有專案、稽核次、狀態、百分比、期限、稽核日期、稽核人員、專案經理；`meta.status_counts` 五個狀態都有數字；用 viewer 帳號打到 403；DB 查 `ui_routes` 多一筆 `audit-plan-list` sort 25 綁 `grc.audit.read` |
| **2** | 清單頁＋選單徽章 | FE 新頁、路由、api 常數、i18n、側邊選單數字 | 登入顧問帳號，左側選單「待辦任務」底下看到「稽核計畫 N」；進去對照雛形：分段鈕切狀態筆數會變、搜「外稽」只剩外稽列、點欄頭排序、翻頁、點列跳到 FR-141 頁且麵包屑顯示對的稽核次；專案經理帳號看到外稽未指派那列是「未指派」橘字、最右「去指派」跳專案規劃頁；覆核者帳號看得到列但只有「檢視」 |

依賴：1 → 2。卡 1 可先用 Swagger 驗完資料再開卡 2。

```{.mermaid cap="圖 1 — 兩張卡的依賴"}
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
flowchart LR
    C1[卡 1 清單端點＋選單登記] --> C2[卡 2 清單頁＋徽章]
    C2 -.點列.-> P[FR-141 稽核計畫頁（不動）]
```

---

## 決策定案 {#decisions nav="決策"}

| 決策 | 定案 | 理由 | 被排除方案 |
|---|---|---|---|
| **D1** 選單名稱與位置 | 「稽核計畫」（不帶「我的」），群組「專案與任務」內 sort 25，排在「待辦任務」（20）與「專案列表」（30）之間 | 填計畫的是顧問、判定的是稽核人員，常同一人但階段不同，分開不用猜；FR-143「改善計畫」入口定案後三個並列：稽核計畫（填）→ 我的稽核（判）→ 改善計畫（排） | 把「我的稽核」改成兩個頁籤 |
| **D2** 規劃中不列 | 清單只列稽核次狀態 `audit_planning` 以後（白名單 `audit_planning, auditing, remediation, pending_reverify, closed`） | 與「我的稽核」同一條白名單邏輯；規劃中的點進去是空的，會被當壞掉 | 列出並標「尚未開始」 |
| **D3** 外稽未指派 | 稽核次到填寫站但 AP 沒有稽核人員、且登入者是該專案 manager → 稽核人員欄「未指派」、最右鈕「去指派」導到 `project-planning-round`；登入者只是 auditor → 該列不出現 | 外稽人員多是外部顧問，先指派才有人填；在清單就看得到「這份沒人」 | 一律顯示「檢視」 |
| **歸屬判準** | 只看 `project_participants`：role in (auditor, manager, reviewer)。auditor／manager 可編輯（待填寫時），reviewer 只能檢視，viewer 不列 | AP 的稽核人員 party 只有姓名與 email、沒連登入帳號，系統無法確定「計畫裡的周雅婷」是不是登入者；「我的稽核」也是用參與者表，兩頁一致 | 用 AP 稽核人員名單判 |
| **粒度** | 一個稽核次一列（「我的稽核」是一輪一列） | 每個稽核次各自一份計畫，一輪一列會把內稽第 2 次、外稽藏起來 | 一輪一列、列內再展開 |
| **進度** | 只列查核項目：有填方法的 AO 數／AO 總數，印百分比；計畫概要六段不列 | 決策者裁：進度條要滑鼠才看得到、概要不用 | 進度條；兩個百分比 |
| **版面** | 一格一件事，最多一行小字；日期完整、有時間帶時間、起迄各一行；不列「我的角色」欄 | 決策者裁（看稽核人員或專案經理欄哪個有自己的名字加粗就知道角色） | 複合欄塞小字；「我的角色」欄 |
| **分頁** | 後端分頁，走 jedi-common `RequestMetaSchema`／`EnvelopeSchema`；分段鈕筆數由 `meta.status_counts` 回 | 資料會成長；筆數若只回當頁算不出來 | 前端一次拉全部自己分頁 |
| **搜尋** | 一個框：專案名、框架、稽核人員、專案經理、稽核性質（打「外稽」「內稽」「外部」「內部」都命中） | 與 FR-142 做法一致，工具列少三個下拉 | 狀態／性質／角色三個下拉 |

---

## 現況接入點 {#inventory nav="接入點"}

| 元件 | 現況 | 本案動作 |
|---|---|---|
| `public.ui_routes` 群組 42「專案與任務」 | 專案儀表板 10／待辦任務 20／專案列表 30／我的稽核 40；`route_capabilities` 綁能力點，我的稽核綁 `grc.audit.read` ALL | 卡 1 seed `audit-plan-list`，url `/project/audit-plans`，icon `pi pi-list`（primeicons 6.0.1 沒有 pi-list-check），sort 25，is_menu true，綁 `grc.audit.read` ALL |
| 「我的稽核」`POST /grc/audits/my/list`（套件 jedi-compliance-audit route → 主專案 `app/readmodel/service/auditor_dashboard_service.py` → `infra/readmodel/audit/auditor_dashboard_query.py`） | raw SQL 讀模型、`.mappings()` 不外流、回 list[dict]；FR-142 線正在改它（加 people／risk 兩支） | **不改**。卡 1 照它的檔案形狀另寫一支；**等 FR-142 那條線的改動 commit 後再開工**，免得對著變動中的樣板抄 |
| `compliance.audit_round_passes` | `round_id`、`pass_no`、`audit_nature`、`nature_seq`、`status`、`assessment_plan_id`（外稽未開始為 NULL）、`updated_at` | 清單主表 |
| `compliance.project_audit_rounds` | `round_no`、`current_pass_id`、`workflow_execution_uid`、`project_id` | 取輪號、是否目前稽核次、連 job |
| `compliance.job_executions` | `template_job_id`、`status`、`due_at`、`workflow_execution_id`；填寫站 job 的 template_job_id 是三個 `*_ap_authoring` 之一；**DEV 樣本 due_at 多為 NULL** | 取填寫期限；NULL 顯示「—」 |
| `oscal.ap_reviewed_controls.control_objective_selections` | FR-141 B1 寫入，形狀 `[{"include-objectives":[{"objective-id":"<part_id>"},…]}]`；**jsonb_array_length 外層恆為 1，分母要數內層** | AO 總數 |
| `oscal.ap_assessment_activities` | 一條 AO 一筆，`steps[].props[{name:"method"}]` | 已填數＝steps 內任一 props 有 method 的 activity 數 |
| `oscal.ap_tasks.timing` | `{"within-date-range":{"start","end"}}` 日期時間字串 | 稽核日期 |
| `oscal.parties`（AP metadata 下） | person、props `responsible-role=assessor` | 稽核人員名單；空＝未指派 |
| FE `src/views/project/MyAuditsView.vue`（245 行）、FR-142 雛形 `prototype/my-audits.html` | 卡片式；FR-142 提案改表格 | 卡 2 新頁 `AuditPlanListView.vue`，照 FR-142 雛形版式刻；若 FR-142 先做完表格版「我的稽核」，兩頁抽一個共用表格殼 |
| FE 路由 `project-ap-authoring-round`（`src/config/router/index.js:1118`） | 帶 `?pass=<uid>` 看非目前稽核次（唯讀） | 點列：目前稽核次不帶 pass，其他帶 |
| FE 側邊選單 `src/layout/AppMenuItem.vue` | label 走 `lang.menu.<route name>`，無徽章機制 | 卡 2 加徽章：選單項可選配 `badge` 計數來源；與 FR-143 改善計畫入口共用 |

---

## 詳細設計 {#detail nav="詳細設計"}

### ① 清單查詢（卡 1）

檔：`infra/readmodel/audit/audit_plan_list_query.py`（新）。照 `auditor_dashboard_query.py`：`@property session`、raw SQL、`.mappings()` 只在函式內讀、回 `list[dict]`＋`total`＋`status_counts`。

主查詢（一句 SQL，分頁與排序在 SQL 做）：

```sql
WITH mine AS (                                  -- 我在哪些專案、什麼角色
  SELECT project_id, array_agg(role) AS roles
    FROM compliance.project_participants
   WHERE user_id = :uid AND role IN ('auditor','manager','reviewer')
   GROUP BY project_id
), base AS (
  SELECT ps.id AS pass_id, ps.uid AS pass_uid, ps.pass_no, ps.audit_nature, ps.nature_seq,
         ps.status, ps.assessment_plan_id, ps.updated_at AS pass_updated_at,
         r.uid AS round_uid, r.round_no, (r.current_pass_id = ps.id) AS is_current,
         r.workflow_execution_uid,
         p.uid AS project_uid, p.name AS project_name, p.framework_name,   -- 框架欄依專案表實際欄位
         m.roles AS my_roles
    FROM compliance.audit_round_passes ps
    JOIN compliance.project_audit_rounds r ON r.id = ps.round_id
    JOIN compliance.projects p ON p.id = r.project_id AND p.deleted_at IS NULL
    JOIN mine m ON m.project_id = r.project_id
   WHERE ps.status = ANY(:visible_statuses)                 -- D2 白名單
)
SELECT b.*,
       -- 進度
       (SELECT count(*) FROM oscal.ap_assessment_activities a
         WHERE a.assessment_plan_id = b.assessment_plan_id
           AND EXISTS (SELECT 1 FROM jsonb_array_elements(a.steps) s, jsonb_array_elements(s->'props') pr
                        WHERE pr->>'name' = 'method' AND coalesce(pr->>'value','') <> '')) AS filled_ao,
       (SELECT count(*) FROM oscal.ap_reviewed_controls rc,
               jsonb_array_elements(rc.control_objective_selections) s,
               jsonb_array_elements(s->'include-objectives') o
         WHERE rc.assessment_plan_id = b.assessment_plan_id) AS total_ao,
       -- 稽核日期
       (SELECT t.timing->'within-date-range'->>'start' FROM oscal.ap_tasks t WHERE t.assessment_plan_id = b.assessment_plan_id LIMIT 1) AS audit_start,
       (SELECT t.timing->'within-date-range'->>'end'   FROM oscal.ap_tasks t WHERE t.assessment_plan_id = b.assessment_plan_id LIMIT 1) AS audit_end,
       -- 填寫期限：該輪 workflow 下、填寫站那張 job
       (SELECT j.due_at FROM compliance.job_executions j
          JOIN compliance.workflow_executions w ON w.id = j.workflow_execution_id
         WHERE w.uid = b.workflow_execution_uid
           AND j.template_job_id IN ('UserTask_ap_authoring','UserTask_internal_ap_authoring','UserTask_external_ap_authoring')
         ORDER BY j.id DESC LIMIT 1) AS plan_due
  FROM base b
 WHERE (:kw IS NULL OR b.project_name ILIKE :kw OR b.framework_name ILIKE :kw
        OR (:kw_nature IS NOT NULL AND b.audit_nature = :kw_nature)
        OR EXISTS (稽核人員名單 ILIKE :kw) OR EXISTS (manager nickname ILIKE :kw))
   AND (:status IS NULL OR b.status = :status)
 ORDER BY <排序> LIMIT :size OFFSET :offset;
```

稽核人員與專案經理名單用第二、三句批次查（`WHERE assessment_plan_id = ANY(:ap_ids)`、`WHERE project_id = ANY(:project_ids) AND role='manager'`）再在 Python 組回每列，不在主查詢 string_agg（名單要保留順序與「是不是我」）。

`status_counts`：同一個 `base`＋搜尋條件、不套 `:status`，`GROUP BY status`。

預設排序：`CASE status WHEN 'audit_planning' THEN 0 … END, plan_due NULLS LAST, pass_updated_at DESC`。可排欄：project（name）、pass（round_no, nature, nature_seq）、status、progress（filled_ao/total_ao）、due、audit（audit_start）、manager、updated。

搜尋詞對稽核性質：「外稽」「外部」→ `external`；「內稽」「內部」→ `internal`；在 app service 層翻成 `:kw_nature`。

### ② App service 與端點（卡 1）

- `app/readmodel/service/audit_plan_list_service.py`（新）：`@transaction list_my_audit_plans(user_id, status, keyword, page, size, sort)` 回 `{"items":[…], "total", "status_counts"}`；`@transaction count_my_pending(user_id)` 只數 `audit_planning` 且非 reviewer-only。專案經理 nickname 走 `common/util/audit_nickname.py` 的既有 enrich。
- DI：`di_containers/flow_control/flow_control_containers.py` 加 Factory（照 `auditor_dashboard_service` 那段）。
- Route：`api/project/routes/audit_plan_list_route.py`（新，主專案，不進套件）。`POST /audit-plans/my/list`、`GET /audit-plans/my/count`。守門 `@jwt_required` ＋ `@require_license("audit")` ＋ `@capability_required("grc.audit.read")`（與「我的稽核」同，從 `common.authz` 取）。
- Schema：`api/project/serializers/audit_plan_list.py`（新）。Request 繼承 `RequestMetaSchema`＋`filters{status, keyword}`；Response 繼承 `EnvelopeSchema`，`data` 是 item 陣列，`meta` 多一個 `status_counts: {audit_planning, auditing, remediation, pending_reverify, closed}`。

每列欄位：

| 欄 | 型別 | 來源 |
|---|---|---|
| project_uid, project_name, framework | str | projects |
| round_uid, round_no | str, int | rounds |
| pass_uid, pass_no, audit_nature, nature_seq, is_current | str, int, str, int, bool | passes |
| status | str | passes.status |
| ap_uid | str／null | AP；null＝尚未建立 |
| filled_ao, total_ao, progress_pct | int, int, int／null | 上述子查詢；ap_uid null 時三者 null |
| plan_due | iso／null | job due_at |
| audit_start, audit_end | iso／null | ap_tasks.timing |
| auditors | [{uuid, name}] | AP parties assessor |
| managers | [{login_name, nickname}] | participants manager |
| my_roles | [str] | participants（登入者） |
| can_edit | bool | status=audit_planning and is_current and ('auditor' in my_roles or 'manager' in my_roles) |
| needs_assign | bool | ap_uid null or auditors 空，且 'manager' in my_roles |
| updated_at | iso | greatest(pass.updated_at, AP 各表 updated_at) |

### ③ 選單登記（卡 1）

`scripts/sql/2026-10-xx-fr144-audit-plan-list-route.sql`，主線 `phase=seed`，照 `2026-10-15-fr139-version-history-routes.sql` 四段：① `ui_routes` INSERT（`WHERE NOT EXISTS name='audit-plan-list'`；root 0、pid 42、name `audit-plan-list`、url `/project/audit-plans`、icon `pi pi-list`（primeicons 6.0.1 沒有 pi-list-check）、sort 25、is_menu true、description 「稽核計畫清單（登入者相關的每一份）」）；② `route_capabilities` 綁 `grc.audit.read` ALL；③ DO 區塊驗「存在、pid=42、恰一顆 ALL」；④ `schema_migrations` 登記。只套 DEV；寫完回報「出貨基線待重產」。

### ④ 清單頁（卡 2）

- 路由：`/project/audit-plans`，name `audit-plan-list`，component `@/views/project/AuditPlanListView.vue`，meta breadcrumb label `audit-plan-list`。
- api 常數：`AUDIT_PLANS_MY_LIST: getUrl('/audit-plans/my/list')`、`AUDIT_PLANS_MY_COUNT: getUrl('/audit-plans/my/count')`。
- i18n：`src/config/locales/i18n/{zh-tw,en}/menu.json` 加 `audit-plan-list`（「稽核計畫」／"Audit Plans"）與描述；新檔 `audit-plan-list.json` 放頁內字串（分段鈕、欄名、空狀態「當你被列為某份稽核計畫的稽核人員，或你管理的專案進到稽核計畫填寫站時，會出現在這裡」、按鈕 tooltip）。
- 頁面照雛形：`SelectButton` 或 Button 群當分段鈕（帶 `meta.status_counts`）、`IconField` 搜尋框（300ms debounce）、PrimeVue `DataTable` lazy 模式（`:lazy="true"` `@page` `@sort` 打後端），欄位與格式照雛形「一格一件事」；整列 `@row-click` 導頁；最右 icon-only Button 必配 `v-tooltip.top`；loading 配 `:loading`。
- 導頁：`router.push({name:'project-ap-authoring-round', params:{id: project_uid, roundUid: round_uid}, query: is_current ? {} : {pass: pass_uid}})`；`needs_assign` → `{name:'project-planning-round', params:{id, roundUid}}`。
- 徽章：`AppMenuItem.vue` 支援 item 可選 `badgeCount`；選單載入時與從本頁離開時打 count 端點一次；FR-143 改善計畫入口沿用同機制。

---

## 端到端驗收 {#acceptance nav="驗收"}

1. **選單**：顧問帳號登入，左側「待辦任務」底下出現「稽核計畫 N」，N＝待填寫筆數；viewer-only 帳號看不到此項。
2. **清單內容**：DEV 建一個專案，走到填寫站（內稽第 1 次），清單出現一列「第 1 輪 · 內稽第 1 次」待填寫 0%；在 FR-141 頁填三條 AO 的方法後回清單，百分比變為 3／總數；填計畫概要的稽核日期後，稽核日期欄兩行顯示。
3. **多稽核次**：同專案走到內稽第 2 次，清單多一列「內稽第 2 次」，第 1 次那列變「稽核中」或「已結案」、只有檢視。
4. **外稽未指派**：走到外稽填寫站且未指派稽核人員；PM 帳號看到該列「未指派」＋「去指派」跳專案規劃頁；只是 auditor 的帳號看不到該列。
5. **覆核者**：reviewer 帳號看得到列、只有「檢視」、按下去 FR-141 頁唯讀。
6. **分段鈕與搜尋**：切「已結案」筆數與列數一致；搜「外稽」只剩外部稽核；搜人名只剩該人參與的；清空回全部。
7. **排序與分頁**：點「填寫期限」升、降、取消三態；每頁 20，第二頁有資料；排序切換後分頁回第 1 頁。
8. **點列導頁**：目前稽核次的列導到 FR-141 頁可編輯；已結束那次的列導過去是唯讀且麵包屑顯示該次。
9. **D2**：規劃中的輪次不在清單。
10. **期限**：填寫站 job 有 due_at 的列，待填寫時顯示「逾期 N 天」或「剩 N 天」；鎖定後不標。

---

## 拆分表 {#cards nav="拆卡"}

| 卡 | 範圍 | 動哪裡 | 套件 | 依賴 | 驗收 |
|---|---|---|---|---|---|
| **1** 清單端點＋選單登記 | 讀模型、app service、DI、route、schema、count 端點、seed migration | BE 新檔 `infra/readmodel/audit/audit_plan_list_query.py`、`app/readmodel/service/audit_plan_list_service.py`、`api/project/routes/audit_plan_list_route.py`、`api/project/serializers/audit_plan_list.py`、`scripts/sql/2026-10-xx-fr144-audit-plan-list-route.sql`；改 `di_containers/flow_control/flow_control_containers.py`、route 註冊 | 無 | **等 FR-142 線對 auditor_dashboard_* 的改動 commit 後再開** | 驗收 2～4（API 部分）、9、10 |
| **2** 清單頁＋徽章 | 新頁、路由、api 常數、i18n、側邊選單徽章 | FE 新檔 `src/views/project/AuditPlanListView.vue`、`src/config/locales/i18n/{zh-tw,en}/audit-plan-list.json`；改 `router/index.js`、`api.js`、`menu.json`×2、`layout/AppMenuItem.vue` | 無 | 卡 1 | 驗收 1～10 |

---

## 坑與陷阱 {#pitfalls nav="坑"}

| # | 坑 | 怎麼避 |
|---|---|---|
| 1 | `control_objective_selections` 外層陣列長度恆為 1，拿它當分母全部變 1 | 分母數內層 `include-objectives` |
| 2 | 目前稽核次帶 `?pass=` 會讓 FR-141 頁進「檢視過去那次」唯讀 | `is_current` 為真不帶 pass |
| 3 | 外稽未開始 `assessment_plan_id` NULL，所有 AP 子查詢回 NULL | 一律 LEFT／子查詢；FE 顯示「尚未建立」「未指派」 |
| 4 | DEV 的填寫站 job `due_at` 多為 NULL，清單期限全空會被當 bug | 驗收 10 要先在流程範本設站期限再測 |
| 5 | 「我的稽核」一輪一列、本案一稽核次一列，兩頁列數對不上 | 刻意的；稽核次欄寫明第幾次 |
| 6 | `route_capabilities` 漏綁 → 所有人看不到選單項且無錯誤 | migration DO 區塊驗恰一顆 ALL |
| 7 | 徽章每切頁打一次 count | 只在選單載入與離開本頁時打；count SQL 不 join AP |
| 8 | 對著 FR-142 線變動中的 `auditor_dashboard_query.py` 抄形狀 | 卡 1 等那條線 commit 後開工，抄 commit 後的版本 |
| 9 | 搜尋詞「外部」同時命中專案名含「外部」的列 | 接受；性質比對是 OR 條件之一，不排除專案名 |
