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:
2026-09-05 10:57:07 -04:00
parent 766702c750
commit dbf2af26c6
1118 changed files with 664 additions and 664 deletions
@@ -0,0 +1,45 @@
# Phase 57 — Edit + Re-embed Document Summaries
**Source:** `TODO.md` L4 — "Be able to edit the summaries for documents in the RAG. Click an edit button in summary box and change the summary that the AI created. re-embed that document after changing the summary."
**Story:** n/a (TODO-derived — owner roadmap confirmation 2026-08-31)
**Context:** The summary box is the `.doc-summary` section rendered by the shared core in `frontend/assets/document.js` (page + modal surfaces) — it renders only when `doc.summary` is non-empty, as a labeled `h2` + text-node `<p>` (XSS contract: `textContent` only). Phase 30 stores a non-markdown document's `lite` digest on `documents.summary` **and** indexes it as one extra embedded chunk (`is_summary=True`, position −1 — `app/rag/importer.py:313–336`). The document viewer is deliberately PUBLIC (phase 16 owner decision — only the catalog is admin-gated), so the new edit affordance and endpoint must be admin-gated (`require_admin`, `app/core/auth.py`); `GET /api/whoami` (`app/api/auth.py:56`) already drives admin reveals on static pages. Async endpoints exist in `app/api/` (`app/api/chat.py:223`, `app/api/git_sources.py:231`), so the re-embed (`await llm.embed([...])`) fits a standard `async def` handler.
## Objective
An admin can edit (or clear) the AI-generated summary directly in the summary box; on save the stored summary and its `is_summary` chunk are updated and the chunk is **re-embedded** — anonymous visitors see the unchanged public viewer with no edit affordance.
## Dependencies
- `56_import_extensions_env` (todo, preceding)
## Tasks
1. `01_update_summary_api.md` — `PATCH /api/documents/summary` (admin): update/clear `documents.summary`, replace the `is_summary` chunk, re-embed it (one `embed` call, DB untouched if the LLM fails).
2. `02_summary_edit_ui.md` — Edit button in the `.doc-summary` panel (admin-only) → inline textarea + Save/Cancel → live-region status on both viewer surfaces.
3. `03_e2e_edit_summaries.md` — story Playwright suite + regressions + the atomic commit.
## Testing & Quality
- Integration: the existing document-content API tests (phase 10) gain the PATCH cases — update + re-embed (chunk content + non-NULL vector + unchanged chunk count), clear (summary NULL + chunk deleted), markdown doc with no prior `is_summary` chunk (one created), 404 unknown pair, 403 anonymous, LLM-failure error mapping (502/503, DB unchanged).
- Frontend source pins (house style, `tests/unit/test_save_chat_ui.py` pattern): `document.js` (whoami gate, editor wiring, PATCH path, `textContent` render contract), `styles.css` (new `.doc-summary-*` classes).
- E2E (mandatory, A16): `tests/e2e/test_edit_summaries.py`, run in isolation (mock `SUMMARY_MODE` fixture KB).
- Coverage: **>90%** on `app/` (validate.sh gate).
## Completion Criteria
- [ ] Admin: `PATCH /api/documents/summary` with new text updates `documents.summary`, replaces the `is_summary` chunk's content, and stores a fresh embedding (content chunks untouched — count unchanged).
- [ ] Admin: PATCH with an empty/whitespace summary clears `documents.summary` (NULL) and deletes the `is_summary` chunk.
- [ ] Anonymous: 403 on PATCH; no Edit button in the viewer; the viewer otherwise renders byte-for-byte as today.
- [ ] The Edit button appears in the summary box (document page **and** modal), opens a textarea prefilled with the current summary, and Save reflects the change in the panel with a live-region confirmation; Cancel restores.
- [ ] `uv run pytest` green; coverage TOTAL >90%.
- [ ] `uv run pytest tests/e2e/test_edit_summaries.py -v --no-cov` green in isolation (DB up).
- [ ] Regression E2E suites green in isolation: `test_document_summaries.py`, `test_document_viewer.py`, `test_cache_busting.py`.
- [ ] `uv run ruff check . && uv run pyright` clean.
- [ ] One `--no-gpg-sign` commit; phase dir moved to `.agents/phases/complete/` (`.agents/` stays untracked — owner instruction, commit 281f355).
## Locked decisions
- **Owner-locked (2026-08-31, roadmap confirmation, D4):**
1. Summary editing is **admin-only** (endpoint + UI affordance). The document viewer stays public.
2. "Re-embed that document" = replace the `is_summary` chunk with a fresh embedding (one `embed` call). The document's content chunks are **not** re-embedded — the summary is the only text that changed.
3. Clearing the summary (empty save) sets `documents.summary = NULL` and deletes the `is_summary` chunk.
- **Fail-before-write:** the embedding happens before any DB mutation; an LLM failure returns an error (502/503, `app/api/git_sources.py` `ModelUnavailableError`-style mapping) and leaves the row and chunk untouched.
## Commit
```bash
git add app/ frontend/ tests/ && git commit --no-gpg-sign -m "feat(kb): edit + re-embed document summaries from the viewer (admin)"
```