# 🟢 START HERE — FR-038 Wave 2B 續：B2/B3a/B4.1 已 shipped，接手 B4.2 → B5

> **給下個 session 的 prompt**：「讀 `docs/features/FR-038-2606-oscal-redesign/handoff/2026-06-15-B4.2-B5-START-HERE-handoff.md`，先過 §0 讀序硬 gate 懂需求，跑 §6 pre-flight + §7 verify 確認 B2-B4 現況，再接手 **B4.2**（AP 編輯端點）→ **B5**（AR 全量矩陣 + 風險 + POA&M + 結案/覆核）。」
> 本檔自包含。所有狀態為 **2026-06-15 verified**（現場跑 smoke + pytest，非假設）。

> ## 🔖 交接現況（2026-06-15 換 session 當下）
> | 項目 | 值 |
> |------|----|
> | **進度** | 2A ✅ · B1 ✅（框架+資源庫三件組）· **B2 ✅**（clone 三件組+SSP 控制項初始化）· **B3a ✅**（輪次核心+snapshot）· **B4.1 ✅**（AP 草稿自動生）· **下一棒 = B4.2**（AP 編輯端點）→ **B5**（最重）|
> | 主專案 branch / HEAD | `feature/oscal-refactor` / **`8111626e`**（本 session 兩 commit：`2ba7a7c4` B2、`8111626e` B3a+B4）|
> | 主專案 working tree | **乾淨，只有 `M pyproject.toml`**（jedi-oscal-v2 dev path-dep，**照規範勿 commit**）|
> | ⚠️ **v2 套件未 commit dev 改動（B1 留下，本 session 沒動套件）** | repo `~/Projects/Jedicogy/module/jedi-python-package`（branch `feature/oscal-refactor`）working tree：`M catalog_service.py`（add_catalog + import_*）、`M framework_service.py`（get_version）、`?? tests/catalog/test_catalog_service_import.py`。**dev path-dep，BE 重啟即生效；發版等整個 feature 完成 + user 明示。別搞丟。** |
> | 跑得起來嗎 | `create_app()` BOOT OK on v2；`python -m pytest test/` = **56 failed + 50 errors**（持平 2A baseline、零新回歸）+ 9 skipped |
> | push | **未 push**，等 user 明示 |

---

## 🧭 開工前必懂：這整件事要幹嘛 + 本棒在大圖的位置（先懂才准碰 code）

**一句話**：FR-038 把舊「只套 OSCAL 概念、大量自定義欄位、拿 AP 兼當稽核輪次」的實作，**打掉重練**成「正式 OSCAL v1.2.2 物件模型 + 三層 clone/snapshot 邊界 + 稽核輪次 first-class」的專業 OSCAL GRC 系統。市場核心價值在 **Phase 3（外部稽核員寫 AR/findings/risks）**——多數產品到此斷掉，這正是要補的。

**目標新模型（必懂）**：
- **三層 + 四 clone/snapshot 邊界**：框架母版(catalog/profile) →①resolve→ 資源庫三件組(catalog+profile+ssp) →②clone脫鉤→ 專案副本(★單一真相) →③啟動稽核 snapshot→ 凍結 SSP 快照。鐵則：副本存內容/指版本化母版，**不可只存 id 即時 join 回會變動母表**。
- **稽核輪次 first-class** = `compliance.project_audit_rounds`（7 態狀態機），取代「AP 當輪次」。**engagement 模型**：initial/surveillance 起新 AP+AR；close-out 覆核沿用母輪 AP+AR、append `ar_results`；`parent_round_id` 串血緣。
- **套件 vs 主專案邊界**（design §4.4）：`jedi_oscal_v2` 只管 OSCAL 物件 CRUD/resolve/snapshot/clone/IO；**輪次狀態機、權限、workflow/job 綁定、`project_audit_rounds` 留主專案**。

**本棒（B4.2 → B5）在大圖位置**：B2 把專案 clone 起來、B3a 讓輪次能 snapshot、B4.1 讓 launch-audit 自動生 AP 草稿。**接下來 B4.2 補 AP 編輯（稽核員調整查核範圍/抽查名單/行程方法），B5 做整個 Phase 3（AR AO 全量判定 + 風險總結 + POA&M 整改 + 結案/覆核）—— 這是市場空白的核心，也是最重的一棒。**

