Files
ewoooc/docs/adr/ADR-017-modularization-cleanup-roadmap.md
2026-05-13 16:15:06 +08:00

9.5 KiB
Raw Permalink Blame History

ADR-017: 模組化收尾路線圖Phase 3f

  • 狀態: Accepted
  • 日期: 2026-04-29
  • 觸發: 12 Agent 全景盤點debugger / refactor-specialist / critic / db-expert / explorer
  • 相關 ADR: ADR-008188 拓撲、ADR-011資源隔離、ADR-016cache fingerprint
  • 相關 Memory: docs/memory/project_phase3f_cleanup_roadmap.mddocs/memory/feedback_db_metadata_import.mddocs/memory/history_logs.md

背景

Phase 3e4/28-29完成 app.py 7,386→6,590 行(-10.8%),但僅完成「搬檔」,未完成「拆乾淨」。12 Agent 盤點揭露 6 個面向的殘留問題,且發現新的 critical 風險DB metadata import 漏洞、孤兒表)。

完成度真相2026-04-29 盤點基線)

維度 完成度 真相
路由搬檔41 條 → 28 BP 68% 13 條 app.py 獨有未遷移
路由「拆乾淨」 0% app.py 41 條一條未刪28 條與 BP 同 URL 雙寫,由 first-registered-wins 決定行為
USE_MODULAR_ROUTES 開關 0% register_blueprints() 從未被 app.py 呼叫,整套設計死碼
services/ 模組化 ~95% 唯一乾淨3 個孤兒 service0 引用)
模板統一 ~50% 三目錄並存 + 1 空檔 + 3 死檔 + 2 TemplateNotFound 風險
DB schema vs Model ~60% manager.py import 漏 3 模組6 張表有 SQL 無 ORMrealtime_sales_monthly 孤兒

實作狀態補記2026-05-13

上表是 2026-04-29 立案時的盤點基線;後續整改已把多個 HIGH 項目落地並加上回歸守門:

  • app.py 已收斂為 Flask bootstrap / Blueprint registration / 啟動自檢active @app.route 為 0並由 tests/test_phase3f_cleanup_contracts.py::test_app_py_stays_blueprint_only_for_routes 守住。
  • USE_MODULAR_ROUTESregister_blueprints()MODULAR_ENDPOINTS、duplicate cleanup shim 已移除;routes/__init__.py 僅保留 package docstring。
  • DB metadata / migration 覆蓋已由 tests/test_migration_metadata_coverage.py 與啟動自檢守住v5 observability / Market Intel 等表不再只靠手動口述。
  • 模板路徑已收斂為 templates/web/templates/vendor_stockout/;根層 placeholder templates/list.html 已刪除並有測試防回歸。
  • 大檔治理仍未結案:routes/openclaw_bot_routes.pyroutes/admin_observability_routes.pyroutes/sales_routes.pyscheduler.py 仍超過 800 行,後續只能做 bugfix、安全修補或往外抽模組。

決策

執行 Phase 3f 五階段收尾,總工期估 12-15 小時(不含驗證),每階段獨立 commit、每階段 critic 審查、每階段先 SSH 驗證 production。

Phase 3f-0DB metadata 救急30 分鐘,最高優先)

  1. database/manager.py 補完 import
    • permission_modelsPermission, UserPermission
    • vendor_models 補 VendorList / VendorEmail / EmailSendLog
    • ai_models 顯式 import 4 個 AI history/template class
    • autoheal_models 顯式 import 7 個 AIOps class移除 ai_models.py re-export shim
  2. 處置 realtime_sales_monthly 孤兒表:
    • 選項 Adatabase/realtime_sales_models.py(推薦,補 ORM 一致性)
    • 選項 B移除 app.py:693 的 importmetrics 不依賴此 model
  3. PostgreSQL 與 SQLite 初始化都執行全域 Base.metadata.create_all()PostgreSQL 路徑以 process-local guard + advisory lock 保護,避免一般流量重複碰 DDL
  4. app.py 啟動加 metadata self-check缺表直接 SystemExit
  5. docker/postgres/init/01-init.sqlrealtime_sales_monthly 欄位同步 ORM避免 fresh volume 先由 init.sql 建出窄表後 create_all 無法補欄位

驗收Base.metadata 含全 34 個 tablecreate_all 在新環境零漏。

Phase 3f-1路由雙註冊徹底解4-6 小時P9 切分)

策略:保留 Blueprint刪 app.py 對應 @app.route28 條13 條 app.py 獨有遷至 BP。實作順序要先處理 API shadow、次要頁面與 /brand_assets,首頁 / 最後動,因為多處 url_for('index') 仍依賴 app endpoint name。

子任務(按 BP 分組獨立 commit

Sprint 範圍 動作
3f-1-a dashboard_bp 刪 app.py:722 /;確認 BP 版可用
3f-1-b edm_bp 刪 app.py:1029, 1280 兩條
3f-1-c export_bp 刪 app.py:1431-1905 共 9 條;補 /api/export/excel/seasonality_detail 進 BP
3f-1-d api_bp 刪 app.py:2219-2451 共 6 條 trigger/run
3f-1-e import_bp 刪 app.py:2691, 2980 兩條
3f-1-f monthly_bp 刪 app.py:3076, 3083 兩條
3f-1-g sales_bp 刪 app.py:3592-5809 共 7 條;同時刪 routes/sales_routes.py 6 處 wrapper174-348,把實作搬進 BP
3f-1-h system routes 補強 現有 system_bp/api/system prefix公開 URL/health /metrics /logs /settings 等)需新建無 prefix 的 system_public_bp 或拆成 public/internal 兩個 BP不能直接塞進現有 system_bp/abc_analysis/detailsales_bp
3f-1-i 死碼清除 routes/__init__.py:32-177 整套register_blueprints / MODULAR_ENDPOINTS / is_endpoint_modular / cleanup_duplicate_routes+ config.py:244-254 USE_MODULAR_ROUTES

