Commit Graph

84 Commits

Author SHA1 Message Date
ogt
a45b61f326 feat(review): 新增 /review pre-commit code review slash command
- .claude/commands/review.md: 整合 12 Agent 的 pre-commit review 指令
  + 依 diff 類型路由:critic / db-expert / migration-engineer / tool-expert
  + Phase B 條件觸發 vuln-verifier(critic 發現 🔴 時)
  + ≥10 Python 檔案改派 refactor-specialist 主審
  + 最終判決:BLOCKED / CAUTION / APPROVED

- scripts/tg_notify.sh: Telegram 告警工具
  + 7 個流程節點全部發送告警(啟動/每個 Agent 完成/最終判決)
  + 支援 info/warn/error 三級別 + jq/bash 雙備案解析
  + token 未設定時 exit 0,不阻斷 review 流程

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 01:23:57 +08:00
ogt
0099543c05 fix(security): 全域健檢 — 40 項安全/Bug/品質修復
🔴 Critical
- auto_heal_service: 補 import re + sqlalchemy.text + 修正 orchestrator 變數名
  + autoheal_playbook→playbooks 表名 + _alert_and_store cooldown 修復
- aider_heal_executor: shell injection 改 shell=False + list 參數
- docker-compose: DISABLE_LOGIN 改 env var + 移除密碼 fallback + POSTGRES_HOST 修正
- app.py: /api/backup /api/run_task 等 6 個管理 API 加 @login_required
- config.py + pg_sync + e2e_test: 移除 wooo_pg_2026 hardcoded 密碼 fallback
- pg_backup.sh: 移除 TELEGRAM_TOKEN= 中間變數,直接用 $TELEGRAM_BOT_TOKEN
- migration 014: trigger_pattern→match_pattern + 補 error_type NOT NULL 欄位

🟡 High
- telegram_bot_service: str(e) 改通用訊息 + session try/finally + 移除 pa:/pr: 舊 callback
- run_scheduler: ElephantAlpha thread 死亡監控 + 自動重啟 + Telegram 告警
  + agent_context 03:30 TTL 定時清理任務
- openclaw_learning_service: build_rag_context 兩路徑加 .limit(200)
- hooks: commit-quality + momo-prod-guard 空 catch 改 stderr+exit(1)
- scripts/code_review: auto_yes 預設改 false
- db_backup_service: PGPASSWORD 透過 env dict 傳遞

📦 Migrations
- 013_autoheal: 修正建表順序 playbooks→incidents(外鍵前向引用)
- 018_add_missing_indexes: heal_logs/incidents 外鍵索引 + cleanup_expired_agent_context()

🟢 Infrastructure
- requirements.txt: 加版本下界 Flask>=2.3 SQLAlchemy>=1.4 等
- cd.yaml: 新增 run_scheduler.py + run_telegram_bot.py 監聽路徑
- .gitignore: insert_playbook_local.py 加入忽略

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 01:12:23 +08:00
ogt
61a9c4c1e3 fix(hooks): 移除重複的 commit-quality.js 呼叫
全域 ~/.claude/hooks/commit-quality.js 已透過 secrets.local.json
涵蓋 Telegram/Gemini/Gitea pattern,momo project 設定不需再執行一次
避免每次 commit 重複告警兩次

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 23:46:21 +08:00
ogt
a13683d655 refactor(claude): Phase B — momo CLAUDE.md 去重 + secrets.local.json
- CLAUDE.md V12.0: 移除與全域重複的 P7/P9/P10、三紅線、委派表、PUA/Loop Mode
  保留 momo 專屬:環境索引、容器架構、診斷指令、CI/CD、PPT 系統、安全架構
- 新增 .claude/hooks/secrets.local.json: Telegram/Gemini/Gitea token 偵測 pattern
  由全域 commit-quality.js 自動載入,補充 momo 環境的專屬保護
