refactor(agents): migrate .agent/ planning tree to .agents/

Standardize on the .agents/ directory (shared with project skills):
phases/, user_stories/, reports/, screenshots/, validate.sh, and
phase-sessions/ + pipeline.log all move to .agents/ (git mv preserves
history; runtime artifacts move alongside).

Updates every reference in AGENTS.md, README.md, .gitignore, app
docstrings, and test story headers. Historical KB content in data/
and the runtime pipeline.log transcript are left untouched.
This commit is contained in:
2026-09-05 10:57:07 -04:00
parent 766702c750
commit dbf2af26c6
1118 changed files with 664 additions and 664 deletions
@@ -0,0 +1,19 @@
All verification complete — everything is green. Final report:
**Phase 55 (save/share UX) — final verification pass: all green, no defects found.**
- Verified anonymous write surface in `app/api/chats.py`: create/PUT/share ungated; list/detail/delete/unshare keep `require_admin`
- Verified frontend pins: no Save control anywhere (HTML/CSS/JS), `chatId` persisted in `bor.chat.v1` record, `showToast` on both share-success paths, `.toast` top-right + reduced-motion rule, `.chat-actions` row (desktop) → column (≤640px, line 2743)
- E2E suite covers all behavioral criteria: auto-save single row, reload link retention, New-chat unlink, share+toast+unshare revocation, 1280/640/360px layout + overflow
**Test / lint / coverage (exact commands):**
- `uv run pytest --cov=app --cov-report=term-missing` → **1072 passed**, coverage **TOTAL 99%** (>90%)
- `uv run pytest tests/e2e/test_save_share_ux.py -v --no-cov` → **5 passed** (isolated, DB up)
- Regressions isolated: `test_share_chat` 4 ✓, `test_chat_history` 5 ✓, `test_chat_persistence` 4 ✓, `test_stale_saved_chats` 3 ✓, `test_smoke` 3 ✓
- `uv run ruff check . && uv run pyright` → clean (0 errors, 0 warnings)
**Completion criteria:** all 9 met — anonymous API matrix ✓, no-Save/auto-save contract ✓, guest share+toast+revocation ✓, layout at 3 widths ✓, unit+integration+coverage ✓, story E2E ✓, regression E2E ✓, lint/types ✓, commit `914097a` with the exact phase message exists ✓
**Decisions/deviations:** none. Uncommitted working-tree deletion of `06_*.md` is the harness's own move record — left untouched per rules.
**Next pending phase:** none — `todo/` contains only this phase.
@@ -0,0 +1,67 @@
........................................................................ [ 6%]
........................................................................ [ 13%]
........................................................................ [ 20%]
........................................................................ [ 26%]
........................................................................ [ 33%]
........................................................................ [ 40%]
........................................................................ [ 47%]
........................................................................ [ 53%]
........................................................................ [ 60%]
........................................................................ [ 67%]
........................................................................ [ 73%]
........................................................................ [ 80%]
........................................................................ [ 87%]
........................................................................ [ 94%]
................................................................ [100%]
=============================== warnings summary ===============================
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
from starlette.testclient import TestClient as TestClient # noqa
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================ tests coverage ================================
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
Name Stmts Miss Cover
-----------------------------------------------
app/__init__.py 1 0 100%
app/api/__init__.py 0 0 100%
app/api/auth.py 22 0 100%
app/api/chat.py 131 0 100%
app/api/chats.py 110 0 100%
app/api/config.py 7 0 100%
app/api/docs.py 23 0 100%
app/api/git_sources.py 143 0 100%
app/api/health.py 10 0 100%
app/api/steering.py 42 0 100%
app/api/suggestions.py 8 0 100%
app/api/sync.py 89 0 100%
app/config.py 79 0 100%
app/core/__init__.py 0 0 100%
app/core/auth.py 20 0 100%
app/core/caching.py 108 0 100%
app/core/debugging.py 29 2 93%
app/core/logging.py 13 0 100%
app/db.py 21 0 100%
app/main.py 50 0 100%
app/models.py 74 0 100%
app/rag/__init__.py 0 0 100%
app/rag/agent.py 78 0 100%
app/rag/archive_upload.py 128 0 100%
app/rag/chunker.py 206 4 98%
app/rag/git_sources.py 14 0 100%
app/rag/importer.py 173 3 98%
app/rag/llm.py 189 0 100%
app/rag/overview.py 71 0 100%
app/rag/prompts.py 65 0 100%
app/rag/retriever.py 94 3 97%
app/rag/sources_meta.py 16 0 100%
app/rag/suggestions.py 27 0 100%
app/rag/summarizer.py 24 0 100%
app/schemas.py 167 0 100%
-----------------------------------------------
TOTAL 2232 12 99%
coverage gate: app/ 99% (>90%) OK
All checks passed!
0 errors, 0 warnings, 0 informations
validation OK
@@ -0,0 +1,16 @@
All checks green. Task 01 is complete.
**Implemented**
- `app/api/chats.py`: removed the router-wide `require_admin` gate; applied `dependencies=[Depends(require_admin)]` to exactly the four management routes (list, detail, delete, unshare) — write surface (`POST` create incl. save-then-share, `PUT`, `POST /{id}/share`) is now public per owner-locked A1
- Rewrote the module docstring to the split contract + WHY (unguessable `uuid4` row id = credential, same trust model as the phase-51 token); per-endpoint docstrings updated (create/update/share "public — no session required"; management routes noted admin-only)
- `tests/integration/test_chats_api.py`: replaced the "403 on every route" pin with guest write-surface pins (create 201+id+auto-title, PUT 200 replacement + `updated_at` bump, share 200 + idempotent token, save-then-share 201 + `share_url` in one commit, immediately publicly readable), guest 403s on exactly the four management routes, and cross-gate revocation (guest unshare 403s, link stays live; admin unshare → public read 404s for guest and admin); all admin pins unchanged
- No migration; `public_router`, `shared_page_router`, `app/core/auth.py` untouched (git diff: only the two files above)
**Results**
- `uv run pytest tests/integration/test_chats_api.py -v` → 54 passed
- `uv run pytest --cov=app --cov-report=term-missing` → 1065 passed, TOTAL coverage **99%** (>90%)
- `uv run ruff check .` clean; `uv run pyright` → 0 errors
**Notes:** no deviations; no commit (the atomic phase commit belongs to task 06 per the phase's Commit section).
**Next pending task:** `.agents/phases/todo/55_save_share_ux/02_auto_save_default.md`
@@ -0,0 +1,67 @@
........................................................................ [ 6%]
........................................................................ [ 13%]
........................................................................ [ 20%]
........................................................................ [ 27%]
........................................................................ [ 33%]
........................................................................ [ 40%]
........................................................................ [ 47%]
........................................................................ [ 54%]
........................................................................ [ 60%]
........................................................................ [ 67%]
........................................................................ [ 74%]
........................................................................ [ 81%]
........................................................................ [ 87%]
........................................................................ [ 94%]
......................................................... [100%]
=============================== warnings summary ===============================
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
from starlette.testclient import TestClient as TestClient # noqa
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================ tests coverage ================================
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
Name Stmts Miss Cover
-----------------------------------------------
app/__init__.py 1 0 100%
app/api/__init__.py 0 0 100%
app/api/auth.py 22 0 100%
app/api/chat.py 131 0 100%
app/api/chats.py 110 0 100%
app/api/config.py 7 0 100%
app/api/docs.py 23 0 100%
app/api/git_sources.py 143 0 100%
app/api/health.py 10 0 100%
app/api/steering.py 42 0 100%
app/api/suggestions.py 8 0 100%
app/api/sync.py 89 0 100%
app/config.py 79 0 100%
app/core/__init__.py 0 0 100%
app/core/auth.py 20 0 100%
app/core/caching.py 108 0 100%
app/core/debugging.py 29 2 93%
app/core/logging.py 13 0 100%
app/db.py 21 0 100%
app/main.py 50 0 100%
app/models.py 74 0 100%
app/rag/__init__.py 0 0 100%
app/rag/agent.py 78 0 100%
app/rag/archive_upload.py 128 0 100%
app/rag/chunker.py 206 4 98%
app/rag/git_sources.py 14 0 100%
app/rag/importer.py 173 3 98%
app/rag/llm.py 189 0 100%
app/rag/overview.py 71 0 100%
app/rag/prompts.py 65 0 100%
app/rag/retriever.py 94 3 97%
app/rag/sources_meta.py 16 0 100%
app/rag/suggestions.py 27 0 100%
app/rag/summarizer.py 24 0 100%
app/schemas.py 167 0 100%
-----------------------------------------------
TOTAL 2232 12 99%
coverage gate: app/ 99% (>90%) OK
All checks passed!
0 errors, 0 warnings, 0 informations
validation OK
@@ -0,0 +1,15 @@
All gates green. Final report:
**Phase 55 / Task 02 — Auto-save every conversation (retire the Save pill): complete**
- `index.html`: removed `#save-chat-btn` + Phase-50 comment (New chat / Share untouched — tasks 03/05 own them)
- `app.js`: `saveCurrentChat()` → headless `persistConversation()` — identical phase-50 upsert (PUT linked / 404→unlink+POST / POST unlinked / 201→link), A2 quiet failure (one-line `#send-status` note, no banner, silent success), module-level `persisting` double-fire guard; wired to save points (user send in `runTurn`'s `!reask` block, `rememberBrainTurn` — pagehide partial rides it, no extra call)
- `app.js`: `bor.chat.v1` record extended in place to `{v, chatId, messages}` — `saveConversation()` persists the link, new `loadStoredRecord()` reads it with old-record safety (missing field → null), `restoreConversation()` hydrates `currentChatId` (reload keeps the link — no duplicate rows); "New chat" still unlinks; no `saveBtn`/`saveCurrentChat` symbol left (tune-form local renamed)
- `styles.css`: all `.save-chat-btn` rules removed (base, ≤900px squeeze, ≤640px overrides)
- Tests: `test_save_chat_ui.py` re-pinned to the new contract; `test_chat_persistence.py` shape pin updated; E2E pins adapted in `test_chat_history.py` + `test_share_chat.py` (Save click → `_wait_saved_row()` admin-list poll; anonymous block now asserts the element is **absent**) and `test_stale_saved_chats.py` (regression gate)
- Fixed pre-existing flake in `test_sources_midstream_bug.py` (5s assertion auto-wait raced the mock's ≈4.7s thinking stream — verified failing on pre-change baseline too; explicit 30s timeout)
- Verified the full anonymous contract with a throwaway E2E (1 row per conversation, same row across turns, reload keeps link, New chat → fresh row) — deleted after passing
**Results:** `uv run ruff check .` clean · `uv run pyright` 0 errors · `uv run pytest --cov=app` 1067 passed, TOTAL **99%** · E2E in isolation: `test_chat_history` 5✓, `test_share_chat` 4✓, `test_chat_persistence` 4✓, `test_stale_saved_chats` 3✓, `test_smoke` 3✓ (plus `test_sources_midstream_bug` 4✓×2, `test_retry_answer` 4✓, `test_stop_generation` 3✓)
**Deviations:** none; no commit made (the phase's single `--no-gpg-sign` commit belongs to task 06). Next pending task: `03_share_for_everyone.md`.
@@ -0,0 +1,67 @@
........................................................................ [ 6%]
........................................................................ [ 13%]
........................................................................ [ 20%]
........................................................................ [ 26%]
........................................................................ [ 33%]
........................................................................ [ 40%]
........................................................................ [ 47%]
........................................................................ [ 53%]
........................................................................ [ 60%]
........................................................................ [ 67%]
........................................................................ [ 74%]
........................................................................ [ 80%]
........................................................................ [ 87%]
........................................................................ [ 94%]
........................................................... [100%]
=============================== warnings summary ===============================
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
from starlette.testclient import TestClient as TestClient # noqa
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================ tests coverage ================================
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
Name Stmts Miss Cover
-----------------------------------------------
app/__init__.py 1 0 100%
app/api/__init__.py 0 0 100%
app/api/auth.py 22 0 100%
app/api/chat.py 131 0 100%
app/api/chats.py 110 0 100%
app/api/config.py 7 0 100%
app/api/docs.py 23 0 100%
app/api/git_sources.py 143 0 100%
app/api/health.py 10 0 100%
app/api/steering.py 42 0 100%
app/api/suggestions.py 8 0 100%
app/api/sync.py 89 0 100%
app/config.py 79 0 100%
app/core/__init__.py 0 0 100%
app/core/auth.py 20 0 100%
app/core/caching.py 108 0 100%
app/core/debugging.py 29 2 93%
app/core/logging.py 13 0 100%
app/db.py 21 0 100%
app/main.py 50 0 100%
app/models.py 74 0 100%
app/rag/__init__.py 0 0 100%
app/rag/agent.py 78 0 100%
app/rag/archive_upload.py 128 0 100%
app/rag/chunker.py 206 4 98%
app/rag/git_sources.py 14 0 100%
app/rag/importer.py 173 3 98%
app/rag/llm.py 189 0 100%
app/rag/overview.py 71 0 100%
app/rag/prompts.py 65 0 100%
app/rag/retriever.py 94 3 97%
app/rag/sources_meta.py 16 0 100%
app/rag/suggestions.py 27 0 100%
app/rag/summarizer.py 24 0 100%
app/schemas.py 167 0 100%
-----------------------------------------------
TOTAL 2232 12 99%
coverage gate: app/ 99% (>90%) OK
All checks passed!
0 errors, 0 warnings, 0 informations
validation OK
@@ -0,0 +1,19 @@
All green. The diff includes task 01/02's uncommitted working-tree changes (commit happens in task 06) plus my task-03 changes layered on top. Final verification summary:
**Task 03 — Share pill visible to every visitor: complete**
**Implemented**
- `frontend/index.html`: `#share-chat-btn` `hidden` attribute removed; Phase-51 comment rewritten — static, always-visible markup (Phase-51 admin-only ship-hidden gate gone, task 01 opened the write surface); save-then-share contract text kept accurate, unshare noted as admin-only History page.
- `frontend/assets/app.js`: boot IIFE `shareBtn.hidden = !isAdmin` reveal line removed; both `shareCurrentChat()` 403/5xx banners neutralized to "Couldn't share the conversation — try again." (network "is the app reachable?" banner kept); module-header, const, binding, and function docstrings updated (no sign-in wording; the Phase-53 admin-only Regenerate path's copy intentionally untouched).
- `tests/unit/test_save_chat_ui.py`: pins flipped to the new contract — pill ships without `hidden`; `shareBtn.hidden` absent anywhere in app.js; neutral error copy ×2 with zero "signed in" wording in the share handler; boot order pin updated (no reveal step).
- `tests/e2e/test_chat_history.py`: anonymous-state block extended with `#share-chat-btn` `to_be_visible()` alongside the existing count-0 / hidden pins; section + header comments updated. No other pin touched.
**Results**
- `uv run pytest --cov=app --cov-report=term-missing` → 1067 passed, TOTAL **99%** (>90% ✓)
- `uv run pytest tests/e2e/test_chat_history.py -v --no-cov` (isolated, DB up) → 5 passed ✓
- Regression, isolated: `tests/e2e/test_share_chat.py` + `tests/e2e/test_smoke.py` → 7 passed ✓
- `uv run ruff check . && uv run pyright` → clean ✓
**Decisions**: no code-to-commit in this task (atomic commit is task 06's job); Phase-53 Regenerate banner copy left as-is per task scope.
**Next pending task**: `.agents/phases/todo/55_save_share_ux/04_share_toast.md`
@@ -0,0 +1,67 @@
........................................................................ [ 6%]
........................................................................ [ 13%]
........................................................................ [ 20%]
........................................................................ [ 26%]
........................................................................ [ 33%]
........................................................................ [ 40%]
........................................................................ [ 47%]
........................................................................ [ 53%]
........................................................................ [ 60%]
........................................................................ [ 67%]
........................................................................ [ 74%]
........................................................................ [ 80%]
........................................................................ [ 87%]
........................................................................ [ 94%]
........................................................... [100%]
=============================== warnings summary ===============================
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
from starlette.testclient import TestClient as TestClient # noqa
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================ tests coverage ================================
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
Name Stmts Miss Cover
-----------------------------------------------
app/__init__.py 1 0 100%
app/api/__init__.py 0 0 100%
app/api/auth.py 22 0 100%
app/api/chat.py 131 0 100%
app/api/chats.py 110 0 100%
app/api/config.py 7 0 100%
app/api/docs.py 23 0 100%
app/api/git_sources.py 143 0 100%
app/api/health.py 10 0 100%
app/api/steering.py 42 0 100%
app/api/suggestions.py 8 0 100%
app/api/sync.py 89 0 100%
app/config.py 79 0 100%
app/core/__init__.py 0 0 100%
app/core/auth.py 20 0 100%
app/core/caching.py 108 0 100%
app/core/debugging.py 29 2 93%
app/core/logging.py 13 0 100%
app/db.py 21 0 100%
app/main.py 50 0 100%
app/models.py 74 0 100%
app/rag/__init__.py 0 0 100%
app/rag/agent.py 78 0 100%
app/rag/archive_upload.py 128 0 100%
app/rag/chunker.py 206 4 98%
app/rag/git_sources.py 14 0 100%
app/rag/importer.py 173 3 98%
app/rag/llm.py 189 0 100%
app/rag/overview.py 71 0 100%
app/rag/prompts.py 65 0 100%
app/rag/retriever.py 94 3 97%
app/rag/sources_meta.py 16 0 100%
app/rag/suggestions.py 27 0 100%
app/rag/summarizer.py 24 0 100%
app/schemas.py 167 0 100%
-----------------------------------------------
TOTAL 2232 12 99%
coverage gate: app/ 99% (>90%) OK
All checks passed!
0 errors, 0 warnings, 0 informations
validation OK
@@ -0,0 +1,17 @@
All green. Task 04 is complete.
**Report — phase 55, task 04 (share-success toast)**
Implemented:
- `styles.css`: `.toast` in the Banners section — fixed top-right under the sticky header (`top: calc(var(--header-h) + 0.75rem)`, `right: 1rem`, `z-index: 1000` overlay contract), brand fill (`--bg` on `--brand` = 5.2:1 AA, `.new-chat-btn` family), 22rem max-width, rounded + shadow, hidden by default (`opacity: 0; pointer-events: none`), 200ms slide-down + fade via `.toast.is-visible`; reduced-motion override drops the transform for **both** states (`.is-visible` out-specifies the bare rule) and keeps a 120ms opacity fade.
- `app.js`: page-local `showToast(message)` — single lazily-created `div.toast` on `document.body`, `textContent` only (XSS-safe), `aria-hidden="true"` (A4: visual only, `#send-status` stays the announcer), re-trigger = clear pending dismiss → remove class → forced reflow → re-add (second toast replaces the first, no stacking), 4000ms auto-dismiss; called from **both** `shareCurrentChat` success branches with their own texts (`"Share link copied."` / `"Share link ready — copy it from the field."`); `sendStatus` lines untouched, no toast on any failure branch. Module + function contract comments updated.
- `tests/unit/test_save_chat_ui.py`: 3 new pins (single-instance/aria-hidden/reflow/dismiss helper; both-success-branches-only with exact texts and no toast in the catch; CSS shape + reduced-motion block) + docstring bullet.
Results:
- `uv run pytest --cov=app --cov-report=term-missing` → **1070 passed**, coverage TOTAL **99%** (>90%)
- `uv run ruff check . && uv run pyright` → clean (0 errors)
- Regression spot-checks (share flow I touched): `test_share_chat.py` 4 passed, `test_chat_history.py` 5 passed — each in isolation
Decisions: toast z-index follows the existing modal overlay contract (1000); JS logic additionally smoke-tested in Node with a stub DOM (single instance, re-trigger, auto-dismiss verified). No CDN/HTML changes; task file untouched.
Next pending task: `.agents/phases/todo/55_save_share_ux/05_chat_actions_layout.md`
@@ -0,0 +1,67 @@
........................................................................ [ 6%]
........................................................................ [ 13%]
........................................................................ [ 20%]
........................................................................ [ 26%]
........................................................................ [ 33%]
........................................................................ [ 40%]
........................................................................ [ 47%]
........................................................................ [ 53%]
........................................................................ [ 60%]
........................................................................ [ 67%]
........................................................................ [ 74%]
........................................................................ [ 80%]
........................................................................ [ 87%]
........................................................................ [ 94%]
.............................................................. [100%]
=============================== warnings summary ===============================
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
from starlette.testclient import TestClient as TestClient # noqa
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================ tests coverage ================================
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
Name Stmts Miss Cover
-----------------------------------------------
app/__init__.py 1 0 100%
app/api/__init__.py 0 0 100%
app/api/auth.py 22 0 100%
app/api/chat.py 131 0 100%
app/api/chats.py 110 0 100%
app/api/config.py 7 0 100%
app/api/docs.py 23 0 100%
app/api/git_sources.py 143 0 100%
app/api/health.py 10 0 100%
app/api/steering.py 42 0 100%
app/api/suggestions.py 8 0 100%
app/api/sync.py 89 0 100%
app/config.py 79 0 100%
app/core/__init__.py 0 0 100%
app/core/auth.py 20 0 100%
app/core/caching.py 108 0 100%
app/core/debugging.py 29 2 93%
app/core/logging.py 13 0 100%
app/db.py 21 0 100%
app/main.py 50 0 100%
app/models.py 74 0 100%
app/rag/__init__.py 0 0 100%
app/rag/agent.py 78 0 100%
app/rag/archive_upload.py 128 0 100%
app/rag/chunker.py 206 4 98%
app/rag/git_sources.py 14 0 100%
app/rag/importer.py 173 3 98%
app/rag/llm.py 189 0 100%
app/rag/overview.py 71 0 100%
app/rag/prompts.py 65 0 100%
app/rag/retriever.py 94 3 97%
app/rag/sources_meta.py 16 0 100%
app/rag/suggestions.py 27 0 100%
app/rag/summarizer.py 24 0 100%
app/schemas.py 167 0 100%
-----------------------------------------------
TOTAL 2232 12 99%
coverage gate: app/ 99% (>90%) OK
All checks passed!
0 errors, 0 warnings, 0 informations
validation OK
@@ -0,0 +1,18 @@
Everything is green. The working tree also carries the uncommitted tasks 01–04 changes (the atomic commit belongs to task 06), so I left the tree exactly as the pipeline expects.
**Report — Task 05: New chat / Share action row**
- `frontend/index.html`: wrapped `#new-chat-btn` + `#share-chat-btn` in one `<div class="chat-actions">` (DOM order New chat → Share); wrapper is a normal `.chat-shell` column child; surrounding kb-banner/stale-banner/steering/announcer structure untouched.
- `frontend/assets/styles.css`: base `.chat-actions { display:flex; flex-direction:row; align-items:center; gap:0.6rem }` (cross-axis `center` keeps pills at intrinsic width, left-aligned); ≤640px override `flex-direction:column; align-items:stretch; gap:0.5rem`; existing mobile pill rules untouched.
- `tests/unit/test_save_chat_ui.py`: 2 new source pins (wrapper holds exactly both pills in A5 order, chat-page only; base row + ≤640px stack rules + intact pill rules) + docstring update.
- Layout verified via ad-hoc Playwright (temp file, deleted): 1280×800 one horizontal row (Share.x > New.x+width, intrinsic widths <200px, left-aligned in 46rem column); 390×844 stacked full-width (New above Share); no overflow at 360px (scrollWidth ≤ 360).
**Results**
- `uv run pytest` → 1072 passed
- `uv run pytest --cov=app --cov-report=term-missing` → TOTAL 99% (>90%)
- `uv run ruff check . && uv run pyright` → clean (0 errors)
- Regression E2E in isolation (all exit 0): `test_smoke`, `test_chat_persistence`, `test_chat_history`, `test_share_chat`, `test_stale_saved_chats`
**Deviations**: none — gap stayed 0.6rem (pair fits easily); commit/phase-move left to task 06 per protocol.
**Next pending task**: `.agents/phases/todo/55_save_share_ux/06_e2e_save_share_ux.md` (story E2E suite + atomic commit).
@@ -0,0 +1,67 @@
........................................................................ [ 6%]
........................................................................ [ 13%]
........................................................................ [ 20%]
........................................................................ [ 26%]
........................................................................ [ 33%]
........................................................................ [ 40%]
........................................................................ [ 47%]
........................................................................ [ 53%]
........................................................................ [ 60%]
........................................................................ [ 67%]
........................................................................ [ 73%]
........................................................................ [ 80%]
........................................................................ [ 87%]
........................................................................ [ 94%]
................................................................ [100%]
=============================== warnings summary ===============================
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
from starlette.testclient import TestClient as TestClient # noqa
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================ tests coverage ================================
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
Name Stmts Miss Cover
-----------------------------------------------
app/__init__.py 1 0 100%
app/api/__init__.py 0 0 100%
app/api/auth.py 22 0 100%
app/api/chat.py 131 0 100%
app/api/chats.py 110 0 100%
app/api/config.py 7 0 100%
app/api/docs.py 23 0 100%
app/api/git_sources.py 143 0 100%
app/api/health.py 10 0 100%
app/api/steering.py 42 0 100%
app/api/suggestions.py 8 0 100%
app/api/sync.py 89 0 100%
app/config.py 79 0 100%
app/core/__init__.py 0 0 100%
app/core/auth.py 20 0 100%
app/core/caching.py 108 0 100%
app/core/debugging.py 29 2 93%
app/core/logging.py 13 0 100%
app/db.py 21 0 100%
app/main.py 50 0 100%
app/models.py 74 0 100%
app/rag/__init__.py 0 0 100%
app/rag/agent.py 78 0 100%
app/rag/archive_upload.py 128 0 100%
app/rag/chunker.py 206 4 98%
app/rag/git_sources.py 14 0 100%
app/rag/importer.py 173 3 98%
app/rag/llm.py 189 0 100%
app/rag/overview.py 71 0 100%
app/rag/prompts.py 65 0 100%
app/rag/retriever.py 94 3 97%
app/rag/sources_meta.py 16 0 100%
app/rag/suggestions.py 27 0 100%
app/rag/summarizer.py 24 0 100%
app/schemas.py 167 0 100%
-----------------------------------------------
TOTAL 2232 12 99%
coverage gate: app/ 99% (>90%) OK
All checks passed!
0 errors, 0 warnings, 0 informations
validation OK
@@ -0,0 +1,20 @@
All green and committed. Final report:
## Task 06 complete — phase 55 (save/share UX) E2E + regressions + commit
**Implemented**
- New story suite `tests/e2e/test_save_share_ux.py` (5 tests, isolated run): anonymous auto-save (no `#save-chat-btn` in DOM → one question → exactly one `saved_chats` row via admin `GET /api/chats`, no button press, silent per A2); no duplicate across reload (link survives, same row, 2→4 messages, count stays one); anonymous share + toast (pill visible logged-out, single `aria-hidden` toast, auto-dismiss ~4s, link from clipboard, fresh incognito read-only zero-controls view, admin History two-step Unshare revokes the URL); action-row layout (1280×800 horizontal row, 390×844 stacked, no overflow at 360px); admin auto-save sanity (A1).
- One self-test fix: full-width mobile pin compares pill to the `.chat-actions` row (column content box) — `.chat-shell` is a `.container`, its border box includes padding.
- Regression suites needed no edits (tasks 02/03 had already adapted them); phase-48/49/51 pins untouched.
**Results (all exact commands)**
- `uv run pytest tests/e2e/test_save_share_ux.py -v --no-cov` → 5 passed (DB up, isolation)
- Isolated regressions: `test_share_chat` 4 passed · `test_chat_history` 5 · `test_chat_persistence` 4 · `test_stale_saved_chats` 3 · `test_smoke` 3
- `uv run pytest --cov=app --cov-report=term-missing` → 1072 passed, coverage TOTAL **99%** (>90%)
- `uv run ruff check . && uv run pyright` → clean / 0 errors
- One `--no-gpg-sign` commit: `914097a feat(chat): save by default + share anonymously — …` (17 files; R100 renames of tasks 01–05 into `complete/` per phase-53 precedent)
**Notable decisions**
- Did not move `06_…`/`00_phase.md` out of `todo/` — harness rule: it moves the task file on success (matches phase-53 choreography).
**Next pending task:** none — 06 was the last task of phase 55; `todo/` holds only this phase's remaining files awaiting the harness move.
@@ -0,0 +1,67 @@
........................................................................ [ 6%]
........................................................................ [ 13%]
........................................................................ [ 20%]
........................................................................ [ 26%]
........................................................................ [ 33%]
........................................................................ [ 40%]
........................................................................ [ 47%]
........................................................................ [ 53%]
........................................................................ [ 60%]
........................................................................ [ 67%]
........................................................................ [ 73%]
........................................................................ [ 80%]
........................................................................ [ 87%]
........................................................................ [ 94%]
................................................................ [100%]
=============================== warnings summary ===============================
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
from starlette.testclient import TestClient as TestClient # noqa
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================ tests coverage ================================
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
Name Stmts Miss Cover
-----------------------------------------------
app/__init__.py 1 0 100%
app/api/__init__.py 0 0 100%
app/api/auth.py 22 0 100%
app/api/chat.py 131 0 100%
app/api/chats.py 110 0 100%
app/api/config.py 7 0 100%
app/api/docs.py 23 0 100%
app/api/git_sources.py 143 0 100%
app/api/health.py 10 0 100%
app/api/steering.py 42 0 100%
app/api/suggestions.py 8 0 100%
app/api/sync.py 89 0 100%
app/config.py 79 0 100%
app/core/__init__.py 0 0 100%
app/core/auth.py 20 0 100%
app/core/caching.py 108 0 100%
app/core/debugging.py 29 2 93%
app/core/logging.py 13 0 100%
app/db.py 21 0 100%
app/main.py 50 0 100%
app/models.py 74 0 100%
app/rag/__init__.py 0 0 100%
app/rag/agent.py 78 0 100%
app/rag/archive_upload.py 128 0 100%
app/rag/chunker.py 206 4 98%
app/rag/git_sources.py 14 0 100%
app/rag/importer.py 173 3 98%
app/rag/llm.py 189 0 100%
app/rag/overview.py 71 0 100%
app/rag/prompts.py 65 0 100%
app/rag/retriever.py 94 3 97%
app/rag/sources_meta.py 16 0 100%
app/rag/suggestions.py 27 0 100%
app/rag/summarizer.py 24 0 100%
app/schemas.py 167 0 100%
-----------------------------------------------
TOTAL 2232 12 99%
coverage gate: app/ 99% (>90%) OK
All checks passed!
0 errors, 0 warnings, 0 informations
validation OK