# AI Processing Visibility Panel — Implementation Plan **Goal:** Make AI processing fully observable. Know if AI is running, what it output, why it routed each item. **Placement:** Above signal source list on SSTC board. Collapsible. Expanded by default in dev mode. **Scope:** Frontend panel + backend logging endpoints. No new pages. --- ## Backend ### 1. Logging (add to existing AI job) Every Feishu message processed must write a log record: - [ ] Create `ai_processing_logs` table: ``` id feishu_message_id feishu_item_id (FK) raw_message -- original Feishu text ai_raw_output -- full JSON from LLM project_score -- float 0–1 signal_confidence -- float 0–1 level -- "project" or "signal" routing_decision -- "auto_create_project" / "auto_enter_signal" / "pending_low_confidence" / "pending_cold_start" / "pending_uncertain_project" / "duplicate_filtered" routing_reason -- plain text, 1 sentence reasoning_bullets -- JSON array, 3 items processing_status -- "success" / "failed" / "processing" error_message -- null if success duration_ms -- processing time created_at ``` - [ ] On duplicate detected (`feishu_message_id` already exists): write log with `routing_decision = "duplicate_filtered"`, do not process further - [ ] On AI job failure: write log with `processing_status = "failed"` + `error_message` ### 2. API endpoints - [ ] `GET /api/ai-logs?project_id=&limit=20&offset=0` — paginated log list for a project - [ ] `GET /api/ai-logs/stats?project_id=&date=today` — daily stats summary - [ ] `GET /api/ai-logs/{id}` — full detail for one log record - [ ] `GET /api/ai-logs/latest?project_id=` — most recent log record (for real-time status) --- ## Frontend ### Panel structure Collapsible section above the signal source table. Toggle button: "AI 处理状态 ▾" Default state: collapsed in production, expanded in dev (`import.meta.env.DEV`). Three blocks inside: --- ### Block 1 — Latest processing status (real-time) Polls `GET /api/ai-logs/latest` every 10 seconds. ``` ┌─────────────────────────────────────────────────────┐ │ 最近处理 │ │ │ │ ✅ 已处理 14:23:01 耗时 3.2s │ │ 原始消息:新增个需求,关于做饭食谱...(点击展开) │ │ │ │ project_score: 0.31 → 信号级别 │ │ confidence: 0.62 → 低于阈值,进待处理队列 │ │ 路由:冷启动期 / 低置信度 │ └─────────────────────────────────────────────────────┘ ``` Status indicator colors: - ✅ green — success - ⏳ yellow — processing (AI job in flight) - ❌ red — failed, shows error message - [ ] Build `LatestProcessingStatus` component - [ ] Poll `/api/ai-logs/latest` every 10s, stop polling if tab not focused - [ ] Show raw message truncated to 1 line, click to expand full text - [ ] Show `project_score`, `signal_confidence`, `routing_decision`, `routing_reason` - [ ] Show `duration_ms` formatted as seconds --- ### Block 2 — Today's stats Fetches `GET /api/ai-logs/stats` once on mount, refetches when new log arrives. ``` ┌─────────────────────────────────────────────────────┐ │ 今日统计 │ │ │ │ 接收 12 │ AI处理成功 10 │ 失败 2 │ 重复过滤 2 │ │ 自动入库 3 │ 待处理 7 │ │ 平均 confidence: 0.71 │ 平均 project_score: 0.28 │ └─────────────────────────────────────────────────────┘ ``` - [ ] Build `DailyStats` component - [ ] Display all 7 counters in a single row of stat chips - [ ] Highlight failed count in red if > 0 - [ ] Show average scores to 2 decimal places --- ### Block 3 — Processing log list Fetches `GET /api/ai-logs?project_id=` with pagination. Shows last 20 records. Each row: ``` 时间 状态 路由决策 confidence project_score 操作 14:23:01 ✅ pending_low_conf 0.62 0.31 [详情] 12:06:25 ✅ auto_enter_signal 0.83 0.29 [详情] 12:00:11 ❌ failed — — [详情] 11:39:27 ✅ duplicate_filtered — — [详情] ``` - [ ] Build `ProcessingLogTable` component - [ ] Columns: time / status icon / routing decision (translated to Chinese label) / confidence / project_score / detail button - [ ] `routing_decision` label map: - `auto_create_project` → 🏗 自动创建项目 - `auto_enter_signal` → ✅ 自动入库 - `pending_low_confidence` → ⏸ 低置信度待处理 - `pending_cold_start` → ⏸ 冷启动期待处理 - `pending_uncertain_project` → ⏸ 项目归属不确定 - `duplicate_filtered` → 🔁 重复过滤 - `failed` → ❌ 处理失败 - [ ] Click `[详情]` → opens a right-side drawer showing: - Raw Feishu message (full text) - AI raw output (JSON, formatted) - All scores and reasoning bullets - Error message if failed - [ ] Pagination: load more button at bottom (not infinite scroll) - [ ] Row color: red background if `processing_status = failed` --- ## Routing decision labels (used in both backend logs and frontend display) | `routing_decision` value | Meaning | |--------------------------|---------| | `auto_create_project` | project_score ≥ 0.85, cold start over, project auto-created | | `auto_enter_signal` | confidence ≥ 0.80, cold start over, signal auto-entered | | `pending_low_confidence` | confidence < 0.80, queued for review | | `pending_cold_start` | cold start period active, all items queued regardless of score | | `pending_uncertain_project` | project_score 0.60–0.84, queued for user to confirm | | `duplicate_filtered` | feishu_message_id already processed, dropped | | `failed` | AI job threw an error | --- ## Implementation order | Task | When | |------|------| | `ai_processing_logs` table + write logs in AI job | First, before anything else — need data to display | | 4 API endpoints | After table exists | | `DailyStats` component | Quick win, shows immediately if AI is running | | `LatestProcessingStatus` component | Core visibility, shows scores + routing | | `ProcessingLogTable` + detail drawer | Last, most complex | --- ## Out of scope - Alerts / notifications when AI fails (add later) - Log retention policy / auto-delete (add later) - Exporting logs (add later)