- 新增 .claude/skills/telegram-bot-menu-restoration.py (已存在,補 track)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 23:13:18 +08:00
ogt
0c9a3cd875 fix(settings): 修正 Claude Code hook 格式為正確 schema
- bypassPermissions -> permissions.defaultMode: "bypassPermissions"
- 移除無效的 thinking/effort 欄位
- Hook 改用 {matcher, hooks: [{type, command}]} 物件格式
- 新增 branch-protection.local.json: momo main 分支可直接 commit

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 23:09:00 +08:00
ogt
cac7303e46 feat(devteam): 引進 my-claude-devteam 架構 V11.0
- CLAUDE.md 升版至 V11.0:整合 P7/P9/P10 工作模式、12 人專家團隊、
  委派鐵律、三條紅線(保留狙擊手模式精神)
- .claude/hooks/:新增 8 個 Hook(momo-prod-guard / commit-quality /
  large-file-warner / mcp-health / audit-log / suggest-compact /
  cost-tracker / session-summary)
- .claude/agents/:新增 11 個 Agent 定義(critic / debugger / db-expert /
  vuln-verifier / fullstack-engineer / planner / refactor-specialist /
  migration-engineer / onboarder / tool-expert / web-researcher)
- .claude/settings.json:啟用 bypassPermissions + Hook 自動政策架構
- .gitignore:加入 settings.local.json 防止 Secret 意外 commit

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 22:13:57 +08:00
ogt
1f7b903d36 fix(code-review): 修復 Hermes 401 與 OpenClaw GEMINI_API_KEY 缺失
Hermes 掃描:改直呼內網 http://192.168.0.111:11434/api/generate
(棄用 ai_provider_service,避開公網 Ollama 401 認證問題)

OpenClaw 評估:Gemini 優先,降級用 elephant_service(OpenRouter)
(容器內無 GEMINI_API_KEY,但 OPENROUTER_API_KEY 一定存在)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 21:16:44 +08:00
ogt
2e0de960ce feat(code-review): 重建為 Post-Deploy AI Agent Pipeline
架構重建:
- 移除 pre-commit hook(本機 commit 不再阻塞)
- 改為 CD 健康檢查通過後自動觸發 webhook

新建 services/code_review_pipeline_service.py:
  5-Step Pipeline(後台 daemon thread)
  Step1 system        讀取部署後變更檔案內容
  Step2 Hermes        程式碼掃描(bugs/security/perf,hermes3:latest)
  Step3 OpenClaw      架構品質評估(Gemini 2.5 Flash)
  Step4 ElephantAlpha 決策協調(severity + auto_fix 裁量)
  Step5 NemoTron      action_plans 寫入 + AiderHeal 觸發
  全程 Telegram 告警(啟動/完成/錯誤)+ ai_insights DB 持久化

重建 routes/code_review_routes.py:
  POST /code-review/api/internal/trigger  CD webhook(X-Internal-Token)
  GET  /code-review/api/status            前端即時 polling
  GET  /code-review/api/history           歷史清單
  GET  /code-review/                      前端儀表板

重建 templates/code_review.html:
  深色儀表板,Pipeline 即時進度 + Severity 分佈 + 問題清單 + EA 決策
  3s polling(running)/ 30s(idle)

.gitea/workflows/cd.yaml:
  健康檢查通過後注入「觸發 AI Code Review」step
  continue-on-error: true(不影響部署結果)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 20:55:23 +08:00
