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:
2026-09-02 01:08:18 -04:00
parent 4677d86f49
commit 8a1f99cb38
30 changed files with 1376 additions and 147 deletions
@@ -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
@@ -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`
@@ -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
@@ -0,0 +1,16 @@
All gates green. The `.agent/phases/todo/64_*` deletions in git status are harness bookkeeping from phase 64's completion (not mine); the commit happens in task 05.
**Task 01 report — `65_bottom_chat_actions/01_move_chat_actions_to_bottom`**
- Moved the entire `.chat-actions` block (Phase 55/14/51 comment + row div) from between `#steering-announcer` and `#messages` to after the messages `</section>`, directly above the composer — buttons verified byte-identical (git diff line-set comparison: only the appended note differs); DOM order New chat (L179) → Share (L211); exactly one `class="chat-actions"` in `frontend/index.html`.
- Appended the Phase 65 relocation note to the row's moved comment block (top of column now banner → steering → announcer → messages).
- No CSS/JS changes; untouched `#kb-banner`, `#stale-banner`, `#steering-panel`, `#steering-announcer`, `#messages`, `#composer`.
- Updated 3 position-pinning unit tests to the new contract: `test_chat_persistence.py::test_new_chat_button_lives_only_on_the_chat_page`, `test_save_chat_ui.py::test_share_button_ships_visible_beside_new_chat` + `test_chat_actions_wrapper_holds_both_pills_in_order` (now pin row below `#messages`, above composer, with nothing else between).
Results (all green):
- `uv run pytest --cov=app --cov-report=term -q` → exit 0, TOTAL coverage **99%** (>90%)
- `uv run ruff check . && uv run pyright` → clean (0 errors)
- `uv run pytest tests/e2e/test_save_share_ux.py -v --no-cov` → **5 passed** (isolation, DB up)
- `uv run pytest tests/e2e/test_pinned_composer.py --no-cov` → exit 0 (isolation); `uv run pytest tests/e2e/test_chat_persistence.py --no-cov` → exit 0 (isolation)
No deviations. Next pending task: `02_pin_bottom_cluster.md` (same phase).
@@ -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
@@ -0,0 +1,16 @@
All gates green. Task 02 complete — no commit (that's task 05's job), task file untouched.
**Report**
- **Implemented (locked A1 pinned bottom cluster):**
- `frontend/index.html`: wrapped the `.chat-actions` row + `#composer` form (with comments, re-indented) in one new `<div class="chat-bottom">` (no id) — the last child of `.chat-shell`, containing exactly `.chat-actions` then `#composer`; appended the Phase 65 A1 note to the row's comment.
- `frontend/assets/styles.css`: new `.chat-bottom` rule directly above `.composer` — `display:flex; flex-direction:column; gap:0.5rem; position:sticky; bottom:env(safe-area-inset-bottom,0)`, no z-index; `#composer` rule body untouched, phase-52 comment gained a one-line Phase 65 note.
- `tests/unit/test_pinned_composer.py`: re-pinned the structure test (renamed `test_chat_bottom_unit_is_last_child_of_the_chat_shell`) — wrapper is last shell child, no id, exactly row→form; updated module docstring (also removed a duplicated bullet block found there).
- **Test/lint results:**
- `uv run pytest --cov=app` → all pass, TOTAL 99% (>90%)
- `uv run ruff check . && uv run pyright` → clean (0 errors)
- `uv run pytest tests/e2e/test_pinned_composer.py -v --no-cov` → 4 passed (pin at every scroll position, empty-chat rest, mobile under header)
- `uv run pytest tests/e2e/test_save_share_ux.py -v --no-cov` → 5 passed
- Extra: `test_chat_persistence.py` (4), `test_smoke.py` (3) passed in isolation; `bash .agent/validate.sh` → validation OK
- **Deviations:** none — wrapper per spec; only pre-existing stale unit assertion updated to the owner-locked A1 structure.
- **Next pending task:** `03_align_button_clusters.md` (right-align the bottom row, verify five-pill geometry).
@@ -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
@@ -0,0 +1,19 @@
Task 03 complete. All gates green.
**Implemented**
- `frontend/assets/styles.css` — added the single `justify-content: flex-end;` declaration to `.chat-actions` (pills keep intrinsic widths; the row now hugs the column's right edge per owner-locked A2) + updated the rule's comment (top member of the pinned `.chat-bottom` cluster, A2 rationale, 0.5rem wrapper gap, ≤640px stack unchanged).
- Five-pill geometry pass: no deviations found → no declaration changes (solid family: 44px/999px/16px icons; ghost family: 44px/999px/14px icons/0.82rem; global `:focus-visible` covers all five).
- No HTML/JS/`.msg-meta` changes; ≤640px stack rule byte-identical.
**Verification**
- Temporary Playwright measurement (file deleted after use): all five pills exactly 44.0px rendered at 1280/390/360; Share's right edge flush with the composer's at 1280 (A2); stacked full-width at 390; no horizontal overflow at 360/390. (Save-as-doc measured via a same-markup probe in the real `.msg-meta` — it's gated off in the e2e app since `BOR_DOCS_REPO` is forced empty; CSS under test is identical.)
- `uv run pytest tests/e2e/test_save_share_ux.py -v --no-cov` → 5 passed (DB up, isolated)
- `uv run pytest tests/e2e/test_pinned_composer.py -v --no-cov` → 4 passed (sanity, isolated)
- `uv run pytest --cov=app --cov-report=term-missing` → 1251 passed, TOTAL **99%** (>90%)
- `uv run ruff check . && uv run pyright` → All checks passed / 0 errors, 0 warnings
**Notes**
- Repo carries uncommitted task 01/02 work — expected; the phase's single atomic commit is task 05's job (not committed here).
- No defects found in prior work.
**Next pending task:** `.agent/phases/todo/65_bottom_chat_actions/04_e2e_bottom_chat_actions.md`
@@ -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
@@ -0,0 +1,17 @@
All gates are green. Final report:
**Implemented**
- `tests/e2e/test_bottom_chat_actions.py` (NEW, house patterns; no other file changes):
- `test_empty_chat_row_rests_at_screen_bottom` — one `.chat-bottom` (row + composer), not scrollable, row rests ≥75% viewport height directly above composer, A2 right-edge alignment (row + Share flush ±2px vs column content edge), composer not clipped.
- `test_bottom_cluster_pinned_at_every_scroll_position` — seeded KB, 6 grounded turns (overflow precondition), sticky range from `.chat-shell` document-bottom (pin_limit > 200, max_scroll > pin_limit); cluster fully in viewport + flush at 0/25/50/75%/pin_limit−1; at document bottom settles above `.app-footer`, composer unglued, row still above composer.
- `test_row_geometry_and_alignment` — one `.chat-actions` in `.chat-bottom`, two pills, DOM order New→Share (compareDocumentPosition); desktop horizontal + intrinsic widths + A2 edge; 390×844 full-width stack (pills == `.chat-bottom` width ±2px); 360px `scrollWidth ≤ 360`; ≥44px targets at 1280 and 390 incl. `.retry-btn` after one seeded turn.
- `test_buttons_still_work_from_the_bottom` — New chat click: `.msg` 0, `#empty-state`, `bor.chat.v1` null, "New chat started"; Share on empty chat: "Nothing to share yet.", no toast, URL unchanged.
**Results** (DB up)
- Each test green in isolation; `uv run pytest tests/e2e/test_bottom_chat_actions.py -v --no-cov` → **4 passed** (13.5s).
- Baseline `uv run pytest tests/e2e/test_pinned_composer.py -v --no-cov` → 4 passed (prior tasks 01–03 defect-free).
- `.agent/validate.sh` → **validation OK**: unit+integration green, coverage TOTAL **99%** (>90%), `ruff check .` + `pyright` clean.
**Decisions** — A2 "shell right edge" measured against the column's *content* edge (`.chat-shell` is a `.container` with padding; computed live), with the rightmost pill asserted flush as the real A2 pin; `_reset_db` truncates all 5 tables per task spec.
**Next pending task:** `.agent/phases/todo/65_bottom_chat_actions/05_regressions_and_commit.md`
@@ -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