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,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 `.agent/phases/complete/` (`.agent/` 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)"
|
||||
```
|
||||
Reference in New Issue
Block a user