# FR-047 Lane B 續跑 Handoff — 系統管理群 + 背景服務

| 項目 | 值 |
|------|-----|
| 緣由 | FR-047 功能 SPEC 量產（連續作業 Lane B）。本 session 已完成稽核執行收尾 + 證據管理 + 協作三群共 12 頁，context 將滿，交下一棒 |
| branch | `main`（不切 branch、不 push；已多次 commit 到 main，與並行 Lane A session 共用 main） |
| 接手前必讀 | 本檔全文 + `writing-feature-specs` skill（SKILL.md + references/page-spec-template.md）+ tracker |
| 本棒範圍 | **Lane B④ 系統管理群（_overview + 15 頁）+ Lane B⑤ 背景服務與排程（1 Opus 無 UI spec）** |
| 預估 | 系統管理 15 頁多為 Sonnet CRUD 頁，可大量並行；背景服務 1 頁 Opus 需自寫 |

## 🧭 原始需求 / WHY（先懂這個再動手）

FR-047 要把整個 Guidant AI 產品的每一條 FE route 寫成一份「給新手全端工程師查功能」的 13 節 spec（`docs/specs/v1.8.0/<群>/<頁>.md`），**markdown 是唯一內容源，HTML 站是 build 產物**。核心原則一句話：**spec 是 living truth，每個事實從 code / DB 掃出來，不憑記憶、不抄舊文件、不信探勘摘要的 schema 名**。

- 一個 spec = 一條 FE route（變體 / 精靈步驟 / form 子頁併入母頁）。
- 每群先寫 `_overview.md`（頁面地圖 / 共用狀態機 / 角色 / 核心資料模型）再放量頁面。**例外：協作群無 _overview（小群），系統管理群 tracker 有列 _overview 要寫。**
- 模型分工：**核心流程頁 = Opus（我自己寫）**、**管理 / 設定 / 列表頁 = Sonnet（派 subagent 寫、主導抽查紅線後才 commit）**。
- 品質紅線（違反 = 退件）：§1.1 功能總覽必須按 FE 實際 UI 元素逐項盤（不是腦補三大類）；§9 schema 名對 `scripts/deliverables/out/db_schema.json`；§6.1 endpoint 對 `scripts/deliverables/out/routes.json`；不憑 FR design 寫行為沒開 code 驗；角色/狀態機定義引用 _overview 不抄進頁面；禁 `git commit -am`、build 必跑、tracker 必更新。

## §0 接手讀序（按順序，先懂再做）

1. 🔒 **本檔全文** + `writing-feature-specs` skill 的 **SKILL.md 8 步流程** + **references/page-spec-template.md 13 節逐節規格 + 圖形化慣例**（全讀，這是硬 gate）
2. 🔒 pilot 合格範本：`docs/specs/v1.8.0/project-management/project-planning.md`（六輪定稿的樣貌）
3. 一份 Sonnet 產出的乾淨範本參考：`docs/specs/v1.8.0/audit-execution/my-audits.md`（簡潔、citation 紮實）
4. tracker：`docs/features/FR-047-2607-feature-spec-handbook/tracker.md`（系統管理群表 = line 105~124；狀態 / 模型 / 🔍 標記）
5. 本檔 §2（前次教訓）+ §3（系統管理群逐頁線索）+ §4（開工順位）+ §5（Sonnet dispatch 範本）

**冷接自檢 4 問（答不出來回去讀）**：
1. 這套 spec 給誰、md 與 HTML 站誰是真相？（新手工程師；md 是 living truth，HTML 是 build 產物）
2. Sonnet 頁與 Opus 頁分工怎麼分、我對 Sonnet 產出負什麼責？（管理/設定/列表→Sonnet 派；核心流程→自寫；Sonnet 產出我抽查 §1.1/§6.1/§9 紅線後才 commit）
3. schema 名 / endpoint 從哪來、可不可以信 subagent 摘要？（db_schema.json / routes.json 為準，subagent 摘要必核）
4. 每頁「完成」定義？（build ✅ + 敏感資訊 grep 0 + 「GRC 系統」grep 0 + 顯式 git add commit + tracker 更新）

## §1 現況（本 session Lane B 已完成）

**稽核執行群收尾**（commits `25c3420f` / `1d923a4c` / `9edea842`）：POA&M 矯正頁 + 我的任務 + 我的稽核。稽核執行群 5 頁全完成。
**證據管理群**（`1a3fdb66`→`c0c8d00b` + tracker `8f3fc789`）：_overview + 覆核 + 報表 + 雲端整合 + 檔案 Agent + 儲存設定 = 6 檔全完成。
**協作群**（`9f57cc84` / `cf26f3b1` / `c38d3309` + tracker `1de8dba2`）：公告管理 + 公告檢視 + 回饋管理 = 3 頁全完成（協作群無 _overview）。

