fix(rag): stop the per-run blocks from folding — the container is the one disclosure
Build and Push Containers / build-and-push-app (push) Successful in 1m43s
Build and Push Containers / build-and-push-db (push) Successful in 15s

The owner refinement (2026-10-06): the per-run thinking and tool-call
blocks inside the Reasoning bubble were individually collapsible
details elements — a fold inside the fold. A tool frame closed the
previous thinking block, so the visible thinking vanished mid-turn;
and the pinned-tail follow died on the append of every run after the
first (the pin was captured AFTER the new block's height growth
contaminated the 32px reading).

- app.js: the in-container runs are now plain divs —
  createThinkingRunEl (div.thinking + static .thinking-summary label +
  .thinking-text) and createToolRunEl (div.tool-calls-disclosure +
  static .tool-calls-summary label + the .tool-calls list); they never
  open or fold (the container is the ONE open/fold control, open
  through the turn, folded at settle — unchanged); the pin capture
  moves BEFORE ensureThinkingRun/ensureToolRun append (plus the
  first-frame edge: no container yet -> always pinned);
  closeCurrentRun just ends the run; closeAllRuns stays the defensive
  legacy guard; restoreTimeline/addSegments (shared.js) use the div
  builders; the legacy no-segments restore path keeps the old
  details-based blocks byte-identical
- styles.css: the in-container runs are distinct by label + rail
  (brand-ink Thinking label on a brand-soft rail; accent-ink
  Tool call(s) (N) label on a neutral rail); the interactive
  treatment (cursor + chevron) is scoped to the legacy <summary>; the
  inner windows stay disabled (the container's .reasoning-body is the
  ONE live scroll surface)
- unit + E2E: the D5-refinement contract is pinned — one
  details.reasoning disclosure, per-run blocks as plain divs, zero
  nested <details> inside the container, the container as the only
  open/fold control, the .reasoning-body window auto-follows the
  tail while streaming

unit+integration 3738 passed (coverage 99%), ruff + pyright clean, all
five affected E2E suites pass in isolation (reasoning_bubble 6,
thinking_timeline 6, thinking_display 5, thinking_scroll 8,
tool_call_compact 4), verified live: the follow holds through a long
thinking stream, the tool-frame transition, and the second thinking
run; restore renders the div structure without client-side errors

