diff --git a/.agents/phases/todo/128_sync_label_mobile/00_phase.md b/.agents/phases/complete/128_sync_label_mobile/00_phase.md similarity index 100% rename from .agents/phases/todo/128_sync_label_mobile/00_phase.md rename to .agents/phases/complete/128_sync_label_mobile/00_phase.md diff --git a/.agents/phases/todo/128_sync_label_mobile/01_label_parts.md b/.agents/phases/complete/128_sync_label_mobile/01_label_parts.md similarity index 100% rename from .agents/phases/todo/128_sync_label_mobile/01_label_parts.md rename to .agents/phases/complete/128_sync_label_mobile/01_label_parts.md diff --git a/.agents/phases/todo/128_sync_label_mobile/02_mobile_css.md b/.agents/phases/complete/128_sync_label_mobile/02_mobile_css.md similarity index 100% rename from .agents/phases/todo/128_sync_label_mobile/02_mobile_css.md rename to .agents/phases/complete/128_sync_label_mobile/02_mobile_css.md diff --git a/.agents/phases/todo/128_sync_label_mobile/03_e2e_mobile_label.md b/.agents/phases/complete/128_sync_label_mobile/03_e2e_mobile_label.md similarity index 100% rename from .agents/phases/todo/128_sync_label_mobile/03_e2e_mobile_label.md rename to .agents/phases/complete/128_sync_label_mobile/03_e2e_mobile_label.md diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__00_phase.a1.err b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__00_phase.a1.err new file mode 100644 index 0000000..e69de29 diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__00_phase.a1.md b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__00_phase.a1.md new file mode 100644 index 0000000..a55df90 --- /dev/null +++ b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__00_phase.a1.md @@ -0,0 +1,14 @@ +All green. Final report: + +**Phase 128 — final verification pass (all 3 tasks already complete)** +- **Verified implementation**: `#sync-label` split into `.sync-label-main` (ellipsizable) + `.sync-label-count` (pinned, `hidden` when absent); single `setSyncLabel(main, count)` writer; builders return parts; A4 untruncated label still rides button `title` + `#sync-result`; CSS flex-row + mobile `flex: 1 1 auto` media query all match the design 1:1. +- **Completion criteria**: + - Mobile 390×844 label fully in viewport, count visible in import AND summaries — ✅ (E2E bounding-box assertions) + - Desktop byte-identical strings/cap/title — ✅ (E2E + unit pins) + - `uv run pytest tests/e2e/test_sync_label_mobile.py -v --no-cov` in isolation — ✅ 4 passed (119s) + - `uv run pytest` (unit+integration) — ✅ 3024 passed +- **Coverage**: `uv run pytest --cov=app --cov-report=term-missing` → TOTAL **99%** (>90% gate). +- **Lint/types**: `uv run ruff check .` clean; `uv run pyright` → 0 errors. +- **Docs**: README.md — fixed 5 pre-existing gaps: added "PDF documents (phase 126)" section + `pdf` token in indexed-formats/config reference; documented hidden-folders toggle (ph.105), document dates (ph.106), private git-source masked tokens (ph.121, old "no credentials stored" claim corrected), doc-draft Discard (ph.115). AGENTS.md — verified consistent, no changes needed. +- **Notable**: no code defects found; pytest "missing summary line" under double-`-q` is standard `-qq` behavior, not a bug. +- **Next pending phase**: `129_sync_chunk_progress`. diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__00_phase.a1.validate b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__00_phase.a1.validate new file mode 100644 index 0000000..cdd7d1e --- /dev/null +++ b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__00_phase.a1.validate @@ -0,0 +1,113 @@ +........................................................................ [ 2%] +........................................................................ [ 4%] +........................................................................ [ 7%] +........................................................................ [ 9%] +........................................................................ [ 11%] +........................................................................ [ 14%] +........................................................................ [ 16%] +........................................................................ [ 19%] +........................................................................ [ 21%] +........................................................................ [ 23%] +........................................................................ [ 26%] +........................................................................ [ 28%] +........................................................................ [ 30%] +........................................................................ [ 33%] +........................................................................ [ 35%] +........................................................................ [ 38%] +........................................................................ [ 40%] +........................................................................ [ 42%] +........................................................................ [ 45%] +........................................................................ [ 47%] +........................................................................ [ 50%] +........................................................................ [ 52%] +........................................................................ [ 54%] +........................................................................ [ 57%] +........................................................................ [ 59%] +........................................................................ [ 61%] +........................................................................ [ 64%] +........................................................................ [ 66%] +........................................................................ [ 69%] +........................................................................ [ 71%] +........................................................................ [ 73%] +........................................................................ [ 76%] +........................................................................ [ 78%] +........................................................................ [ 80%] +........................................................................ [ 83%] +........................................................................ [ 85%] +........................................................................ [ 88%] +........................................................................ [ 90%] +........................................................................ [ 92%] +........................................................................ [ 95%] +........................................................................ [ 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 52 0 100% +app/api/chat.py 262 1 99% +app/api/chat_images.py 50 0 100% +app/api/chats.py 110 0 100% +app/api/config.py 13 0 100% +app/api/doc_drafts.py 99 0 100% +app/api/docs.py 179 1 99% +app/api/git_sources.py 241 0 100% +app/api/health.py 10 0 100% +app/api/steering.py 42 0 100% +app/api/suggestions.py 33 0 100% +app/api/sync.py 139 0 100% +app/api/tokens.py 40 0 100% +app/api/ui_settings.py 55 0 100% +app/config.py 256 0 100% +app/core/__init__.py 0 0 100% +app/core/auth.py 45 0 100% +app/core/caching.py 124 0 100% +app/core/debugging.py 29 2 93% +app/core/docs_push.py 39 0 100% +app/core/errors.py 5 0 100% +app/core/logging.py 13 0 100% +app/core/rate_limit.py 44 0 100% +app/core/security_headers.py 20 0 100% +app/core/theming.py 38 0 100% +app/core/tokens.py 44 0 100% +app/db.py 22 0 100% +app/main.py 68 0 100% +app/models.py 132 0 100% +app/rag/__init__.py 0 0 100% +app/rag/agent.py 374 1 99% +app/rag/archive_upload.py 134 0 100% +app/rag/chunker.py 220 4 98% +app/rag/doc_dates.py 18 0 100% +app/rag/folder_summaries.py 134 0 100% +app/rag/git_sources.py 38 0 100% +app/rag/importer.py 571 9 98% +app/rag/llm.py 244 1 99% +app/rag/md_images.py 63 0 100% +app/rag/overview.py 71 0 100% +app/rag/pdf.py 81 0 100% +app/rag/prompts.py 144 0 100% +app/rag/retriever.py 248 3 99% +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 49 0 100% +app/schemas.py 400 0 100% +-------------------------------------------------- +TOTAL 5133 22 99% +coverage gate: app/ 99% (>90%) OK +All checks passed! +0 errors, 0 warnings, 0 informations +WARNING: there is a new pyright version available (v1.1.411 -> v1.1.414). +Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest` + +validation OK diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__00_phase.a2.err b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__00_phase.a2.err new file mode 100644 index 0000000..e69de29 diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__00_phase.a2.md b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__00_phase.a2.md new file mode 100644 index 0000000..dfc7caa --- /dev/null +++ b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__00_phase.a2.md @@ -0,0 +1,11 @@ +Everything verified and 100% green. The earlier rejection was a report-format issue, not a test failure — all work is in the working tree. Final report: + +**Phase 128 final pass — verified (all 3 tasks complete; no code defects found)** +- Verified: `#sync-label` parts markup, `setSyncLabel` writer, part builders (A4 untruncated title/aria-live), flex-row CSS + mobile media query — all match design 1:1. +- `uv run pytest --cov=app --cov-report=term`: 3024 passed; TOTAL coverage **99%** (>90% gate). +- `uv run pytest tests/e2e/test_sync_label_mobile.py -v --no-cov`: 4 passed (119s, isolated). +- `uv run ruff check .`: clean; `uv run pyright`: 0 errors. +- Criteria: (1) mobile 390×844 label in-viewport, count visible in import+summaries — ✅ E2E; (2) desktop strings/cap/title unchanged — ✅ E2E+unit; (3) E2E isolated green — ✅; (4) full suite green — ✅. +- Docs: README.md fixed 5 pre-existing gaps (PDF phase-126 section + `pdf` token, hidden-folders toggle ph.105, document dates ph.106, private git-source masked tokens ph.121, doc-draft Discard ph.115); AGENTS.md verified consistent — no changes. +- Notable: double-`-q` (addopts `-q` + CLI `-q`) suppresses pytest's summary line — standard `-qq` behavior, not a bug; exit codes confirm green. +- Next pending phase: `129_sync_chunk_progress`. diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__00_phase.a2.validate b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__00_phase.a2.validate new file mode 100644 index 0000000..cdd7d1e --- /dev/null +++ b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__00_phase.a2.validate @@ -0,0 +1,113 @@ +........................................................................ [ 2%] +........................................................................ [ 4%] +........................................................................ [ 7%] +........................................................................ [ 9%] +........................................................................ [ 11%] +........................................................................ [ 14%] +........................................................................ [ 16%] +........................................................................ [ 19%] +........................................................................ [ 21%] +........................................................................ [ 23%] +........................................................................ [ 26%] +........................................................................ [ 28%] +........................................................................ [ 30%] +........................................................................ [ 33%] +........................................................................ [ 35%] +........................................................................ [ 38%] +........................................................................ [ 40%] +........................................................................ [ 42%] +........................................................................ [ 45%] +........................................................................ [ 47%] +........................................................................ [ 50%] +........................................................................ [ 52%] +........................................................................ [ 54%] +........................................................................ [ 57%] +........................................................................ [ 59%] +........................................................................ [ 61%] +........................................................................ [ 64%] +........................................................................ [ 66%] +........................................................................ [ 69%] +........................................................................ [ 71%] +........................................................................ [ 73%] +........................................................................ [ 76%] +........................................................................ [ 78%] +........................................................................ [ 80%] +........................................................................ [ 83%] +........................................................................ [ 85%] +........................................................................ [ 88%] +........................................................................ [ 90%] +........................................................................ [ 92%] +........................................................................ [ 95%] +........................................................................ [ 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 52 0 100% +app/api/chat.py 262 1 99% +app/api/chat_images.py 50 0 100% +app/api/chats.py 110 0 100% +app/api/config.py 13 0 100% +app/api/doc_drafts.py 99 0 100% +app/api/docs.py 179 1 99% +app/api/git_sources.py 241 0 100% +app/api/health.py 10 0 100% +app/api/steering.py 42 0 100% +app/api/suggestions.py 33 0 100% +app/api/sync.py 139 0 100% +app/api/tokens.py 40 0 100% +app/api/ui_settings.py 55 0 100% +app/config.py 256 0 100% +app/core/__init__.py 0 0 100% +app/core/auth.py 45 0 100% +app/core/caching.py 124 0 100% +app/core/debugging.py 29 2 93% +app/core/docs_push.py 39 0 100% +app/core/errors.py 5 0 100% +app/core/logging.py 13 0 100% +app/core/rate_limit.py 44 0 100% +app/core/security_headers.py 20 0 100% +app/core/theming.py 38 0 100% +app/core/tokens.py 44 0 100% +app/db.py 22 0 100% +app/main.py 68 0 100% +app/models.py 132 0 100% +app/rag/__init__.py 0 0 100% +app/rag/agent.py 374 1 99% +app/rag/archive_upload.py 134 0 100% +app/rag/chunker.py 220 4 98% +app/rag/doc_dates.py 18 0 100% +app/rag/folder_summaries.py 134 0 100% +app/rag/git_sources.py 38 0 100% +app/rag/importer.py 571 9 98% +app/rag/llm.py 244 1 99% +app/rag/md_images.py 63 0 100% +app/rag/overview.py 71 0 100% +app/rag/pdf.py 81 0 100% +app/rag/prompts.py 144 0 100% +app/rag/retriever.py 248 3 99% +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 49 0 100% +app/schemas.py 400 0 100% +-------------------------------------------------- +TOTAL 5133 22 99% +coverage gate: app/ 99% (>90%) OK +All checks passed! +0 errors, 0 warnings, 0 informations +WARNING: there is a new pyright version available (v1.1.411 -> v1.1.414). +Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest` + +validation OK diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__01_label_parts.a1.err b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__01_label_parts.a1.err new file mode 100644 index 0000000..e69de29 diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__01_label_parts.a1.md b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__01_label_parts.a1.md new file mode 100644 index 0000000..a10c7b7 --- /dev/null +++ b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__01_label_parts.a1.md @@ -0,0 +1,17 @@ +All green and consistent. Final report: + +**Implemented (task 01 — `#sync-label` parts)** +- `frontend/index.html`: `#sync-label` now ships two child spans — `.sync-label-main` (carries the idle "Sync sources" pre-JS) + `.sync-label-count` (hidden, empty). +- `frontend/assets/sources.js`: new `setSyncLabel(mainText, countText = "")` is the SINGLE label writer (main part textContent; count part textContent + `hidden` toggle — hidden/emptied when absent; the untruncated full label `main + " " + count` on `syncBtn.title` + `#sync-result`, A4). `fmtSyncLabel`/`fmtSyncPhaseLabel` return `{main, count}` (decision trees + byte-identical copy preserved, incl. always-emitted summaries count and bare upload "Importing"); `enterSyncRunningState` and `settleSyncButton` (idle/settle) go through it. textContent only — no HTML strings. +- `tests/unit/test_frontend_sync_upload.py`: label pins re-pointed to the part shape (main/count per state: prelude, import ±total, overview, summaries ±folder, upload, idle/settle; A4 full-string join; hidden toggle; single-writer + no-direct-write pins). `tests/unit/test_sync_button.py`: markup + running/settle pins updated. +- Fixed two existing E2E suites broken by the DOM split (step 8): `test_sync_upload_progress.py` (count-label regexes → new visible concatenation + pinned visible count span + full-space title) and `test_sync_summary_visibility.py` (atomic JS check → main/count part regexes + `title === main + " " + count`). + +**Verification** +- `uv run pytest --cov=app --cov-report=term-missing` → **3024 passed, 0 failed**, `app/` coverage **99%** (>90% gate) +- `uv run ruff check .` → all passed; `uv run pyright` → 0 errors, 0 warnings +- E2E in isolation: `test_sync_button.py` 3 ✓, `test_sync_summary_visibility.py` 3 ✓, `test_sync_upload_progress.py` 4 ✓, `test_sync_model_down.py` 4 ✓, `test_upload_no_scan.py` 3 ✓ +- Node harness: every running/idle/settle full string byte-identical to pre-task; count span hidden whenever absent. + +**Docs:** no doc impact (README's "Syncing…" line stays accurate; AGENTS.md unchanged). +**Decisions:** settled/idle labels now also ride the title + `#sync-result` (the task's unconditional `setSyncLabel` spec — "title + aria-live always carry the whole thing"); visible file↔count space is now the CSS gap (task 02). No live-infra changes. +**Next pending task:** `.agents/phases/todo/128_sync_label_mobile/02_mobile_css.md` diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__01_label_parts.a1.validate b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__01_label_parts.a1.validate new file mode 100644 index 0000000..cdd7d1e --- /dev/null +++ b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__01_label_parts.a1.validate @@ -0,0 +1,113 @@ +........................................................................ [ 2%] +........................................................................ [ 4%] +........................................................................ [ 7%] +........................................................................ [ 9%] +........................................................................ [ 11%] +........................................................................ [ 14%] +........................................................................ [ 16%] +........................................................................ [ 19%] +........................................................................ [ 21%] +........................................................................ [ 23%] +........................................................................ [ 26%] +........................................................................ [ 28%] +........................................................................ [ 30%] +........................................................................ [ 33%] +........................................................................ [ 35%] +........................................................................ [ 38%] +........................................................................ [ 40%] +........................................................................ [ 42%] +........................................................................ [ 45%] +........................................................................ [ 47%] +........................................................................ [ 50%] +........................................................................ [ 52%] +........................................................................ [ 54%] +........................................................................ [ 57%] +........................................................................ [ 59%] +........................................................................ [ 61%] +........................................................................ [ 64%] +........................................................................ [ 66%] +........................................................................ [ 69%] +........................................................................ [ 71%] +........................................................................ [ 73%] +........................................................................ [ 76%] +........................................................................ [ 78%] +........................................................................ [ 80%] +........................................................................ [ 83%] +........................................................................ [ 85%] +........................................................................ [ 88%] +........................................................................ [ 90%] +........................................................................ [ 92%] +........................................................................ [ 95%] +........................................................................ [ 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 52 0 100% +app/api/chat.py 262 1 99% +app/api/chat_images.py 50 0 100% +app/api/chats.py 110 0 100% +app/api/config.py 13 0 100% +app/api/doc_drafts.py 99 0 100% +app/api/docs.py 179 1 99% +app/api/git_sources.py 241 0 100% +app/api/health.py 10 0 100% +app/api/steering.py 42 0 100% +app/api/suggestions.py 33 0 100% +app/api/sync.py 139 0 100% +app/api/tokens.py 40 0 100% +app/api/ui_settings.py 55 0 100% +app/config.py 256 0 100% +app/core/__init__.py 0 0 100% +app/core/auth.py 45 0 100% +app/core/caching.py 124 0 100% +app/core/debugging.py 29 2 93% +app/core/docs_push.py 39 0 100% +app/core/errors.py 5 0 100% +app/core/logging.py 13 0 100% +app/core/rate_limit.py 44 0 100% +app/core/security_headers.py 20 0 100% +app/core/theming.py 38 0 100% +app/core/tokens.py 44 0 100% +app/db.py 22 0 100% +app/main.py 68 0 100% +app/models.py 132 0 100% +app/rag/__init__.py 0 0 100% +app/rag/agent.py 374 1 99% +app/rag/archive_upload.py 134 0 100% +app/rag/chunker.py 220 4 98% +app/rag/doc_dates.py 18 0 100% +app/rag/folder_summaries.py 134 0 100% +app/rag/git_sources.py 38 0 100% +app/rag/importer.py 571 9 98% +app/rag/llm.py 244 1 99% +app/rag/md_images.py 63 0 100% +app/rag/overview.py 71 0 100% +app/rag/pdf.py 81 0 100% +app/rag/prompts.py 144 0 100% +app/rag/retriever.py 248 3 99% +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 49 0 100% +app/schemas.py 400 0 100% +-------------------------------------------------- +TOTAL 5133 22 99% +coverage gate: app/ 99% (>90%) OK +All checks passed! +0 errors, 0 warnings, 0 informations +WARNING: there is a new pyright version available (v1.1.411 -> v1.1.414). +Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest` + +validation OK diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__01_label_parts.a2.err b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__01_label_parts.a2.err new file mode 100644 index 0000000..e69de29 diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__01_label_parts.a2.md b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__01_label_parts.a2.md new file mode 100644 index 0000000..353dcd8 --- /dev/null +++ b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__01_label_parts.a2.md @@ -0,0 +1,15 @@ +All green. Everything verified — final report: + +**Implemented (task 01 — `#sync-label` parts; changes intact from prior attempt, fully re-verified)** +- `frontend/index.html`: `#sync-label` ships `.sync-label-main` (idle "Sync sources" pre-JS) + `.sync-label-count` (hidden, empty). +- `frontend/assets/sources.js`: `setSyncLabel(mainText, countText="")` is the single label writer — parts via textContent (count `hidden` whenever absent), untruncated full label `main + " " + count` on `syncBtn.title` + `#sync-result` (A4); `fmtSyncLabel`/`fmtSyncPhaseLabel` return `{main, count}` (decision trees + byte-identical copy); `enterSyncRunningState` + `settleSyncButton` route through it. No HTML strings. +- Unit pins re-pointed to the part shape (`test_frontend_sync_upload.py`, `test_sync_button.py`); fixed the two E2E suites broken by the DOM split (`test_sync_upload_progress.py`, `test_sync_summary_visibility.py`). + +**Results (exact commands)** +- `uv run pytest --cov=app --cov-report=term-missing` → **3024 passed, 0 failed**; `app/` coverage **99%** (>90% gate) +- `uv run ruff check .` → All checks passed; `uv run pyright` → 0 errors, 0 warnings +- E2E in isolation: `test_sync_button.py` 3 ✓, `test_sync_summary_visibility.py` 3 ✓, `test_sync_upload_progress.py` 4 ✓ (all `--no-cov`) + +**Docs:** no doc impact (README's "Syncing…" line stays accurate; AGENTS.md unchanged). +**Decisions:** settle/idle labels also ride title + `#sync-result` per the task's unconditional `setSyncLabel` spec; the visible file↔count space becomes the CSS gap (task 02's job). No live-infra changes. +**Next pending task:** `.agents/phases/todo/128_sync_label_mobile/02_mobile_css.md` diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__01_label_parts.a2.validate b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__01_label_parts.a2.validate new file mode 100644 index 0000000..cdd7d1e --- /dev/null +++ b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__01_label_parts.a2.validate @@ -0,0 +1,113 @@ +........................................................................ [ 2%] +........................................................................ [ 4%] +........................................................................ [ 7%] +........................................................................ [ 9%] +........................................................................ [ 11%] +........................................................................ [ 14%] +........................................................................ [ 16%] +........................................................................ [ 19%] +........................................................................ [ 21%] +........................................................................ [ 23%] +........................................................................ [ 26%] +........................................................................ [ 28%] +........................................................................ [ 30%] +........................................................................ [ 33%] +........................................................................ [ 35%] +........................................................................ [ 38%] +........................................................................ [ 40%] +........................................................................ [ 42%] +........................................................................ [ 45%] +........................................................................ [ 47%] +........................................................................ [ 50%] +........................................................................ [ 52%] +........................................................................ [ 54%] +........................................................................ [ 57%] +........................................................................ [ 59%] +........................................................................ [ 61%] +........................................................................ [ 64%] +........................................................................ [ 66%] +........................................................................ [ 69%] +........................................................................ [ 71%] +........................................................................ [ 73%] +........................................................................ [ 76%] +........................................................................ [ 78%] +........................................................................ [ 80%] +........................................................................ [ 83%] +........................................................................ [ 85%] +........................................................................ [ 88%] +........................................................................ [ 90%] +........................................................................ [ 92%] +........................................................................ [ 95%] +........................................................................ [ 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 52 0 100% +app/api/chat.py 262 1 99% +app/api/chat_images.py 50 0 100% +app/api/chats.py 110 0 100% +app/api/config.py 13 0 100% +app/api/doc_drafts.py 99 0 100% +app/api/docs.py 179 1 99% +app/api/git_sources.py 241 0 100% +app/api/health.py 10 0 100% +app/api/steering.py 42 0 100% +app/api/suggestions.py 33 0 100% +app/api/sync.py 139 0 100% +app/api/tokens.py 40 0 100% +app/api/ui_settings.py 55 0 100% +app/config.py 256 0 100% +app/core/__init__.py 0 0 100% +app/core/auth.py 45 0 100% +app/core/caching.py 124 0 100% +app/core/debugging.py 29 2 93% +app/core/docs_push.py 39 0 100% +app/core/errors.py 5 0 100% +app/core/logging.py 13 0 100% +app/core/rate_limit.py 44 0 100% +app/core/security_headers.py 20 0 100% +app/core/theming.py 38 0 100% +app/core/tokens.py 44 0 100% +app/db.py 22 0 100% +app/main.py 68 0 100% +app/models.py 132 0 100% +app/rag/__init__.py 0 0 100% +app/rag/agent.py 374 1 99% +app/rag/archive_upload.py 134 0 100% +app/rag/chunker.py 220 4 98% +app/rag/doc_dates.py 18 0 100% +app/rag/folder_summaries.py 134 0 100% +app/rag/git_sources.py 38 0 100% +app/rag/importer.py 571 9 98% +app/rag/llm.py 244 1 99% +app/rag/md_images.py 63 0 100% +app/rag/overview.py 71 0 100% +app/rag/pdf.py 81 0 100% +app/rag/prompts.py 144 0 100% +app/rag/retriever.py 248 3 99% +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 49 0 100% +app/schemas.py 400 0 100% +-------------------------------------------------- +TOTAL 5133 22 99% +coverage gate: app/ 99% (>90%) OK +All checks passed! +0 errors, 0 warnings, 0 informations +WARNING: there is a new pyright version available (v1.1.411 -> v1.1.414). +Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest` + +validation OK diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__02_mobile_css.a1.err b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__02_mobile_css.a1.err new file mode 100644 index 0000000..e69de29 diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__02_mobile_css.a1.md b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__02_mobile_css.a1.md new file mode 100644 index 0000000..bc3d78b --- /dev/null +++ b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__02_mobile_css.a1.md @@ -0,0 +1,18 @@ +All green. Task 02 is complete. + +**Implemented** +- `frontend/assets/styles.css` — `.sync-label` is now a flex row (`inline-flex; align-items: baseline; gap: 0.35rem; min-width: 0; max-width: min(16rem, 40vw)`); new `.sync-label-main` (the shrinkable ellipsizing part) and `.sync-label-count` (`flex: 0 0 auto`, never clipped, `var(--mono)`); phase-64 comment kept + updated to name the parts +- Mobile 640px block — `.sync-label { max-width: none; flex: 1 1 auto; min-width: 0; }` (label fills the full-width pill; count pinned at the right edge); comment updated; `#sync-result` clip / aria-labels / other rules untouched +- Audit: only base + mobile rules exist; sole stylesheet is `styles.css`; theming is variable-only — B4 byte-identity holds (static CSS, no `ui_settings` dependency) +- Updated the existing CSS pin in `tests/unit/test_frontend_sync_upload.py` to the part shape (container props, main/count blocks, mobile fill rule) +- Verified layout in Chromium at 390×844 and 1440×900: long path ellipsizes, `(n/m)` fully on-screen at the pill's right edge on mobile; desktop label caps at exactly 16rem; short/idle labels unclipped, hidden count takes no space + +**Tests / lint** +- `uv run pytest --cov=app --cov-report=term` → 3024 passed, 0 failed; `app/` TOTAL 99% (>90% gate) +- `uv run ruff check .` → All checks passed; `uv run pyright` → 0 errors, 0 warnings + +**Docs:** no doc impact (pure CSS layout fix to an existing feature; README/AGENTS.md don't reference the label CSS) + +**Deviations:** none — CSS applied verbatim per task; only the stale mobile-block comment sentence was updated alongside the rule. + +**Next pending task:** `.agents/phases/todo/128_sync_label_mobile/03_e2e_mobile_label.md` (the Playwright bounding-box E2E, run in isolation) diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__02_mobile_css.a1.validate b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__02_mobile_css.a1.validate new file mode 100644 index 0000000..cdd7d1e --- /dev/null +++ b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__02_mobile_css.a1.validate @@ -0,0 +1,113 @@ +........................................................................ [ 2%] +........................................................................ [ 4%] +........................................................................ [ 7%] +........................................................................ [ 9%] +........................................................................ [ 11%] +........................................................................ [ 14%] +........................................................................ [ 16%] +........................................................................ [ 19%] +........................................................................ [ 21%] +........................................................................ [ 23%] +........................................................................ [ 26%] +........................................................................ [ 28%] +........................................................................ [ 30%] +........................................................................ [ 33%] +........................................................................ [ 35%] +........................................................................ [ 38%] +........................................................................ [ 40%] +........................................................................ [ 42%] +........................................................................ [ 45%] +........................................................................ [ 47%] +........................................................................ [ 50%] +........................................................................ [ 52%] +........................................................................ [ 54%] +........................................................................ [ 57%] +........................................................................ [ 59%] +........................................................................ [ 61%] +........................................................................ [ 64%] +........................................................................ [ 66%] +........................................................................ [ 69%] +........................................................................ [ 71%] +........................................................................ [ 73%] +........................................................................ [ 76%] +........................................................................ [ 78%] +........................................................................ [ 80%] +........................................................................ [ 83%] +........................................................................ [ 85%] +........................................................................ [ 88%] +........................................................................ [ 90%] +........................................................................ [ 92%] +........................................................................ [ 95%] +........................................................................ [ 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 52 0 100% +app/api/chat.py 262 1 99% +app/api/chat_images.py 50 0 100% +app/api/chats.py 110 0 100% +app/api/config.py 13 0 100% +app/api/doc_drafts.py 99 0 100% +app/api/docs.py 179 1 99% +app/api/git_sources.py 241 0 100% +app/api/health.py 10 0 100% +app/api/steering.py 42 0 100% +app/api/suggestions.py 33 0 100% +app/api/sync.py 139 0 100% +app/api/tokens.py 40 0 100% +app/api/ui_settings.py 55 0 100% +app/config.py 256 0 100% +app/core/__init__.py 0 0 100% +app/core/auth.py 45 0 100% +app/core/caching.py 124 0 100% +app/core/debugging.py 29 2 93% +app/core/docs_push.py 39 0 100% +app/core/errors.py 5 0 100% +app/core/logging.py 13 0 100% +app/core/rate_limit.py 44 0 100% +app/core/security_headers.py 20 0 100% +app/core/theming.py 38 0 100% +app/core/tokens.py 44 0 100% +app/db.py 22 0 100% +app/main.py 68 0 100% +app/models.py 132 0 100% +app/rag/__init__.py 0 0 100% +app/rag/agent.py 374 1 99% +app/rag/archive_upload.py 134 0 100% +app/rag/chunker.py 220 4 98% +app/rag/doc_dates.py 18 0 100% +app/rag/folder_summaries.py 134 0 100% +app/rag/git_sources.py 38 0 100% +app/rag/importer.py 571 9 98% +app/rag/llm.py 244 1 99% +app/rag/md_images.py 63 0 100% +app/rag/overview.py 71 0 100% +app/rag/pdf.py 81 0 100% +app/rag/prompts.py 144 0 100% +app/rag/retriever.py 248 3 99% +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 49 0 100% +app/schemas.py 400 0 100% +-------------------------------------------------- +TOTAL 5133 22 99% +coverage gate: app/ 99% (>90%) OK +All checks passed! +0 errors, 0 warnings, 0 informations +WARNING: there is a new pyright version available (v1.1.411 -> v1.1.414). +Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest` + +validation OK diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__03_e2e_mobile_label.a1.err b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__03_e2e_mobile_label.a1.err new file mode 100644 index 0000000..e69de29 diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__03_e2e_mobile_label.a1.md b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__03_e2e_mobile_label.a1.md new file mode 100644 index 0000000..2daa83d --- /dev/null +++ b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__03_e2e_mobile_label.a1.md @@ -0,0 +1,16 @@ +All green. Final report: + +**Implemented (task 03 — `tests/e2e/test_sync_label_mobile.py`, new)** +- Dedicated mock-only Playwright suite (house pattern from `test_sync_summary_visibility.py`): module SLOW app (port 8164) behind the `slow_llm` proxy (8905, `SLOW_DELAY_S=1.5`), `synclabel/` local source (2 files × `alpha/`+`bravo/` → 3 summary candidates), autouse truncate cleanup +- 4 tests: mobile 390×844 import (label in viewport, `(n/4)` count visible & never clipped, `title` untruncated A4) · mobile summaries (`Summarizing folders…` + `(n/3)` visible, settle hides count) · desktop 1280×800 (pre-phase byte-identical string, 256px `min(16rem,40vw)` cap, count pinned) · pre-phase-CSS bug reproduction (permanent pin check) + +**Test / lint / coverage** +- `uv run pytest tests/e2e/test_sync_label_mobile.py -v --no-cov` → 4 passed (in isolation) +- Combined with `test_sync_button` + `test_sync_summary_visibility` + `test_sync_upload_progress` → 14 passed +- `uv run pytest --cov=app` → 3024 passed, app coverage 99% (>90%) · `uv run ruff check .` clean · `uv run pyright` 0 errors + +**Docs:** no doc impact (no setup/command/API changes; README's sync-button "States" bullet remains accurate) + +**Notable decisions:** added the 4th reproduction test to encode the "mobile tests fail pre-phase" criterion permanently (probe-measured: pre-phase count box 352.9→386.2 fully past the 339.2 clip edge — tests 1–2's pins fail exactly there). Pre-phase CSS injected via CSSOM `insertRule` into the origin stylesheet (A20 CSP blocks `add_style_tag`). Two Playwright quirks handled: object `wait_for_function` results need `.json_value()`; this Chromium build's index-less `insertRule` prepends, so an explicit end index is passed. `_settle` polls the status endpoint for the terminal before the UI settle (informative failures). + +**Next pending task:** phase 128 is complete (01/02/03 done); next is `129_sync_chunk_progress` (00_phase onward, per `todo/` order). diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__03_e2e_mobile_label.a1.validate b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__03_e2e_mobile_label.a1.validate new file mode 100644 index 0000000..cdd7d1e --- /dev/null +++ b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__03_e2e_mobile_label.a1.validate @@ -0,0 +1,113 @@ +........................................................................ [ 2%] +........................................................................ [ 4%] +........................................................................ [ 7%] +........................................................................ [ 9%] +........................................................................ [ 11%] +........................................................................ [ 14%] +........................................................................ [ 16%] +........................................................................ [ 19%] +........................................................................ [ 21%] +........................................................................ [ 23%] +........................................................................ [ 26%] +........................................................................ [ 28%] +........................................................................ [ 30%] +........................................................................ [ 33%] +........................................................................ [ 35%] +........................................................................ [ 38%] +........................................................................ [ 40%] +........................................................................ [ 42%] +........................................................................ [ 45%] +........................................................................ [ 47%] +........................................................................ [ 50%] +........................................................................ [ 52%] +........................................................................ [ 54%] +........................................................................ [ 57%] +........................................................................ [ 59%] +........................................................................ [ 61%] +........................................................................ [ 64%] +........................................................................ [ 66%] +........................................................................ [ 69%] +........................................................................ [ 71%] +........................................................................ [ 73%] +........................................................................ [ 76%] +........................................................................ [ 78%] +........................................................................ [ 80%] +........................................................................ [ 83%] +........................................................................ [ 85%] +........................................................................ [ 88%] +........................................................................ [ 90%] +........................................................................ [ 92%] +........................................................................ [ 95%] +........................................................................ [ 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 52 0 100% +app/api/chat.py 262 1 99% +app/api/chat_images.py 50 0 100% +app/api/chats.py 110 0 100% +app/api/config.py 13 0 100% +app/api/doc_drafts.py 99 0 100% +app/api/docs.py 179 1 99% +app/api/git_sources.py 241 0 100% +app/api/health.py 10 0 100% +app/api/steering.py 42 0 100% +app/api/suggestions.py 33 0 100% +app/api/sync.py 139 0 100% +app/api/tokens.py 40 0 100% +app/api/ui_settings.py 55 0 100% +app/config.py 256 0 100% +app/core/__init__.py 0 0 100% +app/core/auth.py 45 0 100% +app/core/caching.py 124 0 100% +app/core/debugging.py 29 2 93% +app/core/docs_push.py 39 0 100% +app/core/errors.py 5 0 100% +app/core/logging.py 13 0 100% +app/core/rate_limit.py 44 0 100% +app/core/security_headers.py 20 0 100% +app/core/theming.py 38 0 100% +app/core/tokens.py 44 0 100% +app/db.py 22 0 100% +app/main.py 68 0 100% +app/models.py 132 0 100% +app/rag/__init__.py 0 0 100% +app/rag/agent.py 374 1 99% +app/rag/archive_upload.py 134 0 100% +app/rag/chunker.py 220 4 98% +app/rag/doc_dates.py 18 0 100% +app/rag/folder_summaries.py 134 0 100% +app/rag/git_sources.py 38 0 100% +app/rag/importer.py 571 9 98% +app/rag/llm.py 244 1 99% +app/rag/md_images.py 63 0 100% +app/rag/overview.py 71 0 100% +app/rag/pdf.py 81 0 100% +app/rag/prompts.py 144 0 100% +app/rag/retriever.py 248 3 99% +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 49 0 100% +app/schemas.py 400 0 100% +-------------------------------------------------- +TOTAL 5133 22 99% +coverage gate: app/ 99% (>90%) OK +All checks passed! +0 errors, 0 warnings, 0 informations +WARNING: there is a new pyright version available (v1.1.411 -> v1.1.414). +Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest` + +validation OK diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__03_e2e_mobile_label.a2.err b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__03_e2e_mobile_label.a2.err new file mode 100644 index 0000000..e69de29 diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__03_e2e_mobile_label.a2.md b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__03_e2e_mobile_label.a2.md new file mode 100644 index 0000000..7f8f6c1 --- /dev/null +++ b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__03_e2e_mobile_label.a2.md @@ -0,0 +1,14 @@ +Everything is green — the previous rejection was a reporting hiccup, not a test failure (the suite was already in place and passing). Full re-verification this run: + +**Implemented** — `tests/e2e/test_sync_label_mobile.py` (task 03): mock-only Playwright suite on a SLOW module app (slow-proxy `SLOW_DELAY_S=1.5`, own port) with the `synclabel/` local source (4 files, 3 summary candidates): mobile 390×844 import (label in viewport, `(n/4)` count visible/never clipped, A4 `title` untruncated) · mobile summaries (`Summarizing folders…` + `(n/3)` visible, settle hides count) · desktop 1280×800 (pre-phase byte-identical string, 256 px `min(16rem,40vw)` cap) · pre-phase-CSS reproduction test (permanent pin check — its "count not clipped" pins are exactly what tests 1–2 fail against). + +**Results (this run)** +- `uv run pytest tests/e2e/test_sync_label_mobile.py -v --no-cov` → **4 passed** in isolation +- `uv run pytest --cov=app --cov-report=term` → **3024 passed**, app coverage **99%** (>90%) +- `uv run ruff check .` → All checks passed · `uv run pyright` → **0 errors, 0 warnings** + +**Docs:** consistency check run (phase final pass) — no impact; README/AGENTS.md remain accurate. + +**Notable decisions:** pre-phase CSS injected via CSSOM `insertRule` with explicit end index into the origin stylesheet (A20 CSP blocks `add_style_tag`; this Chromium build's index-less `insertRule` prepends). `_settle` polls the status endpoint for the terminal first for informative failures. + +**Next pending task:** phase 128 complete → next is `129_sync_chunk_progress` (per `todo/` order). diff --git a/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__03_e2e_mobile_label.a2.validate b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__03_e2e_mobile_label.a2.validate new file mode 100644 index 0000000..cdd7d1e --- /dev/null +++ b/.agents/reports/128_sync_label_mobile/128_sync_label_mobile__03_e2e_mobile_label.a2.validate @@ -0,0 +1,113 @@ +........................................................................ [ 2%] +........................................................................ [ 4%] +........................................................................ [ 7%] +........................................................................ [ 9%] +........................................................................ [ 11%] +........................................................................ [ 14%] +........................................................................ [ 16%] +........................................................................ [ 19%] +........................................................................ [ 21%] +........................................................................ [ 23%] +........................................................................ [ 26%] +........................................................................ [ 28%] +........................................................................ [ 30%] +........................................................................ [ 33%] +........................................................................ [ 35%] +........................................................................ [ 38%] +........................................................................ [ 40%] +........................................................................ [ 42%] +........................................................................ [ 45%] +........................................................................ [ 47%] +........................................................................ [ 50%] +........................................................................ [ 52%] +........................................................................ [ 54%] +........................................................................ [ 57%] +........................................................................ [ 59%] +........................................................................ [ 61%] +........................................................................ [ 64%] +........................................................................ [ 66%] +........................................................................ [ 69%] +........................................................................ [ 71%] +........................................................................ [ 73%] +........................................................................ [ 76%] +........................................................................ [ 78%] +........................................................................ [ 80%] +........................................................................ [ 83%] +........................................................................ [ 85%] +........................................................................ [ 88%] +........................................................................ [ 90%] +........................................................................ [ 92%] +........................................................................ [ 95%] +........................................................................ [ 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 52 0 100% +app/api/chat.py 262 1 99% +app/api/chat_images.py 50 0 100% +app/api/chats.py 110 0 100% +app/api/config.py 13 0 100% +app/api/doc_drafts.py 99 0 100% +app/api/docs.py 179 1 99% +app/api/git_sources.py 241 0 100% +app/api/health.py 10 0 100% +app/api/steering.py 42 0 100% +app/api/suggestions.py 33 0 100% +app/api/sync.py 139 0 100% +app/api/tokens.py 40 0 100% +app/api/ui_settings.py 55 0 100% +app/config.py 256 0 100% +app/core/__init__.py 0 0 100% +app/core/auth.py 45 0 100% +app/core/caching.py 124 0 100% +app/core/debugging.py 29 2 93% +app/core/docs_push.py 39 0 100% +app/core/errors.py 5 0 100% +app/core/logging.py 13 0 100% +app/core/rate_limit.py 44 0 100% +app/core/security_headers.py 20 0 100% +app/core/theming.py 38 0 100% +app/core/tokens.py 44 0 100% +app/db.py 22 0 100% +app/main.py 68 0 100% +app/models.py 132 0 100% +app/rag/__init__.py 0 0 100% +app/rag/agent.py 374 1 99% +app/rag/archive_upload.py 134 0 100% +app/rag/chunker.py 220 4 98% +app/rag/doc_dates.py 18 0 100% +app/rag/folder_summaries.py 134 0 100% +app/rag/git_sources.py 38 0 100% +app/rag/importer.py 571 9 98% +app/rag/llm.py 244 1 99% +app/rag/md_images.py 63 0 100% +app/rag/overview.py 71 0 100% +app/rag/pdf.py 81 0 100% +app/rag/prompts.py 144 0 100% +app/rag/retriever.py 248 3 99% +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 49 0 100% +app/schemas.py 400 0 100% +-------------------------------------------------- +TOTAL 5133 22 99% +coverage gate: app/ 99% (>90%) OK +All checks passed! +0 errors, 0 warnings, 0 informations +WARNING: there is a new pyright version available (v1.1.411 -> v1.1.414). +Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest` + +validation OK diff --git a/README.md b/README.md index 3517ae2..5781b8b 100644 --- a/README.md +++ b/README.md @@ -83,8 +83,13 @@ fresh deployment they seed from `BOR_SUGGESTIONS`. ### RAG / Knowledge base (`/sources.html`) The indexed document list. The *Path* column opens each document in the same -**almost-fullscreen modal**. Admin-only — anonymous visitors see a sign-in -gate instead. +**almost-fullscreen modal**. Document rows carry a *Created* date and folder +rows an *Updated* date (phase 106) — sourced at sync time (git commit dates +for git sources, restored metadata for archive uploads, file mtime otherwise; +unresolvable or future dates fall back to today) — and the admin can correct a +document's date from the document viewer. The date also feeds the small +recency boost in retrieval ranking (`BOR_RECENCY_BOOST`). Admin-only — +anonymous visitors see a sign-in gate instead. ### Git sources (`/git-sources.html`) @@ -118,7 +123,8 @@ everyone — no login or token required. ### Edit doc (`/doc-edit.html`) Review and adjust an AI-generated answer before committing it to the docs -repository. Admin-only flow page. +repository. A draft that should never be pushed can be **Discard**ed from +the same page (permanent; admin-only). Admin-only flow page. --- @@ -200,9 +206,15 @@ reflect the new files. so it is safe to run from cron or after every commit. - Indexed formats: **md, markdown, txt, yaml, yml, json, py**, the Podman quadlet family (**container, network, volume, image, pod, kube, swap, - os, endpoint**), and **j2** Jinja templates (case-insensitive). + os, endpoint**), **j2** Jinja templates — and, **opt-in**, **pdf** + (add the `pdf` token to `BOR_IMPORT_EXTENSIONS`; see + [PDF documents](#pdf-documents-phase-126)). - Hidden files and common cache dirs (`.venv`, `node_modules`, `.git`, - `__pycache__`, etc.) are skipped. + `__pycache__`, etc.) are skipped — unless the per-source **Index hidden + folders** checkbox on the Git sources page is on for that source + (phase 105): then dot-prefixed folders/files with an importable + extension are indexed like visible ones, and switching it off prunes + them on the next sync. - Non-markdown files get format-aware chunking (YAML keys, JSON keys, Python classes/defs). - With `BOR_IMAGES=1`, standalone images (`png, jpg, jpeg, webp, gif, @@ -227,8 +239,14 @@ BOR_GIT_SOURCES=https://git.reeseapps.com/reese/homelab.git,git@github.com:reese BOR_SOURCES_DIR=~/bor-sources # default; each repo lands in
diff --git a/tests/e2e/test_sync_label_mobile.py b/tests/e2e/test_sync_label_mobile.py
new file mode 100644
index 0000000..03f6fb1
--- /dev/null
+++ b/tests/e2e/test_sync_label_mobile.py
@@ -0,0 +1,816 @@
+"""Phase 128 task 03 E2E (Playwright, mock-only): the RUNNING sync label
+is fully visible at a phone viewport — the file path ellipsizes to fit
+and the ``(n/m)`` count span sits in its own non-shrinking part that is
+NEVER clipped — in BOTH long spans (import + summaries), while desktop
+keeps the pre-phase strings and the ``min(16rem, 40vw)`` cap.
+
+The dedicated story suite for ``128_sync_label_mobile`` (A16 — one
+Playwright file per phase, run in isolation): the owner's report was
+that ``Syncing… name/of/file/here (2/3)`` "doesn't show up on mobile" —
+pre-phase, ``#sync-label`` was ONE inline-block span (whole label
+string, one ellipsis) whose mobile media query LIFTED the
+``min(16rem, 40vw)`` cap (``max-width: none``), so the ellipsized tail
+— where ``(n/m)`` lives — was clipped away on a phone. Phase 128 splits
+the label into two parts (``.sync-label-main`, the shrinkable
+prefix + file/folder, + ``.sync-label-count`, the pinned position) so
+the count is never the ellipsis's sacrifice.
+
+Run in isolation (DB must be up: ``podman compose up -d db``):
+
+ uv run pytest tests/e2e/test_sync_label_mobile.py -v --no-cov
+
+MOCK-ONLY suite: ``E2E_REAL_LLM=1`` is not supported — the gate is the
+deterministic mock plus the phase-64 ``tests/e2e/slow_llm.py`` delay
+proxy that stretches the run past the UI's 2 s status poll, so the
+rendered-label assertions are deterministic, not races.
+
+Timing fixture (the phase-98 sizing rationale, re-sized for this
+suite): ``SLOW_DELAY_S = 1.5`` — the import span (4 file embeds
+≈ 6 s) and the summaries span (3 folder summaries ≈ 4.5 s) each
+outlive the UI's 2 s poll by ≥ 2×, so the page's OWN 2 s poll renders
+each running label and holds it in the DOM for at least one full poll
+period (any window ≥ the period catches it). The whole changed sync is
+≈ 10 LLM calls (2 model probes + 4 file embeds + 1 overview +
+3 folder summaries) ≈ 15–18 s — well inside the generous settle
+budgets.
+
+The suite runs ONE module app (the phase-79 full-inventory pattern —
+it binds its own port) over the shared E2E Postgres: the SLOW app
+(``BOR_LLM_BASE_URL`` = the slow proxy in front of the mock).
+
+KB fixture — a host temp dir (``tmp_path_factory``; the app runs on
+the same host) registered as a ``kind=local`` source (the
+``test_local_directory_sources.py`` / phase-94 API-registration
+pattern; no git anywhere): ``synclabel/`` with TWO files in ``alpha/``
+and TWO in ``bravo/`` — the summaries phase then has 3 candidate
+folders (the source root + the two folders — the recursive-subtree
+≥ 1 rule), a non-trivial ``(n/m)``.
+
+Autouse cleanup (the phase-96 pattern): before each test wait for no
+running sync on the app, then truncate the shared registry + KB
+tables (documents/chunks/query_log/steering_notes/kb_overview/
+git_sources/folder_summaries) — each test seeds its own source and
+runs its own sync; after each test the same truncate.
+
+Test → observable mapping (Playwright Mapping Rule):
+1. ``test_mobile_label_fits_viewport_with_count_in_import`` — admin
+ page on the sources view at viewport **390×844** (mobile); click
+ **Sync sources**; while the import phase is running (the page's
+ own 2 s poll): the rendered ``#sync-label``'s bounding box is
+ INSIDE the viewport (left ≥ 0, right ≤ 390 — the bug's direct
+ negation), and the ``.sync-label-count`` part is VISIBLE (non-null
+ box) and NOT clipped — its right edge sits at or inside the label's
+ right edge and the button's right edge, with text matching
+ ``\\(\\d+/\\d+\\)`` once a file is in flight; ``.sync-label-main``
+ carries ``Syncing…