diff --git a/.agents/phases/todo/165_prose_word_wrap/00_phase.md b/.agents/phases/complete/165_prose_word_wrap/00_phase.md similarity index 100% rename from .agents/phases/todo/165_prose_word_wrap/00_phase.md rename to .agents/phases/complete/165_prose_word_wrap/00_phase.md diff --git a/.agents/phases/todo/165_prose_word_wrap/01_doc_prose_block.md b/.agents/phases/complete/165_prose_word_wrap/01_doc_prose_block.md similarity index 100% rename from .agents/phases/todo/165_prose_word_wrap/01_doc_prose_block.md rename to .agents/phases/complete/165_prose_word_wrap/01_doc_prose_block.md diff --git a/.agents/phases/todo/165_prose_word_wrap/02_raw_scroll_pins.md b/.agents/phases/complete/165_prose_word_wrap/02_raw_scroll_pins.md similarity index 100% rename from .agents/phases/todo/165_prose_word_wrap/02_raw_scroll_pins.md rename to .agents/phases/complete/165_prose_word_wrap/02_raw_scroll_pins.md diff --git a/.agents/phases/todo/165_prose_word_wrap/03_e2e_prose_wrap.md b/.agents/phases/complete/165_prose_word_wrap/03_e2e_prose_wrap.md similarity index 100% rename from .agents/phases/todo/165_prose_word_wrap/03_e2e_prose_wrap.md rename to .agents/phases/complete/165_prose_word_wrap/03_e2e_prose_wrap.md diff --git a/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__00_phase.a1.err b/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__00_phase.a1.err new file mode 100644 index 0000000..e69de29 diff --git a/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__00_phase.a1.md b/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__00_phase.a1.md new file mode 100644 index 0000000..31e0f33 --- /dev/null +++ b/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__00_phase.a1.md @@ -0,0 +1,14 @@ +All verification complete. Final report: + +**Phase 165 — Prose word wrap (final verification pass)** +- Verified: `PROSE_FORMATS={txt,text}` + `isProseDoc` (single-site, image arm wins); `renderDocument` three-way branch (md → `.doc-md`, prose → `.doc-prose` text node, else `pre.doc-raw` byte-identical); `.doc-prose` CSS = 72rem column, `pre-wrap` + `overflow-wrap: anywhere`, tokens only, zero literals; `[data-view="pages"]` hide list includes `.doc-prose` as one grouped declaration; phase-116 scrollbar rules intact and modal-scoped; no `innerHTML` in the prose path. +- Tests/lint (all 100% green): + - `uv run pytest` → **3854 passed** (unit + integration) + - `uv run pytest --cov=app --cov-report=term-missing` → **TOTAL 99%** (>90%) + - `uv run ruff check .` → All checks passed; `uv run pyright` → **0 errors** + - `uv run pytest tests/e2e/test_prose_word_wrap.py -v --no-cov` → **5 passed** (isolation) + - Isolation regressions: document_viewer 8, image_documents 4, pdf_pages_in_sources 4, pdf_strip_additive_selfheal 5, edit_summaries 4, summary_in_viewer 4, chat_answer_clusters 4, garbage_pdf 3, pdf_support 6, sticky_navbar 3, smoke 3 — all passed +- Completion criteria: image description wraps, full text, both surfaces ✔; `.txt` wraps same way ✔; `py`/`json`/code keep `pre.doc-raw` + horizontal overflow + themed modal scrollbar (E2E negative control + pins) ✔; no innerHTML, AA `--ink`/`--surface` pair ✔; full gates green ✔; commit + phase-dir move are harness-owned (not executed per pipeline rules). +- Documentation: README already updated by task 03 (viewer section + image-docs section); full README/AGENTS.md review found no further inconsistencies — **verified consistent, no changes needed**. +- Notable deviations: `.doc-prose` omits `font-family: inherit` from 00_phase D2's snippet — task 01's authoritative "exact property set" excludes it and `div` inherits fonts anyway (behavior identical). PDF deferral (A4) intact: `format == "pdf"` stays in `.doc-raw`, owner call recorded. +- Next pending phase: `166_hide_empty_answer_bubble`. diff --git a/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__00_phase.a1.md.status b/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__00_phase.a1.md.status new file mode 100644 index 0000000..9766475 --- /dev/null +++ b/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__00_phase.a1.md.status @@ -0,0 +1 @@ +ok diff --git a/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__00_phase.a1.validate b/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__00_phase.a1.validate new file mode 100644 index 0000000..05305d0 --- /dev/null +++ b/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__00_phase.a1.validate @@ -0,0 +1,125 @@ +........................................................................ [ 1%] +........................................................................ [ 3%] +........................................................................ [ 5%] +........................................................................ [ 7%] +........................................................................ [ 9%] +........................................................................ [ 11%] +........................................................................ [ 13%] +........................................................................ [ 14%] +........................................................................ [ 16%] +........................................................................ [ 18%] +........................................................................ [ 20%] +........................................................................ [ 22%] +........................................................................ [ 24%] +........................................................................ [ 26%] +........................................................................ [ 28%] +........................................................................ [ 29%] +........................................................................ [ 31%] +........................................................................ [ 33%] +........................................................................ [ 35%] +........................................................................ [ 37%] +........................................................................ [ 39%] +........................................................................ [ 41%] +........................................................................ [ 42%] +........................................................................ [ 44%] +........................................................................ [ 46%] +........................................................................ [ 48%] +........................................................................ [ 50%] +........................................................................ [ 52%] +........................................................................ [ 54%] +........................................................................ [ 56%] +........................................................................ [ 57%] +........................................................................ [ 59%] +........................................................................ [ 61%] +........................................................................ [ 63%] +........................................................................ [ 65%] +........................................................................ [ 67%] +........................................................................ [ 69%] +........................................................................ [ 70%] +........................................................................ [ 72%] +........................................................................ [ 74%] +........................................................................ [ 76%] +........................................................................ [ 78%] +........................................................................ [ 80%] +........................................................................ [ 82%] +........................................................................ [ 84%] +........................................................................ [ 85%] +........................................................................ [ 87%] +........................................................................ [ 89%] +........................................................................ [ 91%] +........................................................................ [ 93%] +........................................................................ [ 95%] +........................................................................ [ 97%] +........................................................................ [ 99%] +...................................... [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 277 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 196 1 99% +app/api/git_sources.py 259 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 204 0 100% +app/api/tokens.py 40 0 100% +app/api/ui_settings.py 55 0 100% +app/config.py 266 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 136 0 100% +app/rag/__init__.py 0 0 100% +app/rag/agent.py 454 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 77 0 100% +app/rag/importer.py 841 4 99% +app/rag/llm.py 246 1 99% +app/rag/md_images.py 63 0 100% +app/rag/overview.py 78 0 100% +app/rag/pdf.py 192 0 100% +app/rag/prompts.py 156 0 100% +app/rag/retriever.py 252 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 58 0 100% +app/schemas.py 487 0 100% +-------------------------------------------------- +TOTAL 5883 17 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/165_prose_word_wrap/165_prose_word_wrap__01_doc_prose_block.a1.err b/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__01_doc_prose_block.a1.err new file mode 100644 index 0000000..e69de29 diff --git a/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__01_doc_prose_block.a1.md b/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__01_doc_prose_block.a1.md new file mode 100644 index 0000000..b559b1f --- /dev/null +++ b/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__01_doc_prose_block.a1.md @@ -0,0 +1,16 @@ +**Task 01 complete — all gates green.** + +**Implemented** +- `frontend/assets/document.js`: `PROSE_FORMATS = new Set(["txt","text"])` + `isProseDoc()` (the ONE prose rule, locked A1; image arm unconditional per phase 122 A3); `renderDocument`'s content branch is now three-way — md → `.doc-md` (byte-identical), prose → `
` via `textContent` (never innerHTML), else → `
` (byte-identical); same `slot`, so image block/summary/additive strip order is preserved.
+- `frontend/assets/styles.css`: new `.doc-prose` right after `.doc-raw` (72rem `var(--chat-column)` column, `pre-wrap` + `overflow-wrap: anywhere`, tokens only, zero literals, no animation); `.doc-prose` joined the `[data-view="pages"]` hide list (one grouped declaration, defensive-today comment); stale `.doc-raw`/header comments updated (also `document-modal.js`).
+
+**Tests / gates (exact)**
+- `uv run pytest` → **3844 passed** (incl. new: isProseDoc 26-case node truth table, renderDocument format table `txt/text→doc-prose`, `md→doc-md`, `py/yaml/yml/json/j2/conf/pdf/quadlet/""/unknown→doc-raw`, image→`["doc-image","doc-prose"]`, prose-arm never-innerHTML pin, `.doc-prose`/`.doc-raw` CSS pins, hide-list + wide-column 7→8 updates).
+- `uv run pytest --cov=app` → **TOTAL 99%** (>90, unchanged); `uv run ruff check . && uv run pyright` → clean.
+- Isolated E2E (all 25 viewer-touching suites + reasoning/timeline/answer_images): all passed, incl. re-run `test_document_viewer` (8), `test_image_documents` (4), `test_pdf_support` (6), `test_chat_answer_clusters` (4).
+
+**Pre-existing defects fixed** (all fail identically on clean HEAD): image-modal selectors `pre.doc-raw`→`.doc-prose` (3 suites); phase-116 scroll fixture re-seeded `.txt`→`.json` per this phase's task-03 migration (code proof stays on the locked raw path); `test_chat_answer_clusters` msg-body pins re-targeted to the phase-161 reasoning container (+ tool record inside); `test_sticky_navbar` re-targeted to phase 156's bounded catalogue card (test-only, deep-scroll proof named as test 2).
+
+**Docs**: README updated (viewer content-by-kind contract; image description wraps). AGENTS.md: no change needed.
+
+**Next pending task**: `165_prose_word_wrap/02_raw_scroll_pins.md`.
diff --git a/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__01_doc_prose_block.a1.md.status b/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__01_doc_prose_block.a1.md.status
new file mode 100644
index 0000000..9766475
--- /dev/null
+++ b/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__01_doc_prose_block.a1.md.status
@@ -0,0 +1 @@
+ok
diff --git a/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__01_doc_prose_block.a1.validate b/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__01_doc_prose_block.a1.validate
new file mode 100644
index 0000000..e1ee581
--- /dev/null
+++ b/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__01_doc_prose_block.a1.validate
@@ -0,0 +1,125 @@
+........................................................................ [  1%]
+........................................................................ [  3%]
+........................................................................ [  5%]
+........................................................................ [  7%]
+........................................................................ [  9%]
+........................................................................ [ 11%]
+........................................................................ [ 13%]
+........................................................................ [ 14%]
+........................................................................ [ 16%]
+........................................................................ [ 18%]
+........................................................................ [ 20%]
+........................................................................ [ 22%]
+........................................................................ [ 24%]
+........................................................................ [ 26%]
+........................................................................ [ 28%]
+........................................................................ [ 29%]
+........................................................................ [ 31%]
+........................................................................ [ 33%]
+........................................................................ [ 35%]
+........................................................................ [ 37%]
+........................................................................ [ 39%]
+........................................................................ [ 41%]
+........................................................................ [ 43%]
+........................................................................ [ 44%]
+........................................................................ [ 46%]
+........................................................................ [ 48%]
+........................................................................ [ 50%]
+........................................................................ [ 52%]
+........................................................................ [ 54%]
+........................................................................ [ 56%]
+........................................................................ [ 58%]
+........................................................................ [ 59%]
+........................................................................ [ 61%]
+........................................................................ [ 63%]
+........................................................................ [ 65%]
+........................................................................ [ 67%]
+........................................................................ [ 69%]
+........................................................................ [ 71%]
+........................................................................ [ 73%]
+........................................................................ [ 74%]
+........................................................................ [ 76%]
+........................................................................ [ 78%]
+........................................................................ [ 80%]
+........................................................................ [ 82%]
+........................................................................ [ 84%]
+........................................................................ [ 86%]
+........................................................................ [ 88%]
+........................................................................ [ 89%]
+........................................................................ [ 91%]
+........................................................................ [ 93%]
+........................................................................ [ 95%]
+........................................................................ [ 97%]
+........................................................................ [ 99%]
+............................                                             [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                  277      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                  196      1    99%
+app/api/git_sources.py           259      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                  204      0   100%
+app/api/tokens.py                 40      0   100%
+app/api/ui_settings.py            55      0   100%
+app/config.py                    266      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                    136      0   100%
+app/rag/__init__.py                0      0   100%
+app/rag/agent.py                 454      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            77      0   100%
+app/rag/importer.py              841      4    99%
+app/rag/llm.py                   246      1    99%
+app/rag/md_images.py              63      0   100%
+app/rag/overview.py               78      0   100%
+app/rag/pdf.py                   192      0   100%
+app/rag/prompts.py               156      0   100%
+app/rag/retriever.py             252      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             58      0   100%
+app/schemas.py                   487      0   100%
+--------------------------------------------------
+TOTAL                           5883     17    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/165_prose_word_wrap/165_prose_word_wrap__02_raw_scroll_pins.a1.err b/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__02_raw_scroll_pins.a1.err
new file mode 100644
index 0000000..e69de29
diff --git a/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__02_raw_scroll_pins.a1.md b/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__02_raw_scroll_pins.a1.md
new file mode 100644
index 0000000..60e6a15
--- /dev/null
+++ b/.agents/reports/165_prose_word_wrap/165_prose_word_wrap__02_raw_scroll_pins.a1.md
@@ -0,0 +1,19 @@
+All gates green. Final state:
+
+**Implemented** (task `165_prose_word_wrap/02_raw_scroll_pins.md`)
+- New `tests/unit/test_prose_word_wrap.py` — 10 static-source pins (no app/browser): prose set is exactly `{"txt","text"}` (parsed from the `PROSE_FORMATS` literal) + `isProseDoc` reads `doc.is_image === true` **first**; `.doc-raw` keeps `white-space: pre` + `overflow-x: auto`; `.bubble pre` keeps `overflow-x: auto` with no `white-space` added; `.md-table-wrap` byte-identical (`{ overflow-x: auto; }`) and `.md-table` keeps `min-width: max-content`; all four phase-116 `.doc-modal .doc-raw` scrollbar rules present **and** scope-pinned (every scrollbar-themed rule in the file starts with `.doc-modal .doc-raw`); `.doc-prose` has no `overflow-x` and no bare `pre`; AA pin `var(--ink)` on `var(--surface)` with zero hex/rgb/hsl/color-mix literals; the `[data-view="pages"]` hide list still holds `.doc-prose` in one grouped declaration; and the `doc-raw` writer scan (comments stripped) proving `document.js`'s raw arm + `styles.css` are the only writers.
+- Hygiene finding recorded in the module docstring (step 3): `doc-edit.js` fills a `