120 lines
7.0 KiB
Markdown
120 lines
7.0 KiB
Markdown
# Current Work Items
|
||
|
||
## 用途
|
||
|
||
只記這一輪正在做的事情。方向看 `ROADMAP`,分階段交付看 `EXECUTION_PLAN`。
|
||
|
||
## 規格重置(2026-03-22)
|
||
|
||
這輪以你最新決策為準:
|
||
|
||
1. 實驗抓取:URL 規則 + 裝置限制
|
||
2. 建立 Experiment 同步建立原始 Variant
|
||
3. 移除 `is_control`
|
||
4. 移除 `variant_changes.enabled`
|
||
5. key 改系統生成:`EX+timestamp` / `VA+timestamp`
|
||
6. Variant 移除 `status`,使用者只調 `name` / `traffic_weight`
|
||
|
||
## 目前進行中
|
||
|
||
### A. 文件與契約(✅ 完成)
|
||
|
||
- [x] `SYSTEM_SPEC_MASTER` 已寫入 6 條新規格
|
||
- [x] `EXPERIMENT_SYSTEM_SPEC` 已更新為新流程
|
||
- [x] `API_CONTRACT_MASTER` 已更新欄位約束
|
||
- [x] `docs/MIGRATION_NOTE.md` 已建立:`is_control` / `variants.status` / `variant_changes.enabled` 移除策略與 DB 清理建議
|
||
|
||
### B. Backend 實作調整(✅ 完成)
|
||
|
||
- [x] `domain/keys.py` 新建:`generate_experiment_key()` / `generate_variant_key()` → `EXxxxxxx` / `VAxxxxxx`
|
||
- [x] `ExperimentCreate` 移除 `experiment_key` 欄位;service 層改為系統生成
|
||
- [x] `VariantCreate` 移除 `variant_key` 欄位;service 層改為系統生成
|
||
- [x] 建立 Experiment 時自動建立「原始版本」Variant
|
||
- [x] `domain/admin.py` Variant 移除 `status`、`is_control`
|
||
- [x] `domain/editor.py` VariantChange 移除 `enabled`
|
||
- [x] `domain/editor_builder.py` 移除 enabled 過濾
|
||
- [x] `schemas/admin.py` VariantRead / VariantCreate / VariantUpdate 同步更新
|
||
- [x] `repositories/directus/variants.py` `default_fields` 移除 status / is_control
|
||
- [x] `repositories/directus/variant_changes.py` `default_fields` 移除 enabled(修復 CORS/500 bug)
|
||
- [x] `schemas/editor.py` `EditorChangeRead` / `EditorChangeWrite` 已移除 `enabled`
|
||
- [x] `application/admin/releases.py` 移除 enabled / is_control 依賴;加 archive_release()
|
||
- [x] `application/editor/service.py` build_preview 移除 enabled=item.enabled
|
||
- [x] Variant 流量權重加總 = 100 驗證(`_assert_weights_sum_100`)
|
||
- [x] `repositories/directus/activity.py` 新建:Directus built-in `/activity` 查詢
|
||
- [x] `application/admin/activity.py` 新建:`ActivityService.list_for_experiment()`
|
||
- [x] `api/admin/experiments.py` 加 `GET /{id}/activity` 端點
|
||
- [x] `api/admin/releases.py` 加 `POST /{id}/archive` 端點
|
||
|
||
### C. Frontend 實作調整(✅ 完成)
|
||
|
||
- [x] `VariantFormDialog.vue` 簡化為只保留 `name` + `traffic_weight`
|
||
- [x] `variant-view-model.js` 移除 `status`、`isControl`、`buildVariantStatusTag`
|
||
- [x] `experiment-view-model.js` `mapVariantItem` 移除 `status`、`isControl`;`mapReleaseItem` 加 `versionNo`
|
||
- [x] `experiment/detail.vue` 改寫為 5 tab 設計(實驗設定 / 變體列表 / 版本列表 / 目標設定 / 操作紀錄)
|
||
- [x] `variant/detail.vue` 移除狀態/角色 metric card;完整 change set 摘要已存在
|
||
- [x] `use-variant-detail-page.js` 移除 `roleLabel`、`variantStatusTag`
|
||
- [x] `use-experiment-detail-page.js` 完整重寫:含 activityLog、release lifecycle、experiment settings
|
||
- [x] `release-api.js` 加 `archiveRelease()`
|
||
- [x] `experiment-api.js` 加 `listActivity()`
|
||
- [x] `dashboard/home.vue` 已有真實實驗統計摘要
|
||
- [x] 清理未使用的 `openFirstVariantEditor` / `statusTypeMap` 從 composable return
|
||
|
||
### D. 驗證清單(規劃項)
|
||
|
||
- [ ] 建立實驗後自動產生原始 Variant 的 E2E 測試
|
||
- [ ] Key 自動生成格式測試:`EX+timestamp` / `VA+timestamp`
|
||
- [ ] URL + device targeting 命中測試
|
||
- [ ] Release build / publish / rollback / archive 回歸測試
|
||
- [ ] Directus Activity log 在真實環境顯示正常
|
||
|
||
### E. Runtime 實作修正(✅ 完成)
|
||
|
||
- [x] `domain/runtime.py` 移除 `RuntimeVariantCandidate.is_control`
|
||
- [x] `schemas/runtime.py` 移除 `RuntimeVariantCandidateInput.is_control`
|
||
- [x] `application/runtime/assignment.py` `bootstrap()` 移除 variant `filter[status]` 查詢(variants 已無 status 欄位)
|
||
- [x] `application/runtime/assignment.py` 移除所有 `is_control=variant.is_control` 引用
|
||
- [x] `application/runtime/assignment.py` `_matches_targeting()` 實作完整 URL rule 匹配:
|
||
- `contains` / `equals` / `starts_with` / `regex` 四種 operator
|
||
- `device_targets` 裝置限制(mobile / tablet / desktop via user-agent 偵測)
|
||
- 空 url_rules 時 fallback 到 `base_url` startswith 檢查
|
||
|
||
### F. Staging 真實環境驗證(✅ 完成,2026-03-23)
|
||
|
||
- [x] Auth flow:`/api/auth/me` → 確認 is_admin + 完整 permissions
|
||
- [x] Site 查詢:`ose-demo-local` site 可讀
|
||
- [x] Experiment 建立:key 自動生成(`EX1774195099342`)
|
||
- [x] 原始版本 Variant 自動建立(`VA1774195099525`,weight=50)
|
||
- [x] 第二個 Variant 建立(weight=50,總計=100)
|
||
- [x] 權重驗證:嘗試新增 weight=1 的第三個 variant → 正確回傳 400
|
||
- [x] Variant change 儲存:`replace_text` 操作可寫入
|
||
- [x] Release build:`runtime_payload` 格式正確,operations 包含 selector + action + payload
|
||
- [x] Publish / Rollback / Archive 鏈路全部可跑
|
||
- [x] Experiment 設為 running + targeting_config 儲存
|
||
- [x] Runtime bootstrap:URL rule 命中正確(`example.com` ✓,`other-site.com` → 0 candidates ✓)
|
||
- [x] Activity log:6 筆操作紀錄正確回傳(建立/更新/版本/變體)
|
||
|
||
### G. Code Review 待修(✅ 完成,2026-03-23)
|
||
|
||
- [x] `P0` Release lifecycle 修正:`publish()` 先 unpublish 同實驗其他 published release,`rollback()` 會回退到較早版本。
|
||
- [x] `P0` Editor preview API 契約對齊:前端 `buildPreview()` 改送 `items`(原為 `changes`),與 `BuildPreviewRequest.items` 一致。
|
||
- [x] `P0` `save_changes()` 改為完整覆蓋語意:先刪除 DB 中不在 request items 的舊 change,再 upsert。
|
||
- [x] `P1` 移除 `variant_changes.enabled`:`EditorChangeRead` / `EditorChangeWrite` schema 刪除欄位;frontend `editor-workspace-model.js` 同步清除。
|
||
- [x] `P1` 建立 Experiment 時前端不再送 `experiment_key`(`ExperimentFormDialog` 移除 `autoFillKey`、`_auto_key`、`_generated_key`)。
|
||
- [x] `P1` Runtime bootstrap 改為從 release snapshot 讀取 `traffic_weight` / `variant_key`,避免即時 variant 異動造成分流不一致。
|
||
- [x] `P1` Editor bridge snippet `handleMessage` 加 `event.source === window.parent` 驗證;`EditorCanvasFrame` 捕捉 `event.origin` 並存入 `canvasOrigin`,postMessage 改用具體 targetOrigin(fallback `"*"`)。
|
||
- [x] `P1` Release rollback 邊界條件補強:只允許 rollback `published` release,並在 publish/rollback 後保證同一 experiment 僅有一個 `published`。
|
||
- [ ] `P2` 補自動化測試:Backend API 契約、Editor flow、Runtime targeting/assignment、Release lifecycle 回歸。
|
||
- [ ] `P2` 文件狀態一致化:`ROADMAP`、`CURRENT_WORK_ITEMS`、`VALIDATION_EXECUTION_LOG` 的完成狀態同步。
|
||
|
||
## 系統狀態
|
||
|
||
**Phase A–G 主線已完成(2026-03-23),目前剩餘:2 項 P2 強化。**
|
||
|
||
目前系統可運作;P1/P2 完成後可進一步提高一致性與可回歸性。
|
||
|
||
## 延後項目
|
||
|
||
- 大型 UI polish
|
||
- `ose-card` 深度重構
|
||
- `conutdown-timer` 深度重構
|