Mở app lên là hai mục đã hiện sẵn dù người dùng chưa bấm chọn project nào.
Cổng này có hai mặt và cả hai đều hở:
1. refresh() mặc định row_to_select = 0, nên lúc mở app (_current_id rỗng)
danh sách tự chọn hộ project đầu tiên -> _update_tab_visibility(True).
Cùng đường đó còn làm app nhảy sang project khác ngay sau khi xoá project
đang mở. Đổi mặc định thành -1; có keep khớp thì vẫn giữ đúng dòng cũ.
2. NavRailMixin._rebuild_nav dựng hàng bị cổng đóng ở dạng mờ kèm tooltip
("shown instead of hidden") nên chúng vẫn nằm trên menu trái. Nay bỏ hẳn
hàng cho tới khi chọn project.
Mặt 1 làm selected_project_id() trả rỗng, khiến bộ chọn project trên rail rơi
về mục 0 và chỉ vào project đầu danh sách trong khi cổng vẫn đóng — hai chỗ
nói hai đằng. Thêm mục "Chọn project…" (khoá app.nav.pick_project, khác
no_project: đã có project, chỉ chưa chọn) để rail nói đúng trạng thái.
tools/check_nav.py và một bài trong test_startup_landing.py đang chốt thiết
kế cũ; cập nhật để chốt hành vi mới. Bài startup giữ nguyên từng assert, chỉ
đổi cách mở cổng từ cửa sau setTabVisible sang chọn project thật.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Cowork Local
Cowork Local is the internal AI cowork desktop platform. It provides a local-first desktop runtime, multi-turn conversational agents, workspace isolation, task scheduling, MCP connectors, security guardrails, and model routing.
🏛️ 4-Tier Clean Architecture
The codebase strictly adheres to Clean Architecture with unidirectional inward dependencies:
presentation/ (PySide6 UI, Shell, NavRail, Chat, Scheduling, Settings, Dashboard)
│
▼
application/ (Pure Python Orchestration: Conversations, Scheduling, Workspaces, Monitoring, Routing)
│
▼
domain/ (Pure Python: Entities, Immutable Execution Requests, Agent Events, Descriptors)
▲
│
infrastructure/ (Adapters, LLM Providers, Atomic Persistence, Keyring SecretStore, MCP)
- Domain & Application Layers: 100% Pure Python (zero Qt/UI imports).
- Single Responsibility: Every production module is strictly
<= 400 LOC. - Security & Durability: API keys stored in OS Keyring; atomic JSON disk persistence.
🚀 Quick Start
1. Windows — two double-clicks
install.bat once, to install the Python dependencies
run.bat every time, to start the app
install.bat builds an isolated virtualenv under %LOCALAPPDATA%\CoworkLocal
(deliberately outside the repo — the quality gates walk the whole directory
tree, so a .venv in here would turn every vendored module into a Gate O
violation). Add --dev to also install the test dependencies, or --system to
skip the virtualenv and install into the Python already on PATH.
Both scripts also make the source importable under its package name. That step
is not optional: python -m cowork_local only resolves when the checkout
directory is literally named cowork_local, and the MS365 MCP server is
launched as a subprocess with python -m cowork_local.mcp_servers.ms365_server,
so a differently-named checkout breaks the app and its subprocesses. The
scripts create a junction instead of forcing anyone to rename their folder.
2. Any platform — run from source
From the parent of a checkout directory named cowork_local:
python -m cowork_local
3. Run Automated Tests
python -m pip install -r requirements.txt
pytest -q
There is one requirements file, not a runtime/test pair. A separate test file
would hold only pytest: 64 of the 108 test modules build real widgets, and 20
of them import PySide6 unguarded at module scope, so it would have to pull in
almost the whole runtime list anyway — two files for one near-identical list is
just a second place for the pins to drift.
🛡️ CASAN Quality Gate & Verification
Before submitting any Pull Request, run the unified CASAN Quality Gate:
# Run all 4 quality gates (Clean Arch, Secrets, LOC, and Pytest Suite)
python scripts/run_quality_gate.py
# Run static and architectural guards only (fast check)
python scripts/run_quality_gate.py --skip-tests
Individual guard scripts:
- Clean Architecture Import Guard:
python scripts/check_imports.py - Secrets & Plaintext Audit:
python scripts/audit_security.py - Single Responsibility LOC Guard:
python scripts/check_loc.py --max-lines 400 - Release E2E Smoke Test:
pytest tests/e2e/test_smoke.py -v
🤝 Contributing & Recipes
- Quick Start Guide: See START_CONTRIBUTING.md.
- Contributor Recipes: See docs/governance/contributor-recipes.md for step-by-step recipes to:
- Add a new AI Model Provider.
- Add a new Built-in Tool / MCP Server.
- Add a new Screen / Tab / Widget.
- Security Policy: See SECURITY.md.