chore(agent): track .agent/ planning tree in git
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:
@@ -0,0 +1,12 @@
|
||||
All gates verified green — this was a verification pass only, no defects found, nothing changed.
|
||||
|
||||
**Phase 32 — Admin Sync Button: final verification report**
|
||||
|
||||
- Verified (no code changes needed): `app/api/sync.py` in-process runner (202/409/status state machine, credential masking), admin-only `#sync-btn` in `sources.html` + `header.js` reveal + `sources.js` 2 s poll state machine, README "Sync from the UI" section, story file, phase commit `52136fe`.
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → 515 passed; TOTAL **99%** (`app/api/sync.py` 100%; ≥ pre-change: 1359 stmts/12 miss vs ≈1290/12).
|
||||
- `uv run pytest tests/e2e/test_sync_button.py -v --no-cov` → 3 passed in isolation (real `file://` git fixture, admin lifecycle, idempotent re-run, kb_overview freshness).
|
||||
- Regression E2E `test_admin_auth` + `test_shared_header` + `test_import_documents` (+ `test_global_tuning`) → 21 passed.
|
||||
- `uv run ruff check .` → clean; `uv run pyright` → 0 errors.
|
||||
- Completion criteria: anonymous 403/hidden ✓ · admin lifecycle (202 → Syncing… → Synced HH:MM + counts / error banner) ✓ · double-trigger 409 + no second poll loop ✓ · fixture doc in Sources table + fresh `kb_overview` ✓ · full suite + coverage ✓ · E2E + regressions ✓ · lint/types ✓ · README + story file ✓ · `--no-gpg-sign` commit ✓ (phase-file move left to the harness; task files already in `complete/`).
|
||||
- Notable: uncommitted worktree diffs (`.agent/` phase-file moves, `TODO.md`) are harness-managed — left untouched per rules.
|
||||
- Next pending phase: **33_cache_busting**.
|
||||
@@ -0,0 +1,52 @@
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 27%]
|
||||
........................................................................ [ 41%]
|
||||
........................................................................ [ 55%]
|
||||
........................................................................ [ 69%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 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 103 0 100%
|
||||
app/api/docs.py 23 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 67 0 100%
|
||||
app/config.py 64 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 20 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 38 0 100%
|
||||
app/models.py 53 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/importer.py 173 3 98%
|
||||
app/rag/llm.py 118 0 100%
|
||||
app/rag/overview.py 71 0 100%
|
||||
app/rag/prompts.py 64 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 68 0 100%
|
||||
--------------------------------------------
|
||||
TOTAL 1359 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
@@ -0,0 +1,15 @@
|
||||
All gates green. Final report:
|
||||
|
||||
**Implemented (task 01 — sync API):**
|
||||
- `app/api/sync.py`: `SyncStatus` dataclass + module-level `_status`/`_task`; `GET /api/sync/status` and `POST /api/sync` (both behind `require_admin`); `POST` → 202 + `asyncio.create_task(_run_sync())`, 409 `a sync is already running` when in flight; `_run_sync` runs `clone_or_pull` per `BOR_GIT_SOURCES` repo → `import_sources(prune=True)` → change-gated `regenerate_overview`; success/failed states, ISO-8601 timestamps, `sync: done/failed` logging, credential-masking error sanitizer
|
||||
- `app/main.py`: `sync_router` included under `/api` (after the other routers, before the static mount — no precedence changes)
|
||||
- `tests/integration/test_sync_api.py`: 7 tests — anonymous 403s, admin idle→202→success (full ImportSummary detail + `overview: true`), `prune=True` assertion, 409 double-trigger (running state shape), `GitSyncError` → failed naming the repo with zero import calls, empty `BOR_GIT_SOURCES` → failed loudly, `EmbeddingError` → failed with `user:pass@` masked, unchanged-KB overview skip
|
||||
|
||||
**Results:**
|
||||
- `uv run pytest` → 495 passed (pre-change: 488); `tests/integration/test_chat_api.py` → 13 passed (SSE untouched)
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → `app/api/sync.py` 100%, TOTAL 99% (1359 stmts, 12 missed — identical miss set to pre-change baseline)
|
||||
- `uv run ruff check . && uv run pyright` → clean (0 errors)
|
||||
|
||||
**Decisions:** `start_sync` is `async def` so `create_task` binds to the app event loop (a sync `def` runs in the threadpool with no running loop); integration tests use a context-managed `TestClient` so the loop survives across requests (per-request portals would cancel the background task — mirrors uvicorn); `CancelledError` deliberately uncaught (clean shutdown); commit deferred to task 03 per the phase plan.
|
||||
|
||||
**Next pending task:** `.agent/phases/todo/32_admin_sync_button/02_ui_button.md`
|
||||
@@ -0,0 +1,51 @@
|
||||
........................................................................ [ 14%]
|
||||
........................................................................ [ 29%]
|
||||
........................................................................ [ 43%]
|
||||
........................................................................ [ 58%]
|
||||
........................................................................ [ 72%]
|
||||
........................................................................ [ 87%]
|
||||
............................................................... [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 103 0 100%
|
||||
app/api/docs.py 23 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 67 0 100%
|
||||
app/config.py 64 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 20 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 38 0 100%
|
||||
app/models.py 53 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/importer.py 173 3 98%
|
||||
app/rag/llm.py 118 0 100%
|
||||
app/rag/overview.py 71 0 100%
|
||||
app/rag/prompts.py 64 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 68 0 100%
|
||||
--------------------------------------------
|
||||
TOTAL 1359 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
@@ -0,0 +1,14 @@
|
||||
Everything is green and the scope is exactly this task's files (the `app/` + integration-test entries are task 01's uncommitted work, committed by task 03 per phase protocol).
|
||||
|
||||
**Report — phase 32, task 02 (admin Sync button UI)**
|
||||
|
||||
- `sources.html`: `#sync-btn` (ship-`hidden`, `aria-label="Sync sources"`, refresh svg + `#sync-label`), `#sync-result` (`role="status"` + `aria-live="polite"`) after the button in the shared header; `#sync-error-banner` (`kb-banner is-error`, `role="alert"`, hidden); page-sub copy extended to name the button.
|
||||
- `header.js`: `#sync-btn` joined the `initSharedHeader` admin reveal — same cached whoami as `#nav-sources`/`#nav-tuning`, no extra fetch.
|
||||
- `sources.js`: isolated sync state machine — click → `POST /api/sync` (202 → running; 409 adopts the in-flight run), disabled + `aria-busy` + spinning icon + "Syncing…", 2000 ms `GET /api/sync/status` poll (single-loop guard, no client hard timeout); success → "Synced HH:MM" (local, 24-h) + `{added} added · …` counts (zero terms omitted, aria-live); failed → retry-ready label + `role="alert"` banner with the error; 403 hides the button (POST, poll, and load re-attach); reload re-attaches running/terminal state; idle-observed (server restart) re-enables without banner.
|
||||
- `styles.css`: `.sync-btn` ghost pill (ink-soft on surface ≈6.9:1, ≥44px, `:disabled`), `.is-spinning` on shared `spin` keyframes with `prefers-reduced-motion` opt-out, `.sync-result` styling; ≤640px icon-only pill + visually-hidden (still announced) result — verified no 375px header overflow.
|
||||
- `tests/unit/test_sync_button.py` (new, 20 tests): markup, reveal, API/poll/409/403, terminal states, single-loop guard, no-timeout, CSS states, no-CDN.
|
||||
- Dev-server manual check (Playwright, real login): anonymous hidden → admin reveal → click → "Syncing…" (disabled, spinning) → failed banner naming `no git sources configured (BOR_GIT_SOURCES)` → retry-ready → reload re-attach → banner clears on new run → sign-out hides again. All passed.
|
||||
- `uv run pytest --cov=app --cov-report=term-missing`: 515 passed, TOTAL 99% (unchanged; app/ untouched). `uv run ruff check .` clean; `uv run pyright`: 0 errors.
|
||||
- Regression E2E: `test_shared_header.py` + `test_admin_auth.py` + `test_import_documents.py` = 15 passed.
|
||||
- Deviations: none (the success path is exercised by task 03's E2E, as the task mandates).
|
||||
- Next pending task: `32_admin_sync_button/03_e2e_and_docs.md` (the phase's final task — E2E + README + story file + commit).
|
||||
@@ -0,0 +1,52 @@
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 27%]
|
||||
........................................................................ [ 41%]
|
||||
........................................................................ [ 55%]
|
||||
........................................................................ [ 69%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 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 103 0 100%
|
||||
app/api/docs.py 23 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 67 0 100%
|
||||
app/config.py 64 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 20 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 38 0 100%
|
||||
app/models.py 53 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/importer.py 173 3 98%
|
||||
app/rag/llm.py 118 0 100%
|
||||
app/rag/overview.py 71 0 100%
|
||||
app/rag/prompts.py 64 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 68 0 100%
|
||||
--------------------------------------------
|
||||
TOTAL 1359 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
@@ -0,0 +1,14 @@
|
||||
All green and committed. Final report:
|
||||
|
||||
**Implemented (task 03 — E2E + docs + commit)**
|
||||
- `tests/e2e/test_sync_button.py`: real `file://` git fixture (subprocess `git init`/commit, sentinel `RESE-SYNC-SENTINEL-9b2c`), module-scoped `app_server` override with `BOR_GIT_SOURCES`/`BOR_SOURCES_DIR` (conftest per-module env pattern), KB-truncation isolation; tests: anonymous (button hidden + both endpoints 403), full admin lifecycle (Sync sources → Syncing… disabled → Synced HH:MM, `1 added`, fixture row in `#docs-tbody`, fresh `kb_overview` DB check, idempotent 2nd run `0 added · 1 unchanged`), 409 double-trigger
|
||||
- Defects fixed in prior tasks: `fmtSyncResult` omitted all zero terms (no-op run rendered an empty live region) — "added" always announced, "unchanged" covers no-op; `applySyncSuccess` now re-runs `loadDocs()` so the catalog never sits stale after a sync (both pinned in `tests/unit/test_sync_button.py`)
|
||||
- README "Sync from the UI" subsection; `.agent/user_stories/admin-sync-button.md` (narrative + 7 ACs + Playwright mapping)
|
||||
|
||||
**Gates**
|
||||
- `uv run pytest tests/e2e/test_sync_button.py -v --no-cov` → 3 passed (stable across 4 isolated runs)
|
||||
- Regression isolated: `test_admin_auth` 6, `test_shared_header` 6, `test_import_documents` 3, `test_global_tuning` 6 — all passed
|
||||
- `uv run pytest` → 515 passed; `--cov=app` → TOTAL 99% (`app/api/sync.py` 100%)
|
||||
- `uv run ruff check .` clean; `uv run pyright` → 0 errors
|
||||
|
||||
**Commit**: `52136fe feat(admin): one-click sources sync — …` (13 files, `--no-gpg-sign`, phase files only; phase-dir move left to the harness per rules). Next pending: `33_cache_busting/01_asset_version_token.md`.
|
||||
@@ -0,0 +1,52 @@
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 27%]
|
||||
........................................................................ [ 41%]
|
||||
........................................................................ [ 55%]
|
||||
........................................................................ [ 69%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 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 103 0 100%
|
||||
app/api/docs.py 23 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 67 0 100%
|
||||
app/config.py 64 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 20 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 38 0 100%
|
||||
app/models.py 53 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/importer.py 173 3 98%
|
||||
app/rag/llm.py 118 0 100%
|
||||
app/rag/overview.py 71 0 100%
|
||||
app/rag/prompts.py 64 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 68 0 100%
|
||||
--------------------------------------------
|
||||
TOTAL 1359 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