LLM-Generated: true
This commit is contained in:
2026-10-06 14:44:41 -04:00
parent 051f62deb7
commit 690fd98036
15 changed files with 941 additions and 609 deletions
+75 -36
View File
@@ -211,9 +211,12 @@ def test_per_run_inserts_append_into_the_reasoning_body() -> None:
``.reasoning-body`` — ``ensureThinkingRun`` / ``ensureToolRun``
insert via ``ensureReasoningWrap(wrap).querySelector(
".reasoning-body").appendChild(…)`` (arrival order preserved: a
new run appends after the previous run's block). EVERYTHING ELSE
in both functions is unchanged (closeCurrentRun, ``open = true``
D5, the segRuns push, currentRun)."""
new run appends after the previous run's block). The D5
refinement (owner 2026-10-06): the per-run elements are plain
``div``s through the run builders (never open/foldable — the
container is the ONE disclosure); everything else in both
functions is unchanged (closeCurrentRun, the segRuns push,
currentRun)."""
js = _js()
t = _fn(js, "ensureThinkingRun")
assert (
@@ -221,7 +224,9 @@ def test_per_run_inserts_append_into_the_reasoning_body() -> None:
".appendChild(block)" in t
), "the thinking run appends into the container's body"
assert "closeCurrentRun()" in t
assert "block.open = true" in t, "D5: the per-run open/fold is unchanged"
assert "createThinkingRunEl()" in t, (
"D5 refinement: a plain div — never collapsible"
)
assert "segRuns.push(run)" in t
assert "currentRun =" in t
d = _fn(js, "ensureToolRun")
@@ -230,8 +235,16 @@ def test_per_run_inserts_append_into_the_reasoning_body() -> None:
".appendChild(disc)" in d
), "the tool run appends into the container's body"
assert "closeCurrentRun()" in d
assert "disc.open = true" in d, "D5: the per-run open/fold is unchanged"
assert "createToolRunEl()" in d, (
"D5 refinement: a plain div — never collapsible"
)
assert "segRuns.push(run)" in d
assert ".open =" not in t, (
"D5 refinement: the in-container runs are non-collapsible divs"
)
assert ".open =" not in d, (
"D5 refinement: the in-container runs are non-collapsible divs"
)
def test_the_per_run_bubble_anchor_is_gone() -> None:
@@ -484,10 +497,13 @@ def test_restore_per_run_blocks_append_into_the_reasoning_body() -> None:
append into the container's ``.reasoning-body`` — the per-run
``insertBefore(…, bubble)`` anchor is GONE from
``restoreTimeline`` (the container sits before the bubble; the
runs nest inside it, arrival order preserved). EVERYTHING ELSE
in the loop is unchanged (the per-run create, the closed state,
the tool-run seal, the well-formedness guards, the truncation
note)."""
runs nest inside it, arrival order preserved). The D5
refinement (owner 2026-10-06, parity with app.js): the
in-container runs are plain ``div``s through the run builders
(never collapsible — the container is the ONE disclosure,
created COLLAPSED by the restore); everything else in the loop
is unchanged (the tool-run seal, the well-formedness guards,
the truncation note)."""
body = _fn(_js(), "restoreTimeline")
assert "runsEl.appendChild(block)" in body, (
"the thinking block appends into the container's body"
@@ -501,12 +517,19 @@ def test_restore_per_run_blocks_append_into_the_reasoning_body() -> None:
assert "insertBefore(toolDisc" not in body, (
"the per-run bubble anchor is GONE from restoreTimeline (tool)"
)
# the per-run create + the closed state are unchanged.
assert 'summary.textContent = "Thinking"' in body, (
"the per-run thinking block structure is unchanged"
# the per-run create is the div builder (the D5 refinement).
assert "createThinkingRunEl()" in body, (
"D5 refinement: the in-container run is a plain div (never "
"collapsible — the container is the ONE disclosure)"
)
assert "createToolRunEl()" in body, (
"D5 refinement: the in-container run is a plain div (never "
"collapsible)"
)
assert "block.open = true" not in body, "the in-container runs never open"
assert "toolDisc.open" not in body, (
"D5 refinement: the in-container runs are non-collapsible divs"
)
assert "block.open = true" not in body, "D5: created COLLAPSED (unchanged)"
assert "toolDisc.open = false" in body
assert "if (toolDisc) toolDisc = null" in body, "the tool-run seal is unchanged"
@@ -768,15 +791,20 @@ def test_inner_html_is_absent_from_both_wrappers() -> None:
"innerHTML ABSENT from the shared.js builder (the house rule)"
)
# the ONLY HTML write in each timeline function is the
# escape-first renderMarkdown into .thinking-text.
# escape-first renderMarkdown into .thinking-text (the shared
# builder's local textEl; app.js's restore targets the div
# block's .thinking-text through querySelector).
for fn_name, js in (("restoreTimeline", _js()), ("addSegments", _js_shared())):
body = _fn(js, fn_name)
writes = re.findall(r"\b(\w+)\.innerHTML\s*=\s*([^;\n]+)", body)
writes = re.findall(r"([\w.$()\"'-]+\.?)\.innerHTML\s*=\s*([^;\n]+)", body)
assert len(writes) == 1, (
f"{fn_name}: exactly ONE innerHTML write (the structure is "
f"createElement): {writes}"
)
assert writes[0][0] == "textEl", "the single write is into .thinking-text"
assert (
writes[0][0].rstrip(".") == "textEl"
or 'querySelector(".thinking-text")' in writes[0][0]
), "the single write is into .thinking-text"
assert writes[0][1].strip() == "renderMarkdown(entry.text)", (
"the single write is the escape-first renderMarkdown"
)
@@ -889,29 +917,37 @@ def test_the_reasoning_body_is_the_one_bounded_live_window() -> None:
def test_the_inner_runs_are_compacted_to_one_scroll_surface() -> None:
"""Task 03 item 5: the inner-run compacting (D3 — ONE scroll
surface, the nested border weight removed):
``details.reasoning details.thinking`` is de-bordered (a 2px
``--line`` indent keeps the family rhythm, transparent
background, tight margins); the inner ``.thinking-text``
320px window is DISABLED (``max-height: none`` +
``overflow-y: visible``) so the container's window is the single
scroll surface; the nested ``.tool-calls-disclosure`` keeps its
compact margin (the documented-intent rule)."""
"""Task 03 item 5 + the D5 refinement (owner 2026-10-06): the
inner runs nest as PLAIN DIVS inside ONE scroll surface —
``details.reasoning .thinking`` (the family's brand-soft rail,
the 2px weight — distinct from the tool run's neutral rail) and
``details.reasoning .tool-calls-disclosure`` (the neutral
``--line`` rail), de-bordered (transparent background, no nested
box); the inner ``.thinking-text`` 320px window is DISABLED
(``max-height: none`` + ``overflow-y: visible``) so the
container's window is the single scroll surface. The runs are
distinct from each other by LABEL + RAIL: the brand-ink
"Thinking" label vs the accent-ink "Tool call(s) (N)" label.
"""
css = _css()
run = _rule(css, "details.reasoning details.thinking")
assert "border: 0" in run, ("the nested border weight is removed")
assert "border-left: 2px solid var(--line)" in run
assert "border-radius: 0" in run
assert "margin: 0.25rem 0" in run
assert "background: transparent" in run
inner_text = _rule(css, "details.reasoning details.thinking .thinking-text")
run = _rule(css, "details.reasoning .thinking")
assert "border-left: 2px solid var(--brand-soft)" in run, (
"the thinking run carries the brand-soft rail"
)
inner_text = _rule(css, "details.reasoning .thinking .thinking-text")
assert "max-height: none" in inner_text, (
"the inner 320px window is disabled"
)
assert "overflow-y: visible" in inner_text
disc = _rule(css, "details.reasoning .tool-calls-disclosure")
assert "margin: 0.25rem 0" in disc
assert "border-left: 2px solid var(--line)" in disc, (
"the tool run carries the neutral rail (distinct from the "
"thinking run's brand-soft rail)"
)
label = _rule(css, "details.reasoning .thinking .thinking-summary")
assert "var(--brand-ink)" in label, (
"the thinking label is brand-ink (the family pairing)"
)
def test_the_reasoning_still_is_in_the_house_reduced_motion_block() -> None:
@@ -949,8 +985,11 @@ def test_the_legacy_no_container_rules_are_untouched() -> None:
# line-anchored: the nested details.reasoning selector is a
# different rule).
assert len(re.findall(r"(?m)^\.tool-calls-disclosure \{", css)) == 1
disc = _rule(css, ".tool-calls-disclosure")
assert "margin: 0.25rem 0" in disc
disc = re.search(
r"(?m)^\.tool-calls-disclosure \{([^}]*)\}", css
)
assert disc, "styles.css must style .tool-calls-disclosure (base)"
assert "margin: 0.25rem 0" in disc.group(1)
chevron = _rule(css, ".tool-calls-summary::before")
assert 'content: "▸"' in chevron
assert "margin-right: 0.5rem" in chevron