> **冷接自檢**：你應能回答 ① 四個 clone/snapshot 邊界是哪四個 ② engagement 模型怎麼把 round↔AP↔AR↔ar_results wire 起來 ③ 為何 AP「對著凍結快照」而非 living SSP ④ 為何 Q1 workflow job 目前被卡（見 §2）。答不出 → 回 §0 讀序。

---

## §0 接手讀序（按序，1~2 是硬 gate）

1. 本檔「🧭」節 + 通讀本檔（§1 現況 / §2 陷阱 / §3 下一棒計畫）
2. 🔒 gate：[`requirement-analysis.md`](../requirement-analysis.md) §4.5（AP 四件事）/ §4.6（AR AO 全量矩陣 + 風險）/ §4.7（POA&M 三層）/ §4.8（結案/覆核）+ [`design.md`](../design.md) §3（engagement 模型）
3. 🔒 gate：[`api-contract.md`](../api-contract.md) **§5（AP）/ §6（AR）/ §7（POA&M）/ §8（結案）** ← B4.2/B5 照此重建端點
4. 本 session 兩個 app service 當範本：`app/grc/service/audit_round_app_service.py`（狀態機 pattern）、`app/grc/service/assessment_plan_app_service.py`（包 v2 AP service pattern）
5. 套件對外簽章：design §4.2 + 2A handoff §5.2 v2 wiring map（開工前 pre-flight 複驗）

---

## §1 現況：B2 / B3a / B4.1 已做什麼（2026-06-15 verified）

### canonical 模式（照抄）
新 app service 包 v2 primitive（補主專案職責：pager/filter/uid/RLS/權限/enrich）→ container wire → route → 註冊 → boot + **app-service smoke（真資料）** + pytest 不多紅 → 顯式 git add commit。

### B2 — 專案成立 clone 三件組（commit `2ba7a7c4`）
- `app/project/service/project_start_app_service.py`：`start_project(resource_library_uid, ...)` → 解析資源庫 module_frame 三件組 → `oscal_snapshot_service.clone_resource_library(catalog_id, profile_id, ssp_id)`（**邊界②**）→ 建 `compliance.projects` + `project_extensions`(`living_ssp_id`) + participants（用 lean `project_participant_domain_service`，因 full service 2A-dark）。
- **`project_extensions.living_ssp_id`**（migration `2026-06-15-fr038-project-extensions-living-ssp.sql`，已套 dev）= 專案 OSCAL 資產**唯一錨點**；profile/catalog 由 `ssp.import_profile_id` → `profile_imports.source_catalog_id` 導航（不另存，避免 desync）。
- **B2.1.5**：clone 後 `_init_ssp_control_implementations` 從 `resolve_profile` 為 living SSP 建 1:1 control-implementation + 每控制一筆 implemented-requirement（SoA props 預設 `applicability=applicable` / `implementation-status=unknown`）。
- route `POST /oscal-project/start` 重寫（request 改 `resource_library_uid`，移除 profile_uid/ssp_uid/flow_template_uid）。

### B3a — 稽核輪次核心（commit `8111626e`）
- 完整垂直：`infra/grc/model/project_audit_round.py` + `domain/grc/entities/project_audit_round_entity.py`(+query) + `infra/grc/repository/project_audit_round_repo_impl.py`(get_by_uid/list_by_project/max_round_no) + mapper + `domain/grc/service/project_audit_round_domain_service.py`。
- `app/grc/service/audit_round_app_service.py` 狀態機：`create_round`(initial/surveillance→planning) / `launch_audit`(snapshot living SSP **邊界③**→audit_planning) / `start_auditing`(→auditing) / list / get。角色守門（manager/auditor）+ 非法轉換擋下。
- `project_audit_rounds.uid`（migration `2026-06-15-fr038-audit-rounds-uid.sql`，已套 dev）= 對外操作識別碼。
- route：`POST /projects/<uid>/audit-rounds[/list]`、`GET /audit-round/<uid>`、`/launch-audit`、`/start-auditing`。

### B4.1 — AP 草稿自動生（commit `8111626e`）
- `launch_audit` 對 initial/surveillance 輪呼叫 `assessment_plan_app_service.create_draft_for_snapshot(frozen_ssp_id)` → v2 `generate_draft_from_ssp`（reviewed-controls = 凍結 SSP 的 **SoA 適用集**）→ 回填 `round.assessment_plan_id`。
- `app/grc/service/assessment_plan_app_service.py`：`get_ap_for_round` / `get_ap`（詳情：reviewed-controls 從 `control_selections` JSONB 解析 + subjects + tasks）。
- route `GET /audit-round/<uid>/ap`。**AP `import_ssp_id` = 凍結快照**（PM 教材：AP 對定版快照不是 living SSP）。

