Files
cowork-local/docs/refactor/BaoCao_TeamHoa_R05_R08.md
T
f9f6bc01fd
CI / test (push) Canceled after 0s
Feature/delta team/epic r04 (#7)
## Summary

epic r04 - begin refactor

## Change Type

- [x] Cowork feature
- [ ] Bug fix
- [ ] Core AI contribution
- [ ] Test / hardening
- [ ] Performance
- [ ] Documentation

## Related Work

Cowork Task:

Core Repo: http://34.143.229.138/gitea-admin/fsg-ai-core-assets

Core AI Issue:

Core Task:

Related PR:

## Scope

What is intentionally included?

What is intentionally NOT included?

## Validation

- [ ] Unit tests
- [ ] Integration tests
- [ ] Manual verification
- [ ] Regression check

Commands / evidence:

## Security Impact

Permission / credential / network / customer data impact:

## Compatibility

- [ ] No breaking change
- [ ] Breaking change documented

## Reviewer Notes

Anything Cowork reviewers should pay attention to.

---------

Co-authored-by: Anh Tran Nguyen Minh <anhtnm1@fpt.com>
Co-authored-by: Huong Le Thi Thien <huongltt35@fpt.com>
Co-authored-by: Nam Pham Dinh Thanh <nampdt@fpt.com>
Co-authored-by: Vu Dam Tuan <vudt15@fpt.com>
Co-authored-by: Hiep Ha Van <hiephv3@fpt.com>
Co-authored-by: Lam Hoang Van <lamhv7@fpt.com>
Reviewed-on: #7
Co-authored-by: Duy Le Huu <duylh19@fpt.com>
2026-08-31 05:15:13 +00:00

20 KiB
Raw Blame History

BÁO CÁO KẾT QUẢ — TEAM HOA: EPIC R05, R06, R07, R08 (phần Team Hoa)

  • Dự án: Cowork Local (Cowork-Local BamBOO)
  • Team: 🟢 Team Hoa — Workspace, Filesystem, Scheduling & Tool Registry
  • Nhánh: feature/teamhoa/r05-r08 (tạo từ origin/feature/deltateam/refactor-plan, có sẵn nền R01/R03/R04 của Team Duy; đổi tên từ feature/teamhoa/r05-r06 sau khi gộp thêm R07/R08)
  • Thời gian thực hiện: 21/08/2026 21:40 → 27/08/2026 20:52
  • Ngày báo cáo: 27/08/2026 (bản gộp, thay thế BaoCao_TeamHoa_R05_R06.md và BaoCao_TeamHoa_R07_R08.md)
  • Tài liệu gốc: Feature_Architecture_Proposal.md, Refactoring_Checklist.md, plan.md

1. Tóm tắt điều hành

Hoàn tất toàn bộ 19/19 task thuộc phạm vi Team Hoa trên 4 EPIC: R05 (Tool, MCP & Connector Policy), R06 (Workspace, Filesystem & History Isolation), R07 (Scheduling & Workflow Runtime), R08 (UI/Application Separation — phần Team Hoa, T11→T14).

Chỉ số Kết quả
Task hoàn thành 19/19 (R05: 5, R06: 5, R07: 5, R08: 4 — không tính R07-T06/R08-T01→T10 thuộc Team Duy/Team Nam)
File thay đổi 92+ (phần lớn file mới)
Test cuối cùng 377 pass / 4 fail (xem tiến trình chi tiết ở mục 4)
CASAN Check 3 (scripts/check_imports.py) PASS — 0 Qt import trong domain/, application/
File production > 400 dòng (file mới) 0 — lớn nhất presentation/graph/graph_renderer.py 391 dòng
python -c "import cowork_local.app" OK sau mọi task

3 lỗi thật phát hiện và sửa, 1 quyết định kiến trúc đổi so với plan gốc (xác nhận bằng thực nghiệm) — chi tiết mục 5.


2. Kết quả theo từng EPIC

🔹 EPIC R05 — Tool, MCP & Connector Policy (5/5)

Task Sản phẩm Ghi chú
R05-T01/T02 domain/tools/{tool_descriptor,tool_registry}.py, infrastructure/filesystem/{file_tools,command_tools,fetch_tools}.py Tách if/elif dispatcher của core/tools.py; core/tools.py còn lại là shim strangler-fig (re-export ToolContext/ToolError, dispatch qua dict), 566 ➔ 291 dòng.
R05-T03 application/conversations/tool_policy_gateway.py::ToolPolicyGateway Thay 2 chỗ check hardcode riêng biệt (chat_agent.py, code_agent.py) bằng 1 lookup capability chung.
R05-T04 Sửa core/chat_agent.py, core/mcp_client.py Thay đổi hành vi có chủ đích — xem mục 5, Lỗi 1.
R05-T05 infrastructure/mcp/mcp_source_manager.py::McpToolSourceManager Tách lifecycle connection MCP khỏi state.py::AppContext.

🔹 EPIC R06 — Workspace, Filesystem & History Isolation (5/5)

Task Sản phẩm Ghi chú
R06-T01 domain/workspaces/workspace_session.py::WorkspaceSession Snapshot bất biến (project_id/workspace_root/sandbox_dir/allowed_paths) + is_allowed(path).
R06-T02 infrastructure/persistence/json/{atomic_write,workspace_repository_impl,conversation_repository_impl}.py Sửa bug thật — xem mục 5, Lỗi 2.
R06-T03 infrastructure/filesystem/execution_workspace.py::ExecutionWorkspace Đặt tên cho quy ước .scratch đã có sẵn.
R06-T04 Sửa ui/chat_panel.py Sửa race condition thật — xem mục 5, Lỗi 3.
R06-T05 application/workspaces/file_workspace_service.py::FileWorkspaceService Seam cho File Explorer/AI Editor gọi execute_tool giống agent — chưa có call site thật lúc R06 xong; đã nối dây ở R08-T12 (xem mục 5).

🔹 EPIC R07 — Scheduling & Workflow Runtime (5/5, phạm vi Team Hoa)

Task Sản phẩm Ghi chú
R07-T01 infrastructure/persistence/json/task_repository_impl.py::TaskRepository Bọc CRUD của core/tasks.py. Sửa bug thật: save_task trước đây ghi không atomic — cùng lớp bug đã sửa ở R06-T02.
R07-T02 domain/tasks/schedule_calculator.py::ScheduleCalculator Tách "schedule math" (cron/interval/daily/weekly/monthly + holiday exclusion) thành pure Python, trước đây 0 test, giờ có 14 test.
R07-T03 infrastructure/qt/qt_scheduler_clock.py::QtSchedulerClock Bọc QTimer sau 1 interface nhỏ, inject qua clock=. Đổi vị trí so với plan gốc — xem mục 5.
R07-T04 application/scheduling/task_application_service.py::TaskApplicationService Gom CRUD + luật kéo-thả Kanban (move_to_status).
R07-T05 application/scheduling/ai_task_planner_service.py::AiTaskPlannerService Seam cho plan_tasks/import_tasks.

(R07-T06 Co4EWorkflowService là việc Team Nam — không đụng.)

🔹 EPIC R08 — UI/Application Separation (4/4, phạm vi Team Hoa: T11→T14)

presentation/ chưa tồn tại trước task này — Team Hoa tạo cấu trúc lần đầu.

Task God file gốc Tách thành
R08-T11 ui/schedule_task_tab.py (795 dòng) presentation/scheduling/{kanban_board_widget,calendar_view_widget,ai_task_creator_dialog,ai_task_import_dialog,run_history_dialog}.py + shell
R08-T12 ui/folder_tab.py (1587 dòng — lớn nhất) presentation/folder/{workspace_file_tree,document_preview_manager,code_editor,office_document_renderer,ai_file_editor_dialog,ai_edit_model_resolver,ai_edit_pipeline}.py + shell
R08-T13 ui/dashboard_tab.py (437 dòng) presentation/dashboard/{token_usage_card_widget,usage_chart_widget,habits_widget}.py + shell, application/monitoring/dashboard_query_service.py
R08-T14 ui/structure_graph_view.py (1035 dòng) presentation/graph/{graph_scene_items,graph_renderer,graph_messages_view,graph_qa_widget}.py + shell

(R08-T01→T10 thuộc Team Duy/Team Nam — không đụng.) Mỗi god-file cũ chỉ có 1-2 nơi khởi tạo thật (app.py, ui/workspace_tab.py) nên đã sửa thẳng import site và xoá hẳn file ui/*.py cũ thay vì giữ shim (khác core/tools.py ở R05, có hàng chục call site).


3. Kiến trúc sau refactor

presentation/            (MỚI ở R08 — Team Hoa tạo cấu trúc lần đầu)
      scheduling/  {kanban_board_widget, calendar_view_widget,
                    ai_task_creator_dialog, ai_task_import_dialog,
                    run_history_dialog, schedule_task_tab}.py
      folder/      {workspace_file_tree, document_preview_manager, code_editor,
                    office_document_renderer, ai_file_editor_dialog,
                    ai_edit_model_resolver, ai_edit_pipeline, folder_tab}.py
      dashboard/   {token_usage_card_widget, usage_chart_widget,
                    habits_widget, dashboard_tab}.py
      graph/       {graph_scene_items, graph_renderer, graph_messages_view,
                    graph_qa_widget, structure_graph_view}.py
      shared/      web_engine_support.py (HAS_WEB_ENGINE dùng chung)
      │
      ▼
application/   conversations/tool_policy_gateway.py        ← ALLOW/CONFIRM cho mọi tool call (R05)
               workspaces/{file_workspace_service, file_preview_helpers,
                           ai_edit_output, graph_index_service}.py         (R06, R08)
               scheduling/{task_application_service, ai_task_planner_service}.py   (R07)
               monitoring/dashboard_query_service.py                       (R08)
      │        (100% pure Python — check_imports.py chặn import Qt)
      ▼
domain/        tools/{tool_descriptor,tool_registry}.py     ← capability + catalogue (R05)
               workspaces/workspace_session.py              ← snapshot workspace bất biến (R06)
               tasks/schedule_calculator.py                 ← due-time/cron math thuần Python (R07)
      ▲
infrastructure/ filesystem/{file_tools,command_tools,fetch_tools,tool_context,execution_workspace}.py  (R05/R06)
                mcp/mcp_source_manager.py                   ← lifecycle connection MCP (R05)
                persistence/json/{atomic_write,workspace_repository_impl,
                                   conversation_repository_impl,task_repository_impl}.py  (R06/R07)
                qt/qt_scheduler_clock.py                    ← QTimer đằng sau 1 interface nhỏ (R07)

Nguyên tắc di trú xuyên suốt cả 4 EPIC (ADR-001 mục 4, tiếp nối cách Team Duy làm ở R04): không viết lại engine. core/tools.py::execute_tool, core/chat_agent.py::run_cowork, core/tasks.py, core/task_scheduler.py, core/task_executors.py vẫn là engine bên dưới — tầng mới chỉ sở hữu phần từng nằm rải rác/hardcode trong widget hoặc dispatcher. pytest xanh liên tục giữa các bước, chạy full suite sau MỖI task.

Riêng ở R08: khi 1 file bị tách vượt 400 dòng dù đã theo đúng mapping gốc, đã tách thêm file phụ theo kiểu composition (class phụ nhận owner là widget chính) thay vì service riêng — ví dụ run_history_dialog.py, office_document_renderer.py, ai_edit_pipeline.py, ai_edit_model_resolver.py, graph_messages_view.py. Đây là split kỹ thuật để đạt giới hạn LOC, không phải ranh giới tầng kiến trúc.


4. Bằng chứng kiểm thử

Tiến trình test qua từng EPIC

Mốc Tổng pass Ghi chú
Sau R05+R06 283 (/287, 4 fail) +41 unit test + 2 integration test (Qt offscreen thật)
Sau R07 328 +45 test mới (task repo, schedule calculator, Qt clock, task/AI-planner services)
Sau R08 377 +49 test mới (4 widget split, mỗi cái có unit + integration Qt offscreen)

4 fail cuối cùng — cùng 1 baseline có sẵn từ trước, xuyên suốt cả 4 EPIC, không phải do Team Hoa:

  • tests/test_config_security.py × 2 (EPIC R02/Team Nam — config.py hardcode sandbox_pw)
  • tests/unit/test_routing_wiring.py × 2 (môi trường máy này có Ollama/llama3.1 thật, khác giả định "fresh install" của test)

Đối chiếu Definition of Done

# Tiêu chí Kết quả
1 Mọi file mới < 400 dòng ✅ Lớn nhất: presentation/graph/graph_renderer.py 391 dòng
2 0 import Qt trong domain/, application/ ✅ check_imports.py PASS
3 Comment tiếng Anh giải thích lý do ở mọi khối sửa/mới ✅
4 Có unit/contract/integration test, verify bằng chạy thật ✅ +90 test mới sau R05/R06 lên tới 377; mọi widget Qt test bằng offscreen thật, không double
5 Không hồi quy ✅ 377/381 pass — 4 fail cùng 1 baseline có sẵn, không đổi qua 4 EPIC
6 Ghi Start/End vào Checklist ✅ 19 task đã tick kèm mốc thời gian thật
7 Cổng CASAN (run_quality_gate.py, R10-T02) ⚠️ Chưa viết (thuộc R10, chưa tới lượt) — Check 3 đã PASS

5. Lỗi thật phát hiện & quyết định kiến trúc

🔴 Lỗi 1 (R05-T04) — Tool MCP/Connector chạy hoàn toàn không qua permission gate

core/chat_agent.py::run_cowork có 2 nhánh dispatch tool call: built-in đi qua gate xác nhận khi Settings bật "confirm before running commands"; nhánh extra_tools (mọi tool từ MCP server hoặc Connector) gọi thẳng extra_executor(name, args) không qua bước xác nhận nào. Đây không phải khác biệt thiết kế — không có ghi chú, không có toggle riêng.

Sửa: mọi extra_tools gắn ToolCapability mặc định bảo toàn (WRITE|EXECUTE|NETWORK), đi qua CÙNG ToolPolicyGateway với built-in tools. Thay đổi hành vi người dùng sẽ thấy: tool MCP/connector giờ hỏi xác nhận khi "confirm before running commands" bật. Test: tests/unit/test_cowork_extra_tool_policy.py.

🟠 Lỗi 2 (R06-T02, R07-T01) — Ghi file không atomic ở 3 nơi

core/projects.py::save_project, core/history.py::save_conversation/rename_conversation/set_pinned (R06), và core/tasks.py::save_task (R07) đều từng dùng path.write_text(json.dumps(...)) trần — crash giữa lúc ghi để lại file JSON hỏng, và hàm load_* tương ứng coi file hỏng như "không tồn tại" → mất project/hội thoại/task âm thầm, không báo lỗi. Cả 4 điểm ghi giờ qua infrastructure/persistence/json/atomic_write.py::write_json (temp file + os.replace). Có test giả lập crash giữa lúc ghi xác nhận file cũ không bị hỏng, cho cả 2 đợt sửa.

🟡 Lỗi 3 (R06-T04) — Turn chạy ngầm lưu nhầm lịch sử vào project khác

ui/chat_panel.py::_persist_session gọi save_conversation(self.ctx.config.history_dir(), ...), đọc config._project_history_dir — field dùng chung bị ui/workspace_tab.py::_load_current ghi đè mỗi lần đổi project. Một turn chạy ngầm ở project A hoàn tất SAU khi user đã chuyển sang project B thì bị lưu nhầm vào lịch sử của B.

Sửa: thêm "home_history_dir" vào dict ctx mỗi turn, chụp giá trị tại lúc submit thay vì đọc sống lúc lưu. Test Qt offscreen thật: tests/integration/test_history_dir_race.py.

🔵 Quyết định kiến trúc (R07-T03) — platform/qt/ đè lên module chuẩn platform của Python

Plan gốc đặt tên platform/qt/qt_scheduler_clock.py. Thực nghiệm trước khi viết:

cd <repo_root> && python -c "import cowork_local; import platform; print(platform.system())"

Sau khi tạo platform/__init__.py, lệnh trên báo lỗi AttributeError: module 'platform' has no attribute 'system' — bất cứ khi nào repo root nằm trực tiếp trên sys.path (không qua __main__.py's parent-dir fixup), import platform phân giải nhầm vào package cục bộ. core/windows_sandbox_vm.py/core/appcontainer_sandbox.py đều import platform.

Sửa: chuyển sang infrastructure/qt/qt_scheduler_clock.py (không tạo package platform/ mới) — đúng layer, cùng cấp infrastructure/{filesystem,mcp,persistence,providers,telemetry}/. Verify lại: PASS.

Nối dây FileWorkspaceService (R06-T05 → R08-T12)

Báo cáo R06 để lại nợ: FileWorkspaceService (R06-T05) chưa có call site thật. Xác nhận lại bằng grep trước R08-T12: đúng 0 occurrence trong ui/folder_tab.py. Khi tách document_preview_manager.py (R08-T12), mọi điểm ghi text thuần (save, create_new_file, write_content) chuyển sang gọi FileWorkspaceService.write_file — dùng WorkspaceSession.unscoped(...) vì Folder Explorer duyệt bất kỳ thư mục nào, không giới hạn 1 project sandbox. Nhánh ghi .pptx (binary) vẫn giữ nguyên đường cũ.

Tác dụng phụ có lợi: infrastructure/filesystem/file_tools.py::write_file đã có sẵn cảnh báo cú pháp Python và tự build .xlsx thật từ text — 2 hành vi này trước đây không tồn tại trên đường ghi cũ của folder_tab.py, giờ được hưởng miễn phí.


6. Cải thiện phụ (không nằm trong yêu cầu task)

Cải thiện Ảnh hưởng
McpServerConnection.is_alive() (R05, core/mcp_client.py) Cho McpToolSourceManager biết một connection cached đã chết để khởi động lại.
domain/tasks/schedule_calculator.py có bộ test riêng (R07) core/tasks.py tự nhận "Qt-free, unit-testable" nhưng 0 test tồn tại cho cron/interval/holiday-exclusion trước R07-T02. Giờ 14 test.
AiEditModelResolver.routed_provider/.routed_model (R08-T12, property public mới) Cần thêm để giữ tests/integration/test_routing_surfaces.py's 2 test AI-Edit routing sau khi lớp routing chuyển từ FolderTab sang AiEditModelResolver — tránh hồi quy 1 test có từ EPIC R03.

7. Còn nợ & cần quyết định

# Nội dung Người quyết
1 Xung đột quy hoạch thư mục infrastructure/persistence/json/atomic_write.py (R06) với atomic_json_file.py do Team Nam quy hoạch ở R02-T01 — chưa có xung đột file thật, cần xác nhận hợp nhất hay giữ 2 module song song. Team Nam
2 Xung đột quy hoạch thư mục application/monitoring/ (R08-T13, dashboard_query_service.py) — quy hoạch cho Team Nam ở R08-T07→T10, nhưng plan gốc lại đặt file Dashboard vào đúng thư mục này. Chưa có xung đột file thật (thư mục trống trước đó). Team Nam
3 WorkspaceRepository/ConversationRepository (R06) vẫn chưa có call site sản xuất thật — R08-T12 chỉ nối FileWorkspaceService, chưa đụng 2 repository kia. Chưa có EPIC nào nhận
4 AI-Edit pipeline (ai_edit_pipeline.py) và Graph Q&A ask-flow (graph_qa_widget.py::_ask) chưa có test end-to-end thật — cả 2 chạy trên AgentWorker (QThread) thật, và vốn dĩ đã không có test nào trước khi refactor (xác nhận bằng grep). Có thể thuộc phạm vi R10 Testing Pyramid
5 Dev tooling chưa cập nhật đường dẫn cũ: tools/check_controls_alive.py, tools/capture_screens.py, tools/build_audit_page.py, docs/screens/*.json, docs/ui-audit*.html vẫn tham chiếu ui/schedule_task_tab.py/ui/folder_tab.py/ui/dashboard_tab.py/ui/structure_graph_view.py (không còn tồn tại). Không nằm trong tests/, không ảnh hưởng CI. Chưa quyết định người phụ trách

8. Phạm vi chưa kiểm thử

  • R05-T04 (gate cho MCP/connector) chưa test với MCP server thật — dùng ToolSpec giả, chưa thử core/mcp_client.py::McpServerConnection chạy subprocess thật.
  • McpToolSourceManager (R05-T05) chưa test với subprocess MCP thật — dùng _FakeConnection.
  • presentation/folder/ai_edit_pipeline.py (toàn bộ luồng plan → edit → apply/discard qua AgentWorker streaming) — chỉ verify bằng import/construction, chưa gửi instruction qua worker thật.
  • presentation/graph/graph_qa_widget.py::_ask — tương tự, chỉ test phần không cần AgentWorker thật.
  • office_document_renderer.py's PDF/LibreOffice conversion path — chưa xác nhận kịch bản fallback trên máy không có QtPdf/LibreOffice bằng test thật.
  • Đã mở app thật bằng python -c "import cowork_local.app" sau mỗi task để xác nhận không lỗi import — chưa mở app GUI thật, thao tác tay qua toàn bộ 4 màn hình đã tách để xác nhận trải nghiệm người dùng cuối.

9. Việc kế tiếp của Team Hoa

Toàn bộ 4 EPIC thuộc phạm vi Team Hoa (R05, R06, R07, R08 phần T11→T14) đã hoàn tất. Các bước còn lại không thuộc EPIC riêng của Team Hoa nữa:

Việc Điều kiện
Checkpoint 2 (Services & Sub-widgets, 28/08) Cần Team Duy (R08-T01→T06) và Team Nam (R08-T07→T10) xong phần UI split của họ
CASAN Check 2 (Modularity/LOC, Team Hoa chủ trì, 30/08) scripts/check_loc.py chưa tồn tại (thuộc R10-T02, Team Duy)
Giải quyết mục 7 #1, #2 Khi Team Nam bắt đầu R02-T01 và R08-T07→T10
R10 (Testing, Packaging & Contributor Experience) Team Duy chủ trì, chờ 3 team hoàn tất

10. Lịch sử commit

Commit Nội dung
ae4fe72 feat(R05): tool capability registry, unified policy gateway, MCP lifecycle manager
cf542b7 feat(R06): workspace session snapshot, atomic persistence, history-dir race fix
69ab8e1 feat(R07): task repository, schedule calculator, Qt clock adapter, task/AI-planner services
0e51356 feat(R08): split ScheduleTaskTab, FolderTab, DashboardTab, StructureGraphView
(gộp báo cáo) docs(refactor): merge Team Hoa reports R05→R08 into one; rename branch to feature/teamhoa/r05-r08