ogt
38200a5e93 feat(reports): 新增日報/月報系統,整合圖表推播至 Telegram
- services/openclaw_strategist_service.py:新增 generate_daily_report()(每日09:00業績快報+競品威脅+2圖表)和 generate_monthly_report()(每月1日07:00月度全景洞察+3圖表+MoM/YoY比較)
- services/chart_generator_service.py:新建圖表生成服務(6種深色商業圖表,revenue_trend / category_revenue / monthly_overview / price_gap / price_history_heatmap / price_trend)
- services/telegram_templates.py:重建訊息模板系統(5類模板:告警/報告/決策/系統/洞察)、新增 send_photo + send_report_with_charts 圖文推播
- scheduler.py:新增 run_daily_report_task / run_monthly_report_task(含 auto_heal 保護)
- run_scheduler.py:每日09:00日報 + 每月1日07:00月報排程(月報用每日gate判斷day==1)
- requirements.txt:新增 matplotlib + matplotlib-inline

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 15:17:48 +08:00
ogt
784a3135c1 fix(telegram): 修正 EA 通知格式與 Agent 名稱問題
- 禁止 Gemini 音譯 Agent 名稱(赫瑪斯→Hermes, 內莫特朗→NemoTron)
- _AGENT_ZH 改為 _AGENT_LABEL,保留英文原名
- orchestrator system/user prompt 強制 reasoning 必須含具體數字
- _notify_telegram_executed 改為直接組裝訊息,顯示效益/依據/步驟
- _escalate_to_human 使用 _AGENT_LABEL 替換 _AGENT_ZH

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 13:03:49 +08:00
ogt
a62b83f488 feat(aiops): 完整 MCP + OpenClaw 全景電商分析管線
- 新增 services/mcp_collector_service.py:Gemini Search Grounding 外部情報收集
- 重寫 services/openclaw_strategist_service.py:真實 Gemini 2.5 Flash 分析,DB 持久化
- scheduler.py:修復 generate_meta_analysis_report ImportError,串接 Meta-Analysis
- elephant_alpha_autonomous_engine.py:新增 weekly_insight 觸發器路由 OpenClaw

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 12:50:35 +08:00
ogt
31dfbcdd4d fix(i18n): 強制 Elephant Alpha Gemini 回應繁體中文
- aider_heal_executor.py:全檔簡體→繁體,所有 Telegram 通知節點繁化
- elephant_alpha_orchestrator.py:system prompt 與 user prompt 雙層加入語言強制指令,確保 reasoning/expected_outcome 等欄位輸出繁體中文

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 12:22:13 +08:00
ogt
0cc940fdb1 fix: 恢復 ai_bp Blueprint 並完成全站修復
1. 恢復 ai_bp (routes/ai_routes.py) register — 修復 /ai_intelligence /ai_recommend 404
2. growth_analysis: SQL 月聚合取代 748k 行全表掃描(hang → 瞬間回應)
3. abc_analysis 冷快取: 快速 error 讓 spinner UI 導回 sales_analysis
4. elephant_alpha_routes.py: 補建 Blueprint stub 消除啟動 WARNING

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 00:55:05 +08:00
ogt
c447cbee44 fix(repo): update broken symlink to correct components path 2026-04-20 23:59:33 +08:00
ogt
bf5f0d256a fix(aiops): resolve ADR-014 logical bugs
- Fixed target_file context passing in auto_heal_service
- Fixed docker log scanning inside momo-scheduler using SSHJumpExecutor
- Fixed AiderHealExecutor SSH key path
2026-04-20 23:25:49 +08:00
ogt
e343a85322 docs: add ADR-014 to CLAUDE.md 2026-04-20 23:19:25 +08:00
ogt
3127466a85 feat(aiops): implement ADR-014 Autonomous Code Heal Pipeline
- Added AiderHealExecutor for SSH remote execution of aider-chat
- Added CODE_FIX action_type to AutoHealService
- Added code_exception trigger to Elephant Alpha engine (Traceback log scanning)
- Added 014 playbook migration script
2026-04-20 23:13:32 +08:00
ogt
4f4e7ef062 feat: 實作 PPT 簡報資料庫持久化機制
- 新增 PPTReport 模型,支援快取查詢結果和檔案路徑
- 實作 growth/vendor/bcg 三種報告的快取機制
- 24 小時過期設定,避免重複計算
- 自動清理過期快取記錄

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 22:59:04 +08:00
ogt
b8e6f752fa fix: 修復 Telegram Bot /menu 指令無響應及重複訊息問題
- telegram_bot_service: 新增 /menu 指令處理器,映射到 cmd_start
- openclaw_bot_routes: 優化「今日業績資料尚未匯入」訊息邏輯
  - 區分「資料載入異常」vs「確實未匯入」
  - 避免在已有今日資料時仍顯示未匯入訊息

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 22:48:07 +08:00
ogt
8df8b24043 docs: 新增 ALERT_WEBHOOK_PASSWORD 和 GITLAB_TOKEN 到 .env.example
- 新增 Alert Webhook 認證設定範例
- 新增 GitLab CI/CD API token 設定範例
- 解決啟動時的環境變數警告
2026-04-20 22:45:36 +08:00
ogt
b37658f7be fix: 修復 growth_analysis/abc_analysis 全表掃描 hang + elephant_alpha Blueprint stub
- growth_analysis: 改用 SQL 月度聚合 (3 個 targeted queries) 取代讀取 748k 行進 pandas
- _get_filtered_sales_data: 冷快取補載時 months=0 改為 months=12,避免全表掃描 hang
- elephant_alpha_routes: 補建 Blueprint stub 解除啟動 import 失敗警告

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 20:41:06 +08:00
ogt
74de1dc68a fix: add python-pptx to requirements + fix BCG empty name filter
- requirements.txt: 加入 python-pptx(ADR-014 PPT 系統必要依賴,前次漏加)
- openclaw_bot_routes.py: BCG SQL 補 brand_name/area_name IS NOT NULL 過濾

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 20:38:04 +08:00
ogt
48804553cd feat: PPT 簡報系統 V2 — 新增 growth/vendor/bcg 三種報告 + 原生圖表升級
- ppt_generator.py: 新增 generate_growth_ppt(6頁)、generate_vendor_ppt(5頁)、generate_bcg_ppt(5頁)
- openclaw_bot_routes.py: 新增 query_growth_data()、query_vendor_bcg_data()、_generate_ppt_cmd 三路分支、_submenu_reports 4顆新按鈕、type_labels、await:date_ppt_vendor 流程
- ADR-014: 記錄 V2 完整架構(9種報告類型、圖表技術方案、callback_data 格式)
- CLAUDE.md: 新增 PPT 簡報系統索引表

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 20:26:47 +08:00
ogt
d349b09afd fix: 補建 AIInsight ORM 模型(ai_insights 表缺少 class 定義)
ai_insights 表在 DB 存在且有 39 筆資料,但 database/ai_models.py 從未定義
AIInsight class,導致 quality_rescore_task、openclaw_learning_service
以及所有 AI KM 讀寫全部 ImportError 崩潰。
同步補入 __all__ 匯出,修復 embedding_retry_queue 2 筆卡住。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 20:23:23 +08:00
ogt
b2803c90be fix: DOCKER_RESTART 改走 SSH 跳板(110→188),修復 AIOps AutoHeal 閉環
根本原因:scheduler 容器內無 Docker socket,直接執行 docker restart 失敗。
修正:使用 SSHJumpExecutor(wooo@110 → ollama@188)透過跳板執行 docker restart。
SSH key:/app/config/autoheal_id_ed25519(rw mount 已存在)。
同步關閉 9 筆 2026-04-19 過期 DNS_FAIL incidents(根因已由網路修復解決)。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 20:19:46 +08:00
ogt
34620b7b04 feat: upgrade ppt_generator to v2 with native charts
- daily: 3→4頁,新增 P3 近7日業績柱狀圖
- weekly: 2→5頁,新增 KPI摘要、7日走勢圖、TOP10商品表
- monthly: 2→5頁,新增 KPI卡、品類橫條圖、TOP10商品表
- strategy: 3→5頁,新增策略矩陣柱狀圖+行動清單(含策略標籤)
- promo: 2→5頁,新增促銷vs對比期KPI、業績雙柱圖、TOP商品表
- competitor: 維持4頁,架構不變
- 新增 _add_column_chart / _add_horiz_chart 原生圖表 helper
- 新增 _product_table_slide 通用商品表格元件