---

## §2 ⚠️ 會讓你做錯的陷阱 / 已定決策（先看）

1. **v1/v2 不可共存**（記憶 `project_oscal_v1_v2_cannot_coexist`）：任何新 code 只接 `jedi_oscal_v2`，禁 import 舊 `jedi_oscal`。
2. **2A-dark service 不能用**：`OscalProjectService` 舊 wiring、`project_participant_service`（full）等仍 reference 2A 已移除的 oscal provider → 建構即炸。需要 participant 寫入用 lean `project_participant_domain_service`（B2 已示範）。
3. **【Q1 卡點，已查證】workflow job 沒得建**：requirement §4.3b 的「為 SSP 控制項建 workflow job（My Jobs）」**目前無法做** —— 舊「control→workflow template」設定（`profile_assessment_workflow`）在 v2 重建時 DROP 且沒重建；新資源庫（B1）沒建 workflow 設定（`module_frames.template_uid` 全 NULL）；`workflow_execution_control_mapping_service` 2A stub 成回空。**要做 Q1 得先設計「新模型 workflow 設定掛哪」（B1 資源庫設定 + FE Wave 3 件）** → user 已拍板**延後 Q1**，別在 B4.2/B5 順手做。My Jobs view（`vw_user_job_queue`）2A 已留 control_* NULL 佔位，等 Q1。
4. **SSP 控制項來源是「自動生」（產品取捨，已做）**：v2 原設計 SSP 控制項靠匯入（import-ssp，defer）/ 編輯填；B2.1.5 因 import 未實作，改成專案成立時從 profile 自動帶全控制集。B4 的 AP 草稿就靠這些 SoA props。若日後接 import-ssp 要注意別重複生。
5. **`launch-reverify` / `close-round` 還沒做**：因母輪要走到 `pending_reverify`/`remediation` 才能觸發，而那需要 B5 的 AR finalize / POA&M。**B5 一起做這兩個轉換**（api-contract §4.4 / §8）。
6. **BaseRepositoryImpl.update() 只寫非 None 值 + 用 entity.uid 定位**：狀態轉換改欄位要塞非 None；要清成 NULL 不能走 update（B3a/B4 沒這需求）。
7. **pytest 用 `python -m pytest test/`**（單數 test/，60 檔）；boot 驗證要補 dummy GITLAB/GITHUB env（見 §6）。
8. **plan 假設先 verify**（v2 簽章 / 欄位）才開工。不晶晶體。

---

## §3 下一棒計畫：B4.2 → B5

### B4.2 — AP 編輯端點（中，先做）
api-contract §5.2~§5.4。v2 `AssessmentPlanService` 已備 `set_reviewed_controls` / `set_assessment_subjects` / `set_tasks`（`build_control_selections` 在 `jedi_oscal_v2.domain.service.ap.ap_draft_service`）。在 `AssessmentPlanAppService` 加：
- `PUT /ap/<ap_uid>/reviewed-controls`：body `{control_ids:[...]}` → `build_control_selections` → `set_reviewed_controls`。權限 auditor。
- `PUT /ap/<ap_uid>/assessment-subjects`：全量覆寫（subject_type/subject_uuid/include/title）→ `set_assessment_subjects`。
- `PUT /ap/<ap_uid>/tasks`：行程+方法 → `set_tasks`。
- `POST /audit-round/<uid>/ap/generate-draft`：手動重生草稿（呼叫 generate_draft）。
- error code `GRC_AP_REVIEWED_CONTROLS_REQUIRED`（空清單，412，grep 最大序號續編）。

### B5 — AR + POA&M + 結案/覆核（最重）
api-contract §6/§7/§8 + requirement §4.6~§4.8。v2 service：`AssessmentResultService`（add_ar/add_result/upsert_finding/list_findings 全量矩陣）、`AssessmentRiskService`（add_risk/link_findings 多對多）、`PoamService`（generate_from_findings/upsert_remediation/upsert_milestone）。
- **start-auditing 時建 ar_result**（`round.ar_result_id`）；AR `import_ap_id`=本輪 AP。
- AO 全量判定矩陣（每個 in-scope AO 一筆 finding met/not_met/pending）+ 風險總結（稽核員手動組、多對多 link findings、等級在 risk 層）。
- finalize：無 not_met→round closed；有 not_met→remediation + 自動生 POA&M。
- **補 B3a 延後的** `launch-reverify`（母輪 pending_reverify → 開新 close-out round + 重新 snapshot）+ `close-round`（POA&M 全 closed → 母輪 pending_reverify；close-out 連動關母輪）。
- My Jobs view control_* 接 `ssp_control_implementations`（搭 Q1，視 user 是否解 workflow 設定）。

