phase: 179_git_clone_server_freeze
All gates green; working tree holds exactly the phase's changes for the harness to commit. ## Phase 179 — Final verification report - **Verified (all 3 tasks already complete in `complete/`)**: repro + CONFIRMED verdict, `asyncio.to_thread` fix, dedicated E2E suite. - `app/api/sync.py::_run_sync`: both git ops (`clone_or_pull`, `file_commit_dates`) now `await asyncio.to_thread(...)`; phase-134 boundary note + module docstring document worker-thread-runs-to-completion and the A3 DB-calls-stay-on-loop note. - **Tests / lint / coverage** (full suite 100% green): - `uv run pytest tests/integration/test_sync_git_freeze.py -v` → **4 passed** (post-fix probe <1.5 s during 3 s stub) - `uv run pytest tests/e2e/test_sync_git_freeze.py -v --no-cov` → **2 passed in 25.65 s in isolation** (wall guard 120 s holds) - `uv run pytest --cov=app --cov-report=term-missing` → **4173 passed**, `app/` coverage **99%** (`app/api/sync.py` 100%) - `uv run ruff check .` → All checks passed; `uv run pyright` → **0 errors** - **Completion criteria**: ① integration probe green + verdict (CONFIRMED, mechanism, measured 3.04 s→0.003 s) in docstring — **met**; ② off-loop git ops + boundary/A3 notes — **met**; ③ full suite green, coverage 99% >90%, ruff+pyright clean — **met**; ④ E2E green in isolation (responsive-poll + cancel-during-clone contracts) — **met**; ⑤ atomic commit + move to `complete/` — **harness-owned** (pipeline rule overrides per-phase self-commit; all changes staged-ready in the working tree). - **Documentation**: full README (1526 l) + AGENTS.md review — phase-179 bullets present and accurate (verified against fixture constants, `.env.example` fully covered by the config reference, pages table matches `app/main.py` shell routes, quick-reference commands/artifacts exist); **consistent — no further changes needed**. - **Notable**: task-03 pipeline sessions died on context overflow but their harness validation passed; this pass independently re-ran every gate to confirm. No live infra touched; no git index commands run. - **Next pending phase**: `180_markdown_inline_links_images`.
This commit is contained in:
@@ -527,11 +527,21 @@ whole git-source refresh in one click:
|
||||
client-side timeout — a clone + embed can legitimately take minutes.
|
||||
- One sync at a time: a second trigger while a run is in flight gets a
|
||||
`409`.
|
||||
- **A long clone never freezes the server** (phase 179). The run's git
|
||||
steps (`clone_or_pull` / `file_commit_dates`, the blocking
|
||||
`subprocess` calls) execute in a worker thread
|
||||
(`asyncio.to_thread`), so the event loop keeps serving the whole
|
||||
HTTP surface for their duration — every page, `GET /api/health`, and
|
||||
above all the 2 s `GET /api/sync/status` poll that watches the run.
|
||||
Before this a big first clone stalled the loop thread and the entire
|
||||
app looked dead until git returned.
|
||||
- **Cancel**: while a run is in flight, a **Cancel** button appears
|
||||
next to the sync button; clicking it posts `POST /api/sync/cancel`
|
||||
(admin only) and registers a cooperative cancel (`202`) — the run
|
||||
stops at the next pipeline boundary (a git clone/pull already in
|
||||
flight runs to completion) and settles into a neutral `cancelled`
|
||||
flight runs to completion in its worker thread — the request is not
|
||||
held, and the rest of the app keeps answering meanwhile) and settles
|
||||
into a neutral `cancelled`
|
||||
terminal state (`error: null` — intent, not failure: a "Sync
|
||||
cancelled" result line, no error banner or modal, the button
|
||||
retry-ready) that the status endpoint reports; with no run in
|
||||
@@ -1372,6 +1382,16 @@ uv run pytest tests/e2e/test_chat_rag.py -v --no-cov
|
||||
for f in tests/e2e/test_*.py; do uv run pytest "$f" --no-cov -q || echo "FAIL $f"; done
|
||||
```
|
||||
|
||||
**`git` on `PATH` is an E2E prerequisite** (phase 28): the git-source
|
||||
suites drive real `clone_or_pull` / `file_commit_dates` calls against
|
||||
generated local `file://` fixture repos. The heaviest is phase 179's
|
||||
`tests/e2e/test_sync_git_freeze.py`: it builds a ~150 MiB pack-free repo
|
||||
(30 commits × 5 MiB of seeded pseudo-random bytes) so a fresh
|
||||
`git clone` genuinely costs ≈ 9 s — that clone IS the timing fixture for
|
||||
"a long clone must not freeze the server". It is mock-only
|
||||
(`E2E_REAL_LLM=1` is skipped there: the clone, not the LLM import, is
|
||||
what the suite times).
|
||||
|
||||
**Retrieval regression battery.** `tests/fixtures/retrieval_battery.txt` is
|
||||
the tracked retrieval gate (phases 119 + 162): the name-your-tool questions,
|
||||
the versioned-name (`qwen 3.8 27b`) regression, the out-of-KB deflection
|
||||
|
||||
Reference in New Issue
Block a user