docs(agent): thư viện instruction cho việc sửa bug UI/UX

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>
This commit is contained in:
2026-09-10 01:34:36 +09:00
committed by thanhnv
co-authored by Claude Opus 5
parent dd9bb51509
commit c7d71b77a7
29 changed files with 3513 additions and 0 deletions
+53
View File
@@ -0,0 +1,53 @@
# Checklist sẵn sàng tạo PR
Dùng bởi `fix-implementer` (bước 9) và `regression-reviewer` (bước 8).
Bám theo `.gitea/PULL_REQUEST_TEMPLATE.md` và `docs/governance/definition-of-done.md`.
## A. Cổng chất lượng
- [ ] `python scripts/run_quality_gate.py` — xanh cả 5 cổng, **có dán output thật**.
- [ ] Gate C: `domain/`/`application/` không import PySide6/PyQt/`ui`/`app`.
- [ ] Gate A: không secret/plaintext mới.
- [ ] Gate S: không file nào > 400 LOC.
- [ ] Gate O: không module mồ côi (file mới đã được import trong cùng commit).
- [ ] Gate A/N: pytest xanh; test vốn đỏ từ trước được ghi riêng.
## B. Kiểm chứng
- [ ] Test regression tồn tại và **đỏ trước / xanh sau**.
- [ ] Test chạy được headless (`QT_QPA_PLATFORM=offscreen`).
- [ ] Đã kiểm bằng mắt ở dark + light — hoặc ghi rõ "chưa kiểm chứng bằng mắt" kèm lý do.
- [ ] Đã kiểm ở các ngôn ngữ liên quan.
## C. Phạm vi & lịch sử
- [ ] Một PR = một thay đổi logic. Không refactor lẫn vào.
- [ ] Không đổi format/indent toàn file; diff đọc được.
- [ ] Nhánh riêng, không commit thẳng `main`.
- [ ] Commit message nêu nguyên nhân gốc + `file:line` + issue.
- [ ] Không commit `.env`, `config.json` local, dữ liệu dưới `.cowork_local/`, `.venv`.
## D. Bảo mật
- [ ] Không secret/PII/đường dẫn cá nhân trong code, test fixture, commit message, PR body.
- [ ] Ảnh chụp màn hình đính kèm đã được redact.
- [ ] Nếu chạm permission / credential / MCP write-exec / sandbox / network / TLS /
isolation / model routing / xoá dữ liệu → đánh dấu `security-review: required` và ghi
rõ trong PR rằng **CI xanh không đủ để merge**.
## E. Nội dung PR
- [ ] Summary nói **tại sao**, không chỉ **cái gì**.
- [ ] Change Type đã tick.
- [ ] Scope: nêu rõ cả phần **cố ý không** làm.
- [ ] Validation: có lệnh và output thật.
- [ ] Security Impact: đã điền, kể cả khi là "không có".
- [ ] Compatibility: đã tick.
- [ ] Reviewer Notes: chỉ ra chỗ cần soi kỹ nhất.
- [ ] Tài liệu (`docs/`, ảnh `docs/screens/`) đã cập nhật nếu cần.
## F. Ranh giới
- [ ] Agent **không** tự merge, **không** tự đóng issue.
- [ ] Nếu là đóng góp của FSG AI Core: hiểu rằng chỉ "Done" khi PR đã merge vào Cowork Local,
kèm đủ core issue reference, PR, evidence, reviewer phía Cowork, merge reference.
+49
View File
@@ -0,0 +1,49 @@
# Checklist review bản vá UI (visual)
Dùng bởi `ui-visual-fixer` (bước 7) và `regression-reviewer` (bước 5).
## A. Đúng file
- [ ] Đã `grep` cả `ui/` và `presentation/`; file được sửa là file thực sự import vào runtime.
- [ ] Widget này không có bản trùng tên ở thư mục còn lại.
## B. Màu & theme
- [ ] Không hex literal (`#rrggbb`), không tên màu (`"red"`) ngoài `theme/`.
- [ ] Không `setStyleSheet` cục bộ mới; style đi qua `objectName` + `theme/qss.py`.
- [ ] Token mới có ở **cả** `DARK` và `LIGHT`.
- [ ] Chữ trên nền đặc dùng `accent_solid`, không dùng `accent`.
- [ ] Bậc bề mặt đúng ngữ nghĩa: `bg` / `surface` / `surface_raised` / `overlay` / `sunken`.
- [ ] Contrast ≥ 4.5:1 cho body text và chữ trên nút đặc, ở cả hai theme.
- [ ] Không thêm gradient/glow (trái ràng buộc thiết kế).
- [ ] Nav rail vẫn tối hơn vùng nội dung.
- [ ] Không trả bốn giá trị đã nhích lên WCAG AA về giá trị VS Code gốc.
- [ ] Nếu chạm `_TEMPLATE`: đã liệt kê phạm vi ảnh hưởng toàn app.
## C. Layout & kích thước
- [ ] Không thêm `setFixedWidth` / `setFixedSize` / `setFixedHeight` mới.
- [ ] Stretch factor / size policy được đặt tường minh.
- [ ] `QScrollArea` có `setWidgetResizable(True)`.
- [ ] Margin/spacing của layout lồng nhau không cộng dồn ngoài ý muốn.
- [ ] Còn đúng ở cửa sổ nhỏ nhất **và** maximize.
- [ ] Còn đúng ở scale 125% / 150% nếu bản vá chạm kích thước.
## D. Icon & vẽ tay
- [ ] Icon lấy qua `ui/icons.py::icon`, không load file trực tiếp.
- [ ] `paintEvent` đọc màu qua `current_palette()`, không đọc lại config.
- [ ] Dùng `update()`, không `repaint()` trong vòng lặp.
- [ ] `QPainter` có `end()`; nền được xoá đúng cách.
## E. Vòng đời
- [ ] Bản vá còn đúng khi đổi theme **trước** rồi mới mở màn dựng lười (P07).
- [ ] `setProperty` để đổi style động có kèm `unpolish`/`polish`.
- [ ] Không `connect()` lặp lại trong hàm được gọi nhiều lần.
## F. Bằng chứng
- [ ] Đã đối chiếu `docs/screens/<slug>-dark.png` và `<slug>-light.png`.
- [ ] Ảnh trong `docs/screens/` cần cập nhật thì đã nêu.
- [ ] Có test regression chạy headless, đỏ-trước-xanh-sau.
+48
View File
@@ -0,0 +1,48 @@
# Checklist review bản vá UX (flow)
Dùng bởi `ux-flow-fixer` (bước 8) và `regression-reviewer`.
## A. Bốn trạng thái
Cho mỗi view có dữ liệu bất đồng bộ:
- [ ] **Rỗng** — hiện thông điệp có nghĩa, nói được bước tiếp theo (không phải màn trắng).
- [ ] **Đang tải** — có dấu hiệu chuyển động; nút bị vô hiệu hoá để chống bấm đúp.
- [ ] **Lỗi** — nói *cái gì hỏng* và *làm gì tiếp*; có đường thử lại; không in nguyên exception.
- [ ] **Thành công** — có xác nhận rõ; có undo nếu hành động khó đảo ngược.
## B. An toàn dữ liệu
- [ ] Ô nhập dài (instruction, composer, node property, AI Edit) không mất nội dung khi
chuyển tab / đóng dialog / đổi project.
- [ ] Có dirty-state; `closeEvent` chặn khi còn thay đổi chưa lưu.
- [ ] Hành động phá huỷ (xoá project/task, ghi đè file) có xác nhận.
- [ ] Xác nhận nêu rõ **cái gì** sẽ mất, không phải "Bạn có chắc không?".
- [ ] Nút phá huỷ **không** phải default button, **không** nhận Enter.
## C. Phản hồi theo thời gian
- [ ] 100ms-1s: đổi con trỏ hoặc vô hiệu hoá nút.
- [ ] 1s-10s: chỉ báo tiến trình rõ ràng.
- [ ] \>10s: có tiến trình, **huỷ được**, không chặn phần còn lại của UI.
- [ ] Việc nặng chạy ở service `application/`, không ở GUI thread.
- [ ] Bấm hai lần không chạy hai lần (kiểm `connect()` trùng — P10).
## D. Khám phá được
- [ ] Mọi nút icon-only có tooltip (nav rail thu gọn, toolbar Co4E, top bar).
- [ ] Nút bị vô hiệu hoá nói được **lý do** (mẫu đúng: `app.nav.needs_project`).
- [ ] Chức năng chính không bị chôn sau menu chuột phải mà không có lối vào khác.
- [ ] Thứ tự control khớp thứ tự người dùng thực hiện.
## E. Nhất quán
- [ ] Cùng một hành động dùng cùng một từ trên mọi màn (không chỗ "Lưu" chỗ "Cập nhật").
- [ ] Vị trí nút chính/phụ giống các dialog khác.
- [ ] Chuỗi mới đi qua `tr()` với đủ `en`/`ja`/`vi`.
## F. Phạm vi
- [ ] Bản vá chọn mức can thiệp thấp nhất (thêm thông tin trước, đổi luồng sau).
- [ ] Thay đổi luồng được đánh dấu là **đề xuất** cần Cowork Team duyệt.
- [ ] Có test regression cho signal/state, chạy headless.