phase: 170_edit_bubble_sizing
Build and Push Containers / build-and-push-app (push) Successful in 1m42s
Build and Push Containers / build-and-push-db (push) Successful in 13s

All verification complete. Final report:

**Phase 170 — final verification pass (all 3 tasks were in `complete/`):**

**Verified implemented:**
- Editor renders inside the bubble: `bubble.replaceChildren(form)`, `display:none` rule deleted, `form.style.minWidth` seeded with pre-edit width, `restoreBubble()` (markdown + image re-prepend) before `closeEditor()` on Cancel/Escape, `closeEditor()` reordered before submit re-render
- Label: `editSaveBtn.textContent = "Send"` (app.js L1241)

**Gates (all 100% green):**
- `uv run pytest` → 4066 passed
- `uv run pytest --cov=app --cov-report=term-missing` → 99% on `app/` (gate >90%)
- `uv run ruff check . && uv run pyright` → clean (0 errors, 0 warnings)
- `uv run pytest tests/e2e/test_edit_bubble_sizing.py -v --no-cov` (in isolation) → 6/6 passed
- Regression set in isolation: `test_edit_and_resend.py` 7✓, `test_retry_answer.py` 4✓, `test_failed_turn_retry.py` 4✓, `test_chat_persistence.py` 4✓

**Completion criteria:** in-bubble editor + width pin ✅ · "Send" label + cancel restore + trim re-ask + "Question too long" driver case ✅ · suite/coverage/lint ✅ · E2E + regression isolation ✅ · phase dir moved to `complete/` ✅ (atomic commit is the harness's to make — changes left in the working tree per protocol)

**Documentation:** README.md reviewed in full — edit section already aligned to phase 170 (in-bubble editor + "Send"), pages table matches actual routes, all 29 `.env.example` vars documented, setup commands accurate; AGENTS.md reviewed — all referenced files/commands exist. Both verified consistent — no changes needed.

**Notable decisions:** none — verification pass only, no code changes required.

**Next pending phase:** `171_admin_settings_layout`
This commit is contained in:
2026-10-10 03:25:40 -04:00
parent 1200437bf8
commit c4f098d0c0
27 changed files with 1607 additions and 120 deletions
+18 -13
View File
@@ -110,19 +110,24 @@ origin the browser rejects the clipboard, so the click instead offers the
full path in an inline fallback field that selects itself on focus —
click or Tab, then copy (phase 153).
**Edit** the newest question (phase 159): the latest user bubble carries
an **Edit** button that swaps the bubble for an inline textarea
prefilled with the question (the 4,000-character cap is enforced with
`maxlength`; **Ctrl/⌘+Enter** submits, **Esc** / **Cancel** restore the
original byte-identical, and a whitespace-only save is rejected inline).
Saving rewrites the question in the chat and the saved chat in place,
drops every turn that followed it, and re-asks the trimmed question —
a fresh answer streams in the old answer's place (the question is
never duplicated; an attachment on the question survives the edit and
the re-ask stays text-only). A turn that failed with "Question too
long — trim it and re-ask" (or a mistyped question) is fixed by
trimming it in the editor instead of retyping it. Earlier bubbles
never carry the button (last-question-only scope, owner-locked).
**Edit** the newest question (phase 159, re-housed in phase 170):
the latest user bubble carries an **Edit** button that opens the
editor *inside* the bubble — the editor inherits the bubble's own
box, background, and padding, so it keeps the bubble's dimensions
(the bubble stays visible; the rendered question is replaced by the
form). A labelled textarea is prefilled with the question (the
4,000-character cap is enforced with `maxlength`; **Ctrl/⌘+Enter**
submits, **Esc** / **Cancel** restore the rendered question
byte-identical, and a whitespace-only question is rejected inline).
**Send** rewrites the question in the chat and the saved chat in
place, drops every turn that followed it, and re-asks the trimmed
question — a fresh answer streams in the old answer's place (the
question is never duplicated; an attachment on the question survives
the edit and the re-ask stays text-only). A turn that failed with
"Question too long — trim it and re-ask" (or a mistyped question)
is fixed by trimming it in the editor instead of retyping it.
Earlier bubbles never carry the button (last-question-only scope,
owner-locked).
**When a long answer spends its research budget** (phase 160): the
answer's meta row carries a **Continue researching** button (row order