FR-047 整體進度（tracker 統計）：已完成 23 頁 spec + 4 _overview = 27。並行的 Lane A session 同時在推專案管理群收尾 + 合規框架與 SSP 群（不同 dir，無衝突）。

## §2 前次教訓（本 session 踩過的雷，務必避開）

1. **⚠️ Sonnet full-writer subagent 會陷 delegation loop**：回饋管理那隻 Sonnet writer 自己去 spawn 研究 sub-agent，grandchildren 互相等待、狂燒 token（4 隻 ×~70k）不產出。**dispatch Sonnet writer 時務必在 prompt 明寫「Do NOT use the Agent tool / 不要再 spawn sub-agent，自己用 Read/Grep/Bash 蒐證直接寫」**。cloud-integrations 那隻也發生過但自己救回來了。若發現某隻在 loop：`TaskStop` 掉它，撿它 grandchild 已產出的 facts 自己寫（回饋頁就是這樣救的）。
2. **並行 build 會互撞**：多隻 subagent 同時跑 `render_html.py` 會因彼此 in-flight 的半成品 dot 引用而 build fail。**dispatch prompt 明寫「Do NOT run render_html.py，只 compile 自己的 dot（`dot -Tsvg <f> -o /dev/null`）」，authoritative build 由主導 session 在全部 subagent 回收後跑一次。**
3. **HTML-table label 的 `&` 要 escape**：dot 的 `<TABLE>` label 內 `POA&M` 會 build fail，要寫 `POA&amp;M`。一般 node label 的 `&` 沒事。
4. **schema 名一律查 db_schema.json**：subagent 常寫錯（如把 `compliance.task_assignees` 寫成 `participant.task_assignee`、feedback 主表其實是 `public.issues` 不是 feedback 表）。收 subagent 報告後抽查 §9 表名。
5. **error code 前綴各模組不同**：不是全 `GRC_`。證據分類 = `EC_`、回饋 = `FEEDBACK_`、雲端整合 = `GRC_DRIVE_*`+`GRC_NOT_ADMIN`。系統管理各模組要各自查 error code 檔。
6. **tracker 是並行寫的**：改 tracker 前**必重讀**（Lane A session 也在寫它）；只改自己那幾列 + 統計 + session 列，用 Edit 對唯一字串、別大段覆蓋。

## §3 本棒逐頁線索（系統管理群，tracker line 105~124）

先跑 `python3 -c` 撈 db_schema.json / routes.json（範本見 §6）確認每頁的表 / endpoint。多數是標準 CRUD 管理頁，jedi-* 套件常見。已知線索：

| 頁面 | route / 元件線索 | 模型 | 備註 |
|------|------------------|------|------|
| _overview | — | Sonnet | 系統管理群共用：RBAC 三層（角色→capability→ui_routes）、租戶/部門/使用者關係、system_configs key-value 慣例。權限系統 SOP 見 memory `reference_permission_system_sop` + `docs/claude/` |
| 使用者管理 | user-manage / user-form | Sonnet | routes `/user`,`/users`,`/user/*`；表 `users`；jedi-auth |
| 角色權限管理 | role-manage / role-form | **Opus（自寫）** | RBAC 核心：`/role`,`/roles/menu`,`/capabilities/menu`,`/ui-routes`；表 roles/capabilities/role_capabilities/ui_routes/route_capabilities。這頁是全系統權限樞紐，自己寫 |
| 選單管理 | system-menu-manage | Sonnet | `public.ui_routes`（真選單來源，見 memory `reference_fe_sidebar_menu_highlight`）|
| 部門管理 | department-manage | Sonnet | `/org-unit`,`/org-units/menu`；表 org_units |
| 租戶管理 | tenant-manage | Sonnet | `/tenant`,`/tenants/menu`；表 tenants |
| 設備管理 | device-manage | Sonnet | `/device`,`/devices/menu`；表 devices |
| 資訊系統盤點 | information-system-manage | Sonnet | grep FE 元件 + routes |
| 通知 / SMTP 設定 | notify-config / smtp-config(-manage) | Sonnet | system_configs（NOTIFY/SMTP group）+ `/send-user-test-mail` |
| LDAP 設定 | ldap-config | Sonnet | system_configs（LDAP group） |
| 議題整合設定 | issue-integrate-config | Sonnet | GitLab/GitHub 整合（餵回饋鏡像，見 collab/feedback-management.md §11）；表可能 system_configs 或專表 |
| 工具外掛管理 | tool-plugin-manage | Sonnet | **🔍 先驗 live**（FE 選單 / `ui_routes` enable=1），死 route 除名 |
| 操作日誌 | user-log | Sonnet | api_logs / system_logs（見 memory `reference_audit_event_logging_pattern`：api_logs 90 天 vs system_logs event_code 180 天） |
| 個人資料 | user-profile | Sonnet | `/user-profile/{uid}`,`/user/change-pwd*`,`/totp-secret`,`/otp-*` |
| 網站導覽 | sitemap | Sonnet | **🔍 可能併入 README 不獨立成頁**，先驗；死則除名 |
| 背景服務與排程（Lane B⑤） | —（無 UI） | **Opus（自寫）** | 見 §3.1 |

