diff --git a/.agents/phases/todo/101_tokens_page_overhaul/00_phase.md b/.agents/phases/complete/101_tokens_page_overhaul/00_phase.md similarity index 100% rename from .agents/phases/todo/101_tokens_page_overhaul/00_phase.md rename to .agents/phases/complete/101_tokens_page_overhaul/00_phase.md diff --git a/.agents/phases/todo/101_tokens_page_overhaul/01_regenerate_api.md b/.agents/phases/complete/101_tokens_page_overhaul/01_regenerate_api.md similarity index 100% rename from .agents/phases/todo/101_tokens_page_overhaul/01_regenerate_api.md rename to .agents/phases/complete/101_tokens_page_overhaul/01_regenerate_api.md diff --git a/.agents/phases/todo/101_tokens_page_overhaul/02_two_tables_search_required_name.md b/.agents/phases/complete/101_tokens_page_overhaul/02_two_tables_search_required_name.md similarity index 100% rename from .agents/phases/todo/101_tokens_page_overhaul/02_two_tables_search_required_name.md rename to .agents/phases/complete/101_tokens_page_overhaul/02_two_tables_search_required_name.md diff --git a/.agents/phases/todo/101_tokens_page_overhaul/03_regenerate_ui.md b/.agents/phases/complete/101_tokens_page_overhaul/03_regenerate_ui.md similarity index 100% rename from .agents/phases/todo/101_tokens_page_overhaul/03_regenerate_ui.md rename to .agents/phases/complete/101_tokens_page_overhaul/03_regenerate_ui.md diff --git a/.agents/phases/todo/101_tokens_page_overhaul/04_e2e_tokens_page.md b/.agents/phases/complete/101_tokens_page_overhaul/04_e2e_tokens_page.md similarity index 100% rename from .agents/phases/todo/101_tokens_page_overhaul/04_e2e_tokens_page.md rename to .agents/phases/complete/101_tokens_page_overhaul/04_e2e_tokens_page.md diff --git a/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__00_phase.a1.err b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__00_phase.a1.err new file mode 100644 index 0000000..e69de29 diff --git a/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__00_phase.a1.md b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__00_phase.a1.md new file mode 100644 index 0000000..36302ea --- /dev/null +++ b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__00_phase.a1.md @@ -0,0 +1,20 @@ +All gates verified green — no defects found, nothing to fix. Final report: + +## Phase 101 — final verification pass (all tasks already complete; verified, not re-implemented) + +**Verified against the working tree** (task files 01–04 present in `complete/`): +- Active/revoked table split (Status column gone, section hidden while 0 revoked, per-table search with query state surviving re-renders) in `frontend/index.html` + `tokens.js` +- `generateToken()` refuses blank/whitespace names (`Give the token a name first.`, no request); `|| "token"` fallback deleted +- Atomic rotation: `regenerate_token` service + `POST /api/tokens/{id}/regenerate` (201 new-plaintext-once / 404 / 409 / router-wide 403) + `TokenListItem.revoked_at` (D5) +- Regenerate two-step confirm UI + CSS (`.token-regenerate`, neutral hover, no new hue); A4 pins intact + +**Test / lint / coverage results:** +- `uv run pytest` → **2065 passed** +- `uv run pytest --cov=app --cov-report=term-missing` → **TOTAL 99%** (>90% ✓) +- `uv run ruff check . && uv run pyright` → clean (0 errors) +- `uv run pytest tests/e2e/test_tokens_page.py -v --no-cov` → **4 passed** (isolation, DB up) +- Regression, each in isolation: `test_api_tokens.py` **9 passed**, `test_admin_auth.py` **6 passed**, `test_shared_header.py` **6 passed**, `test_theme_semantic_completion.py` **8 passed** (its revoked-pill pin was correctly re-scoped to the revoked table in this phase) + +**Completion criteria:** 1 ✓ split+search (E2E 1–2) · 2 ✓ required name (E2E 3 + source pin) · 3 ✓ rotation end-to-end, old token refused at gate (E2E 4 + API 404/409 pinned) · 4 ✓ A4 holds (list carries no plaintext/hashes) · 5 ✓ suite/coverage/lint green · 6 ✓ E2E + regressions green in isolation · 7 commit left to the harness per executor rules (all changes uncommitted in the working tree) + +**Deviations:** none. Next pending phase: `98_sync_summary_visibility`. diff --git a/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__00_phase.a1.validate b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__00_phase.a1.validate new file mode 100644 index 0000000..564acd4 --- /dev/null +++ b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__00_phase.a1.validate @@ -0,0 +1,96 @@ +........................................................................ [ 3%] +........................................................................ [ 6%] +........................................................................ [ 10%] +........................................................................ [ 13%] +........................................................................ [ 17%] +........................................................................ [ 20%] +........................................................................ [ 24%] +........................................................................ [ 27%] +........................................................................ [ 31%] +........................................................................ [ 34%] +........................................................................ [ 38%] +........................................................................ [ 41%] +........................................................................ [ 45%] +........................................................................ [ 48%] +........................................................................ [ 52%] +........................................................................ [ 55%] +........................................................................ [ 59%] +........................................................................ [ 62%] +........................................................................ [ 66%] +........................................................................ [ 69%] +........................................................................ [ 73%] +........................................................................ [ 76%] +........................................................................ [ 80%] +........................................................................ [ 83%] +........................................................................ [ 87%] +........................................................................ [ 90%] +........................................................................ [ 94%] +........................................................................ [ 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 52 0 100% +app/api/chat.py 181 0 100% +app/api/chats.py 110 0 100% +app/api/config.py 13 0 100% +app/api/doc_drafts.py 94 0 100% +app/api/docs.py 127 1 99% +app/api/git_sources.py 229 0 100% +app/api/health.py 10 0 100% +app/api/steering.py 42 0 100% +app/api/suggestions.py 29 0 100% +app/api/sync.py 115 0 100% +app/api/tokens.py 40 0 100% +app/api/ui_settings.py 55 0 100% +app/config.py 140 0 100% +app/core/__init__.py 0 0 100% +app/core/auth.py 45 0 100% +app/core/caching.py 124 0 100% +app/core/debugging.py 29 2 93% +app/core/docs_push.py 39 0 100% +app/core/errors.py 5 0 100% +app/core/logging.py 13 0 100% +app/core/rate_limit.py 44 0 100% +app/core/security_headers.py 20 0 100% +app/core/theming.py 38 0 100% +app/core/tokens.py 44 0 100% +app/db.py 21 0 100% +app/main.py 66 0 100% +app/models.py 125 0 100% +app/rag/__init__.py 0 0 100% +app/rag/agent.py 316 1 99% +app/rag/archive_upload.py 128 0 100% +app/rag/chunker.py 206 4 98% +app/rag/folder_summaries.py 121 0 100% +app/rag/git_sources.py 14 0 100% +app/rag/importer.py 190 3 98% +app/rag/llm.py 243 1 99% +app/rag/overview.py 71 0 100% +app/rag/prompts.py 88 0 100% +app/rag/retriever.py 150 3 98% +app/rag/scaffolding.py 55 0 100% +app/rag/source_removal.py 41 0 100% +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 307 0 100% +-------------------------------------------------- +TOTAL 3848 15 99% +coverage gate: app/ 99% (>90%) OK +All checks passed! +0 errors, 0 warnings, 0 informations +WARNING: there is a new pyright version available (v1.1.411 -> v1.1.414). +Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest` + +validation OK diff --git a/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__01_regenerate_api.a1.err b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__01_regenerate_api.a1.err new file mode 100644 index 0000000..e69de29 diff --git a/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__01_regenerate_api.a1.md b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__01_regenerate_api.a1.md new file mode 100644 index 0000000..eb44c4b --- /dev/null +++ b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__01_regenerate_api.a1.md @@ -0,0 +1,19 @@ +Task 01 complete — everything green. + +**Implemented** +- `app/core/tokens.py`: `TokenAlreadyRevoked` exception + `regenerate_token(db, token_id)` — atomic rotation (revoke-stamp + same-label successor create in one flush-only unit; caller owns the single commit), `None` for unknown id; module docstring carries the rotation/A4 contract. +- `app/api/tokens.py`: `POST /api/tokens/{id}/regenerate` → 201 `TokenCreated` (new row's one plaintext moment), 404 `token not found`, 409 `token already revoked`; router-wide `require_admin` covers it; `list_tokens` now passes `revoked_at`. +- `app/schemas.py`: `TokenListItem.revoked_at: datetime | None = None` (D5, wire-additive, docstring pinned). + +**Tests** +- Unit (`tests/unit/test_tokens.py`): rotation matrix — new row/same label/well-formed plaintext/hash round-trip, old row stamped, old plaintext dead, missing → `None`, revoked → raises, rollback undoes BOTH writes (service never commits). +- Integration (`tests/integration/test_tokens_api.py`): 201 rotation (old row revoked w/ ISO `revoked_at`, new row active + newer `created_at` via deterministic gap, A4 list stays secret-free), 404, 409 (row untouched), 403 anonymous on all routes + 403 token-user; phase-79 list pins updated in place for the new field. + +**Results** +- `uv run pytest --cov=app --cov-report=term-missing` → 2060 passed, TOTAL 99% (>90%; tokens modules 100%) +- `uv run ruff check .` → clean; `uv run pyright` → 0 errors +- Regression: `tests/integration/test_auth_api.py` (17) and `uv run pytest tests/e2e/test_api_tokens.py --no-cov` (9) green in isolation + +**Decisions**: none beyond spec; kept house conventions (service flushes/endpoint commits, one message per 404/409, docstring-carried contracts). + +**Next pending task**: `.agents/phases/todo/101_tokens_page_overhaul/02_two_tables_search_required_name.md` diff --git a/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__01_regenerate_api.a1.validate b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__01_regenerate_api.a1.validate new file mode 100644 index 0000000..97c64f7 --- /dev/null +++ b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__01_regenerate_api.a1.validate @@ -0,0 +1,96 @@ +........................................................................ [ 3%] +........................................................................ [ 6%] +........................................................................ [ 10%] +........................................................................ [ 13%] +........................................................................ [ 17%] +........................................................................ [ 20%] +........................................................................ [ 24%] +........................................................................ [ 27%] +........................................................................ [ 31%] +........................................................................ [ 34%] +........................................................................ [ 38%] +........................................................................ [ 41%] +........................................................................ [ 45%] +........................................................................ [ 48%] +........................................................................ [ 52%] +........................................................................ [ 55%] +........................................................................ [ 59%] +........................................................................ [ 62%] +........................................................................ [ 66%] +........................................................................ [ 69%] +........................................................................ [ 73%] +........................................................................ [ 76%] +........................................................................ [ 80%] +........................................................................ [ 83%] +........................................................................ [ 87%] +........................................................................ [ 90%] +........................................................................ [ 94%] +........................................................................ [ 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 52 0 100% +app/api/chat.py 181 0 100% +app/api/chats.py 110 0 100% +app/api/config.py 13 0 100% +app/api/doc_drafts.py 94 0 100% +app/api/docs.py 127 1 99% +app/api/git_sources.py 229 0 100% +app/api/health.py 10 0 100% +app/api/steering.py 42 0 100% +app/api/suggestions.py 29 0 100% +app/api/sync.py 115 0 100% +app/api/tokens.py 40 0 100% +app/api/ui_settings.py 55 0 100% +app/config.py 140 0 100% +app/core/__init__.py 0 0 100% +app/core/auth.py 45 0 100% +app/core/caching.py 124 0 100% +app/core/debugging.py 29 2 93% +app/core/docs_push.py 39 0 100% +app/core/errors.py 5 0 100% +app/core/logging.py 13 0 100% +app/core/rate_limit.py 44 0 100% +app/core/security_headers.py 20 0 100% +app/core/theming.py 38 0 100% +app/core/tokens.py 44 0 100% +app/db.py 21 0 100% +app/main.py 66 0 100% +app/models.py 125 0 100% +app/rag/__init__.py 0 0 100% +app/rag/agent.py 316 1 99% +app/rag/archive_upload.py 128 0 100% +app/rag/chunker.py 206 4 98% +app/rag/folder_summaries.py 121 0 100% +app/rag/git_sources.py 14 0 100% +app/rag/importer.py 190 3 98% +app/rag/llm.py 243 1 99% +app/rag/overview.py 71 0 100% +app/rag/prompts.py 88 0 100% +app/rag/retriever.py 150 3 98% +app/rag/scaffolding.py 55 0 100% +app/rag/source_removal.py 41 0 100% +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 307 0 100% +-------------------------------------------------- +TOTAL 3848 15 99% +coverage gate: app/ 99% (>90%) OK +All checks passed! +0 errors, 0 warnings, 0 informations +WARNING: there is a new pyright version available (v1.1.411 -> v1.1.414). +Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest` + +validation OK diff --git a/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__02_two_tables_search_required_name.a1.err b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__02_two_tables_search_required_name.a1.err new file mode 100644 index 0000000..e69de29 diff --git a/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__02_two_tables_search_required_name.a1.md b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__02_two_tables_search_required_name.a1.md new file mode 100644 index 0000000..7550038 --- /dev/null +++ b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__02_two_tables_search_required_name.a1.md @@ -0,0 +1,14 @@ +All green. Task 02 is complete. + +**Implemented (phase 101, task 02 — two tables, per-table search, required name):** +- `frontend/index.html` `#view-tokens`: 4-column active table (Status `` gone, empty row `colspan=4`), new ship-hidden `#tokens-no-match-row`, both `type=search` inputs (`#token-search-active/-revoked`, `.token-search`), and the new ship-hidden revoked section (heading + search + 4-column table with `Revoked` column) below the active wrap; create row now `aria-label="Token name"` / `e.g. alice — required` +- `frontend/assets/tokens.js`: `loadTokens` splits by `tok.revoked` (server order kept), `setRevokedSectionVisible(n)` (heading+search+wrap shown iff ≥1 revoked), `applyFilter` (case-insensitive label substring, state rows excluded, no-match copy `No tokens match "".`), persistent `activeQuery`/`revokedQuery` re-applied after every render, input listeners armed in the admin branch (no fetch), D3 required-name block (`Give the token a name first.` + re-focus, no request); `confirmRevoke` now relocates the row to the revoked table via the re-entrant load (its `revoked_at` cell needs the server stamp); `|| "token"` fallback deleted +- `styles.css`: `.token-search` (house input surface, full-width, ≥44px), `.tokens-revoked-heading` (phase-97 mono voice); empty/no-match styling already class-based (no-op) +- Source pins: 3 new tests in `tests/unit/test_frontend_router.py` (scaffold, JS split/search/name, CSS) — all pre-existing phase-79 pins still pass +- Defect fixes (in place): `tests/e2e/test_api_tokens.py` revoked-row assertions moved to `#tokens-revoked-tbody` (per phase plan task 04 item 5); `test_theme_semantic_completion.py::test_revoked_pill_gray_labeled` → `test_revoked_table_state_labeled` (pill intentionally gone — D1) + +**Gates:** `uv run pytest --cov=app` → 2063 passed, app 99% (>90%) · `ruff check .` clean · `pyright` 0/0/0 · E2E in isolation: `test_api_tokens.py` 9 ✓, `test_theme_semantic_completion.py` 8 ✓, `test_history_page_width`+`test_admin_auth`+`test_shared_header` 17 ✓ (34 combined); temp in-browser verification of search/re-show/revoke split passed (file deleted) + +**Decisions:** state rows (empty + no-match) excluded from the filter per 00_phase "(no-match/empty rows excluded)"; no-match text quotes the original untrimmed query; no mobile CSS change needed (class-based). + +**Next pending task:** `03_regenerate_ui.md` (Regenerate control + CSS + source pins) diff --git a/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__02_two_tables_search_required_name.a1.validate b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__02_two_tables_search_required_name.a1.validate new file mode 100644 index 0000000..2cc6b5f --- /dev/null +++ b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__02_two_tables_search_required_name.a1.validate @@ -0,0 +1,96 @@ +........................................................................ [ 3%] +........................................................................ [ 6%] +........................................................................ [ 10%] +........................................................................ [ 13%] +........................................................................ [ 17%] +........................................................................ [ 20%] +........................................................................ [ 24%] +........................................................................ [ 27%] +........................................................................ [ 31%] +........................................................................ [ 34%] +........................................................................ [ 38%] +........................................................................ [ 41%] +........................................................................ [ 45%] +........................................................................ [ 48%] +........................................................................ [ 52%] +........................................................................ [ 55%] +........................................................................ [ 59%] +........................................................................ [ 62%] +........................................................................ [ 66%] +........................................................................ [ 69%] +........................................................................ [ 73%] +........................................................................ [ 76%] +........................................................................ [ 80%] +........................................................................ [ 83%] +........................................................................ [ 87%] +........................................................................ [ 90%] +........................................................................ [ 94%] +........................................................................ [ 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 52 0 100% +app/api/chat.py 181 0 100% +app/api/chats.py 110 0 100% +app/api/config.py 13 0 100% +app/api/doc_drafts.py 94 0 100% +app/api/docs.py 127 1 99% +app/api/git_sources.py 229 0 100% +app/api/health.py 10 0 100% +app/api/steering.py 42 0 100% +app/api/suggestions.py 29 0 100% +app/api/sync.py 115 0 100% +app/api/tokens.py 40 0 100% +app/api/ui_settings.py 55 0 100% +app/config.py 140 0 100% +app/core/__init__.py 0 0 100% +app/core/auth.py 45 0 100% +app/core/caching.py 124 0 100% +app/core/debugging.py 29 2 93% +app/core/docs_push.py 39 0 100% +app/core/errors.py 5 0 100% +app/core/logging.py 13 0 100% +app/core/rate_limit.py 44 0 100% +app/core/security_headers.py 20 0 100% +app/core/theming.py 38 0 100% +app/core/tokens.py 44 0 100% +app/db.py 21 0 100% +app/main.py 66 0 100% +app/models.py 125 0 100% +app/rag/__init__.py 0 0 100% +app/rag/agent.py 316 1 99% +app/rag/archive_upload.py 128 0 100% +app/rag/chunker.py 206 4 98% +app/rag/folder_summaries.py 121 0 100% +app/rag/git_sources.py 14 0 100% +app/rag/importer.py 190 3 98% +app/rag/llm.py 243 1 99% +app/rag/overview.py 71 0 100% +app/rag/prompts.py 88 0 100% +app/rag/retriever.py 150 3 98% +app/rag/scaffolding.py 55 0 100% +app/rag/source_removal.py 41 0 100% +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 307 0 100% +-------------------------------------------------- +TOTAL 3848 15 99% +coverage gate: app/ 99% (>90%) OK +All checks passed! +0 errors, 0 warnings, 0 informations +WARNING: there is a new pyright version available (v1.1.411 -> v1.1.414). +Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest` + +validation OK diff --git a/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__03_regenerate_ui.a1.err b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__03_regenerate_ui.a1.err new file mode 100644 index 0000000..e69de29 diff --git a/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__03_regenerate_ui.a1.md b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__03_regenerate_ui.a1.md new file mode 100644 index 0000000..1a03b74 --- /dev/null +++ b/.agents/reports/101_tokens_page_overhaul/101_tokens_page_overhaul__03_regenerate_ui.a1.md @@ -0,0 +1,19 @@ +All green. Final report: + +## Task 03 complete — Regenerate control (rotation UI) + +**Implemented** +- `frontend/assets/tokens.js`: `makeRegenerateControl` (structural mirror of the revoke control: `.token-regenerate` button, `aria-label: "Regenerate token: