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:
@@ -0,0 +1,18 @@
|
||||
All completion criteria verified — nothing needed fixing. Final report:
|
||||
|
||||
**Phase 45 — verification pass (all 3 tasks already complete)**
|
||||
|
||||
- Verified budget removal: `BOR_AGENT_LIST_CALLS`/`BOR_AGENT_READ_CALLS`/exhaustion refusals gone from `app/`, `.env.example`, tests (grep-clean); non-budget rejections (`Unknown tool.`, `MISSING_READ_ARGS`, `Already in your context.`) kept; `agent_max_rounds` (default 10, `0` = kill switch) in place.
|
||||
- Verified `app/rag/agent.py` loop: tools offered whole turn, round cap is only bound, cap forces final `tools=None` answer with log warning, `0` → single `tools=None` request.
|
||||
- Verified PLAN.md §4 carries the phase-45 SSE revision note (owner permission 2026-08-27, `TODO.md` L8) — the only PLAN edit.
|
||||
- Verified atomic commit `b855d0a` `feat(rag): unbounded agent tool calls behind a round cap (owner revision)` (16 files, HEAD); task files in `.agents/phases/complete/`.
|
||||
|
||||
**Results (exact commands):**
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → **756 passed, 99% coverage** (>90%; `agent.py`/`config.py` 100%)
|
||||
- `uv run pytest tests/e2e/test_agent_unlimited_tools.py -v --no-cov` → **4 passed** (DB up; multi-read: 3 tool lines, non-deflected, deduped `done.sources`)
|
||||
- Regressions in isolation: `test_agent_document_tools.py` **4 passed**, `test_chat_rag.py` **3 passed**, `test_smoke.py` **3 passed**
|
||||
- `uv run ruff check . && uv run pyright` → **clean** (0 errors, 0 warnings)
|
||||
|
||||
**Completion criteria: 10/10 met** (budgets gone; multi-read turn; kill switch + cap; SSE/log unchanged; PLAN note; pytest+coverage; story E2E; regression E2Es; lint; commit). No defects found; no deviations.
|
||||
|
||||
**Next pending phase:** `46_mobile_hamburger_nav`.
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
........................................................................ [ 9%]
|
||||
........................................................................ [ 19%]
|
||||
........................................................................ [ 28%]
|
||||
........................................................................ [ 38%]
|
||||
........................................................................ [ 47%]
|
||||
........................................................................ [ 57%]
|
||||
........................................................................ [ 66%]
|
||||
........................................................................ [ 76%]
|
||||
........................................................................ [ 85%]
|
||||
........................................................................ [ 95%]
|
||||
.................................... [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 122 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/docs.py 23 0 100%
|
||||
app/api/git_sources.py 66 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 71 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 72 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 186 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 99 0 100%
|
||||
--------------------------------------------
|
||||
TOTAL 1763 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
All gates green. Task complete — final report:
|
||||
|
||||
**Phase 45 · Task 01 — round cap replaces the per-tool budgets (server core)**
|
||||
|
||||
- `app/config.py`: deleted `agent_list_calls`/`agent_read_calls`; added `agent_max_rounds: int = 10` (0 = kill switch) + a `field_validator` rejecting negatives
|
||||
- `app/rag/agent.py`: loop now offers `AGENT_TOOLS` for the whole turn; `rounds` increments per executed/rejected call; at `rounds >= max_rounds` the cap forces one final `tools=None` answer (now the *only* forced exit); `0` → single `tools=None` request; deleted `LIST_EXHAUSTED`/`READ_EXHAUSTED` + budget params (rejections `Unknown tool.`/`MISSING_READ_ARGS`/`Already in your context.` kept); `read_document` description drops "exactly one"; per-call log line → `agent tool=%s args=%s round=%d/%d`; module/`run_agent` docstrings rewritten
|
||||
- Stale budget wording updated in `app/api/chat.py`, `app/rag/prompts.py`, `README.md` (narrative + config table), `.env.example` (one commented `# BOR_AGENT_MAX_ROUNDS=10` line), `test_chat_gate.py` docstring
|
||||
- Tests: `test_agent.py` rewritten (always-list to cap 3 → forced answer, `max_rounds=0` kill switch, rejected-read spam bounded by cap, re-list counts, multi-read executes, rejections intact); `test_config.py` gains default/0/5/negative tests; integration fixture → `agent_max_rounds=0` (test renamed), `seen_tools` now asserts tools stay offered
|
||||
- Grep: zero hits for the old identifiers in all committed files (`app/`, `tests/`, `scripts/`, `README.md`, `.env.example`, `frontend/`)
|
||||
|
||||
**Gates:** `uv run pytest` → 739 passed · `uv run pytest --cov=app --cov-report=term-missing` → 739 passed, **99%** (agent.py/config.py 100%) · `uv run ruff check .` clean · `uv run pyright` 0 errors · regression E2Es pass in isolation: `test_agent_document_tools.py` 4/4 (unmodified), `test_chat_rag.py`+`test_smoke.py` 6/6
|
||||
|
||||
**Decisions:** `TOOLS_SECTION` prompt text and `mock_llm.py` untouched (owned by tasks 02/03 scope; mock keys off the `<tools>` marker); remaining old-name hits exist only in gitignored `.agents/` history (phase-37 story/reports) and PLAN.md (task 03's single planned edit); dropped a `hasattr` "budgets are gone" test I'd added since it would violate the task's zero-hit grep.
|
||||
|
||||
**Next pending task:** `02_mock_multi_read_flow.md`
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
........................................................................ [ 9%]
|
||||
........................................................................ [ 19%]
|
||||
........................................................................ [ 29%]
|
||||
........................................................................ [ 38%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 58%]
|
||||
........................................................................ [ 68%]
|
||||
........................................................................ [ 77%]
|
||||
........................................................................ [ 87%]
|
||||
........................................................................ [ 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 122 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/docs.py 23 0 100%
|
||||
app/api/git_sources.py 66 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 71 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 72 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 186 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 99 0 100%
|
||||
--------------------------------------------
|
||||
TOTAL 1763 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
Everything is green. The other modified files (`app/`, `.env.example`, other tests) are the uncommitted working-tree state from this phase's task 01 (round cap) — the phase's single atomic commit is task 03's job. My changes are only `tests/e2e/mock_llm.py` + the new `tests/unit/test_mock_tool_flow.py`.
|
||||
|
||||
**Task 02 report — Mock: deterministic multi-read tool flow**
|
||||
|
||||
- `tests/e2e/mock_llm.py`: added `MULTI_READ_TRIGGER = "read two documents"`; `_tool_flow` now classifies the multi-read variant statelessly by the count of `tool`-role read results ("Document " prefix) → `list` (call_0) → read #1 (first catalog line, call_1) → read #2 (first listing line ≠ already-read, call_2) → forced byte-stable answer `Read <sp1>. <content1[:80]> I read <sp1> and <sp2>.`; one-doc catalog degenerates to the single-read answer. New helpers `_read_results` / `_catalog_docs`; module docstring documents both flows.
|
||||
- Single-read (phase-37) flow untouched: same steps, ids, answer bytes; no-tools/`<tools>`-absent gating preserved (`agent_max_rounds=0` path safe).
|
||||
- Added `tests/unit/test_mock_tool_flow.py` (17 tests): single-flow regression + all multi-read branches (incl. listing-order read #2, no-tools answer step, marker-only, degenerate catalog).
|
||||
- Verified end-to-end through real `run_agent` + `LLMClient` + in-process mock: 3 tool executions, `holder.tool_calls == 3`, both reads in `read_docs`.
|
||||
|
||||
Results:
|
||||
- `uv run pytest` → **756 passed** (baseline 739 + 17 new)
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → **99%** on `app/` (gate >90%; `agent.py` 100%)
|
||||
- `uv run pytest tests/e2e/test_agent_document_tools.py -v --no-cov` → **4 passed** (phase-37 E2E unmodified — byte-identity proven)
|
||||
- `uv run ruff check . && uv run pyright` → clean (0 errors)
|
||||
|
||||
No deviations; `tool` SSE event shape and `tool_calls=N` log field untouched (no `app/` changes this task).
|
||||
|
||||
**Next pending task:** `03_unlimited_tools_e2e_and_commit.md` (story E2E `test_agent_unlimited_tools.py` + regressions + PLAN.md revision note + commit).
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
........................................................................ [ 9%]
|
||||
........................................................................ [ 19%]
|
||||
........................................................................ [ 28%]
|
||||
........................................................................ [ 38%]
|
||||
........................................................................ [ 47%]
|
||||
........................................................................ [ 57%]
|
||||
........................................................................ [ 66%]
|
||||
........................................................................ [ 76%]
|
||||
........................................................................ [ 85%]
|
||||
........................................................................ [ 95%]
|
||||
.................................... [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 122 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/docs.py 23 0 100%
|
||||
app/api/git_sources.py 66 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 71 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 72 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 186 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 99 0 100%
|
||||
--------------------------------------------
|
||||
TOTAL 1763 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
All green and committed. Final report:
|
||||
|
||||
**Phase 45 task 03 — unlimited-tools E2E + PLAN revision + commit**
|
||||
|
||||
- `tests/e2e/test_agent_unlimited_tools.py` (new, mock-only, 3-doc fixture): `test_multi_read_turn` (3 ordered tool frames/lines — list + two reads, "is listing documents" / "is reading <sp>" status walk via MutationObserver, both-named non-deflected answer), `test_done_sources_include_reads` (chips + `done.sources` = retrieval doc + both reads, deduped, viewer hrefs), `test_relist_allowed` (listing ran; no pre-phase-45 "…budget left" refusal rendered), `test_single_tool_flow_regression` (phase-37 marker: exactly one read, single tool pair, READ2 absent).
|
||||
- `.agents/PLAN.md`: phase-45 SSE revision note added after the phase-37 note (owner permission 2026-08-27, verbatim per task); phase-37 budget clause marked "(removed in phase 45 — see the revision note below)". Only PLAN change (diff verified).
|
||||
- Tests: `uv run pytest tests/e2e/test_agent_unlimited_tools.py -v --no-cov` → 4 passed (run twice); `test_agent_document_tools.py` (unmodified) → 4 passed; `test_chat_rag.py` → 3 passed; `test_smoke.py` → 3 passed, each in isolation.
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → 756 passed, `app/` coverage **99%** (>90%); `uv run ruff check . && uv run pyright` → clean.
|
||||
- Commit `b855d0a` `feat(rag): unbounded agent tool calls behind a round cap (owner revision)` (`--no-gpg-sign`), staging phase-45 files, `-f .agents/PLAN.md`, and the 45 `todo/ → complete/` moves (01/02 recorded as renames).
|
||||
- Decisions: fixture grown to 3 docs (2-doc corpus would make read #2 the already-in-context retrieval doc → rejection, not the multi-read flow); 40–44 pending `.agents` moves left for the next commit per `02c76ad` precedent; `NOTES.md` (owner file, never committed) left untracked.
|
||||
- Next pending: `45_agent_unlimited_tools` complete (harness moves task 03); roadmap continues with `46_mobile_hamburger_nav`.
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
........................................................................ [ 9%]
|
||||
........................................................................ [ 19%]
|
||||
........................................................................ [ 28%]
|
||||
........................................................................ [ 38%]
|
||||
........................................................................ [ 47%]
|
||||
........................................................................ [ 57%]
|
||||
........................................................................ [ 66%]
|
||||
........................................................................ [ 76%]
|
||||
........................................................................ [ 85%]
|
||||
........................................................................ [ 95%]
|
||||
.................................... [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 122 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/docs.py 23 0 100%
|
||||
app/api/git_sources.py 66 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 71 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 72 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 186 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 99 0 100%
|
||||
--------------------------------------------
|
||||
TOTAL 1763 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
Reference in New Issue
Block a user