fix(rag): stop the per-run blocks from folding — the container is the one disclosure
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:
@@ -62,23 +62,29 @@ def _fn(src: str, name: str) -> str:
|
||||
return src[fn : src.find("\n}\n", fn)]
|
||||
|
||||
|
||||
def test_tool_run_builds_an_open_details_disclosure() -> None:
|
||||
"""Phase 158 (D1/D5) + 161 (D1): ``ensureToolRun`` creates a
|
||||
native ``details.tool-calls-disclosure`` via
|
||||
``createToolDisclosure`` — a ``summary.tool-calls-summary``
|
||||
(first child) + the existing ``.tool-calls`` list (role=list +
|
||||
aria-label "Tool calls", second child) — appended into the
|
||||
phase-161 reasoning container's ``.reasoning-body`` in arrival
|
||||
order (D1 — the container sits above the bubble; the per-run
|
||||
bubble anchor is superseded). It starts OPEN while the run is
|
||||
live; every append re-renders the plain-text per-run "Tool
|
||||
call(s) (N)" count on the summary through textContent (no
|
||||
innerHTML anywhere)."""
|
||||
def test_tool_run_builds_a_div_disclosure_in_the_container() -> None:
|
||||
"""Phase 158 (D1) + 161 (D1) + the D5 refinement (owner
|
||||
2026-10-06): ``ensureToolRun`` creates a plain
|
||||
``div.tool-calls-disclosure`` via ``createToolRunEl`` — a
|
||||
``span.tool-calls-summary`` (first child — the static label, NOT
|
||||
a control: the container is the ONE disclosure) + the existing
|
||||
``.tool-calls`` list (role=list + aria-label "Tool calls",
|
||||
second child) — appended into the phase-161 reasoning
|
||||
container's ``.reasoning-body`` in arrival order (D1 — the
|
||||
container sits above the bubble; the per-run bubble anchor is
|
||||
superseded). The run is ALWAYS VISIBLE while the container is
|
||||
open (never open/foldable — no ``.open`` anywhere); every
|
||||
append re-renders the plain-text per-run "Tool call(s) (N)" count
|
||||
on the summary through textContent (no innerHTML anywhere)."""
|
||||
js = _js()
|
||||
disc = _fn(js, "createToolDisclosure")
|
||||
assert "document.createElement(\"details\")" in disc
|
||||
disc = _fn(js, "createToolRunEl")
|
||||
assert "document.createElement(\"div\")" in disc, (
|
||||
"the D5 refinement: a plain div — never collapsible"
|
||||
)
|
||||
assert "className = \"tool-calls-disclosure\"" in disc
|
||||
assert "document.createElement(\"summary\")" in disc
|
||||
assert "document.createElement(\"span\")" in disc, (
|
||||
"the label is a static span (not a <summary> control)"
|
||||
)
|
||||
assert "className = \"tool-calls-summary\"" in disc
|
||||
# The list keeps its exact phase-37 shape, nested in the disclosure.
|
||||
assert "className = \"tool-calls\"" in disc
|
||||
@@ -89,11 +95,9 @@ def test_tool_run_builds_an_open_details_disclosure() -> None:
|
||||
"style — innerHTML ABSENT)"
|
||||
)
|
||||
run = _fn(js, "ensureToolRun")
|
||||
assert "createToolDisclosure()" in run
|
||||
assert "disc.open = true", (
|
||||
"D5: created OPEN on the first live tool frame of the run — the "
|
||||
"calls and the phase-87 .tool-elapsed suffix stay visible during "
|
||||
"the turn"
|
||||
assert "createToolRunEl()" in run
|
||||
assert ".open =" not in run, (
|
||||
"D5 refinement: the in-container runs are non-collapsible divs"
|
||||
)
|
||||
assert 'insertBefore(disc, body.querySelector(".bubble"))' not in run, (
|
||||
"the per-run bubble anchor is GONE (phase 161 D1)"
|
||||
@@ -186,22 +190,33 @@ def test_run_anchors_are_the_container_in_arrival_order() -> None:
|
||||
append into its ``.reasoning-body``) — the old
|
||||
``.tool-calls-disclosure ?? .tool-calls ?? .bubble`` anchor chain
|
||||
is GONE (with per-run disclosures, "above the tool lines" was the
|
||||
wrong order — arrival order is the contract), and the runs still
|
||||
open while active (D5)."""
|
||||
wrong order — arrival order is the contract), and the runs are
|
||||
ALWAYS VISIBLE inside the open container (the D5 refinement —
|
||||
never open/foldable)."""
|
||||
js = _js()
|
||||
run = _fn(js, "ensureThinkingRun")
|
||||
assert (
|
||||
'ensureReasoningWrap(wrap).querySelector(".reasoning-body")'
|
||||
".appendChild(block)" in run
|
||||
), "phase 161 (D1): the thinking run anchors on the container"
|
||||
assert "block.open = true" in run
|
||||
assert "createThinkingRunEl()" in run, (
|
||||
"the D5 refinement: a plain div — never collapsible"
|
||||
)
|
||||
assert ".open =" not in run, (
|
||||
"the in-container runs are non-collapsible divs"
|
||||
)
|
||||
assert "??" not in run, "the old anchor chain is GONE"
|
||||
d = _fn(js, "ensureToolRun")
|
||||
assert (
|
||||
'ensureReasoningWrap(wrap).querySelector(".reasoning-body")'
|
||||
".appendChild(disc)" in d
|
||||
), "phase 161 (D1): the tool run anchors on the container"
|
||||
assert "disc.open = true" in d
|
||||
assert "createToolRunEl()" in d, (
|
||||
"the D5 refinement: a plain div — never collapsible"
|
||||
)
|
||||
assert ".open =" not in d, (
|
||||
"the in-container runs are non-collapsible divs"
|
||||
)
|
||||
|
||||
|
||||
def test_shared_page_add_tool_lines_builds_a_closed_disclosure() -> None:
|
||||
@@ -277,12 +292,16 @@ def test_tool_call_code_rule_is_dechipped() -> None:
|
||||
|
||||
|
||||
def test_tool_calls_disclosure_and_summary_rules_exist() -> None:
|
||||
"""Phase 117 (D2/D4): the NEW ``.tool-calls-disclosure`` and
|
||||
``.tool-calls-summary`` rules exist — the summary is a native
|
||||
focusable toggle carrying the accent TEXT (``var(--accent-ink)``,
|
||||
"""Phase 117 (D2/D4) + the D5 refinement (owner 2026-10-06): the
|
||||
NEW ``.tool-calls-disclosure`` and ``.tool-calls-summary`` rules
|
||||
exist — the label carries the accent TEXT (``var(--accent-ink)``,
|
||||
≈10.4:1 on the surface; text + color, never color alone, B5),
|
||||
modeled on the details.thinking family, with no new color literal
|
||||
(the phase-92 zero-literal invariant)."""
|
||||
(the phase-92 zero-literal invariant). The D5 refinement: the
|
||||
INTERACTIVE treatment (cursor + the chevron) is scoped to the
|
||||
legacy ``<summary>`` element — the in-container run's label is a
|
||||
static span, not a control (the container is the ONE
|
||||
disclosure)."""
|
||||
css = _css()
|
||||
assert re.search(r"\.tool-calls-disclosure \{", css), (
|
||||
"the .tool-calls-disclosure rule must exist"
|
||||
@@ -293,4 +312,9 @@ def test_tool_calls_disclosure_and_summary_rules_exist() -> None:
|
||||
assert "var(--accent-ink)" in summary, (
|
||||
"the accent rides the summary text (≈10.4:1 on the surface)"
|
||||
)
|
||||
assert "cursor: pointer" in summary, "a toggle affordance"
|
||||
toggle = re.search(r"summary\.tool-calls-summary \{([^}]*)\}", css)
|
||||
assert toggle, (
|
||||
"the D5 refinement: the toggle affordance is scoped to the "
|
||||
"legacy <summary> (the in-container label is a static span)"
|
||||
)
|
||||
assert "cursor: pointer" in toggle.group(1), "a toggle affordance"
|
||||
|
||||
Reference in New Issue
Block a user