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 criteria verified — everything green with zero fixes needed. Final report:
|
||||
|
||||
## Phase 59 — Final Verification Pass (all tasks already complete)
|
||||
|
||||
- **Verified**: "Save as doc" flow (button → edit screen → push), `doc_drafts` CRUD + guard-rails, `docs_push` service, edit screen, E2E suite, config fail-loud/inert behavior — all implemented in commit `725af9f` (tree clean).
|
||||
- **No PR tooling**: grep confirms no `gh`, no PR URL, no GitHub-specific logic in `app/`/`frontend/` (only D3 docstrings + pre-existing git-sources example placeholder).
|
||||
|
||||
**Tests / lint / coverage:**
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → **1187 passed**, TOTAL **99%** (>90% ✓)
|
||||
- `uv run pytest tests/e2e/test_response_to_docs.py -v --no-cov` → **4 passed** (bare repo as source of truth: `git show`/`rev-parse`/`rev-list`; guest-403; unconfigured-409)
|
||||
- Regression E2E in isolation: `test_chat_rag` 3, `test_admin_auth` 6, `test_cache_busting` 4, `test_chat_history` 5 — all passed
|
||||
- `uv run ruff check . && uv run pyright` → clean (0 errors)
|
||||
|
||||
**Completion criteria:** all 11 met — button (admin+configured, bottom-right, live+restored); push lands file on `.env` branch with UI sha = `git rev-parse` tip; ff re-push (2 commits); branch created on first push, `--ff-only` non-ff fails with stderr (502); 409 names `BOR_DOCS_REPO` when empty; anonymous 403 on all 4 endpoints + push; atomic `--no-gpg-sign` commit present.
|
||||
|
||||
**Deviations:** JS lives at `frontend/assets/doc-edit.js` (house layout) not `frontend/doc-edit.js`; commit also touched `Containerfile` (asset serving for the new page) — cosmetic only. Phase dir left for the harness to move.
|
||||
|
||||
**Next pending phase:** `60_sticky_navbar`.
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
........................................................................ [ 6%]
|
||||
........................................................................ [ 12%]
|
||||
........................................................................ [ 18%]
|
||||
........................................................................ [ 24%]
|
||||
........................................................................ [ 30%]
|
||||
........................................................................ [ 36%]
|
||||
........................................................................ [ 42%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 54%]
|
||||
........................................................................ [ 60%]
|
||||
........................................................................ [ 66%]
|
||||
........................................................................ [ 72%]
|
||||
........................................................................ [ 78%]
|
||||
........................................................................ [ 84%]
|
||||
........................................................................ [ 90%]
|
||||
........................................................................ [ 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/chats.py 110 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/doc_drafts.py 93 0 100%
|
||||
app/api/docs.py 50 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 101 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/docs_push.py 39 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 52 0 100%
|
||||
app/models.py 86 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 198 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 2458 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
Task 01 complete. All criteria met.
|
||||
|
||||
**Implemented (phase 59, task 01 — docs-push env settings + `doc_drafts` model):**
|
||||
- `app/config.py`: `docs_repo`/`docs_branch`/`docs_base_branch`/`docs_work_dir` (defaults `""`/`bor-docs`/`main`/`~/bor-docs`, raw work-dir string per `sources_dir` convention) + all-or-nothing `@field_validator` (branch/base rejected — blank/whitespace/`..` — only while `docs_repo` is set, naming the field) + `docs_configured` property (inert-by-default, git-sources fallback pattern)
|
||||
- `alembic/versions/0011_doc_drafts.py` + `DocDraft` model: id UUID PK, `token` UUID unique NOT NULL (unguessable URL credential), title/path/body TEXT NOT NULL, status TEXT NOT NULL default `'draft'` (kind precedent), branch/commit_sha TEXT NULL, created_at/updated_at TIMESTAMPTZ; reversible
|
||||
- `app/schemas.py`: `DocDraftCreate` / `DocDraftUpdate` (partial) / `DocDraft` (full row) / `DocDraftPushed` (`Literal["pushed"]`)
|
||||
- `.env.example`: the specified commented section after the git-sources block
|
||||
|
||||
**Tests / lint / coverage:**
|
||||
- New: 9 config unit tests, 2 model-contract pins, 5 migration integration tests (house pattern: 0010→0011 upgrade, column/index contract, default + pushed-state round-trips, duplicate-token rejection, downgrade/round-trip)
|
||||
- `uv run alembic upgrade head` → 0010→0011 applied cleanly; DB at `0011 (head)`
|
||||
- `uv run pytest --cov=app` → 1131 passed (exit 0), TOTAL coverage **99%** (>90% gate)
|
||||
- `uv run ruff check .` → All checks passed; `uv run pyright` → 0 errors, 0 warnings
|
||||
|
||||
**Decisions:** none deviating — defaults/validation per task file; no commit made (the phase's atomic commit belongs to task 07; `.agents/` stays untracked).
|
||||
|
||||
**Next pending task:** `.agents/phases/todo/59_response_to_docs_push/02_drafts_api.md`
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
........................................................................ [ 6%]
|
||||
........................................................................ [ 12%]
|
||||
........................................................................ [ 19%]
|
||||
........................................................................ [ 25%]
|
||||
........................................................................ [ 32%]
|
||||
........................................................................ [ 38%]
|
||||
........................................................................ [ 45%]
|
||||
........................................................................ [ 51%]
|
||||
........................................................................ [ 57%]
|
||||
........................................................................ [ 64%]
|
||||
........................................................................ [ 70%]
|
||||
........................................................................ [ 77%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 90%]
|
||||
........................................................................ [ 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/chats.py 110 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/docs.py 50 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 101 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 86 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 198 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 2324 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
Task 02 complete. All gates green.
|
||||
|
||||
**Implemented**
|
||||
- `app/api/doc_drafts.py` — admin-only router (`dependencies=[Depends(require_admin)]`, steering pattern): `POST /api/doc-drafts` (201, `token=uuid4`, `status="draft"`, stripped title/body/path), `GET /{token}` (404 `draft not found`), `PUT /{token}` (partial, `updated_at` bumped — ORM onupdate on change, raw-UPDATE fallback for no-op PUTs; pushed→draft reset per D3, last-push branch/sha kept visible)
|
||||
- Shared public `validate_draft_path` guard (empty / absolute / `.`-`..` parts / suffix → 422 naming the rule) — reusable by task 04's push endpoint
|
||||
- `app/main.py`: router included in the existing `include_router` block
|
||||
- `tests/integration/test_doc_drafts_api.py`: 21 tests — create/get round-trip, partial + full + no-op updates, pushed-reset, all four guard-rail paths (POST + PUT), blank-field 422s, unknown/malformed-token 404/422, anonymous 403 on all three routes
|
||||
|
||||
**Results**
|
||||
- `uv run pytest --cov=app` → 1140 passed; TOTAL coverage **99%** (>90%); `doc_drafts.py` 100%
|
||||
- `uv run pytest tests/integration/test_doc_drafts_api.py -v --no-cov` → 21 passed
|
||||
- `uv run ruff check . && uv run pyright` → clean
|
||||
|
||||
**Notes**
|
||||
- Task 01's code (settings, model, migration 0011, schemas) was already in the tree, uncommitted; left as-is — phase commit belongs to task 07
|
||||
- Decision: PUT on a pushed draft resets only `status` (per pin); stale `branch`/`commit_sha` stay until the next push overwrites them (documented in docstring)
|
||||
|
||||
**Next pending task:** `03_docs_push_service.md` (app/core/docs_push.py)
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
........................................................................ [ 6%]
|
||||
........................................................................ [ 12%]
|
||||
........................................................................ [ 18%]
|
||||
........................................................................ [ 25%]
|
||||
........................................................................ [ 31%]
|
||||
........................................................................ [ 37%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 50%]
|
||||
........................................................................ [ 56%]
|
||||
........................................................................ [ 63%]
|
||||
........................................................................ [ 69%]
|
||||
........................................................................ [ 75%]
|
||||
........................................................................ [ 82%]
|
||||
........................................................................ [ 88%]
|
||||
........................................................................ [ 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/doc_drafts.py 75 0 100%
|
||||
app/api/docs.py 50 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 101 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 52 0 100%
|
||||
app/models.py 86 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 198 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 2401 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
Everything is green and the working tree is left functional (task 01/02 changes untouched; the atomic commit belongs to task 07). Final report:
|
||||
|
||||
**Implemented**
|
||||
- `scripts/git_sync.py`: `_run` promoted to public `run_git(argv, cwd) -> str` (verbatim behavior), `__all__` updated, `clone_or_pull` now calls it
|
||||
- `app/core/docs_push.py`: `DocsPushError` + `push_document(...) -> (branch, sha)` — clone-or-ensure on explicit base branch, base re-sync, tolerant branch fetch, branch attach, file write (defensive parts re-check), fixed-identity commit, ff-only push, `rev-parse HEAD`; D3 push-only stated in docstring
|
||||
- `tests/unit/test_docs_push.py`: 7 real-git tests vs a `tmp_path` bare repo (first push, ff re-push, fresh-checkout re-attach, non-ff failure, missing repo, non-repo dir, unsafe rel_path) with `pytest.skip` guard on `git --version`
|
||||
- `tests/unit/test_git_sync.py`: `_run` references renamed to `run_git` — clone_or_pull regressions green
|
||||
|
||||
**Results**
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → 1147 passed, TOTAL **99%** (docs_push.py 100%)
|
||||
- `uv run ruff check . && uv run pyright` → clean (0 errors)
|
||||
|
||||
**Notable deviations** (all empirically verified against this machine's git 2.55.0, Fedora 44)
|
||||
- `git push --ff-only` → plain `git push`: git 2.55 **removed the flag** (`unknown option`); a push without `-f`/`+` already refuses non-ff against live remote refs — same guarantee, portable to older git
|
||||
- Anchors are FETCH_HEAD **shas captured per successful fetch**: a failed fetch clears FETCH_HEAD, and local-path transport never creates `origin/<branch>` for a new branch
|
||||
- Existing local branch keeps its history (no blind `checkout -B` re-attach) — otherwise the spec's own non-ff test could never fire (reattach would silently rebase to ff)
|
||||
- `-c commit.gpgsign=false` added to the commit: global git config here has `commit.gpgsign=true`, which hangs plain commits on a GPG prompt
|
||||
|
||||
**Next pending task:** `.agents/phases/todo/59_response_to_docs_push/04_push_endpoint.md`
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
........................................................................ [ 6%]
|
||||
........................................................................ [ 12%]
|
||||
........................................................................ [ 18%]
|
||||
........................................................................ [ 25%]
|
||||
........................................................................ [ 31%]
|
||||
........................................................................ [ 37%]
|
||||
........................................................................ [ 43%]
|
||||
........................................................................ [ 50%]
|
||||
........................................................................ [ 56%]
|
||||
........................................................................ [ 62%]
|
||||
........................................................................ [ 69%]
|
||||
........................................................................ [ 75%]
|
||||
........................................................................ [ 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/doc_drafts.py 75 0 100%
|
||||
app/api/docs.py 50 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 101 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/docs_push.py 39 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 52 0 100%
|
||||
app/models.py 86 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 198 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 2440 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
Task 04 complete. The working tree also carries tasks 01–03's uncommitted work (the phase's atomic commit is task 07's job, per the phase overview).
|
||||
|
||||
## Report
|
||||
|
||||
**Implemented**
|
||||
- `POST /api/doc-drafts/{token}/push` in `app/api/doc_drafts.py` on the existing admin-gated router, taking `settings: Settings = Depends(get_settings)` (house pattern per `app/api/config.py`)
|
||||
- Outcome chain in spec order: 404 unknown token → 409 `"docs repo not configured (BOR_DOCS_REPO)"` when `settings.docs_configured` is false → 422 re-validating the stored `path` through the task-02 `validate_draft_path` guard → `push_document(...)` → 502 with `detail=str(exc)` (git's stderr, `GitSyncError`→`detail` mapping) leaving the row untouched
|
||||
- On success only: `status="pushed"`, `branch`, `commit_sha` recorded, `updated_at` bumped (model `onupdate` — a successful push always rewrites `commit_sha`), returns `DocDraftPushed(status="pushed", branch, commit_sha)`
|
||||
- Extended `tests/integration/test_doc_drafts_api.py`: 6 new push tests against a real local bare repo (task-03 fixture pattern) with `Settings(_env_file=None, …)` injected via `fastapi_app.dependency_overrides[get_settings]` — success (sha == `git rev-parse bor-docs`, `git show bor-docs:<path>` == body, fixed identity + `docs: <title>` message, row + GET updated, `updated_at` bumped), 409 naming the variable, 502 with git stderr (row stays draft), 404, 422 on a bad stored path (direct-DB insert), anonymous 403 (no branch created, row untouched)
|
||||
|
||||
**Results**
|
||||
- `uv run pytest tests/integration/test_doc_drafts_api.py -v --no-cov` → 27 passed
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → 1153 passed, TOTAL **99%** (`app/api/doc_drafts.py` 100%)
|
||||
- `uv run ruff check .` → clean; `uv run pyright` → 0 errors
|
||||
|
||||
**Decisions**
|
||||
- Settings injection via FastAPI `dependency_overrides[get_settings]` (the `Depends` captured function object is the `app.config` lru_cache'd one — module-attribute monkeypatching would not intercept it)
|
||||
- One assertion fix vs. draft: this git version's clone-refusal stderr is `fatal: repository '…' does not exist`, not "does not appear to be a git repository"
|
||||
|
||||
**Next pending task:** `.agents/phases/todo/59_response_to_docs_push/05_save_as_doc_button.md`
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
........................................................................ [ 6%]
|
||||
........................................................................ [ 12%]
|
||||
........................................................................ [ 18%]
|
||||
........................................................................ [ 24%]
|
||||
........................................................................ [ 31%]
|
||||
........................................................................ [ 37%]
|
||||
........................................................................ [ 43%]
|
||||
........................................................................ [ 49%]
|
||||
........................................................................ [ 56%]
|
||||
........................................................................ [ 62%]
|
||||
........................................................................ [ 68%]
|
||||
........................................................................ [ 74%]
|
||||
........................................................................ [ 81%]
|
||||
........................................................................ [ 87%]
|
||||
........................................................................ [ 93%]
|
||||
........................................................................ [ 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 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/doc_drafts.py 93 0 100%
|
||||
app/api/docs.py 50 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 101 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/docs_push.py 39 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 52 0 100%
|
||||
app/models.py 86 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 198 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 2458 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
All green. Task complete.
|
||||
|
||||
## Report — Phase 59, Task 05: "Save as doc" button
|
||||
|
||||
**Implemented**
|
||||
- `app/api/config.py`: `/api/config` gains `docs_repo_configured` (bool, tracks `settings.docs_configured`)
|
||||
- `brand.js`: parse-time fetch exposed as `window.BOR_CONFIG_PROMISE` (never rejects) + `window.BOR_DOCS_REPO_CONFIGURED` (inert false default), surfaced the way `app_name` is; DOM passes unchanged
|
||||
- `app.js`: boot awaits the config promise before any bubble renders (no second fetch, no flash); `appendSaveAsDocButton` (admin **and** configured, one/bubble, meta-row reuse, listitem ARIA) at live `done` (exact persisted raw text), the empty-answer fallback, and restore (`m.text`, gated `!m.stopped`); click → title = last user question (collapsed ≤120), path `docs/<slug>.md`, `POST /api/doc-drafts {title,path,body: raw markdown}` → `location.assign("/doc-edit.html?draft=" + token)`; failure = neutral one-line banner, no navigation, double-click guard released in `finally`
|
||||
- `markLastRetryable` re-appends the save button after Retry so it stays rightmost on the last bubble
|
||||
- `styles.css`: `.save-as-doc-btn` (tune-btn family + `margin-inline-start: auto`)
|
||||
- Tests: new `tests/unit/test_save_as_doc_button.py` (13 pins incl. the config unit pin); extended `tests/integration/test_api.py`; refreshed two stale `set(body)` pins (`test_api.py`, `test_configurable_brand.py`)
|
||||
|
||||
**Results**
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → 1166 passed, TOTAL **99%** (>90%)
|
||||
- `uv run ruff check .` clean; `uv run pyright` 0 errors; `node --check` both JS files OK
|
||||
- E2E in isolation: `test_chat_rag.py` 3✓, `test_admin_auth.py`+`test_cache_busting.py`+`test_chat_history.py` 15✓, `test_configurable_brand.py` 5✓
|
||||
|
||||
**Decisions**
|
||||
- Empty-answer fallback bubble gets the button (restore parity: "every completed bubble"); stopped partials don't (note ≠ answer)
|
||||
- Local named `saveDocBtn` — phase 55 pins the `saveBtn` identifier absent from app.js
|
||||
- No commit made: phase 59 commits atomically in task 07
|
||||
|
||||
**Next pending task:** `06_edit_screen.md`
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
........................................................................ [ 6%]
|
||||
........................................................................ [ 12%]
|
||||
........................................................................ [ 18%]
|
||||
........................................................................ [ 24%]
|
||||
........................................................................ [ 30%]
|
||||
........................................................................ [ 37%]
|
||||
........................................................................ [ 43%]
|
||||
........................................................................ [ 49%]
|
||||
........................................................................ [ 55%]
|
||||
........................................................................ [ 61%]
|
||||
........................................................................ [ 67%]
|
||||
........................................................................ [ 74%]
|
||||
........................................................................ [ 80%]
|
||||
........................................................................ [ 86%]
|
||||
........................................................................ [ 92%]
|
||||
........................................................................ [ 98%]
|
||||
.............. [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/doc_drafts.py 93 0 100%
|
||||
app/api/docs.py 50 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 101 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/docs_push.py 39 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 52 0 100%
|
||||
app/models.py 86 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 198 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 2458 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
All verification complete. Final state confirmed:
|
||||
|
||||
**Implemented (task 06 — the edit screen)**
|
||||
- `frontend/doc-edit.html` — house flow-page shell (no CDN): skip-link, slim header (brand + "Back to chat" → `/`), 46rem **hard-coded** form column (not `--chat-column`), `#draft-title`/`#draft-path`/`#draft-body` (labeled, mono path/body, 20rem floor), `#push-doc-btn` "Push to docs branch" + back link, `#push-status` (role=status, aria-live) + hidden `#push-error` (role=alert), `sources-gate` admin gate (ship-hidden, `?next=/doc-edit.html` fallback)
|
||||
- `frontend/assets/doc-edit.js` — whoami gate (anonymous: gate, **zero** draft API calls), token handling (missing → "No draft specified."; non-uuid → "Draft not found.", no fetch), GET draft (values, never markup), push = sanity → disable/"Pushing…" → **PUT edits → POST push** (endpoint commits the row), success "Pushed to \<branch\> — commit \<sha7\>.", failure banner with git stderr trimmed to first meaningful lines + fields preserved + re-enable (never stale)
|
||||
- 21 unit pins in `tests/unit/test_doc_edit_screen.py` (HTML/JS/CSS)
|
||||
- House-contract wiring: `/doc-edit.html` in `caching.HTML_PAGES` (no-cache + `?v=` rewrite), Containerfile stage-1 (cp + esbuild bundle), page tuples in `test_frontend_brand.py`/`test_caching.py`
|
||||
|
||||
**Results**
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → **1187 passed, 0 failed/skipped; TOTAL 99%** (caching.py 100%)
|
||||
- `uv run ruff check . && uv run pyright` → clean
|
||||
- Real-browser check vs local bare repo: gate/no-leak, load, push (sha = `git rev-parse bor-docs`), re-push (2 commits), non-ff failure banner with git stderr + preserved edits — all pass
|
||||
|
||||
**Decisions**
|
||||
- Push persists edits via PUT first (push endpoint commits the stored row — the task's "three API paths")
|
||||
- Phase-58 pin updated: `.doc-edit-shell` is now a second hard-coded 46rem form column (task-06 mandates no `--chat-column`)
|
||||
- Flagged edge (left fail-loud, task-03 service untouched): re-pushing byte-identical content → 502 with git's "nothing to commit" stderr
|
||||
|
||||
**Next pending task:** `07_e2e_response_to_docs.md` (story Playwright suite + regressions + atomic commit)
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
........................................................................ [ 6%]
|
||||
........................................................................ [ 12%]
|
||||
........................................................................ [ 18%]
|
||||
........................................................................ [ 24%]
|
||||
........................................................................ [ 30%]
|
||||
........................................................................ [ 36%]
|
||||
........................................................................ [ 42%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 54%]
|
||||
........................................................................ [ 60%]
|
||||
........................................................................ [ 66%]
|
||||
........................................................................ [ 72%]
|
||||
........................................................................ [ 78%]
|
||||
........................................................................ [ 84%]
|
||||
........................................................................ [ 90%]
|
||||
........................................................................ [ 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/chats.py 110 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/doc_drafts.py 93 0 100%
|
||||
app/api/docs.py 50 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 101 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/docs_push.py 39 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 52 0 100%
|
||||
app/models.py 86 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 198 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 2458 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
Everything is green and committed. The phase-dir move to `complete/` is left to the harness (per the isolation rules; `.agents/` is gitignored anyway).
|
||||
|
||||
**Phase 59, task 07 — complete**
|
||||
|
||||
- **E2E suite** `tests/e2e/test_response_to_docs.py` (4 tests, bare repo as source of truth):
|
||||
- `test_save_edit_push` — save button bottom-right (x past bubble midline) → `/doc-edit.html?draft=<uuid>` prefilled (auto-title, `docs/<slug>.md`, body == exact markdown source via deterministic SSE replay) → edit + push → `git show bor-docs:<path>` == edited body, UI sha7 == `rev-parse bor-docs`[:7], 1 commit beyond main
|
||||
- `test_second_push_fast_forwards` — unedited second push → `rev-list --count main..bor-docs` == 2, file 1 byte-identical
|
||||
- `test_guest_has_no_button` — no button, httpx 403, edit screen gates with zero draft-API calls
|
||||
- `test_unconfigured_hides_button` — second app boot (no `BOR_DOCS_REPO`, port+1): no button for admin, draft 201, push 409 naming the variable
|
||||
- **Cache busting**: `/doc-edit.html` added to the walked page list
|
||||
- **Results**: `uv run pytest` 1187 passed · `--cov=app` TOTAL **99%** (>90%) · `tests/e2e/test_response_to_docs.py -v --no-cov` 4 passed (isolated, DB up) · regressions isolated: chat_rag 3 ✓, admin_auth 6 ✓, cache_busting 4 ✓, chat_history 5 ✓ · `ruff check .` + `pyright` clean
|
||||
- **Commit**: one atomic `--no-gpg-sign` commit `725af9f` (overview's exact message, 32 files); staged `scripts/` + `Containerfile` + `alembic/versions/0011` beyond the overview's add-list — all are task 01–06 phase-59 work required for the tree to function at HEAD
|
||||
- **Notable**: seed commit uses `-c commit.gpgsign=false` (global gitconfig signs by default); no PR/`gh`/GitHub logic anywhere in `app/`/`frontend/` (grep-verified)
|
||||
- **Next pending task**: `60_sticky_navbar/01_sticky_header_css.md`
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
........................................................................ [ 6%]
|
||||
........................................................................ [ 12%]
|
||||
........................................................................ [ 18%]
|
||||
........................................................................ [ 24%]
|
||||
........................................................................ [ 30%]
|
||||
........................................................................ [ 36%]
|
||||
........................................................................ [ 42%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 54%]
|
||||
........................................................................ [ 60%]
|
||||
........................................................................ [ 66%]
|
||||
........................................................................ [ 72%]
|
||||
........................................................................ [ 78%]
|
||||
........................................................................ [ 84%]
|
||||
........................................................................ [ 90%]
|
||||
........................................................................ [ 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/chats.py 110 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/doc_drafts.py 93 0 100%
|
||||
app/api/docs.py 50 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 101 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/docs_push.py 39 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 52 0 100%
|
||||
app/models.py 86 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 198 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 2458 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