# Phase 2 A0.1 執行收尾 — 完整 ship 報告

> **日期**：2026-05-19
> **本檔角色**：A0.1 task arc 收尾總結（執行 session 完成）
> **前置文件**：[00-plan-handoff.md](00-plan-handoff.md) 是設計階段的 handoff，本檔是執行階段的收尾
> **狀態**：**A0.1 shipped** ✅

---

## 一句話總結

A0.1 結構重整補丁（rename items + 新建 main / join + column rename + caller 改寫）按 plan 全跑完，**8 個 commits 跨 2 repos + 1 個 device_id e2e 補丁 commit**，所有 unit test 全綠，DB schema / DI / yaml 序列化全驗證，主 BE smoke 因環境問題改 partial smoke 也通。

---

## 本 session 完成的事

### 1. 執行 SQL Migration

`scripts/sql/2026-05-19-ssp-system-implementation-restructure.sql` 已在 dev DB 跑通：
- 既有表 rename `system_security_plan_system_implementations` → `ssp_system_implementation_items`
- Column rename `information_system_id` → `system_characteristic_id`
- 新建 main `ssp_system_implementations`（129 個 distinct scope → 129 rows backfill）
- 新建 join `ssp_inventory_item_components`
- Items 加 `system_implementation_id` NOT NULL FK + 140 筆全部補齊

### 2. 10 個 Task 全部 ship

| Task | Commit | 範圍 | 模型 |
|------|--------|------|------|
| 0 | — | Pre-flight verification | — |
| 1 | jedi-oscal `762d8fc` | items stack 8 檔 rename `Ssp*Item*` + 5 父層引用 + 3 `__init__` + test 改名 | haiku impl + sonnet 雙 reviewer |
| 2 | jedi-oscal `cc65e3b` | main stack 8 新檔（含 `upsert_by_scope`）+ 25 個 unit test | haiku |
| 3 | jedi-oscal `c0fcae9` | column `information_system_id` → `system_characteristic_id` 跨 7 檔 | haiku |
| 4 | jedi-oscal `d2178c1` | items 加 NOT NULL FK + relationship + 7 個新 test | haiku |
| 5 | jedi-oscal `8e3e58b` | join stack 8 新檔（含 add_link type 語意驗證）+ 11 個新 test | haiku |
| 6 | jedi-oscal `4666091` | yaml_mapper 加 main block-level + implemented-components + 4 個新 test | sonnet impl + sonnet 雙 reviewer |
| 7 | 主 BE `eb9fa7e` | 2 個 caller + DI + 既有/新 regression test | sonnet impl + sonnet 雙 reviewer |
| 8 | — | BE smoke partial（DI / service / DB 4 項都通；完整 boot 撞 gitlab/github env 問題與 A0.1 無關）| — |
| 9 | 主 BE `87126ab` | changelog + tracker + design §11 reconciliation | (inline) |
| 10 | — | 通知 user + 收口 | — |

### 3. A0.1 e2e 驗證 + 1 個 follow-up fix

**驗證**（user 提供 SSP id=244, AP cd128dce-...）：
- AP → SSP 串接 / project 229 / 4 人 / 3 設備 / 3 系統都對齊 UI
- A0.1 三表 main(136) / items(168-170) / FK 全部正確寫入
- **發現**：items 的 `device_id` 全 NULL（A0 既有 caller 忘了填）

**follow-up fix**（同日 ship）：
- 主 BE `6deacef` — `project_device_mapping_service.add()` 加 `device_id=device_entity.id`
- `scripts/sql/2026-05-19-backfill-ssp-system-implementation-items-device-id.sql` 已執行 → UPDATE 135 筆 + 10 筆 unmatchable 保留 NULL

### 4. 文件交付

| 文件 | 路徑 |
|------|------|
| A0.1 主 changelog | `docs/changelog/2026-05-19-tweak-ssp-system-impl-restructure.md` |
| device_id fix changelog | `docs/changelog/2026-05-19-fix-ssp-impl-item-device-id.md` |
| tracker README | `docs/features/FR-011.2-2605-ssp-import-export-phase2/README.md`（A0.1 row → shipped + 7 commits）|
| design + reconciliation | `docs/features/FR-011.2-2605-ssp-import-export-phase2/design-A0.1.md` §11（5 條偏離紀錄） |
| analysis | `docs/analysis/2026-05-19-ssp-system-impl-restructure-rationale.md` |
| plan handoff | `docs/conversation-history/2026-05-19/ssp-import-export-phase2-A0.1/00-plan-handoff.md` |
| 執行收尾（本檔）| `docs/conversation-history/2026-05-19/ssp-import-export-phase2-A0.1/SUMMARY.md` |

---

## 完整 commit 鏈

### jedi-oscal（6 commits, 全 path-dep 未推 Nexus）

```
4666091 refactor(ssp-system-impl): yaml_mapper 加 main block-level + implemented-components
8e3e58b feat(ssp-system-impl): 新增 inventory_item_components M:N join 表完整 stack
d2178c1 feat(ssp-system-impl): items 表加 system_implementation_id NOT NULL FK + relationship to main
c0fcae9 refactor(ssp-system-impl): items column rename information_system_id → system_characteristic_id
cc65e3b feat(ssp-system-impl): 新增 main 表 OscalSspSystemImplementation 完整 stack
762d8fc refactor(ssp-system-impl): rename items stack to Ssp* + _items suffix
```

### 主 BE（3 commits）

```
6deacef fix(associations): ProjectDeviceMappingService 寫 SSP item 補填 device_id soft FK
87126ab docs(ssp-import-export-phase2): A0.1 shipped — changelog + tracker + design §11
eb9fa7e fix(ssp-system-impl): 主 BE caller 改寫支援 main 表 + 對齊新 class 命名
```

**累計 9 commits**（不含 Task 9 之前的 design / plan / SQL handoff commits）。

---

## 測試結果

| 範圍 | passed |
|------|--------|
| jedi-oscal 全套 regression | **93** |
| 主 BE A0.1-related (regression + main_regression + versioning) | **33** |
| **累計** | **126 個 unit test 全綠** |

---

## DB Schema 最終狀態（dev DB）

```
oscal.ssp_system_implementations         129 rows (1:1 per SSP scope)
oscal.ssp_system_implementation_items    140 rows (全部 system_implementation_id 補齊)
oscal.ssp_inventory_item_components        0 rows (預期 — 等 caller / UI 觸發)

Hardware items device_id backfill 後:
  hw_total=145, hw_has_device=135, hw_null_device=10 (unmatchable)
```

---

## 關鍵設計決策（design-A0.1.md §11 reconciliation 條目）

1. **yaml_mapper 簽章 backward-compat** — items_list 維持第一 positional，避免破壞既有 7 個 yaml_mapper test
2. **`_clone_system_implementations` 用 SSP relationship** — 直接 `old_ssp.system_implementations`，不另建 `old_main → items` 反向 relationship
3. **9 個 OSCAL extension 欄位 clone** — 7 個 getattr 安全取，2 個 scope_type/scope_id hardcode
4. **BE smoke partial** — 完整 boot 撞 gitlab/github env 環境問題（非 A0.1），改 DI / service / DB sanity 4 項驗證
5. **3 個 minor robustness follow-up** — main audit `created_user=None`、orphan main、yaml `implemented-components` 排序

---

## 已知 follow-up（不阻 A0.1）

| # | 項目 | 嚴重度 | 建議 |
|---|------|--------|------|
| 1 | jedi-oscal Nexus 發版 | 例行 | Phase 2 整體完工再一次性 bump |
| 2 | `pyproject.toml` path-dep 還原 pin Nexus 版本 | 例行 | 整 Phase 2 收口時做 |
| 3 | `created_user=None` 在 main upsert | minor | caller 從 auth context 取 |
| 4 | 刪 item 後 main 變孤兒 | minor (deliberate) | 評估是否要 cleanup |
| 5 | yaml `implemented-components` 多 component 排序 | minor | sort 一行修正 |
| 6 | 10 筆 hardware items device_id 無法 backfill | 業務判斷 | 確認對應 device 是否該刪 |
| 7 | 主 BE jedi-issue/github boot env | 環境 | 補 `GITHUB_PRIVATE_TOKEN` / `GITLAB_*` 到 .env |
| 8 | `delete*()` by-name 查找改 by-device-id | 中型 refactor | 另開 task |
| 9 | items.system_characteristic_id 沒 caller 填 | 預期 | 預留欄位，未來 caller 鉤稽 information_system 時用 |
| 10 | Join 表 (`ssp_inventory_item_components`) 沒 caller 自動填 | 預期 | 等 SSP 編輯頁「設定 component 屬於哪 inventory-item」feature |