圖表來源對照:daily_sales trendChart、monthly_summary_analysis、
growth_analysis revenueChart/momChart

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 20:08:18 +08:00
ogt
65de5d7893 fix: 所有 Telegram 告警內容統一繁體中文
新增 _TRIGGER_ZH / _AGENT_ZH / _ACTION_ZH 翻譯表:
- trigger_type 英文代碼 → 繁中標籤(價格下滑警報、市場機會偵測等)
- agent 名稱 → 繁中(Hermes 分析師、NemoTron 監控、OpenClaw 策略師)
- action 代碼 → 繁中(競品價格分析、派送告警通知等)
- 升級審核觸發類型、參與模組、執行步驟全面繁中化

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 20:07:36 +08:00
ogt
c8da68125d fix: add python-telegram-bot[job-queue] for daily 09:00 push schedule
JobQueue 是每日推播的依賴套件,缺少會導致定時推播靜默失敗

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 19:52:16 +08:00
ogt
704f5b6538 fix: restore full scheduler + telegram-bot + fix momo-app network isolation
三個關鍵修復:
1. momo-app 加入 momo-pro_default 網路 → 修復 momo-db DNS 解析失敗(crash loop)
2. 新增 telegram-bot compose 服務 → momo-telegram-bot 容器從未啟動,小龍蝦群組零訊息
3. 重寫 run_scheduler.py → 完整載入 scheduler.py 13 個真實排程任務
4. 新增 run_telegram_bot.py 至 repo(原本只存在 server,未納入版控)
5. cd.yaml 同步更新:三容器 restart/rebuild(app/scheduler/telegram-bot)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 19:48:32 +08:00
ogt
9ce8a51326 fix: add momo-pro_default external network to scheduler for momo-db access
Scheduler container needs to reach momo-db (on momo-pro_default network).
Without this, psycopg2 fails with DNS name resolution error on every recreate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 08:54:28 +08:00
ogt
cab57c4fb5 fix: correct POSTGRES_HOST momo-postgres → momo-db in docker-compose.yml
Compose env section was overriding the .env file fix with the wrong hostname,
causing psycopg2 name resolution failure after scheduler recreated via compose.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 08:46:42 +08:00
ogt
4c8edecd12 feat: rewrite ppt_generator.py with premium dark-theme design
Previous version was an emergency stub (緊急復原版) using plain white
PowerPoint default layouts. This commit restores the full premium design
visible in the product screenshot.

