docs(adr): add ADR-022 PPT v3 redesign + warm paper + matplotlib + cache versioning
紀錄本次 PPT 全面重做的架構決策: - 視覺:暖紙風(_BG_PAPER #F3EEE2)取代暖墨黑封面 - 圖表:matplotlib 暖色系(橫條/折線/帕雷托)取代 python-pptx 原生 - 字型:lxml 直寫 a:latin/a:ea 中英分軌(Consolas + JhengHei) - 快取:TEMPLATE_VERSIONS 字典自動注入 cache key (tpl_ver) - AI prompt:升級到顧問深度(市場趨勢脈絡 + SMART 框架) - 安全:admin 白名單(OPENCLAW_ADMIN_USER_IDS)+ cleanup dry_run 預設 涵蓋 8 commit chain:38967ce →3b0b4b3→52c06f6→1c81866→b5a2b09→c7b7cee→92b8035→5a7012fCritic 全清紀錄:0 critical / 2 HIGH / 4 medium / 3 info 全部修補。 對應 memory: - reference_ppt_system.md(既存)已更新到 v3 實況 - project_ppt_v3_campaign_20260502.md(新建)戰役紀錄含三大踩坑 - feedback_template_version_cache_pattern.md(新建)可重用設計模式 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
120
docs/adr/ADR-022-ppt-system-v3-redesign.md
Normal file
120
docs/adr/ADR-022-ppt-system-v3-redesign.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# ADR-022: PPT 簡報系統 v3 — 暖紙風 + matplotlib 專業圖表 + 模板版本快取
|
||||
|
||||
- **Status**: Accepted
|
||||
- **Date**: 2026-05-02 / 03
|
||||
- **Deciders**: 統帥
|
||||
- **Related**: 取代 ADR-014 中的 PPT 視覺/結構描述(V2 → V3);不影響 V2 既有「6 種報告 vs 9 種報告」校正(growth/vendor/bcg 仍未落地)
|
||||
- **Affects**: `services/ppt_generator.py`、`routes/openclaw_bot_routes.py`、`Dockerfile`、`scripts/ppt_cleanup.sh` 等
|
||||
- **Commit chain**: `38967ce` → `3b0b4b3` → `52c06f6` → `1c81866` → `b5a2b09` → `c7b7cee` → `92b8035` → `5a7012f`
|
||||
|
||||
## Context
|
||||
|
||||
2026-05-02 統帥檢視月報(V2)後指出五項視覺品質缺陷:
|
||||
|
||||
1. 圖表醜(python-pptx 原生柱狀圖無資料標註、無顏色分級)
|
||||
2. 熱銷商品只 10 品(用戶要求 50 品)
|
||||
3. 專案 RAG 情報內容太陽春(單一 textbox 顯示靜態節日字串)
|
||||
4. 排版亂(封面大面積暖墨黑、AI 頁深色 + 白字過於濃重)
|
||||
5. 字體未對齊設計系統(中英混排撞 Courier New)
|
||||
|
||||
並要求對齊「市場上專業日報/週報/月報」的標準(McKinsey/BCG 等級顧問報告)。
|
||||
|
||||
第一輪重做後又抓出三類延伸需求:
|
||||
- 同份 PPT 可秒回(cache);但模板升版時舊 cache 必須自動失效
|
||||
- AI 分析內容要詳盡且專業,能直接幫銷售/行銷做決策參考
|
||||
- 容器 CJK 字型必須真正能渲染中文
|
||||
|
||||
## Decision
|
||||
|
||||
### A. 視覺重做 — 暖紙風(取代暖墨黑)
|
||||
|
||||
**封面**:`_BG_PAPER (#F3EEE2)` 米紙底取代 `_BG_DARK (#2A2520)`,焦糖橘左寬條 + 暖墨色標題。
|
||||
|
||||
**KPI 卡(v2)**:value 大字含右下角 △% 徽章(綠↑紅↓),含 `delta_label="vs 上月"` / inverse 反轉模式(用於成本類指標)。
|
||||
|
||||
**字型分軌**:透過 lxml 直寫 `<a:latin>`+`<a:ea>` (`_set_run_fonts`),數字/英文走 Consolas(點陣等寬感),中文走 Microsoft JhengHei。`_insert_rpr_child` 依 ECMA-376 §21.1.2.3 順序插入子元素(避免 LibreOffice/Keynote 拒絕讀取)。
|
||||
|
||||
### B. 圖表升級 — matplotlib 暖色系(取代 python-pptx 原生)
|
||||
|
||||
| Helper | 用於 | 特色 |
|
||||
|---|---|---|
|
||||
| `_mpl_horiz_bar_png` | 月報品類橫條 | TOP3 焦糖橘 / 4-6 蜂蜜金 / 7+ 焦土,條右標 NT$X.X萬+佔比% |
|
||||
| `_mpl_line_chart_png` | 日/週/月趨勢 | 本月實線+上月虛線+日均水平線+高低點標註,N≤2 sparse 防呆 |
|
||||
| `_mpl_pareto_chart_png` | 月報品類雙視圖 | 業績條(80% 主力焦糖橘)+ 累計%曲線+80% 主力線 |
|
||||
|
||||
容器 CJK fallback:`fonts-noto-cjk` 套件 ttc 檔在 matplotlib `font_manager.ttflist` 只認 `Noto Sans CJK JP` 變體,但 ttc 內漢字字型表共用,可正常渲染中文。`_mpl_setup` fallback 列表必須包含 `Noto Sans CJK JP`。
|
||||
|
||||
### C. 模板版本快取(template_version cache invalidation)
|
||||
|
||||
```python
|
||||
# services/ppt_generator.py
|
||||
TEMPLATE_VERSIONS = {
|
||||
'monthly': 'v3.1.3',
|
||||
'daily': 'v3.0.2',
|
||||
...
|
||||
}
|
||||
|
||||
# routes/openclaw_bot_routes.py
|
||||
def _normalize_ppt_parameters(parameters):
|
||||
"""自動把 tpl_ver 注入 cache key"""
|
||||
params['tpl_ver'] = get_template_version(report_type)
|
||||
return json.dumps(params, sort_keys=True)
|
||||
```
|
||||
|
||||
**Bump 規則**:major 設計改版 +0.1(如 v3.0 → v3.1);補丁修正 +0.01(v3.1.1 → v3.1.2)。bump 即觸發舊快取自動 miss。
|
||||
|
||||
**緊急清空**:`_invalidate_ppt_cache(report_type=None)` Python helper / `/cache flush` Telegram 指令(admin only)。
|
||||
|
||||
**磁碟清理**:`cleanup_expired_ppt_cache(days_old=7, dry_run=True)` — 安全預設 dry_run=True,呼叫方明確傳 False 才實刪。launchd plist 排程每日 03:15 跑(macOS 開發機)。
|
||||
|
||||
### D. AI prompt 升級到顧問深度
|
||||
|
||||
**月報 prompt 升級**(`_ppt_ai_analysis`):
|
||||
- 角色:BCG/麥肯錫策略顧問 + momo 行銷主管 + 品類採購(三合一)
|
||||
- 必含「市場趨勢脈絡」段:當期檔期 + 2026 熱門賽道(永續美妝/母嬰高端/敏弱肌/銀髮保健等)+ 平台競爭(蝦皮/PChome/酷澎)
|
||||
- 行動建議走 SMART 框架(Specific/Measurable/Achievable/Relevant/Time-bound),分本週/本月/下月三層
|
||||
- 禁用「可能/也許/建議考慮」等模糊用詞
|
||||
- 字數 900-1200,max_tokens 2400
|
||||
|
||||
**AI 段落 parser**(`_parse_ai_sections`):丟掉空 body 段(避免顯示「本段無內容」);上限 6→10 容納 SMART 9 段。
|
||||
|
||||
### E. 安全機制 — admin 白名單 + dry_run 預設
|
||||
|
||||
- **`OPENCLAW_ADMIN_USER_IDS` 環境變數**:`/cache flush` 與 `/cache cleanup confirm` 限管理員執行;未設時退回 ALLOWED_USERS(向後兼容 fail-closed)
|
||||
- **`_CURRENT_USER_ID_CTX` ContextVar**:webhook 入口(msg + callback)set;handle_cmd 讀取,避免改 30+ 處呼叫端簽名
|
||||
- **cleanup days<1 強制乾跑**(防呆)
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
1. **視覺對齊市場專業標準**:與 McKinsey/BCG 月度報告一致的暖紙風+圖表標註+帕雷托雙視圖
|
||||
2. **模板升版零阻力**:bump TEMPLATE_VERSIONS 即生效,無需手動清快取
|
||||
3. **記憶體穩定**:matplotlib helpers 全部 try/finally 包好,渲染失敗不洩漏 figure
|
||||
4. **AI 內容可實戰**:每段含具體商品名+量化目標+期限,BU 主管可直接做決策
|
||||
5. **容器化部署**:Dockerfile 加 `fonts-noto-cjk`,CI/CD 自動帶字型
|
||||
|
||||
### Negative
|
||||
|
||||
1. **月報 cache miss 路徑變慢**:cache miss 時連續查 current/prev_month/prev_year 三次(12 SQL),延遲 3×。命中後正常(同份秒回)。
|
||||
2. **PPT 檔變大**:matplotlib PNG 取代原生 chart,月報 130KB → 326KB(含 3 張高品質圖)
|
||||
3. **`fonts-noto-cjk-extra` 增加 ~100MB image 大小**:可瘦身但 trade-off 字型完整度
|
||||
|
||||
### Risks Mitigated
|
||||
|
||||
- **figure 洩漏 → OOM**:try/finally 修復(critic HIGH-1)
|
||||
- **靜默實刪災難**:cleanup 預設 dry_run=True(critic HIGH-2)
|
||||
- **群組成員誤觸破壞性指令**:admin 白名單(critic Medium-3)
|
||||
- **未來改讀模板 .pptx schema 違反**:`_insert_rpr_child` 維護順序(critic Medium-1)
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
1. **保留 python-pptx 原生 chart**:拒絕 — 原生不支援資料標註、顏色分級無法做到 BCG 級觀感
|
||||
2. **用 hash(ppt_generator.py 內容)[:8] 自動 cache key**:拒絕 — 改個 typo 也 invalidate 全部,過度敏感
|
||||
3. **改 handle_cmd 簽名加 user_id**:拒絕 — 30+ 處呼叫端要動,風險大;用 ContextVar 更乾淨
|
||||
|
||||
## References
|
||||
|
||||
- Critic 完整審查報告:見 commit `38967ce` 之後的 critic agent run
|
||||
- 實戰驗證:在 188 prod 容器內生成 monthly v3.1.3,AI 內容 3 頁全 SMART 行動建議
|
||||
- 原 ADR-014(V2 PPT):未廢止,但視覺/結構/cache 部分由本 ADR 取代
|
||||
@@ -43,6 +43,7 @@
|
||||
| [019](ADR-019-telegram-bot-agentic-conversation-layer.md) | Telegram Bot Agentic Conversation Layer(菜單→Agent 決策統一入口) | Accepted | 2026-05-02 |
|
||||
| [020](ADR-020-code-review-full-autoheal.md) | Code Review 全自動修復政策(局部覆寫 ADR-012 HITL) | Accepted | 2026-05-02 |
|
||||
| [021](ADR-021-ea-hitl-prefetch-and-alert-impact.md) | EA HITL Pre-fetch + 競價告警必填金額影響量化 | Accepted | 2026-05-03 |
|
||||
| [022](ADR-022-ppt-system-v3-redesign.md) | PPT v3 — 暖紙風 + matplotlib 專業圖表 + 模板版本快取 | Accepted | 2026-05-02/03 |
|
||||
|
||||
## 規範
|
||||
|
||||
|
||||
Reference in New Issue
Block a user