Files
cowork-local/docs/refactor/tin-gui-team-hoa.md
T
Nam Pham Dinh ThanhandClaude Opus 5 2b90492994 refactor(ui): R08-T07 — bóc settings_dialog.py 727 → 407 dòng thành 4 widget
Bốn mục trong Cài đặt tách thành widget riêng dưới presentation/settings/:

    general_settings_widget.py     ngôn ngữ, giao diện, khay, gợi ý
    provider_settings_widget.py    provider, base URL, key, model + 2 nút nền
    parameter_settings_widget.py   đính kèm, cấu trúc, giới hạn sandbox
    routing_settings_widget.py     Auto Model Routing

Mỗi widget tự dựng control, tự nạp giá trị, tự có apply_to(data). Dialog chỉ
còn lắp ráp và gọi apply_to lúc lưu — _save từ 34 dòng xuống còn phần khung.

Làm lưới an toàn trước khi bóc: tests/ui/test_settings_dialog_dac_ta.py, 7
bài đặc tả hành vi hiện tại (mục nào có mặt, nạp đúng giá trị gì, lưu ghi vào
đúng ô nào, đổi % sang phân lẻ, xoá cache sau lưu). Bóc xong cả 7 vẫn xanh,
và trong lúc bóc chúng đã đỏ đúng hai lần ở chỗ đáng đỏ.

Đây là repo chưa từng có test Qt nào — thêm tests/ui/conftest.py dựng
QApplication offscreen. Offscreen là bắt buộc chứ không phải cho nhanh: máy
dev là máy làm việc thật, test bật cửa sổ lên là nó nhảy ra che màn hình.

Dọn kèm:
* bỏ vòng "dựng vào layout rồi lại gỡ ra" của mục Chung, cùng widget cao 0px
  làm mốc cuộn — không cần nữa khi mục đó tự là một widget
* bỏ _select_combo, _secret, _model_combo, _with_load và 4 hàm provider khác
  đã chuyển vào widget (127 dòng)
* bỏ 5 import chết theo (Dict, QSizePolicy, PROVIDER_LABELS, SegmentedControl,
  LANGUAGES)

Giữ cầu tương thích: self.routing_*, self.prov_*, self.attach_* … thành
property trỏ vào widget con, vì 5 checker trong tools/ đọc thẳng tên cũ. Bỏ
được khi tools/ chuyển sang đọc self._provider_page.

Hai điều KHÔNG làm, ghi lại để khỏi tưởng là quên:
1. Plan ghi 4 widget và có tên `connector`. Thực tế UI connector đã dời khỏi
   Cài đặt từ trước (ghi chú ở settings_dialog.py:180 bản cũ), nên số mục thật
   là 5, không phải 4, và không có mục nào tên connector. Bốn mục bóc ra là 4
   mục có thật; mục Bảo mật sandbox để nguyên trong dialog lần này.
2. Còn ~108 dòng chết của MS365 (_refresh_ms365_status, _ms365_sign_in,
   _show_ms365_device_code, _ms365_sign_out): đọc self.ms365_status,
   self.ms365_signin_btn, self.ms365_signout_btn — ba thuộc tính KHÔNG BAO GIỜ
   được gán, và không hàm nào có người gọi. Gọi vào là AttributeError. Chưa
   xoá vì đó là quyết định của anh Nam, không phải việc kèm theo của T07.

437 test xanh. check_dialogs, check_no_hscroll, check_design_parity đều qua.

Kèm docs/refactor/tin-gui-team-hoa.md — tin báo Hoa về platform/ -> adapters/
và bản vá Windows của AtomicJsonFile.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 19:22:54 +09:00

3.1 KiB

Tin nhắn gửi Team Hoa — 25/08/2026

Nam (Team Gamma) soạn. Hai việc, không cần trả lời, chỉ cần đọc trước khi bắt đầu R07-T03 và R06.


Chào team Hoa,

Có hai thứ trong nhánh gamma/refactor ảnh hưởng trực tiếp tới phần các bạn sắp làm. Gửi trước để khỏi mất thời gian truy lỗi.

1. platform/ đã đổi tên thành adapters/ — plan.md ghi tên cũ

Plan chỉ đích danh platform/qt/qt_scheduler_clock.py (R07-T03, dòng 407 và lịch 25/08 ở dòng 229). Đừng tạo thư mục platform/.

Lý do: platform là tên một module trong thư viện chuẩn của Python. Tạo thư mục platform/ ở gốc repo là nó che mất module chuẩn khi chạy từ chính thư mục gốc — mà đó là cách toàn bộ script trong tools/ và scripts/ đang chạy. Triệu chứng không hề chỉ về đúng chỗ:

AttributeError: module 'platform' has no attribute 'system'

Ném ra từ import keyring, không liên quan gì tới file bạn vừa tạo.

Tôi đã mắc đúng lỗi này hôm 21/08. Lúc thử thì đứng ở thư mục cha nên không tái hiện được, tưởng an toàn. Đổi tên thành adapters/ và thêm tests/test_no_stdlib_shadow.py để lần sau đỏ ngay.

Việc cần làm: tạo adapters/qt/qt_scheduler_clock.py thay vì platform/qt/.... Thư mục adapters/qt/ đã có sẵn __init__.py trên nhánh gamma/refactor, kéo về là dùng được.

2. AtomicJsonFile vừa vá một lỗi Windows — lấy bản mới trước khi dựng lên

Plan giao các bạn hai repository ngồi trên AtomicJsonFile:

  • infrastructure/persistence/json/task_repository_impl.py (R07-T01, dòng 403)
  • infrastructure/persistence/json/workspace_repository_impl.py (R06, dòng 387)

Và tiêu chí nghiệm thu A (dòng 244) bắt mọi thao tác ghi tệp phải đi qua nó.

Hôm nay tôi bắt được lỗi thật trong đó:

PermissionError: [WinError 5] Access is denied
  .dem.json.xxxxxxx.tmp -> dem.json

os.replace trên Windows bị từ chối khi Defender hoặc Search Indexer đang giữ handle lên file vừa tạo — vài chục mili-giây rồi nhả. Đo được: hỏng 1 trong 7 lượt chạy 20 lần ghi, tức khoảng 1 trên 140 lần lưu. Người dùng thỉnh thoảng bấm Lưu là văng lỗi và không tài nào tái hiện để báo.

Đã thêm vòng thử lại (commit 9d6a7be). Nếu các bạn dựng repository trên bản trước đó thì lưu task và lưu workspace cũng hỏng với tần suất y hệt — nhân lên ba nơi ghi file.

Việc cần làm: git pull nhánh gamma/refactor (hoặc chờ nó vào main) trước khi bắt đầu R06/R07-T01.

Tiện thể

domain/security/tool_policy.py là bản đề xuất DTO ToolPolicyGateway tôi viết hộ cho R05 của các bạn — ba trạng thái ALLOW/DENY/ASK, kèm fake và test contract. Không có gì của Gamma phụ thuộc vào nó, nên các bạn cứ sửa hoặc bỏ thoải mái, không phải giữ ý.

Nam