驗收

  • app.url_map.iter_rules() 任一 (rule, methods) 皆唯一
  • 啟動加 self-checkduplicate detect 直接 raise SystemExit
  • 全 endpoint smoke testcritic 監督)

Phase 3f-2Cache 統一2-3 小時)

  1. Dockerfile + docker-compose.yml gunicorn 加 --preload,只作為 COW 記憶體優化,不作為一致性保證
  2. 新建 services/cache_manager.py 套用 ADR-016 fingerprint 模式
  3. 移除三處重複 _SALES_*_CACHE 定義app.py:82, routes/sales_routes.py:32, services/cache_service.py:16→ 統一 import services.cache_manager
  4. clear_cache endpoint 從「N-POST 廣播」改「DB fingerprint pull」已在 daily_sales bp 完成,擴及 sales

Phase 3f-3穩定性補強1-2 小時)

  1. 先在 services/event_router.py 補同步安全 facadenotify_failure() / dispatch_sync()),因現有 EventRouter 只有 async dispatch()scheduler 直接呼叫會掉告警
  2. scheduler.py 7 處裸 except: passline 243, 254, 582, 587, 653, 890, 1222改為 except Exception as e: logger.exception(...)P1/P2 經 EventRouter 同步 facade 強制告警
  3. docker-compose.yml 刪 7 條死路徑 mountvendor_routes.py / vendor_stockout_*.html
  4. routes/vendor_routes.py:28-30 template_folder 改用絕對路徑,移除靠 Flask fallback 的脆弱依賴

Phase 3f-4模板統一2-3 小時)

  1. 補 2 個 TemplateNotFoundtrends.htmltrend_routes.py:33login_history.htmluser_routes.py:40→ 找回或停用對應 endpoint
  2. web/templates/sales_analysis.html0-byte 空檔)
  3. 刪 3 個雙寫死檔:web/templates/brand_assets.htmlweb/templates/growth_analysis.html、根目錄 logs.html
  4. 根目錄 11 個 *.html 全搬 templates/,確認 docker-compose 舊 mount 已清理後,再移除 app.py:185-188 ChoiceLoader 的 BASE_DIR fallback
  5. web/templates/ 僅留 vendor_stockout/ 子目錄vendor_bp 自帶 template_folder

Phase 3f-5死碼清除30 分鐘)

  1. 確認並刪除 3 個孤兒 service
    • services/elephant_alpha_decision_router.py
    • services/telegram_ai_integration.py
    • services/watcher_agent.py
  2. .env.example 補齊 15+ 個程式碼實際讀但 example 缺的變數AIDER_, ELEPHANT_ALPHA_, HEAL_SSH_*, NVIDIA_API_KEY 等)

風險與回滾

每階段獨立 commitCI/CD 失敗自動回滾(依賴 ADR-014 防線。Phase 3f-1 為高風險區,必須:

  1. 先在本機 python app.py 啟動驗證 url_map 無重複
  2. critic 審 diff 過關
  3. 部署後 SSH 健康檢查 /health + 抽測 5 條核心 endpoint

不做的事

  • 不做模組化開關設計回填USE_MODULAR_ROUTES 已死,直接刪)
  • 不做 ORM 全面遷移25 張無 SQL migration 軌跡的 table 留待 Phase 4
  • 不在 3f-0 修 docker/postgres/init/01-init.sql 與 ORM 的 products 中文欄位 schema drift這是 Phase 4 migration 題
  • 不做 openclaw_bot_routes.py5,543 行)拆解(留 Phase 4
  • 不撤換 NGROK Token統帥 2026-04-29 明示先忽略)

完成定義

  • app.py < 5,000 行
  • url_map 零重複
  • create_all 新環境零漏表
  • 模板僅存 templates/ + web/templates/vendor_stockout/
  • gunicorn --preload 啟用、cache 跨 worker 一致
  • scheduler 7 處 except 全改、docker-compose mount 全清

2026-04-30 補充決策:模組化治理守門

Phase 3f 已陸續完成 DB metadata、路由註冊、cache、scheduler、模板與 orphan cleanup 的多個收斂項目,但 line-count 盤點仍顯示 15 個 Python 檔案超過 800 行。為避免後續功能開發再次把 route / service 寫成巨檔,本 ADR 補充以下守門規則:

  1. app.py 只保留 Flask app bootstrap、Blueprint registration、啟動自檢、版本與全域設定不得新增 route 或商業邏輯。
  2. routes/ 必須保持 thin controller重複邏輯需抽到 services/utils/
  3. 超過 800 行的 Python 檔案列入 docs/memory/code_modularization_inventory_20260430.md只能做安全修補、bugfix、或往外抽模組新增功能應先拆分。
  4. 新增 Python 檔案超過 600 行需提出拆分理由;超過 800 行需同步更新 inventory 與測試。
  5. tests/test_modularization_governance.py 是守門測試:新巨檔沒有被盤點會失敗。

詳細操作規則以 docs/guides/modularization_governance.md 為準。