An edge that is not drawn, and a panel that stopped eating the site

`hx-get=""` is not "fetch nothing". htmx looks for the attribute, not for a
value, so the empty one the canvas rendered before a chat existed was a real
request for the empty path -- which the browser resolves against the current
document. Opening the canvas on the new-chat screen fetched the new-chat screen
and swapped the whole site into the panel. The attribute is omitted now, and a
test refuses an empty verb anywhere on the page.

Which panels can exist is the server's answer; which are offered is the
browser's. Both need an agent chat on a chosen connection, and before a chat
exists those are controls in the composer -- so answering with the first profile
offered a terminal on an ordinary chat with nothing selected. They follow
`lembas:agent-target` now, and an open panel whose target goes away is closed
rather than left showing one machine under another's name.

`.tabs__body` is only sometimes the scroller: true where the tabs are a bounded
flex child, false under the admin layout, where the page scrolls instead. So
setting its scrollTop on every tab change had never once run on /admin/prompts,
silently, while the reader was dragged to the bottom of a document that had just
got shorter. The rule names the position now, and the handler finds the
container that actually scrolls.

The two top borders come off. They were what made the misalignment at the bottom
of the shell visible; `--footer-height` stays, because two ends at different
heights are visible without a line to prove it. The top of the shell keeps its
line -- there, everything is `--header-height` and aligns by construction.

And one version. pyproject carried its own copy and had drifted three minors
from the one everything actually reads.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jaroslav Beneš
2026-08-06 09:42:06 +02:00
parent 4c78215e31
commit bdd7e09753
13 changed files with 281 additions and 39 deletions
+63
View File
@@ -13,6 +13,7 @@ from lembas.db.models import (
Connection,
Model,
ScratchDoc,
SshProfile,
User,
)
from lembas.services import canvas as canvas_service
@@ -602,3 +603,65 @@ def test_a_chat_with_no_machine_is_offered_no_file_dialog(
assert "data-canvas-open" not in body
# Scratch is still there: it needs no machine.
assert "scratch:" in body
def test_the_new_chat_screen_leaves_no_empty_htmx_verb(
client: TestClient, db, registered
):
"""`hx-get=""` is not "fetch nothing" -- htmx looks for the attribute, not
for a value (`if(s(t,"hx-"+r))` is hasAttribute), so an empty one is a real
request for the empty path. The browser resolves that against the current
document, so opening the canvas on the new-chat screen fetched the new-chat
screen and swapped the whole site into the panel.
Asserted over the entire page rather than over the canvas markup: the same
`{{ ... if chat else "" }}` shape would do the same thing anywhere, and the
failure looks like a rendering bug rather than a request.
"""
_add_connection(db)
profile = SshProfile(
owner_id=db.scalars(select(User)).first().id,
name="box",
host="10.0.0.9",
username="deploy",
auth="password",
password_encrypted=encrypt("hunter2"),
host_key="ssh-ed25519 AAAA",
enabled=True,
)
db.add(profile)
settings_store.update(db, {"enabled": True}, key=settings_store.AGENTS)
db.commit()
body = client.get("/chat").text
for verb in ("get", "post", "patch", "put", "delete"):
assert f'hx-{verb}=""' not in body
def test_the_panel_buttons_start_hidden_before_a_chat_exists(
client: TestClient, db, registered
):
"""Which connection is chosen, and whether this is going to be an agent chat
at all, are decisions being made in the browser. The server answered with
the first profile regardless, so both buttons were offered on an ordinary
new chat with nothing selected."""
_add_connection(db)
db.add(
SshProfile(
owner_id=db.scalars(select(User)).first().id,
name="box",
host="10.0.0.9",
username="deploy",
auth="password",
password_encrypted=encrypt("hunter2"),
host_key="ssh-ed25519 AAAA",
enabled=True,
)
)
settings_store.update(db, {"enabled": True}, key=settings_store.AGENTS)
db.commit()
body = client.get("/chat").text
assert "data-agent-only hidden" in body