feat(web): move the chat action cluster to the pinned bottom and align the button sets
- task 01: relocate the .chat-actions row (New chat + Share, comments byte-identical with a Phase 65 note) from the top of the column to the bottom of .chat-shell, directly above the composer - task 02 (owner-locked A1): wrap the row + #composer in ONE sticky .chat-bottom unit (position: sticky; bottom: env(safe-area-inset-bottom, 0), no z-index) — the pills stay at the bottom of the screen at every scroll position and settle into flow above the footer - task 03 (owner-locked A2): right-align the bottom row to the column's right edge (justify-content: flex-end), mirroring the right-aligned Save-as-doc corner; the five action pills share one 44px / 999px-pill geometry - task 04: dedicated Playwright suite tests/e2e/test_bottom_chat_actions.py (resting geometry, the A1 pin across the sticky range, A2 alignment + DOM order + mobile stack + 360px overflow bound + 44px touch targets, New chat / Share click-through) — green in isolation - task 05: regression matrix green in isolation (pinned_composer 4, save_share_ux 5, chat_persistence 4, share_chat 4, chat_history 5, smoke 3); full gate green — unit + integration pass, app/ coverage 99% (>90%), ruff + pyright clean
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
All verification complete — nothing to fix; the phase commit `4677d86` contains the full implementation. Final report:
|
||||
|
||||
**Phase 64 final verification pass** (tasks 01–06 already complete; verified all criteria, no defects found)
|
||||
|
||||
- **Test/lint/coverage**
|
||||
- `uv run pytest --cov=app --cov-report=term -q` → 1251 passed, 0 failed; `app/` coverage **99%** (gate >90% OK)
|
||||
- `uv run ruff check . && uv run pyright` → "All checks passed!" / "0 errors, 0 warnings, 0 informations"
|
||||
- `uv run pytest tests/e2e/test_sync_upload_progress.py -v --no-cov` → **4 passed** (isolation, DB up)
|
||||
- Regressions, each in isolation: `test_archive_upload_sources` **5 passed**, `test_sync_button` **3 passed**, `test_git_sources_admin` **6 passed**, `test_sync_model_down` **4 passed**
|
||||
- **Completion criteria**
|
||||
1. `current_file`/`files_done`/`files_total` on both status endpoints — ✅ idle live-checked via running app (both return `null`/`0`/`0`); running states asserted by unit + E2E
|
||||
2. `POST /upload` → 202 + background scan + 409 in-flight — ✅ (unit contract + E2E green)
|
||||
3. Toast at 202, navigate-away mid-scan shows "Importing \<file\>", settle + catalog refresh — ✅ `test_upload_toast_then_navigate_away`
|
||||
4. Live labels "Syncing… \<file\>" / "Importing \<file\>" / "Processing… \<file\>" — ✅ E2E green
|
||||
5. Full pytest green, coverage >90% — ✅ (99%)
|
||||
6. All 5 E2E suites green in isolation — ✅
|
||||
7. ruff + pyright clean — ✅
|
||||
8. Commit `4677d86` (`feat(sources): real-time file progress…`, `--no-gpg-sign`) exists; overview move to `complete/` left to the harness — ✅
|
||||
- **Decisions/deviations:** none — no code changes needed.
|
||||
- **Next pending phase:** `65_bottom_chat_actions`
|
||||
@@ -0,0 +1,72 @@
|
||||
........................................................................ [ 5%]
|
||||
........................................................................ [ 11%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 23%]
|
||||
........................................................................ [ 28%]
|
||||
........................................................................ [ 34%]
|
||||
........................................................................ [ 40%]
|
||||
........................................................................ [ 46%]
|
||||
........................................................................ [ 51%]
|
||||
........................................................................ [ 57%]
|
||||
........................................................................ [ 63%]
|
||||
........................................................................ [ 69%]
|
||||
........................................................................ [ 74%]
|
||||
........................................................................ [ 80%]
|
||||
........................................................................ [ 86%]
|
||||
........................................................................ [ 92%]
|
||||
........................................................................ [ 97%]
|
||||
........................... [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
|
||||
|
||||
Name Stmts Miss Cover
|
||||
-----------------------------------------------
|
||||
app/__init__.py 1 0 100%
|
||||
app/api/__init__.py 0 0 100%
|
||||
app/api/auth.py 22 0 100%
|
||||
app/api/chat.py 131 0 100%
|
||||
app/api/chats.py 110 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/doc_drafts.py 93 0 100%
|
||||
app/api/docs.py 50 0 100%
|
||||
app/api/git_sources.py 181 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 8 0 100%
|
||||
app/api/sync.py 101 0 100%
|
||||
app/config.py 112 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 20 0 100%
|
||||
app/core/caching.py 108 0 100%
|
||||
app/core/debugging.py 29 2 93%
|
||||
app/core/docs_push.py 39 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 52 0 100%
|
||||
app/models.py 86 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 78 0 100%
|
||||
app/rag/archive_upload.py 128 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/git_sources.py 14 0 100%
|
||||
app/rag/importer.py 180 3 98%
|
||||
app/rag/llm.py 189 0 100%
|
||||
app/rag/overview.py 71 0 100%
|
||||
app/rag/prompts.py 65 0 100%
|
||||
app/rag/retriever.py 94 3 97%
|
||||
app/rag/sources_meta.py 16 0 100%
|
||||
app/rag/suggestions.py 27 0 100%
|
||||
app/rag/summarizer.py 24 0 100%
|
||||
app/schemas.py 201 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 2529 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
**Task 06 complete — Phase 64 (sync + upload real-time progress) is done and committed.**
|
||||
|
||||
**Implemented**
|
||||
- `tests/e2e/test_sync_upload_progress.py` (new story suite, 4 tests): toast-on-202 → navigate away → sync button "Importing <file>" + settle + catalog refresh; live `current_file` at both layers (100 ms endpoint recorder + UI label poll); sync "Syncing… <file>" both layers with preserved pre-64 settle; mid-scan reload re-attach (no second upload, pinned on `started_at`).
|
||||
- `tests/e2e/test_archive_upload_sources.py` adapted to the 202 contract: toast while running, "Uploading… → Processing… → restore", result/row from status `success`, 2nd-run status `detail` prune/refresh counts, 422 gates unchanged, anonymous 403 extended to `GET /upload/status`.
|
||||
- `tests/e2e/slow_llm.py` (new helper): delay-injecting proxy in front of the mock LLM — the mock indexes 25 files in ≈0.4 s (benchmark), so the scan could never outlive the 2 s UI poll; the proxy makes scan duration deterministic (0.15 s/req → ≈4.2 s; 0.6 s in the archive suite).
|
||||
|
||||
**Results (all green)**
|
||||
- `uv run pytest tests/e2e/test_sync_upload_progress.py -v --no-cov` → 4 passed (×3 runs); `test_archive_upload_sources.py` → 5 passed (×2); `test_sync_button.py` → 3 passed; `test_git_sources_admin.py` → 6 passed; `test_sync_model_down.py` → 4 passed (all isolated, DB up).
|
||||
- `uv run pytest --cov=app` → all passed, TOTAL 99% (>90%); `uv run ruff check .` → clean; `uv run pyright` → 0 errors.
|
||||
- Commit `4677d86` `--no-gpg-sign`: "feat(sources): real-time file progress for sync and upload — background upload with success toast"; `TODO.md` contains only `# TODO`.
|
||||
|
||||
**Decisions/deviations**
|
||||
- Per harness rules I did **not** move the phase dir — the todo→complete move of task 06 is left to the harness; the commit (per the task's exact `git add` scope) also swept phases 61–63 pending `.agent/` bookkeeping, matching the repo's established pattern.
|
||||
- Recorder ignores residual terminal states (in-memory run state survives across module tests) and the autouse fixture waits for no in-flight job before each truncate — without these, a prior test's run leaked into the next.
|
||||
|
||||
**Next pending task:** `.agent/phases/todo/65_bottom_chat_actions/01_move_chat_actions_to_bottom.md`
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
........................................................................ [ 5%]
|
||||
........................................................................ [ 11%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 23%]
|
||||
........................................................................ [ 28%]
|
||||
........................................................................ [ 34%]
|
||||
........................................................................ [ 40%]
|
||||
........................................................................ [ 46%]
|
||||
........................................................................ [ 51%]
|
||||
........................................................................ [ 57%]
|
||||
........................................................................ [ 63%]
|
||||
........................................................................ [ 69%]
|
||||
........................................................................ [ 74%]
|
||||
........................................................................ [ 80%]
|
||||
........................................................................ [ 86%]
|
||||
........................................................................ [ 92%]
|
||||
........................................................................ [ 97%]
|
||||
........................... [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
|
||||
|
||||
Name Stmts Miss Cover
|
||||
-----------------------------------------------
|
||||
app/__init__.py 1 0 100%
|
||||
app/api/__init__.py 0 0 100%
|
||||
app/api/auth.py 22 0 100%
|
||||
app/api/chat.py 131 0 100%
|
||||
app/api/chats.py 110 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/doc_drafts.py 93 0 100%
|
||||
app/api/docs.py 50 0 100%
|
||||
app/api/git_sources.py 181 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 8 0 100%
|
||||
app/api/sync.py 101 0 100%
|
||||
app/config.py 112 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 20 0 100%
|
||||
app/core/caching.py 108 0 100%
|
||||
app/core/debugging.py 29 2 93%
|
||||
app/core/docs_push.py 39 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 52 0 100%
|
||||
app/models.py 86 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 78 0 100%
|
||||
app/rag/archive_upload.py 128 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/git_sources.py 14 0 100%
|
||||
app/rag/importer.py 180 3 98%
|
||||
app/rag/llm.py 189 0 100%
|
||||
app/rag/overview.py 71 0 100%
|
||||
app/rag/prompts.py 65 0 100%
|
||||
app/rag/retriever.py 94 3 97%
|
||||
app/rag/sources_meta.py 16 0 100%
|
||||
app/rag/suggestions.py 27 0 100%
|
||||
app/rag/summarizer.py 24 0 100%
|
||||
app/schemas.py 201 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 2529 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
Reference in New Issue
Block a user