> 每 phase：app service 包 v2 → wire → route → 註冊 → boot + 真資料 smoke + pytest 不多紅 → 顯式 git add commit。

---

## §4 開工順位

1. 跑 §6 pre-flight（branch / 兩 repo / v2 import / BOOT OK / pytest baseline）。
2. 讀 §0 讀序 2~5。
3. 跑 §7 verify 確認 B2-B4 真的可動（建資源庫→成立專案→輪次→launch-audit→AP）。
4. B4.2：照 §3 把 AP 編輯端點接 v2 `set_*`，每端點 smoke + commit。
5. B5：照 api-contract §6/§7/§8 分增量（AR 矩陣 → 風險 → finalize+POA&M → close/reverify），每增量 smoke + commit。
6. 收尾等 user 明示（changelog/SUMMARY/analysis/Notion/push）。

---

## §5 該讀的檔案 / 預期改動範圍（BE only；FE 是 Wave 3）

| 檔案 | 為何讀 |
|------|--------|
| `app/grc/service/assessment_plan_app_service.py` | B4.2 在這加 set_* 端點 |
| `app/grc/service/audit_round_app_service.py` | B5 在 start-auditing 建 ar_result、補 close/reverify 狀態轉換 |
| `~/Projects/Jedicogy/.../jedi-oscal-v2/.../app/service/ar/*.py`、`poam/*.py` | B5 接的 v2 service 簽章 |
| `di_containers/grc/grc_containers.py` | wire 新 AR/POA&M app service |
| `api/project/routes/audit_round_route.py` + `api/project/__init__.py` | 加 AP/AR/POA&M route + 註冊 |
| `common/code/grc_error_code.py` | 新 error code（**下一個可用：404→404039、412→412035**；412031-034 / 404038 已被 B2/B3a 用；403 沿用 NOT_MANAGER/NOT_AUDITOR；**開工前再 grep 複驗**）|

---

## §6 Pre-flight（必跑，可複製貼）

```bash
cd /Users/chouraymond/Projects/Billows/Audit-Manager/compliance-manager-be
git branch --show-current                      # feature/oscal-refactor
git status --short                             # 僅 ' M pyproject.toml'
git log --oneline -2                           # 8111626e (B3a+B4) / 2ba7a7c4 (B2)
( cd ~/Projects/Jedicogy/module/jedi-python-package && git status -sb | head -5 )  # 套件 dev 改動還在
poetry run python -c "import jedi_oscal_v2; print('v2 OK')"
# BOOT（補 dummy env 否則撞 jedi_issue）
set -a; source .env; set +a 2>/dev/null
export GITLAB_API_VERSION=4 GITLAB_URL=http://localhost GITLAB_PRIVATE_TOKEN=dummy GITHUB_PRIVATE_TOKEN=dummy
poetry run python -c "import eventlet; eventlet.monkey_patch(all=False, socket=True); import sys; sys.setrecursionlimit(5000); from core.app_factory import create_app; create_app(); print('BOOT OK')"
poetry run python -m pytest test/ -q -p no:cacheprovider --continue-on-collection-errors 2>&1 | tail -1  # 56 failed,...,50 errors（持平）
```

> **注意 `.env` 在 shell `source` 會在 JSON 行報 parse error**；跑 python script 改用 `from dotenv import load_dotenv; load_dotenv()`（見下方 §7 smoke 開頭）。

---

## §7 Verify B2-B4 確實可動（必跑，可複製貼）

本 session 的 smoke script 收尾時已刪（會寫 dev 測資）。下面是可複製貼的等價 verify（fabricate 最小三件組 → 走完 B2→B3a→B4，斷言 clone 脫鉤 + snapshot 凍結 + AP 草稿）。存成 `scripts/_verify.py` 跑完即刪：

