phase: 159_edit_and_resend_message
All completion criteria verified. Final report:
**Phase 159 — Edit the last question and re-ask it: VERIFIED COMPLETE** (all 4 tasks already in `complete/`; this pass verified end-to-end)
**Verified (implementation landed + tests green):**
- `app.js`: `EDIT_ICON`, `lastUserWrap`, `appendEditButton`/`markLastEditable` (single-target discipline, in-flight guard), `openEditor` (labelled textarea, `maxlength=4000`, Escape/Ctrl+⌘+Enter, empty guard), save path: replace → splice tail → DOM removal → `lastBrainWrap=null` → `saveConversation`+`persistConversation` → `runTurn(text,{reask:true})` — matches README exactly
- `styles.css`: `.edit-btn`/`.edit-form`/`.edit-error`/`.is-editing` + mobile 44px; unit pins 40, E2E 7, integration `test_chats_api.py` extended
**Test/lint results (all green):**
- `uv run pytest` — 3,661 tests, exit 0
- `uv run pytest --cov=app --cov-report=term-missing` — TOTAL **99%** (>90%)
- `uv run ruff check . && uv run pyright` — all checks passed; 0 errors
- `uv run pytest tests/e2e/test_edit_and_resend.py -v --no-cov` (DB up) — **7/7 passed**
- Regressions in isolation: `test_retry_answer.py` 4/4, `test_failed_turn_retry.py` 4/4, `test_chat_persistence.py` 4/4
**Completion criteria:** all 7 ✓ — Edit on last bubble + prefill + Escape/Cancel restore (E2E #3); replace+truncate+re-ask with no duplicated question (E2E #1); refresh survival (E2E #4); failed/“question too long” turn editable + trim re-asks (E2E #5); earlier bubbles un-editable + byte-identical Retry/Stop/persistence (E2E #2 + regressions + unit pins); suite/coverage/lint ✓; E2E + regressions isolated ✓. Commit + phase-dir move: harness's job (no git ops by me, per protocol).
**Documentation:** README.md — full review; phase 159 section cross-checked against `app.js` source (cap, keys, truncate, image survival) — consistent, no changes needed; all 30 `.env.example` vars documented. AGENTS.md — full review; all rules/quick-ref commands valid — verified consistent, no changes needed.
**Notable:** none — no defects found in prior work; no live-infrastructure changes required.
**Next pending phase:** `160_tool_budget_telemetry`
This commit is contained in:
@@ -319,8 +319,22 @@ def test_stop_branch_keeps_partial_and_persists_stopped() -> None:
|
||||
assert "stopped: true" in branch, "the owner-locked optional marker"
|
||||
assert "thinking: thinkingAcc || undefined" in branch
|
||||
assert "tools: toolAcc.length ? toolAcc : undefined" in branch
|
||||
# The confirmation rides the single settle in the finally.
|
||||
finally_block = js[finally_idx : finally_idx + 900]
|
||||
# The confirmation rides the single settle in the finally —
|
||||
# brace-matched from the finally's opening brace, so the
|
||||
# phase-159 settle additions (the markLastEditable pass + its
|
||||
# comment) cannot push the line out of a fixed window.
|
||||
finally_brace = js.index("{", finally_idx)
|
||||
depth = 0
|
||||
finally_end = finally_brace
|
||||
for k in range(finally_brace, len(js)):
|
||||
if js[k] == "{":
|
||||
depth += 1
|
||||
elif js[k] == "}":
|
||||
depth -= 1
|
||||
if depth == 0:
|
||||
finally_end = k
|
||||
break
|
||||
finally_block = js[finally_idx : finally_end + 1]
|
||||
assert 'if (stoppedByUser) sendStatus.textContent = "Answer stopped."' in finally_block
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user