### §3.1 Lane B⑤ 背景服務與排程 spec（無 UI 頁，Opus 自寫）

非頁面 spec：盤點全部背景 job 的觸發 / 頻率 / 寫入表 / 故障行為，13 節模板適用的節照寫、不適用的標「N/A（無 UI）」。已知素材（本 session 蒐證副產品）：
- **Drive sync worker**：`app/cloud_integration/service/drive_sync_worker.py::run_once`，APScheduler interval job（`core/scheduler.py` job id `drive_sync_worker`，**每 5 秒** poll，batch_size=10，`claim_batch` FOR UPDATE SKIP LOCKED），8 個 handler 在 `app/cloud_integration/service/handlers/`。寫 `public.drive_sync_jobs`（webhook 驅動佇列）。
- **AI 分類容器**：`ClassifierContainerRunner`（Docker `cmmc-classifier`）背景跑，寫 `evidence_classification_runs` + Drive。
- 其他：socket 事件、心跳（remote_agents `last_seen_at`）、session 維護、通知寄送等——grep `core/scheduler.py`、`APScheduler`、`socketio`、`main_socketio.py` 盤全。
- 放檔位置：tracker 沒指定群，建議 `docs/specs/v1.8.0/system-admin/background-services.md`（與系統管理同群）或另開 `docs/specs/v1.8.0/background/`。看 render_html.py 的 `GROUP_NAMES`（`scripts/deliverables/render_html.py:22`）——system-admin 已註冊，background 未註冊。**放 system-admin 群省事**（不用改 render_html.py）。

## §4 開工順位

1. **pre-flight**（§6）：確認 branch=main、working tree、db_schema.json/routes.json 在、`dot` 可用、build 目前 ✅。
2. **建群 dir**：`mkdir -p docs/specs/v1.8.0/system-admin/assets/img`（render_html.py 已註冊 `system-admin`→「系統管理」，dir 自動被掃）。
3. **驗 🔍**：tool-plugin-manage / sitemap 先驗 live（grep FE nav 進入點 + `ui_routes`），死 route 在 tracker 標除名跳過。
4. **_overview 先寫**（Sonnet 可派，但建議自寫或親自審——它是全群共用知識，RBAC 三層是樞紐）。
5. **Opus 頁自寫**：role-manage、背景服務。用 Explore agent 蒐證（唯讀、產出佳、不會亂 spawn）+ 主導 synthesize。
6. **Sonnet 頁批次派**：其餘 12~13 頁，一批派 3~4 隻 Sonnet full-writer（prompt 帶 §5 鐵則）。分批以免同時太多。
7. 每批回收後：抽查 §1.1/§6.1/§9 紅線 → authoritative build 一次 → 每頁 `git add <md>+<dots>` 顯式 commit → 更新 tracker（重讀後改）。
8. 系統管理群全完 + 背景服務完 → tracker 統計 + session 列 + README 索引 → 給 user 一句話回報。

## §5 Sonnet full-writer dispatch 鐵則（複製進每個 prompt）

```
- STEP 0 讀 SOP：.claude/skills/writing-feature-specs/SKILL.md + references/page-spec-template.md
  + pilot（project-management/project-planning.md）+ 該群 _overview.md（若已寫）+ 一份 sibling 範例
- 事實三來源：FE 全讀目標 .vue + children/service/i18n；BE grep route→service→serializer（cite file:line）；
  schema 名只信 db_schema.json、endpoint 只信 routes.json
- ⚠️ 絕不 spawn sub-agent（不用 Agent tool），自己 Read/Grep/Bash 蒐證直接寫
- ⚠️ 不跑 render_html.py（主導統一 build），只 compile 自己的 dot（dot -Tsvg <f> -o /dev/null）
- 不 git add/commit、不改 tracker/README
- 語言繁中、技術詞英文、禁晶晶體、產品名 Guidant AI（禁「GRC 系統」）
- §5 UI 留 📸 亮色模式佔位 callout（截圖另有專責 session）
- 敏感資訊禁入（IP/密碼/token 只描述欄位不寫值）
- HTML-table dot label 內 & 要寫 &amp;
- 回報：files created / §1.1 bullet / §6.1 endpoints / §9.1 tables(驗證名) / dot compile 結果 /
  兩個 self-check grep（192.168|password=|Billows@ 與 「GRC 系統」）貼實際輸出 / flag 未驗證項
```