```python
import eventlet; eventlet.monkey_patch(all=False, socket=True)
import os, sys, uuid; sys.setrecursionlimit(5000)
sys.path.insert(0, os.getcwd())
from datetime import datetime, timezone
from dotenv import load_dotenv; load_dotenv()
for k,v in {"GITLAB_API_VERSION":"4","GITLAB_URL":"http://localhost","GITLAB_PRIVATE_TOKEN":"dummy","GITHUB_PRIVATE_TOKEN":"dummy"}.items(): os.environ.setdefault(k,v)
from core.app_factory import create_app; app=create_app()
from jedi_common.session.database.db import session_scope
from jedi_common.session.database.session_context import get_session
import sqlalchemy as sa
from jedi_oscal_v2.common.enum.oscal_enums import PublishStatus
from jedi_oscal_v2.domain.entity.base.oscal_metadata_entity import MetadataEntity
from jedi_oscal_v2.domain.entity.catalog.oscal_catalog_entity import CatalogEntity
from jedi_oscal_v2.domain.entity.catalog.oscal_catalog_control_entity import CatalogControlEntity
from jedi_oscal_v2.domain.entity.profile.oscal_profile_entity import ProfileEntity
from jedi_oscal_v2.domain.entity.profile.oscal_profile_import_entity import ProfileImportEntity
from jedi_oscal_v2.infra.repository.base.metadata_repo_impl import MetadataRepoImpl
from jedi_oscal_v2.infra.repository.catalog.catalog_repo_impl import CatalogRepoImpl
from jedi_oscal_v2.infra.repository.catalog.catalog_control_repo_impl import CatalogControlRepoImpl
from jedi_oscal_v2.app.service.profile.profile_service import ProfileService
from jedi_oscal_v2.app.service.ssp.ssp_service import SspService
U,UU,UID="blsadmin","eac362ed-1fc7-48ac-b7e5-88c71f412c03",17
AUU,AID="9d895dc8-e189-4ed6-a830-a9e468a00a04",18  # blsit (auditor)
CIDS=["AC.L2-3.1.1","AC.L2-3.1.2","AC.L2-3.1.3"]
md=lambda t: MetadataRepoImpl().add(MetadataEntity(uid=str(uuid.uuid4()),title=t,last_modified=datetime.now(timezone.utc),version="1.0",oscal_version="1.1.2",created_user=U,updated_user=U))
with session_scope():
    s=get_session()
    cat=CatalogRepoImpl().add(CatalogEntity(uid=str(uuid.uuid4()),metadata_id=md("c").id,status=PublishStatus.DRAFT.value,created_user=U,updated_user=U))
    for i,c in enumerate(CIDS): CatalogControlRepoImpl().add(CatalogControlEntity(uid=str(uuid.uuid4()),catalog_id=cat.id,control_id=c,title=c,sort_order=i,created_user=U,updated_user=U))
    prof=ProfileService().add_profile(ProfileEntity(uid=str(uuid.uuid4()),metadata_id=md("p").id,status=PublishStatus.DRAFT.value,created_user=U,updated_user=U),imports=[ProfileImportEntity(source_catalog_id=cat.id,include_all=True,created_user=U,updated_user=U)])
    ssp=SspService().add_empty_ssp(metadata_id=md("s").id,import_profile_id=prof.id)
    rl=str(uuid.uuid4())
    s.execute(sa.text("INSERT INTO compliance.module_frames (uid,\"group\",frequency,version,name,enable,is_delete,tenant_id,oscal_profile_uid,template_ssp_id,created_user,updated_user,created_at,updated_at) VALUES (:u,'resource-library','none','1.0','vfy',1,0,102,:p,:s,:c,:c,now(),now())"),{"u":rl,"p":prof.uid,"s":ssp.id,"c":U})
from di_containers.containers import Containers; C=Containers()
p=C.project_container.project_start_app_service().start_project(name=f"vfy {uuid.uuid4().hex[:6]}",resource_library_uid=rl,participants=[{"user_uid":AUU,"role":"auditor"}],curr_user=U,curr_user_uid=UU,curr_user_id=UID)
assert p["control_count"]==3 and p["ssp_uid"]
r=C.grc_container.audit_round_app_service().create_round(project_uid=p["project_uid"],name="r1",round_type="initial",curr_user=U,curr_user_id=UID)
r2=C.grc_container.audit_round_app_service().launch_audit(r["uid"],curr_user=U,curr_user_id=UID)
assert r2["status"]=="audit_planning" and r2["ssp_uid"] and r2["ap_uid"]
ap=C.grc_container.assessment_plan_app_service().get_ap_for_round(r["uid"])
assert sorted(c["control_id"] for c in ap["reviewed_controls"])==sorted(CIDS) and ap["import_ssp_uid"]==r2["ssp_uid"]
print("✅ VERIFY PASS — B2 clone + SSP 控制項 + B3a snapshot + B4 AP 草稿全綠")
```
跑：`poetry run python scripts/_verify.py && rm scripts/_verify.py`

