first commit

This commit is contained in:
Chris
2026-03-23 20:23:58 +08:00
commit 74d612aca1
3193 changed files with 692056 additions and 0 deletions

119
docs/CURRENT_WORK_ITEMS.md Normal file
View File

@@ -0,0 +1,119 @@
# 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 bootstrapURL rule 命中正確(`example.com` ✓,`other-site.com` → 0 candidates ✓)
- [x] Activity log6 筆操作紀錄正確回傳(建立/更新/版本/變體)
### G. Code Review 待修(✅ 完成2026-03-23
- [x] `P0` Release lifecycle 修正:`publish()` 先 unpublish 同實驗其他 published release`rollback()` 設自身為 draft 並自動升版前一個 draft release。
- [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 改用具體 targetOriginfallback `"*"`)。
- [ ] `P1` Release rollback 邊界條件補強:限制只能 rollback `published` release並在 rollback 流程最後再次保證同一 experiment 僅有一個 `published`
- [ ] `P2` 補自動化測試Backend API 契約、Editor flow、Runtime targeting/assignment、Release lifecycle 回歸。
- [ ] `P2` 文件狀態一致化:`ROADMAP``CURRENT_WORK_ITEMS``VALIDATION_EXECUTION_LOG` 的完成狀態同步。
## 系統狀態
**Phase AG 主線已完成2026-03-23目前剩餘1 項 P1 邊界條件 + 2 項 P2 強化。**
目前系統可運作P1/P2 完成後可進一步提高一致性與可回歸性。
## 延後項目
- 大型 UI polish
- `ose-card` 深度重構
- `conutdown-timer` 深度重構