Files
cowork-local/docs/refactor/bug.md
T

12 KiB

NHẬT KÝ THEO DÕI VÀ PHÒNG NGỪA LỖI TÁI CẤU TRÚC (BUG & LESSONS LEARNED LOG)

DỰ ÁN: COWORK LOCAL (COWORK-LOCAL BAMBOO)

Tài liệu này dùng để ghi nhận toàn bộ các lỗi, xung đột kiến trúc và sự cố phát sinh trong suốt quá trình refactoring của cả 3 team (Team Duy, Team Nam, Team Hoa).

Important

🛡️ NGUYÊN TẮC VÀNG VỀ QUẢN TRỊ CHẤT LƯỢNG (ZERO RECURRENCE):

  1. Ghi nhận ngay lập tức: Khi gặp bất kỳ lỗi nào (Syntax, Circular Import, Type Error, Test Failure, Thread Freeze, Data Corruption), kỹ sư/AI phải ghi ngay vào tài liệu này trước khi tiếp tục task.
  2. Phân tích nguyên nhân gốc rễ (Root Cause): Không chỉ sửa phần ngọn mà phải giải thích rõ bản chất vì sao lỗi xảy ra.
  3. Rút ra quy tắc phòng ngừa (Prevention Rule): Đặt ra nguyên tắc kỹ thuật để TUYỆT ĐỐI KHÔNG TÁI PHẠM ở các task tiếp theo.
  4. Checklist đầu vào: Trước khi bắt đầu bất kỳ task mới nào, kỹ sư/AI bắt buộc phải đọc lại toàn bộ file này.

📌 BẢNG TỔNG HỢP CÁC LỖI ĐÃ PHÁT HIỆN & KHẮC PHỤC

Bug ID Ngày Phát Hiện Phân Hệ / File Bị Ảnh Hưởng Loại Lỗi Trạng Thái Team Phụ Trách
BUG-001 2026-08-20 core/model_pricing.py ↔ core/usage_tracker.py Circular Dependency 🟡 Đã có giải pháp (R09) Team Duy & Team Nam
BUG-002 2026-08-20 core/agent_security.py ↔ core/agent_security_alert.py Circular Dependency 🟡 Đã có giải pháp (R09) Team Nam
BUG-003 2026-08-20 state.py::active_project_id & ui/workspace_tab.py Race Condition / Global State Leak 🟡 Đã có giải pháp (R06) Team Hoa
BUG-004 2026-08-20 core/task_scheduler.py ↔ PySide6.QtCore.QTimer Architecture Violation (Qt in Domain/App) 🟡 Đã có giải pháp (R07) Team Hoa
BUG-005 2026-08-20 ui/chat_panel.py#L638, ui/co4e_tab.py, ui/folder_tab.py Code Duplication (Copy Routing Logic) 🟡 Đã có giải pháp (R03) Team Duy
BUG-006 2026-08-21 scripts/check_imports.py UnicodeEncodeError (Windows CP932 console emoji) 🟢 Đã khắc phục (R01) Team Duy
BUG-007 2026-08-21 platform/ ➔ infrastructure/platform/ Standard Library Shadowing (import platform) 🟢 Đã khắc phục (R01) Team Duy

🔍 CHI TIẾT TỪNG LỖI & QUY TẮC PHÒNG NGỪA


🔴 BUG-001: Circular Import giữa Module Định Giá (model_pricing.py) và Theo Dõi Token (usage_tracker.py)

  • Phân hệ: core/model_pricing.py & core/usage_tracker.py
  • Triệu chứng (Symptom): Lỗi ImportError: cannot import name 'ModelPricing' from partially initialized module khi khởi động ứng dụng hoặc chạy test độc lập.
  • Nguyên nhân gốc rễ (Root Cause):
    • model_pricing.py import UsageTracker để cập nhật dữ liệu tiêu thụ.
    • Ngược lại, usage_tracker.py import ModelPricing để tính toán chi phí theo từng model ID.
  • Giải pháp khắc phục (Resolution):
    • Tách Data Transfer Object (DTO) ModelPricing sang tầng Domain thuần túy domain/models/model_pricing.py.
    • Cả model_pricing.py và usage_tracker.py đều import DTO từ domain/models/, chuyển quan hệ thành 1 chiều (Dependency Inversion).
  • Quy tắc phòng ngừa (Prevention Rule - TUYỆT ĐỐI KHÔNG TÁI PHẠM):

    Quy tắc: Không bao giờ để 2 service hoặc 2 module nghiệp vụ import lẫn nhau. Mọi cấu trúc dữ liệu dùng chung (DTO/Value Object/Event) phải được đặt tại tầng domain/.


