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,41 @@
|
||||
# Phase 49 — Retry the Last Answer (Redo)
|
||||
|
||||
**Source:** `TODO.md` L4 — "Need a retry button to retry the last answer, like a redo button"
|
||||
**Story:** n/a (TODO-derived — owner roadmap confirmation 2026-08-29)
|
||||
**Context:** `frontend/assets/app.js` — `handleSend` owns the whole turn (user-bubble append + conversation push → fetch/SSE → save points), `appendTuneButton` is the house pattern for a per-bubble meta-row action (reuses the `.msg-meta` row, the `role=list` → `role=listitem` rule, the admin gate), `conversation`/`rememberBrainTurn` hold the persisted records, and phase 48's Stop button means the last brain bubble can be a **stopped partial** — the natural retry candidate.
|
||||
|
||||
## Objective
|
||||
A **Retry** button on the last brain answer re-asks the preceding question in place — the old answer is removed (DOM + persisted record), the fresh answer streams into its place, and the conversation never duplicates the question.
|
||||
|
||||
## Dependencies
|
||||
- `48_stop_generation` (todo) — the button/state-machine work it builds on (the meta-row button family, the in-flight guard) and the stopped partials it makes retryable.
|
||||
- `14_chat_persistence` (complete) — the conversation records the retry edits in place.
|
||||
|
||||
## Tasks
|
||||
1. `01_retry_button.md` — the `runTurn` extraction + the Retry button + redo-in-place semantics + CSS.
|
||||
2. `02_e2e_retry_answer.md` — the story Playwright suite + regressions + commit.
|
||||
|
||||
## Testing & Quality
|
||||
- Frontend source pins (house pattern): the `runTurn(text, {reask})` extraction (reask skips the user append/push), last-bubble-only Retry management, the redo-in-place record edit, the in-flight no-op.
|
||||
- Coverage: **>90%** on `app/` (unchanged — frontend-only phase).
|
||||
- E2E (mandatory, A16): `tests/e2e/test_retry_answer.py`, run in isolation.
|
||||
|
||||
## Completion Criteria
|
||||
- [ ] The last brain bubble (completed, deflected, empty-fallback, or stopped partial — admin and anonymous alike) carries a Retry button; earlier brain bubbles do not.
|
||||
- [ ] Clicking Retry removes the old answer (DOM + `bor.chat.v1` record), re-sends the preceding question without duplicating it, and streams the fresh answer into its place; the new answer carries the Retry button (it is the new last).
|
||||
- [ ] While a turn is in flight, Retry does nothing (no double turn).
|
||||
- [ ] `uv run pytest` green; coverage TOTAL unchanged (>90%).
|
||||
- [ ] `uv run pytest tests/e2e/test_retry_answer.py -v --no-cov` green in isolation (DB up).
|
||||
- [ ] Regression E2E suites green in isolation: `test_chat_rag.py`, `test_chat_persistence.py`, `test_stop_generation.py`.
|
||||
- [ ] `uv run ruff check . && uv run pyright` clean.
|
||||
- [ ] One `--no-gpg-sign` commit; phase dir moved to `.agent/phases/complete/`.
|
||||
|
||||
## Locked decisions
|
||||
- **Owner-locked (2026-08-29, roadmap confirmation):** redo-in-place (the old answer is replaced, the question is not duplicated); only the **last** brain bubble is retryable; Retry is available to **all** visitors (chat is public — unlike Tune, which is admin-only); inert while a turn is in flight.
|
||||
- **A10 untouched** — retry is a fresh `POST /api/chat` (the API stays stateless).
|
||||
- **A16/A17 honoured** — one story E2E suite, one atomic commit.
|
||||
|
||||
## Commit
|
||||
```bash
|
||||
git add -A .agent/ frontend/ tests/ && git commit --no-gpg-sign -m "feat(chat): retry the last answer — redo-in-place Retry button on the latest brain bubble"
|
||||
```
|
||||
Reference in New Issue
Block a user