Bộ 7 role chuyên biệt (triage → specialist → implementer → reviewer) cùng lớp dùng chung: guardrail, tri thức về repo, checklist, và contract đầu ra. Vì sao có: bug UI/UX được báo bằng lời kể triệu chứng, và người sửa hay bỏ qua ba thứ mà repo này rất dễ vi phạm — luật "không file nào ngoài theme/ được đặt tên một màu", trần LOC theo bánh cóc, và việc ui/ với presentation/ cùng tồn tại nên sửa nhầm file là "đã fix mà vẫn thấy lỗi". knowledge/qt_pitfalls.md chép lại 20 nguyên nhân gốc hay gặp của bug PySide6; examples/bad_fix.md có hai ca CÓ THẬT, gồm ca chính bản vá trong nhánh này từng mắc (compare_digest trên str ngoài ASCII) và lọt qua vòng review đầu. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
102 lines
5.0 KiB
Markdown
102 lines
5.0 KiB
Markdown
# Project Map — Cowork Local (dành cho agent sửa bug UI/UX)
|
|
|
|
Nguồn sự thật: `README.md`, `docs/architecture/ADR-001-layered-architecture.md`,
|
|
`docs/governance/contributor-recipes.md`. File này chỉ tóm tắt phần **một người sửa bug
|
|
UI cần biết**.
|
|
|
|
---
|
|
|
|
## 1. Bốn tầng
|
|
|
|
```text
|
|
presentation/ PySide6 UI — Shell, NavRail, Chat, Scheduling, Settings, Dashboard
|
|
↓
|
|
application/ Orchestration thuần Python — Conversations, Scheduling, Workspaces, Monitoring, Routing
|
|
↓
|
|
domain/ Entity, ExecutionRequest bất biến, AgentEvent, Descriptor (thuần Python)
|
|
↑
|
|
infrastructure/ Adapter — LLM provider, persistence atomic JSON, Keyring SecretStore, MCP
|
|
```
|
|
|
|
- `domain/` và `application/` **không được** import PySide6/PyQt/`ui`/`app`
|
|
(`scripts/check_imports.py::FORBIDDEN_MODULE_PREFIXES`).
|
|
- Widget chỉ gọi xuống service của `application/`, không chạm SQLite/JSON/LLM trực tiếp.
|
|
- Mọi module production `<= 400 LOC`.
|
|
|
|
## 2. ⚠️ Hai thư mục UI cùng tồn tại — điểm dễ sửa nhầm file nhất
|
|
|
|
| Thư mục | Vai trò hiện tại | Sửa bug ở đây khi |
|
|
|---|---|---|
|
|
| `presentation/` | Kết quả refactor R08 — các màn đã tách module | Bug thuộc Chat, Co4E, Dashboard, Folder, Graph, Scheduling, Settings, Shell |
|
|
| `ui/` | **Vẫn đang chạy**, không phải code chết | Bug thuộc Monitoring, Workspace, các dialog, icon, widget dùng chung |
|
|
|
|
`presentation/` vẫn import ngược sang `ui/` cho phần dùng chung, ví dụ:
|
|
|
|
```text
|
|
presentation/shell/page_registry.py:14 from ...ui.monitoring_tab import MonitoringTab
|
|
presentation/shell/main_window.py:38 from ...ui.workspace_tab import WorkspaceTab
|
|
presentation/dashboard/dashboard_tab.py:24 from cowork_local.ui.icons import icon
|
|
```
|
|
|
|
**Luật:** trước khi sửa, `grep` tên class/hàm trên **cả hai** thư mục. Sửa bản không được
|
|
import vào runtime là lỗi "đã fix nhưng user vẫn thấy lỗi" phổ biến nhất của repo này.
|
|
|
|
```bash
|
|
grep -rn "class DashboardTab" ui/ presentation/
|
|
```
|
|
|
|
## 3. Điểm vào & trạng thái
|
|
|
|
| File | Vai trò |
|
|
|---|---|
|
|
| `app.py`, `__main__.py` | Bootstrap `QApplication`, dựng `MainWindow` |
|
|
| `presentation/shell/main_window.py` | Cửa sổ chính, `_nav_defs`, top bar, toast, help agent |
|
|
| `presentation/shell/page_registry.py` | Chuyển trang; Dashboard/Schedule/Monitoring **dựng lười** |
|
|
| `presentation/shell/nav_rail.py` | Nav rail trái, thu gọn/mở rộng, cây project & recents |
|
|
| `presentation/shell/top_bar.py` | Thanh trên: theme switch, language switch |
|
|
| `presentation/shell/toast.py` | Popup "task xong" góc trên trái |
|
|
| `state.py` | `AppContext` — cầu nối UI ↔ service |
|
|
| `config.py` | Đọc/ghi cấu hình người dùng (theme, ngôn ngữ, provider...) |
|
|
| `paths.py` | Vị trí dữ liệu runtime (`%USERPROFILE%\.cowork_local`) |
|
|
| `theme/` | Toàn bộ màu sắc & stylesheet (xem `theme_tokens.md`) |
|
|
| `i18n/` | Toàn bộ chuỗi hiển thị (xem `i18n_rules.md`) |
|
|
|
|
### Hệ quả của "dựng lười" khi debug
|
|
|
|
Dashboard, Schedule và Monitoring **chưa tồn tại** cho tới lần đầu người dùng bấm vào.
|
|
Nghĩa là:
|
|
|
|
- Bug "lần đầu mở màn X bị nhấp nháy / sai theme / sai ngôn ngữ" gần như luôn nằm ở
|
|
`_ensure_page` / `_goto` chứ không nằm trong widget của màn đó.
|
|
- Widget dựng lười **bỏ lỡ** các sự kiện đã phát trước đó (đổi theme, đổi ngôn ngữ).
|
|
Xem `qt_pitfalls.md` P07.
|
|
|
|
## 4. Bảng đối chiếu tính năng → file
|
|
|
|
| Khu vực | File chính |
|
|
|---|---|
|
|
| Chat / composer / bubble | `presentation/chat/` (`chat_panel.py`, `composer_widget.py`, `chat_bubble_style.py`) |
|
|
| Co4E canvas & node | `presentation/co4e/` (`co4e_canvas_widget.py`, `node_property_panel.py`, `canvas_geometry.py`) |
|
|
| Dashboard & biểu đồ | `presentation/dashboard/` + `ui/spline_chart.py`, `ui/widgets.py` |
|
|
| Folder / preview tài liệu | `presentation/folder/` (`folder_tab.py`, `code_editor.py`, `office_document_renderer.py`) |
|
|
| GraphRAG | `presentation/graph/` |
|
|
| Lịch / Kanban | `presentation/scheduling/` |
|
|
| Settings | `presentation/settings/` + `ui/settings_dialog.py` |
|
|
| Monitoring (8 sub-view) | `ui/monitoring_tab.py` + `presentation/monitoring/` |
|
|
| Workspace + sub-tab | `ui/workspace_tab.py`, `ui/cowork_tab.py`, `ui/co4e_tab.py` |
|
|
| Dialog (login, permission, skill, task...) | `ui/*_dialog.py` |
|
|
| Icon | `ui/icons.py` |
|
|
| Widget dùng chung (StatCard, BudgetCard...) | `ui/widgets.py` |
|
|
|
|
## 5. Test
|
|
|
|
| Đường dẫn | Nội dung |
|
|
|---|---|
|
|
| `tests/ui/` | Test widget, có `conftest.py` riêng |
|
|
| `tests/integration/` | Test ghép nhiều thành phần |
|
|
| `tests/e2e/test_smoke.py` | Smoke test bản release |
|
|
| `tests/characterization/` | Chốt hành vi hiện tại trước khi refactor |
|
|
|
|
Chạy headless: `QT_QPA_PLATFORM=offscreen pytest tests/ui -q`.
|
|
64/108 module test dựng widget thật, nên môi trường phải có PySide6.
|