🔴 BUG-002: Circular Import giữa An Ninh Agent (agent_security.py) và Cảnh Báo (agent_security_alert.py)

  • Phân hệ: core/agent_security.py & core/agent_security_alert.py
  • Triệu chứng (Symptom): Lỗi khởi tạo vòng tròn khi runtime bắn ra alert sự kiện bảo mật.
  • Nguyên nhân gốc rễ (Root Cause):
    • Module security vừa kiểm tra policy vừa khởi tạo trực tiếp instance alert dialog, trong khi alert dialog lại import ngược lại rule security để hiển thị chi tiết mã lỗi.
  • Giải pháp khắc phục (Resolution):
    • Tách sự kiện cảnh báo thành Event DTO SecurityAlertEvent tại domain/security/security_event.py.
    • Tầng Security chỉ phát ra Event (emit_event), tầng Presentation/UI tự lắng nghe Event để render Dialog.
  • Quy tắc phòng ngừa (Prevention Rule - TUYỆT ĐỐI KHÔNG TÁI PHẠM):

    Quy tắc: Logic an ninh và xử lý nghiệp vụ không bao giờ được gọi trực tiếp UI Dialog. Luôn giao tiếp thông qua cơ chế Event-Driven (AgentEvent, SecurityEvent).


🔴 BUG-003: Xung Đột Race Condition do Sử Dụng Biến Toàn Cục active_project_id trong state.py

  • Phân hệ: state.py, ui/workspace_tab.py, Scheduled Task Runners
  • Triệu chứng (Symptom): Khi task scheduler chạy ngầm hoặc người dùng chuyển tab nhanh, file bị ghi nhầm vào thư mục dự án khác với dự án đang hiển thị trên màn hình.
  • Nguyên nhân gốc rễ (Root Cause):
    • Ứng dụng đọc và ghi trực tiếp vào biến toàn cục AppContext.active_project_id từ nhiều luồng khác nhau mà không có cơ chế snapshot ngữ cảnh.
  • Giải pháp khắc phục (Resolution):
    • Xóa bỏ việc đọc biến toàn cục. Mỗi lần khởi chạy turn hoặc task, tạo một snapshot bất biến WorkspaceSession(project_id, root_path, allowed_paths).
    • Luồng ngầm chỉ thao tác trên WorkspaceSession được truyền vào từ lúc khởi tạo.
  • Quy tắc phòng ngừa (Prevention Rule - TUYỆT ĐỐI KHÔNG TÁI PHẠM):

    Quy tắc: Tuyệt đối không dùng biến toàn cục (Global State / Singletons có trạng thái thay đổi) để điều khiển luồng thực thi nền. Mọi ngữ cảnh phải được truyền tường minh qua DTO snapshot.


🔴 BUG-004: Vi Phạm Ranh Giới Kiến Trúc Khi Import PySide6.QtCore.QTimer trong Domain / Scheduling Engine

  • Phân hệ: core/task_scheduler.py#L20
  • Triệu chứng (Symptom): Không thể viết Unit Test cho thuật toán tính toán lịch chạy (cron/interval) trên môi trường CI/CD (GitHub Actions / Linux Server headless) nếu thiếu driver màn hình X11/Wayland hoặc chưa cài PySide6.
  • Nguyên nhân gốc rễ (Root Cause):
    • Động cơ lập lịch bị gắn chặt cứng với QTimer của framework Qt thay vì tách riêng logic tính toán thời gian.
  • Giải pháp khắc phục (Resolution):
    • Tách thuật toán tính lịch sang domain/tasks/schedule_calculator.py (Pure Python 100%).
    • Tạo platform/qt/qt_scheduler_clock.py làm adapter bọc QTimer cho app chạy thật, và tests/fakes/fake_clock.py cho unit test.
  • Quy tắc phòng ngừa (Prevention Rule - TUYỆT ĐỐI KHÔNG TÁI PHẠM):

    Quy tắc: Tầng Domain và Application tuyệt đối không import thư viện GUI (PySide6, PyQt). Luôn bọc các thành phần phụ thuộc framework bên ngoài qua Adapter Interface.


🔴 BUG-005: Nhân Bản Mã Nguồn (Code Duplication) Logic Routing Mô Hình AI tại Nhiều Màn Hình

  • Phân hệ: ui/chat_panel.py#L638, ui/co4e_tab.py, ui/folder_tab.py
  • Triệu chứng (Symptom): Khi cập nhật thêm model provider mới (như FPT Gateway hay Claude 3.7), phải sửa code thủ công ở 3 file UI khác nhau; phát sinh sai lệch quy tắc fallback giữa các màn hình.
  • Nguyên nhân gốc rễ (Root Cause):
    • Thiếu một tầng Application Service tập trung, dẫn đến việc lập trình viên copy-paste hàm chọn model từ ChatPanel sang các tab khác.
  • Giải pháp khắc phục (Resolution):
    • Xây dựng application/model_routing/routing_application_service.py duy nhất, cung cấp API route_request(request) -> ModelRouteDecision.
    • Mọi màn hình UI chỉ gọi service này, không tự viết lại logic kiểm tra key hay fallback.
  • Quy tắc phòng ngừa (Prevention Rule - TUYỆT ĐỐI KHÔNG TÁI PHẠM):

    Quy tắc: Nghiệp vụ dùng chung giữa các màn hình phải được đưa vào application/ services. Không bao giờ viết logic nghiệp vụ trực tiếp trong các file Widget UI.