Design system:
  - 16:9 canvas (33.87 × 19.05 cm)
  - Cover: deep navy bg #0D1B2A + orange brand stripe #FF5722
  - Header bar: orange #FF5722 on all content slides
  - KPI cards: blue #1565C0 / green #2E7D32 / orange #E65100
  - Horizontal bar chart for competitor distribution
  - Striped data table with red/green price-diff coloring
  - Footer: ♥ Powered by OpenClaw on every slide

Slides per report type:
  competitor_ppt: Cover → KPI+BarChart → ProductTable → AI Insight
  daily_ppt:      Cover → KPI+TOP5     → AI Insight
  strategy_ppt:   Cover → KPI+TOP5     → AI Insight
  weekly/monthly/promo: Cover → AI Insight
2026-04-20 06:56:14 +08:00
ogt
fca235eb8d fix: close missing double-quote in sync restart step (shell parse error)
Line 134 was missing the closing " after the echo statement:
  echo '...'   (broken)
  echo '...'"  (fixed)

Caused: 'unexpected EOF while looking for matching"'
2026-04-20 06:49:32 +08:00
ogt
2ffbe06eab fix: resolve container name conflict in rebuild CD step
'docker compose up --force-recreate' fails when the existing container
was started by a different compose invocation, leaving a stale container
with the same name. Error: 'container name already in use'.

Fix: explicitly stop + rm the two containers before compose build & up.
Using 2>/dev/null to ignore errors if containers are already stopped.
Removed --force-recreate (no longer needed after explicit rm).
2026-04-20 06:46:04 +08:00
ogt
456c031955 fix: remove defunct momo-telegram-bot from all CD/compose references
CD was failing with 'No such container: momo-telegram-bot' because
the Gitea Actions restart step still listed all three containers.

Changes:
1. .gitea/workflows/cd.yaml:
   - Sync mode: docker restart now only targets momo-pro-system momo-scheduler
   - Rebuild mode: docker compose up no longer includes telegram-bot service

2. docker-compose.yml:
   - Removed telegram-bot service block (38 lines)
   - Syncs local repo with remote server state (already removed there)
2026-04-20 06:19:44 +08:00
ogt
e0d3b54527 feat: add PPT shortcut buttons after sales & trend query results
Previously after querying sales or trend data, there were no direct
PPT generation buttons — users had to navigate back to 簡報報表 menu.

Changes:
1. sales_quick_kb(date_str):
   + [📊 產出日報 PPT]  → cmd:ppt:daily <date>
   + [📄 策略簡報]      → cmd:ppt:strategy <date>

2. trend ≤35 days (weekly/monthly view):
   + [📊 產出趨勢簡報] → cmd:ppt:strategy <start_date>
   + [📅 產出日報 PPT] → cmd:ppt:daily <end_date>
   + [← 返回業績查詢]  → menu:sales

