phase: 161_reasoning_bubble
All gates verified. Final check — AGENTS.md rules against the project (commands, gates, protocols) — the quick-reference commands all exist and the rules (PLAN §2/§7/§9 references, phase protocol, No CDN, Debugpy, git gates) accurately describe the project; the reasoning bubble is a pure UI change with no new commands or env vars, so no AGENTS.md change is needed.
**Verification complete — full results:**
- **Verified** (implemented by prior task passes, all in working tree): `createReasoningWrap`/`ensureReasoningWrap` live container (D1), `settleReasoning` fold at the 3 settle sites + not at delta (D2), 320px `.reasoning-body` window + pinned-tail follow (D3), zero persistence change (D4), collapsed restore + shared-page parity with D6 step counts, `styles.css` family treatment + reduced-motion still, mock `REASONING_MIDROUND_TRIGGER` flow, 6-test story suite, phase-158 pin updates
- **Full suite:** `uv run pytest` → **3738 passed, 0 failed** · `uv run pytest --cov=app --cov-report=term-missing` → **TOTAL 99% (>90%)** · `uv run ruff check .` → all checks passed · `uv run pyright` → **0 errors, 0 warnings**
- **E2E in isolation** (DB up; port-8123 collision with an unrelated `undercooked` service → `E2E_APP_PORT=8125`/`E2E_MOCK_PORT=8902`, no live change made): `test_reasoning_bubble.py` **6/6** · `test_thinking_timeline.py` ✓ · `test_thinking_display.py` ✓ · `test_tool_call_compact.py` ✓ · `test_big_read_progress.py` ✓ · `test_turn_progress_loader.py` ✓ · `test_share_chat.py` ✓ · `test_chat_persistence.py` ✓ · `test_smoke.py` ✓ (all exit 0, zero failures)
- **Completion criteria:** all 9 checked against the code + test outcomes — container open/live/nested ✓, stays open past mid-round delta ✓, folds at done ✓, restore + shared collapsed with "3 steps" ✓, plain turn = no container ✓, regression suites green ✓, suite/coverage/lint green ✓, diff scope limited to `frontend/assets/{app.js,shared.js,styles.css}` + `tests/` + `README.md` + phase files (no `app/` — D4) ✓
- **Documentation:** README.md "Thinking" section names the Reasoning bubble accurately (320px window, open-until-settle incl. mid-round deltas, "N steps", byte-identical no-container, collapsed on restore/shared) — verified consistent, no changes needed; AGENTS.md — verified consistent, no changes needed; all `.env.example` vars documented
- **Decisions:** commit + phase-dir move left to the harness (per pass rules — no git index/history commands executed); `undercooked` dev server on port 8123 untouched, E2E used the env port overrides
- **Next pending phase:** none — `161_reasoning_bubble` is the last in `todo/`
This commit is contained in:
@@ -140,8 +140,10 @@ def test_tool_lines_render_into_the_bubble_wrap() -> None:
|
||||
"""Phase 158 (D1): the tool lines render into the run's
|
||||
disclosure — ``createToolDisclosure`` builds the phase-117
|
||||
structure (a ``.tool-calls`` list, role=list + accessible name
|
||||
"Tool calls") and ``ensureToolRun`` inserts it BEFORE the bubble
|
||||
(D2: above the answer, in arrival order); each line is a
|
||||
"Tool calls") and ``ensureToolRun`` appends it into the
|
||||
phase-161 reasoning container's ``.reasoning-body`` (D1: the
|
||||
container sits ABOVE the answer bubble — the per-run bubble
|
||||
anchor is superseded; arrival order preserved); each line is a
|
||||
.tool-call listitem with the exact marks: 🔎 Listing documents /
|
||||
📄 Reading <code>path</code>. The path goes through textContent
|
||||
(storage can never inject HTML)."""
|
||||
@@ -155,8 +157,12 @@ def test_tool_lines_render_into_the_bubble_wrap() -> None:
|
||||
)
|
||||
fn2 = js.find("function ensureToolRun")
|
||||
run = js[fn2 : js.find("\n}\n", fn2)]
|
||||
assert 'insertBefore(disc, body.querySelector(".bubble"))' in run, (
|
||||
"the disclosure sits ABOVE the answer, in arrival order"
|
||||
assert (
|
||||
'ensureReasoningWrap(wrap).querySelector(".reasoning-body")'
|
||||
".appendChild(disc)" in run
|
||||
), (
|
||||
"phase 161 (D1): the disclosure nests in the container, which "
|
||||
"sits above the answer (arrival order preserved)"
|
||||
)
|
||||
fn = js.find("function appendToolLine")
|
||||
assert fn != -1, "appendToolLine must exist"
|
||||
@@ -266,25 +272,34 @@ def test_tool_lines_re_render_on_restore() -> None:
|
||||
|
||||
|
||||
def test_segments_keep_arrival_order_above_the_bubble() -> None:
|
||||
"""Phase 158 (D2): both run builders insert their element
|
||||
BEFORE the bubble — later insertions land after earlier ones, so
|
||||
document order is ARRIVAL order (a tool frame preceding the
|
||||
first thinking frame lands the scratchpad BELOW the tool lines —
|
||||
the timeline order; the old "scratchpad on top" anchor chain is
|
||||
gone)."""
|
||||
"""Phase 158 (D2) + 161 (D1): both run builders append their
|
||||
element into the reasoning container's ``.reasoning-body`` —
|
||||
later appends land after earlier ones, so document order is
|
||||
ARRIVAL order (a tool frame preceding the first thinking frame
|
||||
lands the scratchpad BELOW the tool lines — the timeline order;
|
||||
the old "scratchpad on top" anchor chain is gone). The
|
||||
container itself sits before the bubble (the ONE anchor)."""
|
||||
js = _js()
|
||||
fn = js.find("function ensureThinkingRun")
|
||||
t = js[fn : js.find("\n}\n", fn)]
|
||||
fn2 = js.find("function ensureToolRun")
|
||||
d = js[fn2 : js.find("\n}\n", fn2)]
|
||||
assert 'insertBefore(block, body.querySelector(".bubble"))' in t, (
|
||||
"the thinking run inserts before the bubble"
|
||||
assert (
|
||||
'ensureReasoningWrap(wrap).querySelector(".reasoning-body")'
|
||||
".appendChild(block)" in t
|
||||
), "the thinking run appends into the container's body"
|
||||
assert (
|
||||
'ensureReasoningWrap(wrap).querySelector(".reasoning-body")'
|
||||
".appendChild(disc)" in d
|
||||
), "the tool run appends into the container's body"
|
||||
assert "insertBefore" not in t, (
|
||||
"the per-run bubble anchor is GONE (phase 161 D1)"
|
||||
)
|
||||
assert 'insertBefore(disc, body.querySelector(".bubble"))' in d, (
|
||||
"the tool run inserts before the bubble"
|
||||
assert "insertBefore" not in d, (
|
||||
"the per-run bubble anchor is GONE (phase 161 D1)"
|
||||
)
|
||||
assert "??" not in t, ("the old anchor chain is GONE — the bubble is "
|
||||
"the only anchor")
|
||||
assert "??" not in t, ("the old anchor chain is GONE — the container "
|
||||
"append is the only anchor")
|
||||
assert "block.open = true" in t
|
||||
assert "disc.open = true" in d
|
||||
|
||||
|
||||
Reference in New Issue
Block a user