fix(ci): Harbor HTTP registry + Telegram secrets
CD 修復: - 修復 buildx HTTP vs HTTPS 問題 (insecure registry 設定) - 移除 UAT 環境 (違反 Memory 鐵律) - 新增 Production 部署 Telegram 通知 - 修復 deploy-prod.yml 硬編碼 Token (改用 secrets) docs: - 新增 guidelines/ 結構化指引目錄 - ARCHITECTURE.md, FRONTEND.md, OPERATIONS.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
137
docs/guidelines/ARCHITECTURE.md
Normal file
137
docs/guidelines/ARCHITECTURE.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# AWOOOI 架構指引
|
||||
|
||||
> 架構相關的核心原則與規範
|
||||
|
||||
## 快速索引
|
||||
|
||||
| 主題 | 核心原則 | 詳細章節 |
|
||||
|------|---------|---------|
|
||||
| OpenClaw | 產品核心,只能增強不能移除 | [→ OpenClaw](#openclaw-核心架構) |
|
||||
| 模組化 | Interface → Memory → Brain → Skill | [→ leWOOOgo](#lewooogo-模組化) |
|
||||
| API 整合 | Props Mapping 五步驟檢查 | [→ API](#api-整合) |
|
||||
| 防禦性 | 先質疑後實作 | [→ 防禦性工程](#防禦性工程) |
|
||||
|
||||
---
|
||||
|
||||
## OpenClaw 核心架構
|
||||
|
||||
**Memory 來源:** `feedback_architecture_openclaw_core.md`
|
||||
|
||||
### 原則
|
||||
|
||||
```
|
||||
✅ OpenClaw 是 AWOOOI 產品核心
|
||||
✅ 只能增強,不能移除
|
||||
✅ 決策鏈必須可視化 (ThinkingTerminal)
|
||||
✅ 雙軌決策: LLM + Expert System Fallback
|
||||
```
|
||||
|
||||
### 決策流程
|
||||
|
||||
```
|
||||
Signal → IncidentEngine → DecisionManager → Telegram/UI
|
||||
↓
|
||||
LLM 提案 + Expert System 備援
|
||||
```
|
||||
|
||||
### 命名規範
|
||||
|
||||
- ✅ 正確: OpenClaw, openclaw
|
||||
- ❌ 禁止: ClawBot, clawbot (舊稱)
|
||||
|
||||
---
|
||||
|
||||
## leWOOOgo 模組化
|
||||
|
||||
**Memory 來源:** `feedback_modular_architecture.md`, `feedback_modular_core_spirit.md`
|
||||
|
||||
### 四層架構
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Skill Layer (技能層) │
|
||||
│ - 特定領域知識 │
|
||||
│ - 可組合、可替換 │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Brain Layer (決策層) │
|
||||
│ - LLM + Expert System │
|
||||
│ - 決策邏輯 │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Memory Layer (記憶層) │
|
||||
│ - Working: Redis (短期) │
|
||||
│ - Episodic: PostgreSQL (長期) │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Interface Layer (介面層) │
|
||||
│ - Telegram Gateway │
|
||||
│ - REST API │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 核心精神
|
||||
|
||||
1. **Interface 先行** - 先定義清晰的介面契約
|
||||
2. **Memory 分離** - Working Memory ≠ Episodic Memory
|
||||
3. **Brain 獨立** - 決策邏輯不綁定特定 LLM
|
||||
4. **Skill 可組合** - 技能可插拔、可替換
|
||||
|
||||
---
|
||||
|
||||
## API 整合
|
||||
|
||||
**Memory 來源:** `feedback_api_response_verification.md`
|
||||
|
||||
### Props Mapping 五步驟檢查
|
||||
|
||||
新增 API 欄位時,必須確認完整鏈路:
|
||||
|
||||
```
|
||||
1. API Response 有該欄位 ✓
|
||||
2. Mapper 函數有轉換該欄位 ✓ ← 最常遺漏!
|
||||
3. TypeScript 型別有定義該欄位 ✓
|
||||
4. 組件 Props 有接收該欄位 ✓
|
||||
5. 組件有使用該欄位 ✓
|
||||
```
|
||||
|
||||
### 快速診斷
|
||||
|
||||
```bash
|
||||
# 確認 API 有回傳
|
||||
curl -s API_URL | jq '.[0].decision'
|
||||
|
||||
# 確認 Mapper 有轉換
|
||||
grep -n "decision" apps/web/src/app/*/page.tsx
|
||||
```
|
||||
|
||||
### 2026-03-23 教訓
|
||||
|
||||
Y/n 按鈕灰色無法點擊,因為 `mapToDualState()` 遺漏傳遞 `decision` 欄位。
|
||||
|
||||
---
|
||||
|
||||
## 防禦性工程
|
||||
|
||||
**Memory 來源:** `feedback_defensive_engineering.md`
|
||||
|
||||
### 原則
|
||||
|
||||
```
|
||||
1. 先質疑,後實作
|
||||
2. 看到可疑代碼,先問為什麼存在
|
||||
3. 不確定的變更,先問統帥
|
||||
4. 任何刪除操作,三思後行
|
||||
```
|
||||
|
||||
### 常見陷阱
|
||||
|
||||
- 「這段代碼看起來沒用」→ 先 grep 確認沒人用
|
||||
- 「這個 TODO 很久了」→ 先確認是否已完成
|
||||
- 「這個邏輯很奇怪」→ 可能是特殊 case 處理
|
||||
|
||||
---
|
||||
|
||||
## 相關 ADR
|
||||
|
||||
- [ADR-003: leWOOOgo 模組架構](adr/ADR-003-lewooogo-module-architecture.md)
|
||||
- [ADR-006: AI Fallback 策略](adr/ADR-006-ai-fallback-strategy.md)
|
||||
- [ADR-008: Python 模組化](adr/ADR-008-python-modular-packages.md)
|
||||
- [ADR-009: OpenClaw Agent Teams](adr/ADR-009-openclaw-agent-teams.md)
|
||||
159
docs/guidelines/FRONTEND.md
Normal file
159
docs/guidelines/FRONTEND.md
Normal file
@@ -0,0 +1,159 @@
|
||||
# AWOOOI 前端指引
|
||||
|
||||
> 前端開發的核心原則與規範
|
||||
|
||||
## 快速索引
|
||||
|
||||
| 主題 | 核心原則 | 詳細章節 |
|
||||
|------|---------|---------|
|
||||
| i18n | 100% next-intl,零硬編碼 | [→ i18n](#i18n-雙語) |
|
||||
| 視覺 | Nothing.tech 風格 | [→ 視覺規範](#視覺規範) |
|
||||
| 狀態 | Zustand (禁止 Redux) | [→ 狀態管理](#狀態管理) |
|
||||
| 數據 | 真實 API,禁止假數據 | [→ 數據規範](#數據規範) |
|
||||
|
||||
---
|
||||
|
||||
## i18n 雙語
|
||||
|
||||
**Memory 來源:** `feedback_i18n_zero_hardcode.md`, `feedback_naming_i18n.md`
|
||||
|
||||
### 鐵律
|
||||
|
||||
```tsx
|
||||
// ❌ 禁止 - 任何硬編碼文字
|
||||
<button>Submit</button>
|
||||
<span>Loading...</span>
|
||||
<p>System Status</p>
|
||||
|
||||
// ✅ 正確 - 100% next-intl
|
||||
<button>{t('common.submit')}</button>
|
||||
<span>{t('common.loading')}</span>
|
||||
<p>{t('dashboard.systemStatus')}</p>
|
||||
```
|
||||
|
||||
### 支援語言
|
||||
|
||||
- `zh-TW` - 繁體中文 (預設)
|
||||
- `en` - English
|
||||
|
||||
### 翻譯檔位置
|
||||
|
||||
```
|
||||
apps/web/src/messages/
|
||||
├── zh-TW.json
|
||||
└── en.json
|
||||
```
|
||||
|
||||
### 新增翻譯流程
|
||||
|
||||
1. 在 `zh-TW.json` 新增 key
|
||||
2. 在 `en.json` 新增對應翻譯
|
||||
3. 在組件使用 `t('your.key')`
|
||||
|
||||
---
|
||||
|
||||
## 視覺規範
|
||||
|
||||
**Memory 來源:** `feedback_naming_i18n.md`
|
||||
|
||||
### Nothing.tech 風格
|
||||
|
||||
```
|
||||
- 白玻璃毛玻璃效果 (awoooi-glass)
|
||||
- 點陣紋理背景
|
||||
- DataPincer 數據鉗容器
|
||||
- 黑白紅極簡配色
|
||||
```
|
||||
|
||||
### 顏色系統
|
||||
|
||||
```css
|
||||
/* 主色 */
|
||||
--nothing-black: #000000
|
||||
--nothing-white: #ffffff
|
||||
--claw-red: #ff0000
|
||||
|
||||
/* 狀態色 */
|
||||
--status-healthy: #00ff00
|
||||
--status-warning: #ffaa00
|
||||
--status-critical: #ff0000
|
||||
```
|
||||
|
||||
### 組件規範
|
||||
|
||||
```tsx
|
||||
// DataPincerPanel - 標準容器
|
||||
<DataPincerPanel title={t('dashboard.title')} status="healthy">
|
||||
{children}
|
||||
</DataPincerPanel>
|
||||
|
||||
// DataPincerCard - 卡片容器
|
||||
<DataPincerCard>
|
||||
{content}
|
||||
</DataPincerCard>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 狀態管理
|
||||
|
||||
**Memory 來源:** ADR-004
|
||||
|
||||
### 鐵律
|
||||
|
||||
```tsx
|
||||
// ❌ 禁止 - Redux
|
||||
import { useSelector } from 'react-redux'
|
||||
|
||||
// ✅ 正確 - Zustand
|
||||
import { useStore } from '@/stores/xxx.store'
|
||||
```
|
||||
|
||||
### Store 結構
|
||||
|
||||
```
|
||||
apps/web/src/stores/
|
||||
├── agent.store.ts - Agent 狀態
|
||||
├── incident.store.ts - Incident 狀態
|
||||
└── ui.store.ts - UI 狀態
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 數據規範
|
||||
|
||||
**Memory 來源:** `feedback_no_fake_data.md`
|
||||
|
||||
### 鐵律
|
||||
|
||||
```tsx
|
||||
// ❌ 禁止 - 假數據
|
||||
const data = DEMO_DATA
|
||||
const mockMetrics = generateMockData()
|
||||
|
||||
// ✅ 正確 - 真實 API
|
||||
const { data } = useRealAPI()
|
||||
const { metrics } = useGlobalPulseMetrics()
|
||||
```
|
||||
|
||||
### 2026-03-23 教訓
|
||||
|
||||
`GlobalPulseChartDemo` 使用假數據,導致用戶無法看到真實系統狀態。已修正為 `GlobalPulseChart` 連接真實 API。
|
||||
|
||||
### Loading/Error 處理
|
||||
|
||||
```tsx
|
||||
const { data, isLoading, error } = useAPI()
|
||||
|
||||
if (isLoading) return <Spinner />
|
||||
if (error) return <ErrorState message={error} />
|
||||
return <RealData data={data} />
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 相關 ADR
|
||||
|
||||
- [ADR-002: Nothing.tech 設計系統](adr/ADR-002-nothing-tech-design-system.md)
|
||||
- [ADR-004: 狀態管理 (Zustand)](adr/ADR-004-state-management.md)
|
||||
- [UX-001: Incident Card Fatigue](design/UX-001-incident-card-fatigue.md)
|
||||
165
docs/guidelines/OPERATIONS.md
Normal file
165
docs/guidelines/OPERATIONS.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# AWOOOI 維運指引
|
||||
|
||||
> 維運、部署、CI/CD 的核心原則與規範
|
||||
|
||||
## 快速索引
|
||||
|
||||
| 主題 | 核心原則 | 詳細章節 |
|
||||
|------|---------|---------|
|
||||
| Telegram | 絕對禁止 logOut | [→ Telegram](#telegram-整合) |
|
||||
| 部署 | Dev + Prod (禁止 UAT) | [→ 部署拓撲](#部署拓撲) |
|
||||
| CI/CD | self-hosted runner | [→ CI/CD](#cicd) |
|
||||
| 構建 | Git Clone Only | [→ 構建流程](#構建流程) |
|
||||
|
||||
---
|
||||
|
||||
## Telegram 整合
|
||||
|
||||
**Memory 來源:** `feedback_telegram_token_disaster.md`, `feedback_openclaw_security.md`
|
||||
|
||||
### 2026-03-23 災難事件
|
||||
|
||||
```python
|
||||
# ❌ 禁止 - 會導致 Token 永久失效!
|
||||
await bot.log_out()
|
||||
|
||||
# ✅ 正確流程
|
||||
1. 先停止舊 Bot 的 Long Polling
|
||||
2. 確認舊 Bot 完全停止
|
||||
3. 再啟動新 Bot
|
||||
```
|
||||
|
||||
### Long Polling 規則
|
||||
|
||||
```
|
||||
一個 Bot Token 只能有一個 Long Polling 實例!
|
||||
|
||||
✅ OpenClaw (192.168.0.188) - 唯一 Polling 實例
|
||||
❌ AWOOOI API - 只發送,不接收
|
||||
```
|
||||
|
||||
### 心跳監控
|
||||
|
||||
```python
|
||||
# 防止 Telegram 靜默盲點
|
||||
heartbeat_interval = 30 minutes
|
||||
silence_threshold = 2 hours
|
||||
|
||||
# 超過 2 小時沒訊息 → 主動告警
|
||||
```
|
||||
|
||||
### 安全規則
|
||||
|
||||
```
|
||||
✅ Webhook Secret 驗證
|
||||
✅ Chat ID 白名單
|
||||
✅ Rate Limiting
|
||||
❌ 禁止在 Telegram 傳送敏感資訊 (密碼、Token)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 部署拓撲
|
||||
|
||||
**Memory 來源:** `feedback_deployment_topology.md`, `feedback_no_uat_environment.md`
|
||||
|
||||
### 環境
|
||||
|
||||
```
|
||||
✅ Dev - 開發環境 (localhost)
|
||||
✅ Prod - 生產環境 (K3s)
|
||||
❌ UAT - 禁止 (資源浪費)
|
||||
```
|
||||
|
||||
### 五主機架構
|
||||
|
||||
| Host | IP | 角色 | 服務 |
|
||||
|------|-----|------|------|
|
||||
| wooo-nas | 192.168.0.100 | NAS + 監控 | Grafana, ClickHouse |
|
||||
| wooo-k3s | 192.168.0.101 | K3s Master | API 調度 |
|
||||
| awoooi-110 | 192.168.0.110 | K3s Worker | GitHub Runner |
|
||||
| openclaw-188 | 192.168.0.188 | AI 服務 | OpenClaw, Ollama |
|
||||
| wooo-router | 192.168.0.1 | 路由 | DDNS, 防火牆 |
|
||||
|
||||
### Port 分配
|
||||
|
||||
```
|
||||
:3000 - Next.js (Web)
|
||||
:8000 - FastAPI (API)
|
||||
:8088 - OpenClaw Legacy
|
||||
:11434 - Ollama
|
||||
:8123 - ClickHouse
|
||||
:3001 - Grafana
|
||||
:4317 - OTEL gRPC
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CI/CD
|
||||
|
||||
**Memory 來源:** `feedback_github_billing.md`
|
||||
|
||||
### 鐵律
|
||||
|
||||
```yaml
|
||||
# ❌ 禁止 - 帳單額度限制
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# ✅ 正確 - self-hosted runner
|
||||
runs-on: self-hosted
|
||||
```
|
||||
|
||||
### Self-Hosted Runner
|
||||
|
||||
```
|
||||
位置: 192.168.0.110 (awoooi-110)
|
||||
名稱: awoooi-110
|
||||
狀態: 需確認是否在線
|
||||
```
|
||||
|
||||
### 自動檢查
|
||||
|
||||
Pre-commit 腳本自動檢查:
|
||||
```bash
|
||||
# .claude/hooks/pre-commit-check.sh
|
||||
grep -r "runs-on: ubuntu-latest" .github/workflows/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 構建流程
|
||||
|
||||
**Memory 來源:** `feedback_build_from_git_only.md`
|
||||
|
||||
### 鐵律
|
||||
|
||||
```bash
|
||||
# ❌ 禁止 - 直接在伺服器編輯
|
||||
vim /path/to/file.py
|
||||
nano /path/to/config.yaml
|
||||
|
||||
# ✅ 正確 - 只從 Git 部署
|
||||
git clone → build → deploy
|
||||
```
|
||||
|
||||
### 部署流程
|
||||
|
||||
```
|
||||
1. 本地開發 → 2. git push → 3. CI/CD 構建 → 4. K3s 部署
|
||||
```
|
||||
|
||||
### Docker 構建
|
||||
|
||||
```yaml
|
||||
# Next.js 必須 build-time 注入環境變數
|
||||
ARG NEXT_PUBLIC_API_URL
|
||||
ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 相關 ADR
|
||||
|
||||
- [ADR-005: BFF 架構](adr/ADR-005-bff-architecture.md)
|
||||
- [ADR-010: Secrets 管理](adr/ADR-010-secrets-management.md)
|
||||
- [ADR-011: NetworkPolicy 治理](adr/ADR-011-networkpolicy-governance.md)
|
||||
Reference in New Issue
Block a user