3. trend >35 days (quarterly/half-year/yearly view):
   + [📊 產出趨勢簡報] → cmd:ppt:strategy <period>
   + [📅 月報 PPT]     → cmd:ppt:monthly <month>
   + [← 返回業績查詢]  → menu:sales
2026-04-20 06:14:39 +08:00
ogt
6435bed005 feat: implement missing PChome high-level comparison functions
Previously pchome_crawler.py only had low-level crawling primitives.
All high-level functions used by openclaw_bot_routes.py were missing,
causing _PCHOME_AVAILABLE = False on startup and '簡報生成失敗' errors.

Implemented:
  search_pchome(keyword, limit)        — simplified search → list of dicts
  find_best_match(keyword, momo_price) — best PChome match for a product
  compare_product(name, price, icode)  — single momo vs PChome comparison
  batch_compare_top(db, top_n, date)   — batch compare TOP-N momo hottest
  save_matches(db, results)            — persist results to pchome_matches
  ensure_tables(db)                    — idempotent table creation
  fmt_compare_msg(results, keyword)    — Telegram Markdown single-item msg
  fmt_daily_report(results, date_str)  — Telegram Markdown daily report msg

After this commit _PCHOME_AVAILABLE will be True and competitor PPT
generation will no longer throw RuntimeError.
2026-04-20 06:09:33 +08:00
ogt
3da9ba247c remove: delete defunct momo-telegram-bot service
This service was a dead-weight remnant from early development:
- Only 148 lines, no real business logic (just a startup scaffold)
- Supported /trend /search /copy /keywords — all superseded by OpenClaw
- Used same Bot Token as OpenClaw → called deleteWebhook on startup,
  destroying OpenClaw webhook and causing /menu and all commands to fail
- JobQueue not installed so daily push also did not work

Actions taken:
- Stopped and removed momo-telegram-bot container
- Removed telegram-bot service block from docker-compose.yml on 188
- Deleted run_telegram_bot.py from repo
- Webhook re-set to https://mo.wooo.work/bot/telegram/webhook
2026-04-20 06:03:30 +08:00
ogt
043ad3e6d9 fix: /menu@BotName in group chat not parsed correctly
Root cause: Telegram appends @BotUsername to commands in group chats:
  /menu@OpenClawAwoool_Bot

The parser did:
  q = question.lstrip('/')   → 'menu@OpenClawAwoool_Bot'
  cmd = q.split()[0].lower() → 'menu@openclawawoool_bot'

This did NOT match 'menu' in KNOWN set, so the command fell through
to openclaw_answer() (natural language mode) → no menu appeared.

Fix: cmd = raw_cmd.split('@')[0]
  → strips @mention suffix before KNOWN lookup
  → /menu@OpenClawAwoool_Bot now correctly dispatches to handle_cmd('menu')

Affects all slash commands in group chat mode.
2026-04-20 05:55:00 +08:00
ogt
20e83306fe security: fix SSH command injection in SSHJumpExecutor + implement AutoHealService
Issues fixed:

