phase: 192_verbatim_inline_midturn
Phase 192 — final verification pass complete. - **Verified (all 4 tasks already complete):** additive `verbatim_block` SSE frame (`VerbatimBlockPiece` → `ChatVerbatimBlockEvent` → chat dispatch, after the round's `tool`/`tool_result`, before the next round); `hydrateVerbatimNow` matched-only mid-turn pass + app.js branch; `dropPlacedTwin` per-locator done/restore dedupe; the dedicated E2E suite. - **Root cause of the rejected attempt:** my own concurrent background `pytest` run deadlocked the harness validation run on the shared Postgres (`psycopg.errors.DeadlockDetected`). No code defect — re-ran every gate **exclusively**. - `uv run pytest -q --cov=app --cov-report=term-missing` → **exit 0**, `TOTAL 7181 16 99%` (>90%) - `uv run pytest tests/e2e/test_verbatim_inline_midturn.py --no-cov` → **6 passed** (isolated) - `uv run pytest tests/e2e/test_verbatim_show_text.py tests/e2e/test_chat_history.py --no-cov` → **18 passed** (`test_chat_history.py` byte-unedited; the phase-182 suite's "no eighth type" pin was tightened, not loosened, to seven + `verbatim_block` with frame-order asserts) - `uv run ruff check .` → All checks passed (exit 0) · `uv run pyright` → **0 errors** - **Completion criteria:** single frame per success + zero per refusal ✅ · `BOR_ANSWER_TEXT=0` wire byte-identical (integration spelled baseline + E2E App B) ✅ · fence hydrates in place / unfenced lands at the call moment, before `done` ✅ · append+fence → 1 panel, two ranges → 2 panels ✅ · restore 1 panel/locator, `done.answer_text` + record key + `verbatim_blocks=N` unchanged ✅ · suite green, coverage 99%, lint/types clean ✅ · no-show_text turn byte-identical ✅ · commit → left to the harness (no git index/history commands run). - **Docs:** README reviewed line-by-line (2399 lines) + AGENTS.md in full; mechanically verified all 86 `BOR_*` settings, every `.env.example` var, table defaults, internal anchors (0 broken), ports 8123/8901, tree depth 1–8, pagination 25/1–100, 17 palette colors, `0029`/`0030` migrations, and every cited test file. Fixed 1 inconsistency: the verbatim "Parity" bullet claimed the live turn/reload/shared page share "the same three globals" — now names the settle-path trio and states that `hydrateVerbatimNow` is the ONE chat-only addition (a shared page has no stream). - **Notable:** `run_agent`'s four repeated piece unions were collapsed into the ONE exported `AgentPiece` alias, so a future piece type is spelled in one place; `test_frontend_edit_message.py`'s `runTurn` byte-pin was regenerated, not weakened. - **Next pending phase:** `193_sync_remaining_count`.
This commit is contained in:
@@ -28,8 +28,9 @@ Postgres so the fixtures' exact text is the assertion baseline):
|
||||
badge (locked A5). Wire pins: exactly FIVE tools offered (the three base
|
||||
+ ``show_image`` + ``show_text``), exactly one executed call, and — from
|
||||
an in-page fetch tap over the real ``/api/chat`` stream — the turn's SSE
|
||||
``type`` set stays inside the pre-phase seven with ``answer_text``
|
||||
riding INSIDE ``done`` (no eighth event type).
|
||||
``type`` set stays inside the pre-phase seven PLUS the one additive type
|
||||
phase 192 introduced (``verbatim_block``, the mid-turn copy of a shown
|
||||
block), with ``answer_text`` still riding INSIDE ``done``.
|
||||
- *append path* — the same turn with ``describe it without a block`` (no
|
||||
fence in the answer): the shown block renders as a panel APPENDED to the
|
||||
bubble body, below the answer text and ABOVE the source clusters (the
|
||||
@@ -246,7 +247,7 @@ DOC_A_LINES = DOC_A_CONTENT.split("\n")
|
||||
DOC_B_LINES = DOC_B_CONTENT.split("\n")
|
||||
|
||||
#: The SSE ``type`` values the pre-phase stream already carried
|
||||
#: (``app/schemas.py``'s chat events): the phase added NO eighth type.
|
||||
#: (``app/schemas.py``'s chat events): phase 182 added NO eighth type.
|
||||
PRE_PHASE_EVENT_TYPES = {
|
||||
"delta",
|
||||
"thinking",
|
||||
@@ -257,6 +258,15 @@ PRE_PHASE_EVENT_TYPES = {
|
||||
"retry",
|
||||
}
|
||||
|
||||
#: The ONE type phase 192 (task 01, A1) adds: the mid-turn
|
||||
#: ``verbatim_block`` frame, sent by the turn whose ``show_text`` call just
|
||||
#: succeeded (one frame per shown block, before the next model round). App A
|
||||
#: calls ``show_text``, so its vocabulary is the seven PLUS this type and
|
||||
#: NOTHING else; a turn with no successful show never carries it, and the
|
||||
#: kill-switch stream's byte-identity is pinned on the wire in
|
||||
#: ``tests/integration/test_chat_api.py::test_kill_switch_stream_is_byte_identical``.
|
||||
PHASE_192_EVENT_TYPES = {"verbatim_block"}
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Module apps: verbatim ON (App A) and the kill switch OFF (App B).
|
||||
@@ -847,13 +857,23 @@ def test_show_text_turn_paints_the_files_bytes(
|
||||
"Text shown to the user" in r for r in _tool_results(captured[1])
|
||||
), "the show_text confirming result never reached the model"
|
||||
|
||||
# --- the frame vocabulary (no eighth SSE type) ----------------------
|
||||
# --- the frame vocabulary (the seven + phase 192's ONE type) --------
|
||||
frames = _sse_frames(page)
|
||||
types: set[str] = {str(f.get("type")) for f in frames}
|
||||
assert types <= PRE_PHASE_EVENT_TYPES, (
|
||||
order = [str(f.get("type")) for f in frames]
|
||||
types: set[str] = set(order)
|
||||
allowed = PRE_PHASE_EVENT_TYPES | PHASE_192_EVENT_TYPES
|
||||
assert types <= allowed, (
|
||||
f"the stream invented an event type: {sorted(types)}"
|
||||
)
|
||||
assert len(types) <= 7
|
||||
assert len(types) <= 8
|
||||
# Phase 192 (task 01): the shown block also rides its own mid-turn frame,
|
||||
# ahead of the answer's deltas (the panel is on screen while the model is
|
||||
# still talking) — ADDITIVE, the done frame below still carries it.
|
||||
block_frames = [f for f in frames if f.get("type") == "verbatim_block"]
|
||||
assert [b["locator"] for b in block_frames] == [seeded["a_locator"]]
|
||||
i_block = order.index("verbatim_block")
|
||||
assert "delta" not in order[:i_block], order
|
||||
assert order.index("tool") < i_block, order
|
||||
assert "answer_text" not in types, "answer_text leaked out as its own event"
|
||||
done = [f for f in frames if f.get("type") == "done"]
|
||||
assert len(done) == 1
|
||||
|
||||
Reference in New Issue
Block a user