## §6 Pre-flight / 常用命令（可直接複製）

```bash
cd /Users/chouraymond/Projects/Billows/Audit-Manager/compliance-manager-be
git branch --show-current            # 必須 main；不對停下問 user
git status --short docs/specs/v1.8.0
which dot && dot -V
# 撈某群相關表：
python3 -c "import json,re; d=json.load(open('scripts/deliverables/out/db_schema.json')); \
t={x['schema']+'.'+x['name']:x for x in d['tables']}; \
[print(k,'—',(t[k].get('comment') or '')[:50]) for k in sorted(t) if re.search(r'<關鍵字>',k,re.I)]"
# 撈某群 endpoint：
python3 -c "import json,re; d=json.load(open('scripts/deliverables/out/routes.json')); \
[print(r['method'],r['path']) for r in d['routes'] if re.search(r'<關鍵字>',r.get('path',''),re.I)]"
# authoritative build（全部 subagent 回收後跑一次）：
python3 scripts/deliverables/render_html.py "docs/specs/v1.8.0" 2>&1 | grep -E "❌|Error" || echo "BUILD CLEAN"
# self-check（某群）：
grep -rEn '192\.168\.|password\s*=|Billows@' docs/specs/v1.8.0/system-admin/*.md | grep -v assets/img || echo clean
grep -rn 'GRC 系統' docs/specs/v1.8.0/system-admin/*.md || echo clean
```

## §7 每頁完成定義 / commit 慣例

- build ✅ + 敏感資訊 grep 0 + 「GRC 系統」grep 0 + dot 全 compile + 內部連結不斷。
- 顯式 `git add docs/specs/v1.8.0/system-admin/<page>.md docs/specs/v1.8.0/system-admin/assets/<prefix>-*.dot`（**禁 `-am` / `add -A`**）→ commit（訊息尾 `Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>`）。
- 每頁（或每批）commit 後**重讀 tracker** 再更新對應列狀態 / commit / 日期。

## §8 行為規範重要提醒

- **不切 branch、不 push**（push 永遠等 user 明示）；在當下 main 工作。
- **§5 截圖一律留佔位**（截圖另有專責 session，別自己截）。
- **HTML 站是 build 產物、gitignored**（commit 只含 md + dot，不含 html/）。
- **tracker 並行寫**：改前重讀、只動自己的列。
- **每完成一個功能群給 user 一句話回報後直接續**（不用等）。
- **context 快滿再走本 handoff 同款中繼交接**（closing-and-handoff skill），別撐到自動摘要。

## §9 不在本棒 scope（別順手做）

- §5 實機截圖（專責 session）。
- 其他 Lane 的群（問卷 / 報表 / 認證 = 可能是 Lane A 或別的 session；合規框架與 SSP、專案管理 = Lane A 進行中）。**只做系統管理群 + 背景服務**。
- 修 code / 修那些 §12 記錄的安全缺口（只記錄不修，那是另開 bug session 的事）。

## §10 本 session（Lane B）commits 清單（origin 未 push）

稽核執行收尾：`25c3420f` `1d923a4c` `9edea842` + tracker `e3e4def6`
證據管理：`1a3fdb66` `8b9c1fa5` `0caf4a53` `3f86d320` `fc7e33ae` `c0c8d00b` + tracker/README `8f3fc789`
協作：`9f57cc84` `cf26f3b1` `c38d3309` + tracker/README `1de8dba2`
（另有更早本 session 的稽核執行三頁 `adc82bcf` 在前一輪。全部在 main，**未 push**。）

## §11 給 fresh session 的超短 prompt

```
接手 FR-047 Lane B 續跑。先讀 docs/features/FR-047-2607-feature-spec-handbook/handoff/2026-07-05-laneB-system-admin-handoff.md 全文
+ writing-feature-specs skill（SKILL.md + references/page-spec-template.md），答出 §0 冷接自檢 4 問再動手。
本棒：系統管理群（_overview + 15 頁；role-manage 與背景服務 Opus 自寫，其餘 Sonnet 派 subagent、
dispatch 帶 §5 鐵則「不 spawn sub-agent、不跑 render_html」）+ 背景服務 spec。
先 pre-flight（§6）+ 驗 🔍（tool-plugin-manage / sitemap）。每頁獨立 commit + 重讀後更新 tracker，
不切 branch、不 push、§5 截圖留佔位。每完成一群給我一句話回報後直接續，context 快滿照本檔同款中繼交接。
```