1. [HIGH] OS Command Injection in execute_command() (CWE-78)
   command was accepted as a string and passed as the final SSH positional
   arg. Remote SSH executes it via sh -c, so shell metacharacters in
   command (semicolons, pipes, backticks) are interpreted.
   e.g. command="id; curl attacker.com" → two commands execute on target.
   Fix: command parameter changed to List[str]; TypeError raised if str
   is passed; SSH cmd built with ['--, *command] so remote shell sees
   argv, not a shell string. '--' stops SSH from interpreting options.

2. [HIGH] SSH Option Injection via host/user parameters (CWE-88)
   jump_host, target_host, jump_user, target_user were unsanitized.
   Attacker-controlled host like "-oProxyCommand=curl attacker.com #"
   could inject SSH options.
   Fix: _validate_host() / _validate_user() with strict regex on init
   and in execute_command(); ValueError raised on invalid input.

3. [BUG] AutoHealService.handle_exception() did not exist
   elephant_alpha_autonomous_engine.py imports and calls
   AutoHealService().handle_exception() — this would raise AttributeError
   at runtime. AutoHealService is now fully implemented:
   - Playbook lookup from DB (autoheal_models.Playbook)
   - ALLOWED_ACTION_TYPES allowlist (DOCKER_RESTART/WAIT_RETRY/ALERT_ONLY/SSH_CMD)
   - DOCKER_RESTART: static ['docker','restart',<validated_container>]
   - SSH_CMD: requires action_params.argv as list; host/user validated

4. [DESIGN] Duplicate SSHJumpExecutor across two files
   auto_heal_service.py and openclaw_strategist_service.py were byte-for-
   byte copies. Single source of truth now in auto_heal_service.py;
   openclaw_strategist_service.py re-exports SSHJumpExecutor.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 05:53:08 +08:00
ogt
38586deff1 security: harden alert_routes.py — auth coverage + input validation
Issues fixed:

1. [CRITICAL] /api/alert/fix unauthenticated (CWE-306)
   POST /api/alert/fix had no @check_alert_auth and was CSRF-exempt.
   Any unauthenticated caller could trigger docker restart or
   docker exec on arbitrary container names (container_name is validated
   by is_valid_container_name but restart of any valid name is still
   a DoS vector). Fix: @check_alert_auth added.

2. [HIGH] Hardcoded ALERT_WEBHOOK_PASSWORD fallback (CWE-798)
   Default 'wooo_alert_2026' exposed in source. Fix: default='',
   startup warning if unset. check_alert_auth now fail-secure:
   returns 503 if password not configured.

3. [MEDIUM] /api/alert/history and /api/alert/analyze unauthenticated
   Both endpoints expose container names, memory usage, CPU stats,
   system recommendations. Fix: @check_alert_auth added to both.

4. [MEDIUM] issue_type unvalidated in manual_fix (CWE-20)
   Any string value could be passed through to auto_fix_container.
   Fix: ALLOWED_ISSUE_TYPES frozenset — only memory/cpu variants allowed.

5. [LOW] limit parameter unbounded in get_alert_history
   Arbitrarily large limit → large list slice → memory pressure.
   Fix: clamped to [1, 200].

NOTE: L177 docker stats command (original report) is SAFE as-is —
list argv, fixed arguments, no user input. nosec B603 correctly placed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 05:49:04 +08:00
ogt
96e19b6b72 security: harden system_routes.py — auth + input validation
Issues fixed:

1. [CRITICAL] No authentication on destructive routes (CWE-306)
   POST /api/system/cleanup/docker was unauthenticated (system_bp is
   CSRF-exempt, before_request only refreshes session, no login check).
   Any unauthenticated HTTP client could trigger docker system prune.
   Fix: _require_internal_key() checks X-Internal-Key header against
   INTERNAL_API_KEY env var on all 4 routes; fail-secure if key unset.

2. [MEDIUM] Unvalidated numeric inputs in find commands (CWE-20)
   max_size_mb / older_than_hours came from POST body and were
   interpolated into find -size / -mmin args. Negative/huge values
   could cause unexpected behavior.
   Fix: _validate_int() clamps to [1..10000] / [1..8760] with defaults.

3. [LOW] find -mmin arg missing leading '+' (logic bug)
   '-mmin 168' matches FILES EXACTLY 168 min old, not older-than.
   Fix: '-mmin', f'+{older_than_hours * 60}' (+ = older than)

4. [LOW] subprocess(['date', ...]) in health_check replaced
   with Python datetime.now(UTC).isoformat() — no subprocess needed.

INTERNAL_API_KEY added to .env.example with generation instructions.
Generate with: openssl rand -hex 32

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 05:47:04 +08:00
ogt
1c03d213ac security: fix shell injection + hardcoded credentials in cicd_routes.py
CVE-class issues fixed:

1. [HIGH] Shell Injection in gitlab_api_via_ssh (CWE-78)
   endpoint and json_data were interpolated into f-string cmd and passed
   as a single SSH remote command string → shell parses it → injection.
   Fix: build remote_argv as list; each curl argument is a separate item,
   SSH receives them as independent argv (no shell parsing of user data).

2. [HIGH] Hardcoded credentials in source code (CWE-798)
   GITLAB_TOKEN, TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID all had live
   secrets as default fallback values. Tokens are now '' (empty) with a
   startup warning if env vars are missing.

3. [MEDIUM] Missing pre-validation allowlist on fix_action (CWE-20)
   ALLOWED_FIX_ACTIONS frozenset added before route handler; any unknown
   action is rejected with 400 before reaching execution logic.

Note: fix_registry/fix_pods/execute_*_rollback use static SSH commands
(no user input in cmd strings) so they are not injection risks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 05:44:18 +08:00
ogt
61496af2c5 fix: stop runaway EA Telegram spam (cooldown + API key detection + dedup)
Root cause: OPENROUTER_API_KEY not set → fallback confidence=0.60 →
always below threshold → _escalate_to_human() every 60s loop → infinite
Telegram messages, all meaningless.

Three-layer fix:
1. API Key detection: if fallback_decision triggered (reasoning contains
   "Elephant Alpha unavailable"), silently skip — no Telegram, no cost,
   update last_triggered to prevent infinite retry
2. Per-trigger cooldown in _check_triggers():
   price_drop_alert 30min / market_opportunity 60min /
   threat_escalation 15min / resource_optimization 60min
3. Escalation dedup in _escalate_to_human(): _last_escalated[] tracks
   last Telegram send time per trigger type; suppresses within cooldown

Valid HITL escalations (when EA is actually online) still work correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 05:34:21 +08:00
ogt
d8d1f3dee8 fix: create ADR-012 agent tables migration + fix telegram_models import
Migration 017:
- CREATE TABLE IF NOT EXISTS agent_context, action_plans, action_outcomes,
  agent_strategy_weights (all four ADR-012 tables were missing from production DB)
- These tables are required by ElephantAlpha AutonomousEngine coordination loop

telegram_templates.py:
- Fix: from database.telegram_models → database.trend_models (TelegramUser
  has always lived in trend_models; telegram_models module does not exist)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 05:21:17 +08:00
ogt
47cfd79513 fix: add Migration 016 — playbooks.description column missing from DB schema
Playbook SQLAlchemy model has description column but production DB table
does not, causing seed_playbooks() to fail with UndefinedColumn error.
ADD COLUMN IF NOT EXISTS is idempotent — safe to re-run.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 05:01:01 +08:00
ogt
aef8982cbb fix: add Incident/Playbook/HealLog to autoheal_models.py (was never committed)
ADR-013 AIOps classes Incident, Playbook, HealLog existed locally but were
missing from git. manager.py imports them → ImportError on every scheduler
restart. Also fixes transitive MetaData conflict with ai_models.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 04:50:28 +08:00
ogt
f2b20c1892 fix: eliminate duplicate SQLAlchemy table definitions in ai_models.py
AgentContext/ActionPlan/ActionOutcome/AgentStrategyWeights were defined
in both ai_models.py and autoheal_models.py, causing:
  "Table 'agent_context' is already defined for this MetaData instance"
on every scheduler startup.

ai_models.py is now a pure re-export shim from autoheal_models.py.
autoheal_models.py remains the single source of truth (ADR-013).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 04:47:23 +08:00
ogt
266af27fd6 fix: correct broken ai_models imports in database/manager.py
AIGenerationHistory/AIInsight/AIUsageTracking/AIPromptTemplate never existed;
actual classes are AgentContext/ActionPlan/ActionOutcome/AgentStrategyWeights.
This caused momo-scheduler to crash on every restart.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 04:30:47 +08:00
ogt
ba86f98514 feat: integrate Elephant Alpha ecosystem with full ADR-012/013 compliance
- Add ElephantService, AutonomousEngine, Orchestrator, DecisionRouter (EA 4-file stack)
- Fix 10 bugs: URL typo, SQL schema mismatches (price_records JOIN), enum mapping,
  metadata_json, NemoTron PriceThreat dispatch, async/await mismatch, broken imports
- Wire ADR-012 Agent Action Ladder: EventRouter L2 → EA first + AIOrch fallback;
  all decisions dual-write DB + triaged_alert Telegram; momo: callback prefix
- Wire ADR-013 AutoHeal: resource_optimization trigger → AutoHealService
- Add W3 guards: connection cache 300s TTL, $5/hr cost hard limit
- Add W4 persistence: routing decisions + agent performance snapshots → ai_insights
- Add Migration 015: confidence + created_by columns on ai_insights
- Fix run_scheduler.py broken imports (DecisionTracker service didn't exist)
- Fix verify_elephant_integration.py: check_status() → check_connection()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 04:28:26 +08:00