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
+53 -29
View File
@@ -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"