---

## 部署 handover

### 對 dev DB 已執行
- ✅ `scripts/sql/2026-05-19-ssp-system-implementation-restructure.sql`
- ✅ `scripts/sql/2026-05-19-backfill-ssp-system-implementation-items-device-id.sql`

### 對 staging / production
- ⏸ 上述 2 個 SQL migration 需要 user 在對應環境執行
- ⏸ jedi-oscal 仍在 path-dep 模式，要正式 deploy 前需：
  1. jedi-oscal `pyproject.toml` bump version
  2. 推 Nexus
  3. 主 BE `pyproject.toml` 改回 `pin Nexus 版本`
  4. `poetry update jedi-oscal`

### BE 重啟（user 在配齊 GITLAB_*/GITHUB_PRIVATE_TOKEN env 環境）
```bash
lsof -ti:8000 | xargs kill -9
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
set -a; source .env; set +a
nohup poetry run python main_app.py > /dev/null 2>&1 &
```

---

## 下一階段 — Phase 2 A0.1 之後可推進

### 兩條 parallel paths

**A1：Excel 樣板設計 + 下載**
- 中型 phase（design 段落 + plan，不獨立 brainstorm）
- 依賴 A0.1（已 ship ✓）
- 範圍：產出 9 大資料領域（metadata / 單位 / 人員 / 設備 / 資訊系統 / leveraged / 控制項 / AO / 程序書）的 Excel 樣板 + 下載 API

**B1：Docx 樣板 + generator 骨架**
- 中型 phase
- 依賴 A0.1（已 ship ✓）
- 範圍：SSP docx 匯出格式樣板 + python-docx generator 基礎

兩條可平行起手，依 user 優先級決定。

### 建議

- 接手前讀本 SUMMARY.md（執行階段全脈絡）+ 00-plan-handoff.md（設計階段脈絡）
- A1 or B1 開工前先 brainstorm scope（中型不必但建議先列範圍）
- 建議先看 `docs/features/FR-011.2-2605-ssp-import-export-phase2/requirement-understanding.md` §3、§4 確認最新 scope

---

## session 規範遵守清單

- [x] 顯式 `git add <file>`，禁 `-am` / `-A` — 全 9 commits 都遵守
- [x] 所有 commits 含 `Co-Authored-By: Claude Opus 4.7 (1M context)` footer
- [x] jedi-oscal 仍 path-dep，未推 Nexus
- [x] `pyproject.toml` dev-only path-dep 改動沒被 commit（仍在 working tree）
- [x] BE 重啟必 `kill -9`（過程中遵守）
- [x] SQL migration 帶日期標記 + 帳號用 cmmgr
- [x] 重型 task (1 / 6 / 7) 過雙 reviewer（spec + code quality）
- [x] 沒做未授權的破壞性操作

---

## 結語

A0.1 是 A0 ship 後 e2e 校正的補丁 — 從「items 表名稱誤導 / 缺 main / 缺 join / 鉤稽路徑重疊 / 命名不一致」5 個結構問題收口到「items + main + join 三層完整 OSCAL block 鏡像」。execution 階段照 plan 跑完 10 個 task 沒大偏差，最大的驚喜是 e2e 驗證階段意外發現了 A0 既有 `device_id` caller 沒填的 bug 並順手修正。

A0.1 task arc 完整收尾。Phase 2 的基礎建設層完成，後續可開始 Track A（Excel 匯入）或 Track B（SSP 匯出）的具體 phase。