---

## §8 行為規範重要提醒（適用本棒）

- **不切 branch**（兩 repo 都在 `feature/oscal-refactor`；branch 不對停下問 user）。
- **可自行階段性 commit**（顯式 `git add` 檔名、**禁 `-am`**；各 repo 分開）；**push / 收尾等 user 明示**。
- `pyproject.toml` path-dep **勿 commit**（dev-only）；v2 套件 dev 改動別搞丟、別發版。
- **改 BE 後提醒 user 重啟 BE**（無 hot reload）；**服務 user 自己起**。
- 跨 schema FK 字串帶 schema 前綴（記憶 `feedback_cross_schema_fk_must_qualify`）。
- SQL migration：cmmgr + `--single-transaction -v ON_ERROR_STOP=1`，新表 GRANT cm_app，收尾 INSERT schema_migrations；**stg/poc 待遷移**（本期 2 條 migration 只套 dev）。
- 新 error code grep `common/code/grc_error_code.py` 最大序號續編。
- **遇到架構/資料模型取捨、需選方案、scope 邊界 → 停下問 user**（這 arc 已有多次：living-triple 存放、SSP 控制項來源、Q1 workflow 設定）。

---

## §9 收尾流程（B4.2/B5 做完 + user 明示才做）

盤點 commits → changelog（`docs/changelog/`，type=feat）→ **2 份 analysis 取捨文件待補**（① living-triple 只存 ssp 錨點 ② SSP 控制項自動生 vs import 取捨，含 Q1 workflow 設定缺口）→ SUMMARY → 回頭更新本 handoff ✓ + api-contract 偏差註記 → memory feedback → Notion。push 等 user。

---

## §10 不在本期 scope（別順手做）

- **Q1 workflow job / My Jobs control_* 接線**（卡資源庫 workflow 設定，B1/FE 件，user 已拍板延後）。
- FE（Wave 3）。
- 套件發 Nexus（feature 全完成 + user 明示）；`pyproject.toml` 改回 pin。
- 正式環境 schema 遷移（D7；stg/poc 本期 migration 待辦）。
- ISO/NIST（本期 CMMC-only，design §7）；import-ssp 套件實作（defer）。

---

## §11 本 session commits（branch `feature/oscal-refactor`，未 push）

- `2ba7a7c4` feat(FR-038): Wave 2B B2 — 專案成立 clone 三件組（邊界②）+ 專案 SSP 控制項初始化
- `8111626e` feat(FR-038): Wave 2B B3a+B4 — 稽核輪次 first-class + 啟動稽核 snapshot + AP 草稿
- 前置：`87eaf290`（2B handoff 定版）等。working tree 僅 `M pyproject.toml`（dev path-dep）。
- **2 條 migration 已套 dev**（stg/poc 待辦）：`2026-06-15-fr038-project-extensions-living-ssp.sql`、`2026-06-15-fr038-audit-rounds-uid.sql`。

---

## §12 給 fresh session 的超短 prompt

```
讀 docs/features/FR-038-2606-oscal-redesign/handoff/2026-06-15-B4.2-B5-START-HERE-handoff.md。
先過「🧭 開工前必懂」+ §0 讀序硬 gate（requirement §4.5~4.8 + design §3 + api-contract §5~§8），
能答冷接自檢 4 問（四邊界 / engagement 模型 / AP 為何對凍結快照 / Q1 為何卡）才往下。
跑 §6 pre-flight（BOOT OK + pytest 56f/50e 持平）+ §7 verify（確認 B2-B4 可動）。
接手 B4.2（AP 編輯端點接 v2 set_*）→ B5（AR 全量矩陣 + 風險 + POA&M + 結案/覆核，含補 B3a 延後的
launch-reverify/close-round）。Q1 workflow job 延後（卡資源庫 workflow 設定）。
每 phase：app service 包 v2 → wire → route → boot+真資料 smoke → pytest 不多紅 → 顯式 git add commit。
push / 收尾 / 套件發版等 user 明示。
```

---
### 冷接可行性自檢 ✅
看本檔 + §0 讀序 + 跑 §6/§7 → 能確認現況（B2/B3a/B4.1 shipped + commits + 套件 dev 改動）、懂 WHY（三層邊界 / engagement / Phase 3 核心價值）、知道 B4.2/B5 接哪個 v2 service、知道 Q1 為何延後、知道規範界線。不需 user 額外解釋即可開工。
