1efa1d29d1a517585731dcf71bef5ed09dc9ee7e
2
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
69ab8e125b |
feat(R07): task repository, schedule calculator, Qt clock adapter, task/AI-planner services
Team Hoa, EPIC R07 (Scheduling & Workflow Runtime) - Team Hoa scope only (R07-T01 -> T05; R07-T06 Co4EWorkflowService is Team Nam's). - R07-T01: infrastructure/persistence/json/task_repository_impl.py wraps core/tasks.py's CRUD; core/tasks.py::save_task now writes through atomic_write.write_json (same durability fix as R06-T02, save_task was still doing a plain write_text). - R07-T02: domain/tasks/schedule_calculator.py::ScheduleCalculator - the cron/interval/daily/weekly/monthly due-time math extracted from core/tasks.py, pure Python with is_holiday/make_cron injected so domain/ never imports core (ADR-001 I2). core/tasks.py keeps its old function names as thin wrappers so every existing caller is unchanged. This was previously untested; now has its own unit suite. - R07-T03: infrastructure/qt/qt_scheduler_clock.py::QtSchedulerClock wraps the QTimer TaskScheduler used to own directly, injected via a new `clock=` constructor param (defaults to a real one). Originally planned at platform/qt/... ; moved after confirming that name shadows the stdlib platform module (used by core/windows_sandbox_vm.py, core/appcontainer_sandbox.py) whenever the repo root is on sys.path. tests/fakes/fake_clock.py lets scheduler dispatch be tested tick-by-tick with no Qt event loop. - R07-T04: application/scheduling/task_application_service.py centralizes run_now/duplicate/pause/delete/bulk_delete and the Kanban drag-drop business rules (move_to_status), currently only reachable by driving the real ui/schedule_task_tab.py widget. - R07-T05: application/scheduling/ai_task_planner_service.py wraps core/ai_task_planner.py::plan_tasks and core/task_import.py::import_tasks as a seam, plus the attachment-stamping step that used to only exist inside the AI-create dialog's worker closure. pytest: 328 pass (same 4 pre-existing failures as the R05/R06 baseline, unrelated to this work - see docs/refactor/BaoCao_TeamHoa_R05_R06.md). scripts/check_imports.py: PASS. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
cf542b7416 |
feat(R06): workspace session snapshot, atomic persistence, history-dir race fix
EPIC R06 (Team Hoa) - workspace/filesystem isolation, no cross-project
mutable state.
R06-T01 domain/workspaces/workspace_session.py
WorkspaceSession - project_id/workspace_root/sandbox_dir/allowed_paths
frozen snapshot + is_allowed(path), same "capture once at submit time"
shape as R04's ConversationExecutionRequest.
R06-T02 infrastructure/persistence/json/{atomic_write,workspace_repository_impl,conversation_repository_impl}.py
Real bug fixed: core/projects.py::save_project and core/history.py's
save_conversation/rename_conversation/set_pinned did a plain
path.write_text(json.dumps(...)) - two syscalls, no atomicity. A crash
between them leaves a half-written file that load_project/load_conversation
then silently treat as "missing". All four now write through
atomic_write.write_json (temp file + os.replace). WorkspaceRepository/
ConversationRepository are thin object-shaped facades over the same
(now-atomic) functions, for future application-layer callers.
NOTE: atomic_write.py is deliberately NOT named atomic_json_file.py -
R02-T01 (Team Nam) claims that filename for the same purpose app-wide;
see the checklist for the consolidation TODO.
R06-T03 infrastructure/filesystem/execution_workspace.py
ExecutionWorkspace names the output_dir/scratch_dir split that already
exists (core/chat_agent.py's flat workspace_root/.scratch) - does not
move anything.
R06-T04 ui/chat_panel.py
The actual race: ChatPanel._persist_session (saves a BACKGROUND turn's
conversation) resolved its save directory via a live
self.ctx.config.history_dir() read at save time. ui/workspace_tab.py::
_load_current mutates that same config field on every project switch, so
a turn still running when the user switched projects got saved into the
NEW project's history folder. Fixed by adding "home_history_dir" to the
per-turn ctx dict (same "home_*" snapshot convention already used for
session id/messages/title), captured at submit time. Verified with a real
offscreen-Qt test, not just a unit double:
tests/integration/test_history_dir_race.py.
R06-T05 application/workspaces/file_workspace_service.py
FileWorkspaceService - the File Explorer / AI Editor entry point for the
same safe read/write/edit operations the agent tool loop has, by calling
core/tools.py::execute_tool directly (same dispatch, same ToolContext
containment, same audit log) rather than reimplementing any of it.
New tests: tests/unit/test_workspace_session.py,
test_atomic_write_and_repositories.py, test_execution_workspace.py,
test_file_workspace_service.py, tests/integration/test_history_dir_race.py
(29 new tests, incl. 2 real offscreen-Qt integration tests).
Suite: 283 passed, 4 pre-existing failures unrelated to R05/R06 (see
checklist). check_imports: PASS. All new files < 400 LOC.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|