Files
brain-of-reese/tests/unit/test_tool_call_compact.py
T
ducoterra 690fd98036
Build and Push Containers / build-and-push-app (push) Successful in 1m43s
Build and Push Containers / build-and-push-db (push) Successful in 15s
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
2026-10-06 14:44:41 -04:00

321 lines
14 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Unit: the phase-117 tool-calls DISCLOSURE contract (task 01).
The owner's visual-glitch report (2026-09-15): one per-call tool "card"
per ``tool`` frame — 6+ stacked full-width bordered cards on a phone —
swamped a completed answer, and the flex row broke the label
mid-word. The fix (phase 117, owner decisions D1–D6) wraps the
existing ``.tool-calls`` list in a native ``details`` disclosure with a
plain-text "Tool call(s) (N)" summary — phase 158 (D1): one
disclosure per CONTIGUOUS tool-call run, created OPEN on the first
live ``tool`` frame of the run, folded at rest (delta folds the
active run via ``closeCurrentRun``; done/stop/finalizeFailedTurn fold
every run via ``closeAllRuns``), and rendered CLOSED on the restore
path and the shared page (D3). The count is per run (the per-run
"Tool call(s) (N)", D3). The line bytes, the four label literals, and
the ``<code>`` textContent arguments stay byte-identical (D6), so the
phase-37/70/87/95 pins stay green.
No ``app/`` logic (frontend-only, D1) — like
``test_frontend_tool_states.py``, this module pins the JS/CSS markers
at source level: the disclosure/summary build (task 01) and the
debox/dechip + disclosure CSS contract (task 02). The E2E story suite
(task 03) completes the phase.
"""
from __future__ import annotations
import re
from pathlib import Path
FRONTEND = Path(__file__).resolve().parents[2] / "frontend"
APP_JS = FRONTEND / "assets" / "app.js"
SHARED_JS = FRONTEND / "assets" / "shared.js"
STYLES_CSS = FRONTEND / "assets" / "styles.css"
#: The four pinned tool-line label literals (D6) — the emoji guard and
#: the phase-37/70 pins key off these exact bytes.
PINNED_LABELS = (
'line.textContent = "📄 Reading "',
'line.textContent = "🔎 Searching for "',
'line.textContent = "🔎 Listing documents in "',
'line.textContent = "🔎 Listing documents"',
)
def _js() -> str:
return APP_JS.read_text(encoding="utf-8")
def _shared_js() -> str:
return SHARED_JS.read_text(encoding="utf-8")
def _css() -> str:
return STYLES_CSS.read_text(encoding="utf-8")
def _fn(src: str, name: str) -> str:
"""The flat function body (house extraction: first ``\n}\n`` after
the definition — the function must stay flat, no nested
declarations)."""
fn = src.find(f"function {name}")
assert fn != -1, f"{name} must exist"
return src[fn : src.find("\n}\n", fn)]
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, "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(\"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
assert 'setAttribute("role", "list")' in disc
assert 'setAttribute("aria-label", "Tool calls")' in disc
assert "innerHTML" not in disc, (
"the tool builder stays createElement/textContent (phase 117 "
"style — innerHTML ABSENT)"
)
run = _fn(js, "ensureToolRun")
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)"
)
assert (
'ensureReasoningWrap(wrap).querySelector(".reasoning-body")'
".appendChild(disc)" in run
), (
"phase 161 (D1): appended into the container's body — the "
"container sits above the answer, arrival order preserved"
)
# D5: the count rides the summary — the template fragment itself
# (singular for one call, plural otherwise), textContent-built.
append = _fn(js, "appendToolLine")
assert "Tool call${n === 1 ? \"\" : \"s\"} (${n})" in append, (
"the per-run plain-text count template (D3) on every append"
)
assert "innerHTML" not in append, (
"no HTML injection surface on tool lines — textContent only"
)
def test_append_tool_line_keeps_the_four_pinned_labels() -> None:
"""D6: the four ``line.textContent`` label literals and the
``<code>`` textContent arguments stay byte-identical — the emoji
guard, the phase-37/70 unit pins, and the E2E text assertions all
key off these exact bytes."""
body = _fn(_js(), "appendToolLine")
for label in PINNED_LABELS:
assert label in body, f"pinned label literal changed: {label!r}"
assert "code.textContent = argument" in body, (
"the path/pattern/scope is data — textContent, never innerHTML"
)
def test_close_all_runs_defined_and_called_at_every_rest_site() -> None:
"""Phase 158 (D5): ``closeAllRuns`` — the terminal settle (the
phase-117 ``closeToolCalls`` + the D15 block close, merged):
closes EVERY open ``details.thinking`` +
``details.tool-calls-disclosure`` in the wrap (defensive; a late
double-close is a no-op), called at ALL rest sites — the done
handler (the turn ended), the stop/abort settle (the turn was
stopped), and the failed-turn funnel — so the definition + ≥3
calls. The `delta` handler folds only the active run
(``closeCurrentRun``)."""
js = _js()
body = _fn(js, "closeAllRuns")
assert "details.thinking, details.tool-calls-disclosure" in body, (
"targets both run kinds in the given wrap"
)
assert "el.open = false" in body, "fold: open=false (idempotent)"
assert js.count("closeAllRuns(wrap)") >= 3, (
"the definition + the done handler + the stop/abort settle + "
"the failed-turn funnel — the runs settle exactly where the "
"Thinking blocks settle"
)
delta_idx = js.find('ev.type === "delta"')
done_idx = js.find('ev.type === "done"')
delta_branch = js[delta_idx:done_idx]
assert "closeCurrentRun()" in delta_branch, (
"the delta folds the ACTIVE run (not every run — a later "
"thinking frame opens a new one)"
)
def test_restore_path_folds_the_disclosure() -> None:
"""renderStoredMessage (D3): a restored brain record with `tools`
re-renders through the SAME appendToolLine (byte-identical — the
caller passes the run's disclosure, phase 158), and the
disclosure is FOLDED right after the loop (``restoreDisc.open =
false``) — a completed turn from storage is one compact
"Tool calls (N)" line, not N stacked cards (the space fix;
mirrors the thinking restore rendering collapsed)."""
js = _js()
fn = js.find("function renderStoredMessage")
assert fn != -1
body = js[fn : js.find("function restoreConversation", fn)]
assert "appendToolLine(restoreDisc, t.name, arg, tOffset, tLimit, tPath)" in body
assert "restoreDisc.open = false" in body
assert (
body.find("appendToolLine(restoreDisc, t.name, arg, tOffset, tLimit, tPath)")
< body.find("restoreDisc.open = false")
), "the fold sits AFTER the tool-line restore loop"
def test_run_anchors_are_the_container_in_arrival_order() -> None:
"""Phase 158 (D2) + 161 (D1): the anchor moved to the REASONING
CONTAINER for both run kinds (the phase-161 documented
supersession — the container sits before the bubble; the runs
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 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 "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 "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:
"""shared.js addToolLines (D3 parity): the SAME
``details.tool-calls-disclosure`` + summary + ``.tool-calls`` list —
but created CLOSED (a pure render has no live turn to open it),
with the count set once at the end. The four label literals, the
three textContent-only argument lines, and the phase-95 marker stay
byte-identical (no innerHTML anywhere)."""
body = _fn(_shared_js(), "addToolLines")
assert "document.createElement(\"details\")" in body
assert "className = \"tool-calls-disclosure\"" in body
assert "document.createElement(\"summary\")" in body
assert "open = false" in body, (
"D3: the shared page renders the disclosure CLOSED — never an "
"auto-expanded record"
)
assert "className = \"tool-calls\"" in body
for label in PINNED_LABELS:
assert label in body, f"pinned label literal changed: {label!r}"
assert "Tool call${n === 1 ? \"\" : \"s\"} (${n})" in body, (
"the same plain-text count template (D5), set once at the end"
)
assert body.count("code.textContent = argument") == 3, (
"all three argument-bearing lines (read / grep / ls) stay "
"textContent-only"
)
assert "innerHTML" not in body, (
"no HTML injection surface on shared tool lines — textContent only"
)
def test_tool_call_rule_is_deboxed_inline_flow() -> None:
"""D4: the ``.tool-call`` rule is DEBOXED — no ``display: flex``,
no card (no background / border / radius / padding), and no
``var(--accent-line)`` left border. The accent now rides the TEXT
(``var(--accent-ink)``, ≈10.4:1 on the surface), and the line keeps
the compact status metrics + ``overflow-wrap: anywhere`` so the
label + inline ``code`` flow as ONE continuous run — a long path
wraps to the left edge and the label never breaks mid-word (the
"Rea/ding" glitch is gone)."""
m = re.search(r"\.tool-call \{([^}]*)\}", _css())
assert m, "the .tool-call rule must exist"
row = m.group(1)
assert "display: flex" not in row, (
"deboxed: no flex — the label + code are one inline run"
)
assert "var(--accent-line)" not in row, "deboxed: no accent left border"
assert "border" not in row, "deboxed: no card borders at all"
assert "background" not in row, "deboxed: no card background"
assert "padding" not in row, "deboxed: no card padding"
assert "var(--accent-ink)" in row, (
"the accent now rides the text color (≈10.4:1 on the surface)"
)
assert "font-size: 0.8rem" in row, "the compact status metrics stay"
assert "overflow-wrap: anywhere" in row, "the path wraps inside the run"
def test_tool_call_code_rule_is_dechipped() -> None:
"""D4: the ``.tool-call code`` rule KEEPS ``var(--mono)`` +
``var(--ink)`` (≈11.5:1 on the surface — AA) but LOSES the chip
(no background, no padding, no radius) — the path is inline text
in the line's run now."""
m = re.search(r"\.tool-call code \{([^}]*)\}", _css())
assert m, "the .tool-call code rule must exist"
code = m.group(1)
assert "var(--mono)" in code
assert "var(--ink)" in code
assert "background" not in code, "dechipped: no chip background"
assert "padding" not in code, "dechipped: no chip padding"
assert "border-radius" not in code, "dechipped: no chip radius"
assert "overflow-wrap: anywhere" in code
def test_tool_calls_disclosure_and_summary_rules_exist() -> None:
"""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 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"
)
m = re.search(r"\.tool-calls-summary \{([^}]*)\}", css)
assert m, "the .tool-calls-summary rule must exist"
summary = m.group(1)
assert "var(--accent-ink)" in summary, (
"the accent rides the summary text (≈10.4:1 on the surface)"
)
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"