chore(agent): track .agent/ planning tree in git
Build and Push Containers / build-and-push-app (push) Successful in 12s
Build and Push Containers / build-and-push-db (push) Successful in 10s

Remove the blanket .agent/ gitignore so the phase roadmap, user
stories, reports, and PLAN.md are versioned with the code. Only
runtime artifacts (.agent/phase-sessions/, .agent/pipeline.log)
remain ignored. Update AGENTS.md git protocol rule to match.
This commit is contained in:
2026-09-01 10:18:22 -04:00
parent 5fa620fde5
commit 4971e2859d
818 changed files with 23964 additions and 4 deletions
@@ -0,0 +1,10 @@
Phase 48 final verification pass — all green, no fixes needed.
**Verified (tasks 01–03 already complete, commit `1a60ecb`):**
- Teardown chain: `chat_stream`/`run_agent` `aclose()` in `finally`, `settled` flag + cancel log in `app/api/chat.py` — 9 unit tests pass
- Stop button: `is-stop` rose `#be123c`/`#fff` (6.3:1), `min-height: 44px`, global `:focus-visible` ring, click + Enter both stop (E2E-pinned); partial kept, `stopped: true` persisted, "Stopped" note on live + reload, no error banner
- **Tests/lint/coverage:** `uv run pytest --cov=app` → 893 passed, TOTAL **99%** (>90%); `uv run ruff check . && uv run pyright` → clean
- **E2E isolation:** `test_stop_generation.py` 3/3; regressions `test_chat_persistence.py` 4/4, `test_loading_feedback.py` 5/5 (revised contract), `test_chat_rag.py` 3/3
- **Completion criteria:** all 9 met — Stop button contract ✓, mid-stream partial + persistence + reload ✓, pre-token stop ✓, stream teardown + `cancelled` log + no `query_log` ✓, full suite/coverage ✓, phase E2E ✓, 3 regression suites ✓, ruff/pyright ✓, single `--no-gpg-sign` commit + task files in `complete/` ✓ (overview in `todo/` left for the harness to move)
- **Deviations:** none
- **Next pending phase:** `49_retry_answer`
@@ -0,0 +1,63 @@
........................................................................ [ 8%]
........................................................................ [ 16%]
........................................................................ [ 24%]
........................................................................ [ 32%]
........................................................................ [ 40%]
........................................................................ [ 48%]
........................................................................ [ 56%]
........................................................................ [ 64%]
........................................................................ [ 72%]
........................................................................ [ 80%]
........................................................................ [ 88%]
........................................................................ [ 96%]
............................. [100%]
=============================== warnings summary ===============================
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
from starlette.testclient import TestClient as TestClient # noqa
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================ tests coverage ================================
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
Name Stmts Miss Cover
-----------------------------------------------
app/__init__.py 1 0 100%
app/api/__init__.py 0 0 100%
app/api/auth.py 22 0 100%
app/api/chat.py 131 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 81 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 92 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 44 0 100%
app/models.py 60 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/suggestions.py 27 0 100%
app/rag/summarizer.py 24 0 100%
app/schemas.py 109 0 100%
-----------------------------------------------
TOTAL 2004 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 01 complete.
**Report — Phase 48, Task 01 (LLM stream teardown):**
- `app/rag/llm.py`: `chat_stream` now tracks the SDK stream explicitly — after a successful `create()`, `await stream.close()` (openai `AsyncStream.close()` → httpx `response.aclose()`; the SDK exposes `close()`, not `aclose()`) runs in a `finally` on every exit: exhaustion, wrapped failure, and GeneratorExit (consumer stop). `create()`-failure wrap and mid-iteration wrap are byte-identical to before.
- `app/rag/agent.py`: `run_agent` binds each round's stream to a variable and wraps the `async for` in `try/finally await stream.aclose()` — including the round-cap's final `tools=None` call. Loop logic/holders unchanged.
- `app/api/chat.py`: `stream()` gains a `settled` flag set at every terminal exit (before the `done` yield; before every error-then-return) and a non-yielding `finally` that logs `chat: turn cancelled question=%r total_ms=%d` only when unsettled; the `QueryLog` write sits after the loop so cancelled turns write no row.
- New tests: `tests/unit/test_llm_stream_teardown.py` (5 — full-consumption close, mid-iteration abandon close, create/mid-iteration/materialization failure pins) and `tests/unit/test_chat_cancel.py` (4 — real ASGI app with a slow fake SDK stream; ASGI-level `http.disconnect` after 2 frames since TestClient buffers the whole body; grounded + deflected cancel, completed + mid-stream-LLMError regressions). `test_llm_client.py` fake gained `close()`.
**Results:**
- `uv run pytest --cov=app --cov-report=term-missing` → 886 passed, TOTAL **99%** (>90%)
- `uv run ruff check . && uv run pyright` → all checks passed / 0 errors
- E2E regressions in isolation: `test_chat_rag` 3, `test_loading_feedback` 5, `test_chat_persistence` 4, `test_thinking_display`+`test_agent_document_tools` 9 — all green; new unit tests deterministic across 5 runs
**Notable:** disconnect emulated at the ASGI boundary (Starlette spec-2.0 listen-for-disconnect contract; TestClient can't drop a mid-stream connection); SDK `close()` vs task text's `aclose()` (same underlying `response.aclose()`). No commit — that's task 03.
**Next pending task:** `.agent/phases/todo/48_stop_generation/02_stop_button.md`
@@ -0,0 +1,63 @@
........................................................................ [ 8%]
........................................................................ [ 16%]
........................................................................ [ 24%]
........................................................................ [ 32%]
........................................................................ [ 40%]
........................................................................ [ 48%]
........................................................................ [ 56%]
........................................................................ [ 65%]
........................................................................ [ 73%]
........................................................................ [ 81%]
........................................................................ [ 89%]
........................................................................ [ 97%]
...................... [100%]
=============================== warnings summary ===============================
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
from starlette.testclient import TestClient as TestClient # noqa
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================ tests coverage ================================
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
Name Stmts Miss Cover
-----------------------------------------------
app/__init__.py 1 0 100%
app/api/__init__.py 0 0 100%
app/api/auth.py 22 0 100%
app/api/chat.py 131 0 100%
app/api/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 81 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 92 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 44 0 100%
app/models.py 60 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/suggestions.py 27 0 100%
app/rag/summarizer.py 24 0 100%
app/schemas.py 109 0 100%
-----------------------------------------------
TOTAL 2004 12 99%
coverage gate: app/ 99% (>90%) OK
All checks passed!
0 errors, 0 warnings, 0 informations
validation OK
@@ -0,0 +1,17 @@
Everything verified green — the previous rejection was a harness/report-level issue; the code state was already complete. Re-verified from scratch.
**Report — Phase 48, Task 01 (LLM stream teardown):**
- `app/rag/llm.py`: `chat_stream` tracks the SDK stream explicitly — after a successful `create()`, `await stream.close()` (openai `AsyncStream.close()` → httpx `response.aclose()`; the SDK exposes `close()`, not `aclose()`) runs in a `finally` on every exit: exhaustion, wrapped failure, GeneratorExit (consumer stop). `create()`-failure and mid-iteration wraps byte-identical to before.
- `app/rag/agent.py`: `run_agent` binds each round's stream and wraps the `async for` in `try/finally await stream.aclose()` — including the round-cap's final `tools=None` call; loop logic/holders unchanged.
- `app/api/chat.py`: `stream()` gains a `settled` flag set at every terminal exit (before the `done` yield; before every error-then-return) and a non-yielding `finally` logging `chat: turn cancelled question=%r total_ms=%d` only when unsettled; cancelled turns never reach the `QueryLog` write.
- New tests: `tests/unit/test_llm_stream_teardown.py` (5) + `tests/unit/test_chat_cancel.py` (4 — real ASGI app, slow fake SDK stream, ASGI-level `http.disconnect` after 2 frames since TestClient can't drop mid-stream; grounded + deflected cancel, completed + mid-stream-LLMError regressions). `test_llm_client.py` fake gained `close()`.
**Results (re-run this session):**
- `uv run pytest --cov=app --cov-report=term-missing` → 886 passed, TOTAL **99%** (>90%)
- `uv run ruff check .` → all checks passed; `uv run pyright` → 0 errors
- E2E in isolation: `test_chat_rag` 3, `test_loading_feedback` 5, `test_chat_persistence` 4 — all green; new unit tests deterministic (5 prior runs)
**Notable:** disconnect emulated at the ASGI boundary (Starlette spec-2.0 listen-for-disconnect contract); SDK `close()` vs task text's `aclose()` (same underlying `response.aclose()`). No commit — that's task 03.
**Next pending task:** `.agent/phases/todo/48_stop_generation/02_stop_button.md`
@@ -0,0 +1,63 @@
........................................................................ [ 8%]
........................................................................ [ 16%]
........................................................................ [ 24%]
........................................................................ [ 32%]
........................................................................ [ 40%]
........................................................................ [ 48%]
........................................................................ [ 56%]
........................................................................ [ 65%]
........................................................................ [ 73%]
........................................................................ [ 81%]
........................................................................ [ 89%]
........................................................................ [ 97%]
...................... [100%]
=============================== warnings summary ===============================
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
from starlette.testclient import TestClient as TestClient # noqa
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================ tests coverage ================================
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
Name Stmts Miss Cover
-----------------------------------------------
app/__init__.py 1 0 100%
app/api/__init__.py 0 0 100%
app/api/auth.py 22 0 100%
app/api/chat.py 131 0 100%
app/api/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 81 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 92 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 44 0 100%
app/models.py 60 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/suggestions.py 27 0 100%
app/rag/summarizer.py 24 0 100%
app/schemas.py 109 0 100%
-----------------------------------------------
TOTAL 2004 12 99%
coverage gate: app/ 99% (>90%) OK
All checks passed!
0 errors, 0 warnings, 0 informations
validation OK
@@ -0,0 +1,13 @@
All gates green. Final report:
## Task 02 — Stop button (Send↔Stop morph): complete
**Implemented** (all in `frontend/`): `setUiState` morphs `#send-btn` — always enabled, "Stop" + `.is-stop` (rose `#be123c`, contrast 6.3:1) while in flight, spinner never shows; `stopTurn()` + per-turn `AbortController` (`signal:` on the fetch, 120s guard sets `aborted` before aborting the same controller); catch stop-path keeps the partial, adds Tune button + `.stopped-note` ("Stopped"), persists with `stopped: true` (pre-token/thinking-only stops persist nothing brain-side); "Answer stopped." lands in the live region via the single settle; tool frames no longer relabel the button; restore path re-renders the note.
**Latent defect found + fixed:** the composer textarea was `required`; the input is empty in flight, so browser constraint validation swallowed the Stop click/Enter (`submit` never fired — proven by event instrumentation + server "turn cancelled" logs). Fixed with `novalidate` on `#composer` (the `!text` guard is the real empty-check; tuning-form precedent) — verified live: stop now settles in ~0.3s with `stopped: true` persisted, restore intact, 3/3 server-side cancels.
**Tests:** old-contract pins revised in place (`test_loading_feedback`, tool-states, scroll, 5 E2E suites) + 7 new unit pins (abort plumbing, stop branch, novalidate, restore). Also hardened 6 E2E settle-waits: in-flight detection now uses `#send-label` with explicit timeouts (the old disabled-button wait no longer blocks).
**Gates:** `uv run pytest --cov=app` → 893 passed, app/ 99%; `ruff` + `pyright` clean; all 44 E2E suites pass in isolation (the 6 batch-run failures in git/sync suites reproduce identically on pristine HEAD — pre-existing inter-suite DB interference, verified by frontend swap).
**Next pending:** `03_e2e_stop_generation.md` (dedicated stop E2E suite + commit; working tree stays uncommitted per protocol).
@@ -0,0 +1,63 @@
........................................................................ [ 8%]
........................................................................ [ 16%]
........................................................................ [ 24%]
........................................................................ [ 32%]
........................................................................ [ 40%]
........................................................................ [ 48%]
........................................................................ [ 56%]
........................................................................ [ 64%]
........................................................................ [ 72%]
........................................................................ [ 80%]
........................................................................ [ 88%]
........................................................................ [ 96%]
............................. [100%]
=============================== warnings summary ===============================
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
from starlette.testclient import TestClient as TestClient # noqa
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================ tests coverage ================================
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
Name Stmts Miss Cover
-----------------------------------------------
app/__init__.py 1 0 100%
app/api/__init__.py 0 0 100%
app/api/auth.py 22 0 100%
app/api/chat.py 131 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 81 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 92 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 44 0 100%
app/models.py 60 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/suggestions.py 27 0 100%
app/rag/summarizer.py 24 0 100%
app/schemas.py 109 0 100%
-----------------------------------------------
TOTAL 2004 12 99%
coverage gate: app/ 99% (>90%) OK
All checks passed!
0 errors, 0 warnings, 0 informations
validation OK
@@ -0,0 +1,9 @@
**Task 03 complete — `48_stop_generation/03_e2e_stop_generation.md`**
- Implemented `tests/e2e/test_stop_generation.py` (3 tests): `test_stop_mid_stream` (in-flight Stop button contract → partial kept + `.stopped-note` + no error banner + `stopped: true` in `bor.chat.v1` + no `query_log` row), `test_stop_pre_token` (click **and** Enter stops in the 3s warm-up; question kept, nothing brain-side), `test_stopped_turn_survives_reload` (stopped partial + note restore, order intact, idle Send).
- E2E: `uv run pytest tests/e2e/test_stop_generation.py -v --no-cov` → **3 passed** (2 consecutive runs, no flakes).
- Regressions in isolation: `test_chat_persistence.py` **4 passed**, `test_loading_feedback.py` **5 passed**, `test_chat_rag.py` **3 passed**.
- `uv run pytest` → **893 passed**; `uv run pytest --cov=app --cov-report=term-missing` → TOTAL **99%** (>90% gate); `uv run ruff check . && uv run pyright` → clean (0 errors).
- Committed `1a60ecb` `feat(chat): stop an in-flight answer — …` (`--no-gpg-sign`), working tree clean. Phase dir left in `todo/` for the harness to move.
- Notable: (1) the overview's `git add -A .agent/` errors on the gitignored pathspec in git 2.55 — staged `app/ frontend/ tests/` instead; the commit also records 166 `.agent` file deletions that were already staged in the index before this task (harness cleanup of retired pipeline files, all preserved in git history). (2) Added live DB `query_log`-empty assertions after browser-side stops to prove the server teardown end-to-end (unit-proven in `test_chat_cancel.py`).
- Next pending task: none in this phase — phase 48 is complete; the pipeline's next phase is whatever follows in `.agent/phases/todo/` (currently 48 is the only entry).
@@ -0,0 +1,63 @@
........................................................................ [ 8%]
........................................................................ [ 16%]
........................................................................ [ 24%]
........................................................................ [ 32%]
........................................................................ [ 40%]
........................................................................ [ 48%]
........................................................................ [ 56%]
........................................................................ [ 64%]
........................................................................ [ 72%]
........................................................................ [ 80%]
........................................................................ [ 88%]
........................................................................ [ 96%]
............................. [100%]
=============================== warnings summary ===============================
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
from starlette.testclient import TestClient as TestClient # noqa
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================ tests coverage ================================
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
Name Stmts Miss Cover
-----------------------------------------------
app/__init__.py 1 0 100%
app/api/__init__.py 0 0 100%
app/api/auth.py 22 0 100%
app/api/chat.py 131 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 81 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 92 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 44 0 100%
app/models.py 60 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/suggestions.py 27 0 100%
app/rag/summarizer.py 24 0 100%
app/schemas.py 109 0 100%
-----------------------------------------------
TOTAL 2004 12 99%
coverage gate: app/ 99% (>90%) OK
All checks passed!
0 errors, 0 warnings, 0 informations
validation OK