🟢 BUG-006: UnicodeEncodeError khi in Emojis trên Console Windows (CP932/CP1252)

  • Phân hệ / File: scripts/check_imports.py
  • Triệu chứng (Symptom):
    Traceback (most recent call last):
      File "scripts/check_imports.py", line 127, in main
        print(f"\U0001f6e1\ufe0f  Running Clean Architecture Import Guard...")
    UnicodeEncodeError: 'cp932' codec can't encode character '\U0001f6e1' in position 0: illegal multibyte sequence
    
  • Nguyên nhân gốc rễ (Root Cause):
    • Trên hệ điều hành Windows sử dụng locale tiếng Nhật (mã trang CP932) hoặc tiếng Anh (CP1252), sys.stdout mặc định không hỗ trợ các ký tự Unicode/Emoji ngoài bảng mã, dẫn đến crash khi in log dòng lệnh.
  • Giải pháp khắc phục (Resolution):
    • Tự động bọc lại sys.stdout và sys.stderr bằng io.TextIOWrapper với encoding="utf-8" và errors="replace".
    • Thay thế các emoji phức tạp bằng các tag văn bản ASCII chuẩn hóa như [Clean Arch Guard], [PASS], [FAIL].
  • Quy tắc phòng ngừa (Prevention Rule - TUYỆT ĐỐI KHÔNG TÁI PHẠM):

    Quy tắc: Mọi script CLI (scripts/*.py) phải có cơ chế cấu hình utf-8 stream wrapper và ưu tiên sử dụng text tags ([INFO], [WARN], [ERROR]) thay vì emoji Unicode trực tiếp để đảm bảo chạy mượt mà trên mọi môi trường Windows đa ngôn ngữ.


🟢 BUG-007: Xung Đột Tên Thư Mục Trùng Với Standard Library (platform/ Shadowing import platform)

  • Phân hệ / File: platform/ ➔ Chuyển thành infrastructure/platform/
  • Triệu chứng (Symptom):
    INTERNALERROR> File "_pytest/terminal.py", line 853: verinfo = platform.python_version()
    INTERNALERROR> AttributeError: module 'platform' has no attribute 'python_version'
    
  • Nguyên nhân gốc rễ (Root Cause):
    • Khi tạo một package ở thư mục gốc có tên trùng với module thư viện chuẩn của Python (platform, email, test, asyncio, logging), Python trên sys.path sẽ ưu tiên import thư mục local thay vì thư viện chuẩn của Python runtime, dẫn đến crash toàn bộ pytest runner và các thư viện bên thứ ba.
  • Giải pháp khắc phục (Resolution):
    • Xóa bỏ package platform/ ở root.
    • Đưa adapter Qt Scheduler Clock vào đúng vị trí hạ tầng: infrastructure/platform/qt/.
  • Quy tắc phòng ngừa (Prevention Rule - TUYỆT ĐỐI KHÔNG TÁI PHẠM):

    Quy tắc: Tuyệt đối không đặt tên package/thư mục ở root trùng với tên các module built-in của Python (platform, logging, types, time, io, os, sys). Mọi platform adapter phải nằm trong infrastructure/platform/ hoặc platform_adapters/.


📝 MẪU GHI NHẬN BUG MỚI (BUG REPORT TEMPLATE)

Khi gặp bất kỳ bug mới nào trong quá trình làm việc, hãy sao chép khối mẫu sau và điền vào cuối tài liệu:

### 🔴 `BUG-XXX`: [Tóm tắt ngắn gọn tên lỗi]

* **Phân hệ / File**: `[Đường dẫn file bị lỗi]`
* **Triệu chứng (Symptom)**: `[Mô tả hiện tượng lỗi, paste thông báo traceback hoặc kết quả test fail]`
* **Nguyên nhân gốc rễ (Root Cause)**: `[Giải thích tại sao lỗi lại xảy ra]`
* **Giải pháp khắc phục (Resolution)**: `[Mô tả cách sửa, file DTO/Service tạo mới hoặc cách refactor]`
* **Quy tắc phòng ngừa (Prevention Rule - TUYỆT ĐỐI KHÔNG TÁI PHẠM)**:
  > **Quy tắc**: `[Nguyên tắc kỹ thuật cụ thể để không bao giờ tái phạm lỗi này]`