feat: phases 77–80 — navbar view refresh, static background, API tokens, history suggestion chips
Single consolidated commit for four completed, validated phases (77, 78, 79, 80). The pipeline run left all work uncommitted because the harness commits only with PHASE_COMMIT=1 while child executors are forbidden from committing; the phases themselves all passed validation and moved to .agents/phases/complete/. Phase 77 — navbar view refresh - router.js dispatches bor:view-refresh on re-show / active re-click / popstate (gated on wasMounted; first show and boot exempt) - History / RAG / Sources / Tuning re-fetch on refresh (admin branch); Chat deliberately excluded (stream survival) - History "Refresh" button (admin-only, in-flight disable + status line) - New story suite tests/e2e/test_navbar_refresh.py (7 tests) Phase 78 — static background - Removed the animated glow layers; static 44px grid over the flat --bg canvas; default and reduced-motion renders byte-identical - Updated background/theme E2E suites; removed bg-glow test pins Phase 79 — API tokens - api_tokens model + migration 0012; hash-only token service - Admin tokens API + Tokens admin view; POST /api/token-auth; live-revoking require_user on chat / suggestions / document content - Frontend token gate with localStorage cache; anonymous E2E suites migrated to token login - New story suite tests/e2e/test_api_tokens.py (9 tests) Phase 80 — history suggestion chips - last_questions() endpoint with SEED fallback; startNewChat() refetch - Seed-semantics docs (config.py, .env.example, README) - Integration state matrix + E2E suite rewritten to the 4 chip states Also included: phase-76 report artifacts and the repo restore-test-db skill (previously untracked), scripts/* ruff fixes from phase 77. Final gate state (phase 80 final pass, covers everything above): - uv run pytest --cov=app → 1637 passed, 0 failed, app/ coverage 99% - uv run ruff check . && uv run pyright → clean, 0 errors - Per-phase story E2E suites green in isolation
This commit is contained in:
+13
@@ -0,0 +1,13 @@
|
||||
All completion criteria verified green — no defects found, no fixes needed. Final report:
|
||||
|
||||
**Phase 80 (history_suggestion_chips) — final verification pass: ALL GREEN**
|
||||
- Verified implementation: `last_questions()` + seed-fallback in `app/api/suggestions.py` (100% cov); `startNewChat()` refetch via `loadSuggestions()` in `app.js`; seed-semantics docs in `config.py` docstring, `.env.example:55`, README L114/L823; integration state matrix in `test_suggestions_api.py`; E2E suite rewritten to the 4 states + carried-over story behavior.
|
||||
- `uv run pytest tests/e2e/test_suggestion_chips.py -v --no-cov` → **7 passed** (isolated).
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → **1637 passed**, TOTAL **99%** (>90%).
|
||||
- `uv run ruff check . && uv run pyright` → **All checks passed / 0 errors, 0 warnings**.
|
||||
- Criterion: E2E isolated green → ✅.
|
||||
- Criterion: deflection unchanged → ✅ (`app/rag/suggestions.py` no diff vs HEAD; `test_honest_deflection.py` 3 passed; 100% cov).
|
||||
- Criterion: full suite + coverage + lint/types → ✅ (above).
|
||||
- Criterion: atomic commit + phase dir move → deferred per harness override: all changes left uncommitted in the working tree; task files already in `complete/80_history_suggestion_chips/`; harness commits and moves the phase dir.
|
||||
- Notable: none — no defects found in prior work.
|
||||
- Next pending phase: **none** (phase 80 is the last in the roadmap; `todo/` contains only this phase).
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 21%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 30%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 39%]
|
||||
........................................................................ [ 43%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 52%]
|
||||
........................................................................ [ 57%]
|
||||
........................................................................ [ 61%]
|
||||
........................................................................ [ 65%]
|
||||
........................................................................ [ 70%]
|
||||
........................................................................ [ 74%]
|
||||
........................................................................ [ 79%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 87%]
|
||||
........................................................................ [ 92%]
|
||||
........................................................................ [ 96%]
|
||||
..................................................... [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 40 0 100%
|
||||
app/api/chat.py 178 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 212 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 29 0 100%
|
||||
app/api/sync.py 101 0 100%
|
||||
app/api/tokens.py 28 0 100%
|
||||
app/config.py 140 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 45 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/core/tokens.py 33 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 62 0 100%
|
||||
app/models.py 94 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 222 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 216 0 100%
|
||||
app/rag/overview.py 71 0 100%
|
||||
app/rag/prompts.py 88 0 100%
|
||||
app/rag/retriever.py 150 3 98%
|
||||
app/rag/scaffolding.py 55 0 100%
|
||||
app/rag/source_removal.py 41 0 100%
|
||||
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 231 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 3154 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
**Task 01 complete** — `/api/suggestions` now returns the last 3 questions asked, seed before the first.
|
||||
|
||||
- `app/api/suggestions.py`: module-level `last_questions(db, limit=3)` — `saved_chats` walked `updated_at DESC, created_at DESC`, each `bor.chat.v1` message list walked in reverse, `who=="user"` non-blank trimmed texts, exact case-sensitive dedup, cap 3; endpoint returns `qs if qs else get_settings().suggestions` (phase-79 `require_user` gate kept, `db` dep now used).
|
||||
- New `tests/integration/test_suggestions_api.py` (10 tests): empty DB → seed; 4-q chat → `[q4,q3,q2]`; distinct-`updated_at` chat order; verbatim cross-chat dedup; case-sensitive dedup; exactly-2 and exactly-1 chips (no seed top-up); brain/blank-skip + all-brain → seed; anonymous → 401.
|
||||
- Fixed stale pre-change pins in `tests/integration/test_api.py` (shape pin no longer assumes ≥3; env-override pin now conditioned on empty `saved_chats`, documented as the module's DB exception).
|
||||
- `app/rag/suggestions.py` (deflection "Maybe try") untouched; its suites green.
|
||||
|
||||
Results: `uv run pytest --cov=app --cov-report=term` → 1637 passed, app/ coverage 99% (suggestions.py 100%); `uv run ruff check .` clean; `uv run pyright` → 0 errors.
|
||||
|
||||
No deviations. Dev DB left as found (saved_chats empty). Next pending task: `02_seed_semantics_docs.md`.
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 21%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 30%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 39%]
|
||||
........................................................................ [ 43%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 52%]
|
||||
........................................................................ [ 57%]
|
||||
........................................................................ [ 61%]
|
||||
........................................................................ [ 65%]
|
||||
........................................................................ [ 70%]
|
||||
........................................................................ [ 74%]
|
||||
........................................................................ [ 79%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 87%]
|
||||
........................................................................ [ 92%]
|
||||
........................................................................ [ 96%]
|
||||
..................................................... [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 40 0 100%
|
||||
app/api/chat.py 178 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 212 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 29 0 100%
|
||||
app/api/sync.py 101 0 100%
|
||||
app/api/tokens.py 28 0 100%
|
||||
app/config.py 140 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 45 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/core/tokens.py 33 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 62 0 100%
|
||||
app/models.py 94 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 222 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 216 0 100%
|
||||
app/rag/overview.py 71 0 100%
|
||||
app/rag/prompts.py 88 0 100%
|
||||
app/rag/retriever.py 150 3 98%
|
||||
app/rag/scaffolding.py 55 0 100%
|
||||
app/rag/source_removal.py 41 0 100%
|
||||
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 231 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 3154 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
Task 02 complete. All four doc sites updated (docs-only, no behavior change):
|
||||
|
||||
- **`app/config.py`** — comment block above `suggestions: list[str]` now documents the SEED semantics: shown only while no saved chat has ever asked a question; afterwards `GET /api/suggestions` serves the last 3 questions (deployment-wide, newest first); `BOR_SUGGESTIONS` overrides the seed. Default list untouched.
|
||||
- **`.env.example:55`** — comment now reads "JSON seed chips — shown only before any question has been saved (phase 80)".
|
||||
- **`README.md` env-table row** — "JSON seed for the onboarding chips — shown only before the first saved question; afterwards the chips are the last 3 questions asked (phase 80)".
|
||||
- **`README.md` chat feature description** — one sentence added: onboarding chips follow the last 3 questions asked, seeding from `BOR_SUGGESTIONS` on a fresh deployment. Deflection note and access-table row left as-is (unchanged contracts).
|
||||
|
||||
**Verification:**
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → 1637 passed, `app/` coverage **99%** (>90% gate)
|
||||
- `uv run ruff check .` → All checks passed
|
||||
- `uv run pyright` → 0 errors, 0 warnings
|
||||
|
||||
**Notable:** no defects found; deflection contract (`app/rag/suggestions.py` + suites) green and untouched. The e2e story-suite rewrite for the new chip semantics remains deferred to task 04 per the phase plan (phase-76 precedent), so the old-contract e2e pins are expected to go until then.
|
||||
|
||||
**Next pending task:** `03_chips_new_chat_refetch.md` (app.js refetch on New chat + source pin).
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 21%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 30%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 39%]
|
||||
........................................................................ [ 43%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 52%]
|
||||
........................................................................ [ 57%]
|
||||
........................................................................ [ 61%]
|
||||
........................................................................ [ 65%]
|
||||
........................................................................ [ 70%]
|
||||
........................................................................ [ 74%]
|
||||
........................................................................ [ 79%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 87%]
|
||||
........................................................................ [ 92%]
|
||||
........................................................................ [ 96%]
|
||||
..................................................... [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 40 0 100%
|
||||
app/api/chat.py 178 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 212 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 29 0 100%
|
||||
app/api/sync.py 101 0 100%
|
||||
app/api/tokens.py 28 0 100%
|
||||
app/config.py 140 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 45 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/core/tokens.py 33 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 62 0 100%
|
||||
app/models.py 94 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 222 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 216 0 100%
|
||||
app/rag/overview.py 71 0 100%
|
||||
app/rag/prompts.py 88 0 100%
|
||||
app/rag/retriever.py 150 3 98%
|
||||
app/rag/scaffolding.py 55 0 100%
|
||||
app/rag/source_removal.py 41 0 100%
|
||||
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 231 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 3154 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
Task 03 complete — all gates green.
|
||||
|
||||
**Implemented**
|
||||
- `frontend/assets/app.js`: `startNewChat()` (the `bor:new-chat` handler) now calls `loadSuggestions()` right after the empty state is restored — the onboarding chips refetch `/api/suggestions` so the row reflects the current last-3 state, never the stale boot fetch. Progressive enhancement unchanged (swallows 401/network failures); boot path untouched; in-flight-turn guard still exempts a live turn.
|
||||
- `tests/unit/test_chat_persistence.py`: source pin in `test_new_chat_clears_key_and_ui` — containment assertion that `loadSuggestions()` appears in the `startNewChat` function-body slice (house style, two literals).
|
||||
|
||||
**Test / lint / coverage**
|
||||
- `node --check frontend/assets/app.js` — valid JS
|
||||
- `uv run pytest -q` (unit + integration) — exit 0, all passed
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` — TOTAL **99%** (>90% floor)
|
||||
- `uv run ruff check .` — All checks passed; `uv run pyright` — 0 errors
|
||||
- `uv run pytest tests/unit/test_chat_persistence.py::test_new_chat_clears_key_and_ui` — passed
|
||||
|
||||
**Decisions / notes**
|
||||
- Pin placed in `test_chat_persistence.py` (the existing `startNewChat` body-slice pin — the file the task names first).
|
||||
- `.agents/PLAN.md` is absent from the repo; the phase files carry the binding decisions (no deviation).
|
||||
- E2E refetch assertion belongs to task 04's suite (per task file); no other files touched. My diff is only the 2 files above (working tree also carries uncommitted harness work from phases 77–79, left as-is).
|
||||
|
||||
**Next pending task:** `.agents/phases/todo/80_history_suggestion_chips/04_e2e_suite_commit.md`
|
||||
+215
@@ -0,0 +1,215 @@
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 21%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 30%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 39%]
|
||||
........................................................................ [ 43%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 52%]
|
||||
........................................................................ [ 57%]
|
||||
........................................................................ [ 61%]
|
||||
........................................................................ [ 65%]
|
||||
........................................................................ [ 70%]
|
||||
........................................................................ [ 74%]
|
||||
........................................................................ [ 79%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 87%]
|
||||
........................................................................ [ 92%]
|
||||
........................................................................ [ 96%]
|
||||
..................................................... [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 40 0 100%
|
||||
app/api/chat.py 178 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 212 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 29 0 100%
|
||||
app/api/sync.py 101 0 100%
|
||||
app/api/tokens.py 28 0 100%
|
||||
app/config.py 140 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 45 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/core/tokens.py 33 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 62 0 100%
|
||||
app/models.py 94 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 222 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 216 0 100%
|
||||
app/rag/overview.py 71 0 100%
|
||||
app/rag/prompts.py 88 0 100%
|
||||
app/rag/retriever.py 150 3 98%
|
||||
app/rag/scaffolding.py 55 0 100%
|
||||
app/rag/source_removal.py 41 0 100%
|
||||
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 231 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 3154 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
I001 [*] Import block is un-sorted or un-formatted
|
||||
--> tests/e2e/test_toggle_after_nav.py:2:1
|
||||
|
|
||||
1 | """Quick diagnostic: does the toggle still work after SPA navigation?"""
|
||||
2 | / import pytest
|
||||
3 | | from playwright.sync_api import Browser, expect
|
||||
| |_______________________________________________^
|
||||
4 |
|
||||
5 | def test_toggle_after_spa_nav(browser, app_url, db_ready):
|
||||
|
|
||||
help: Organize imports
|
||||
|
|
||||
4 |
|
||||
5 +
|
||||
6 | def test_toggle_after_spa_nav(browser, app_url, db_ready):
|
||||
|
|
||||
|
||||
F401 [*] `pytest` imported but unused
|
||||
--> tests/e2e/test_toggle_after_nav.py:2:8
|
||||
|
|
||||
1 | """Quick diagnostic: does the toggle still work after SPA navigation?"""
|
||||
2 | import pytest
|
||||
| ^^^^^^
|
||||
3 | from playwright.sync_api import Browser, expect
|
||||
|
|
||||
help: Remove unused import: `pytest`
|
||||
|
|
||||
1 | """Quick diagnostic: does the toggle still work after SPA navigation?"""
|
||||
- import pytest
|
||||
2 | from playwright.sync_api import Browser, expect
|
||||
|
|
||||
|
||||
F401 [*] `playwright.sync_api.Browser` imported but unused
|
||||
--> tests/e2e/test_toggle_after_nav.py:3:33
|
||||
|
|
||||
1 | """Quick diagnostic: does the toggle still work after SPA navigation?"""
|
||||
2 | import pytest
|
||||
3 | from playwright.sync_api import Browser, expect
|
||||
| ^^^^^^^
|
||||
4 |
|
||||
5 | def test_toggle_after_spa_nav(browser, app_url, db_ready):
|
||||
|
|
||||
help: Remove unused import: `playwright.sync_api.Browser`
|
||||
|
|
||||
2 | import pytest
|
||||
- from playwright.sync_api import Browser, expect
|
||||
3 + from playwright.sync_api import expect
|
||||
4 |
|
||||
|
|
||||
|
||||
W293 [*] Blank line contains whitespace
|
||||
--> tests/e2e/test_toggle_after_nav.py:15:1
|
||||
|
|
||||
13 | timeout=10_000,
|
||||
14 | )
|
||||
15 |
|
||||
| ^^^^^^^^
|
||||
16 | # Open the menu
|
||||
17 | page.click("#nav-toggle")
|
||||
|
|
||||
help: Remove whitespace from blank line
|
||||
|
|
||||
14 | )
|
||||
-
|
||||
15 +
|
||||
16 | # Open the menu
|
||||
|
|
||||
|
||||
W293 [*] Blank line contains whitespace
|
||||
--> tests/e2e/test_toggle_after_nav.py:19:1
|
||||
|
|
||||
17 | page.click("#nav-toggle")
|
||||
18 | expect(page.locator("#nav-toggle")).to_have_attribute("aria-expanded", "true")
|
||||
19 |
|
||||
| ^^^^^^^^
|
||||
20 | # Navigate to a different view via SPA
|
||||
21 | page.click("#nav-sources")
|
||||
|
|
||||
help: Remove whitespace from blank line
|
||||
|
|
||||
18 | expect(page.locator("#nav-toggle")).to_have_attribute("aria-expanded", "true")
|
||||
-
|
||||
19 +
|
||||
20 | # Navigate to a different view via SPA
|
||||
|
|
||||
|
||||
W293 [*] Blank line contains whitespace
|
||||
--> tests/e2e/test_toggle_after_nav.py:23:1
|
||||
|
|
||||
21 | page.click("#nav-sources")
|
||||
22 | expect(page).to_have_url(app_url + "/sources.html", timeout=15_000)
|
||||
23 |
|
||||
| ^^^^^^^^
|
||||
24 | # Menu should be closed
|
||||
25 | expect(page.locator("#nav-toggle")).to_have_attribute("aria-expanded", "false")
|
||||
|
|
||||
help: Remove whitespace from blank line
|
||||
|
|
||||
22 | expect(page).to_have_url(app_url + "/sources.html", timeout=15_000)
|
||||
-
|
||||
23 +
|
||||
24 | # Menu should be closed
|
||||
|
|
||||
|
||||
W293 [*] Blank line contains whitespace
|
||||
--> tests/e2e/test_toggle_after_nav.py:26:1
|
||||
|
|
||||
24 | # Menu should be closed
|
||||
25 | expect(page.locator("#nav-toggle")).to_have_attribute("aria-expanded", "false")
|
||||
26 |
|
||||
| ^^^^^^^^
|
||||
27 | # NOW try to open the menu again - THIS IS THE BUG CHECK
|
||||
28 | page.click("#nav-toggle")
|
||||
|
|
||||
help: Remove whitespace from blank line
|
||||
|
|
||||
25 | expect(page.locator("#nav-toggle")).to_have_attribute("aria-expanded", "false")
|
||||
-
|
||||
26 +
|
||||
27 | # NOW try to open the menu again - THIS IS THE BUG CHECK
|
||||
|
|
||||
|
||||
E501 Line too long (104 > 100)
|
||||
--> tests/e2e/test_toggle_after_nav.py:30:101
|
||||
|
|
||||
28 | page.click("#nav-toggle")
|
||||
29 | try:
|
||||
30 | expect(page.locator("#nav-toggle")).to_have_attribute("aria-expanded", "true", timeout=3000)
|
||||
| ^^^^
|
||||
31 | print("PASS: Toggle still works after SPA navigation")
|
||||
32 | except Exception as e:
|
||||
|
|
||||
|
||||
Found 8 errors.
|
||||
[*] 7 fixable with the `--fix` option.
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation FAILED (see output above)
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
Everything is green — the only "error" match is pyright's "0 errors" line.
|
||||
|
||||
**Fixed**
|
||||
- `tests/e2e/test_toggle_after_nav.py` (stray diagnostic file, pre-existing lint debt that failed the harness gate): removed unused imports (`pytest`, `Browser`), fixed the isort order (third-party `playwright` block, then first-party `e2e.auth_helpers` — house style), stripped whitespace-only lines, wrapped the >100-char `expect(...)` line. Preserved the file's current semantics (phase-79 `login(page, app_url, next="/")` admin wait — the variant present on disk).
|
||||
|
||||
**Test / lint / coverage**
|
||||
- `bash .agents/validate.sh` (the harness gate) — **exit 0, "validation OK"**
|
||||
- Inside it: `uv run pytest --cov=app` — all unit + integration passed; TOTAL **99%** (>90% floor)
|
||||
- `uv run ruff check .` — All checks passed; `uv run pyright` — 0 errors
|
||||
|
||||
**Decisions / notes**
|
||||
- The diagnostic file was being updated concurrently (a parallel process overwrote my first fix with the `login`-helper variant); I lint-cleaned that on-disk variant instead and re-validated immediately — final state verified green.
|
||||
- Task-03 work (app.js `loadSuggestions()` in `startNewChat()` + the source pin in `test_chat_persistence.py`) remains in the tree, untouched and green.
|
||||
|
||||
**Next pending task:** `.agents/phases/todo/80_history_suggestion_chips/04_e2e_suite_commit.md`
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 21%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 30%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 39%]
|
||||
........................................................................ [ 43%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 52%]
|
||||
........................................................................ [ 57%]
|
||||
........................................................................ [ 61%]
|
||||
........................................................................ [ 65%]
|
||||
........................................................................ [ 70%]
|
||||
........................................................................ [ 74%]
|
||||
........................................................................ [ 79%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 87%]
|
||||
........................................................................ [ 92%]
|
||||
........................................................................ [ 96%]
|
||||
..................................................... [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 40 0 100%
|
||||
app/api/chat.py 178 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 212 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 29 0 100%
|
||||
app/api/sync.py 101 0 100%
|
||||
app/api/tokens.py 28 0 100%
|
||||
app/config.py 140 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 45 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/core/tokens.py 33 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 62 0 100%
|
||||
app/models.py 94 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 222 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 216 0 100%
|
||||
app/rag/overview.py 71 0 100%
|
||||
app/rag/prompts.py 88 0 100%
|
||||
app/rag/retriever.py 150 3 98%
|
||||
app/rag/scaffolding.py 55 0 100%
|
||||
app/rag/source_removal.py 41 0 100%
|
||||
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 231 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 3154 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 04 complete — all gates green. Report:
|
||||
|
||||
**Implemented**
|
||||
- Rewrote `tests/e2e/test_suggestion_chips.py` (7 tests) to the phase-80 contract: **seed** state (chips == exact `SEED` literal copied from the `Settings.suggestions` default, role=list/buttons/style pins), **last-3** (2 chats via `POST /api/chats`, 5 questions, older saved first → fresh load shows exactly the 3 newest, newest-first), **partial** (2 saved questions → exactly 2 chips, no seed top-up), **new-chat refetch** (click `#new-chat-btn` → chips become Q + a second `GET /api/suggestions` in the request log, timestamped after the click) — plus carried-over one-tap submit, Tab+Enter keyboard walk, and the mobile single-scroll-row contract.
|
||||
- Added an autouse `clean_chats` fixture truncating `saved_chats` before/after every test — this also fixed pre-existing defects I found: the old suite (unmodified by prior tasks) was already failing 2/4 because auto-saved chat rows leaked between tests and the new DB-derived contract turned them into 1 deduped chip.
|
||||
|
||||
**Results**
|
||||
- `uv run pytest tests/e2e/test_suggestion_chips.py -v --no-cov` → 7 passed (green in isolation, repeated runs stable)
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → 1637 passed, **99%** on `app/` (`app/api/suggestions.py` 100%)
|
||||
- `uv run ruff check .` → clean; `uv run pyright` → 0 errors
|
||||
- Deflection untouched: `app/rag/suggestions.py` has no diff; `uv run pytest tests/e2e/test_honest_deflection.py --no-cov` → 3 passed
|
||||
|
||||
**Notes**
|
||||
- No `git add`/`commit` and no phase-dir move performed — the harness owns the atomic commit and the move (overrides the task's commit step).
|
||||
- Playwright's `APIRequestContext.post` in this version has no `json=` kwarg — JSON is sent via `data=` + `Content-Type: application/json`.
|
||||
|
||||
**Next pending task:** none — task 04 was the final task; phase 80 is complete, awaiting the harness commit.
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 21%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 30%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 39%]
|
||||
........................................................................ [ 43%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 52%]
|
||||
........................................................................ [ 57%]
|
||||
........................................................................ [ 61%]
|
||||
........................................................................ [ 65%]
|
||||
........................................................................ [ 70%]
|
||||
........................................................................ [ 74%]
|
||||
........................................................................ [ 79%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 87%]
|
||||
........................................................................ [ 92%]
|
||||
........................................................................ [ 96%]
|
||||
..................................................... [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 40 0 100%
|
||||
app/api/chat.py 178 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 212 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 29 0 100%
|
||||
app/api/sync.py 101 0 100%
|
||||
app/api/tokens.py 28 0 100%
|
||||
app/config.py 140 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 45 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/core/tokens.py 33 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 62 0 100%
|
||||
app/models.py 94 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 222 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 216 0 100%
|
||||
app/rag/overview.py 71 0 100%
|
||||
app/rag/prompts.py 88 0 100%
|
||||
app/rag/retriever.py 150 3 98%
|
||||
app/rag/scaffolding.py 55 0 100%
|
||||
app/rag/source_removal.py 41 0 100%
|
||||
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 231 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 3154 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