From 7d0067a324fa17fbafeca8f2c22f677cb18f95a1 Mon Sep 17 00:00:00 2001 From: tegwick Date: Tue, 29 Sep 2026 11:01:51 +0200 Subject: [PATCH] UI: state marking top right of the step frame, number and title left Co-Authored-By: Claude Sonnet 5.5 Assistant: claude-code Assistant-Model: sonnet Assistant-Process: 295952@bnt-lap001 Assistant-Session: e93f64ad-516c-46eb-9666-aad8d300c477 --- rtut/ui.py | 8 +++++--- tests/test_ui.py | 8 ++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/rtut/ui.py b/rtut/ui.py index 69f1131..0da1f9b 100644 --- a/rtut/ui.py +++ b/rtut/ui.py @@ -19,7 +19,7 @@ h1,h2{font-weight:600}a{color:inherit}hr{border:0;border-top:1px solid #8886} .step{border:1px solid #8886;padding:.8rem 1rem;margin:.8rem 0}.step.running{border-color:currentColor} .pill{font:12px ui-monospace,monospace;border:1px solid #8886;padding:0 .4rem} pre{border:1px solid #8886;padding:.5rem;overflow:auto;margin:.4rem 0} -button,input,select{font:inherit;padding:.25rem .5rem}.row{display:flex;gap:.5rem;align-items:center;flex-wrap:wrap}.grow{flex:1;min-width:12rem}[hidden]{display:none}#current{scroll-margin-top:1rem}.note{opacity:.75}.bad{font-weight:600}""" +button,input,select{font:inherit;padding:.25rem .5rem}.head{display:flex;justify-content:space-between;align-items:baseline;gap:1rem}.row{display:flex;gap:.5rem;align-items:center;flex-wrap:wrap}.grow{flex:1;min-width:12rem}[hidden]{display:none}#current{scroll-margin-top:1rem}.note{opacity:.75}.bad{font-weight:600}""" def page(title: str, body: str) -> bytes: @@ -148,8 +148,10 @@ class App: waiting_for = f"step {n}, {s['title']}" rb = f"

Rollback: {e(s['rollback'])}

" if s.get("rollback") and state in ("running", "failed") else "" anchor = " id=current" if s["id"] == current else "" - out.append(f"{state} {n}. {e(s['title'])} " - f"[{e(s['owner'])}] {e(s.get('risk', 'read-only'))}{block}" + out.append(f"
" + f"{n}. {e(s['title'])} " + f"[{e(s['owner'])}] {e(s.get('risk', 'read-only'))}" + f"{state}
{block}" f"

Done when: {e(s['verify']['done_when'])}

{rb}{act}") if r.complete: out.append("

All steps done. To record this run as exercising the pack, review and apply: " diff --git a/tests/test_ui.py b/tests/test_ui.py index 318fb8c..7f531fb 100644 --- a/tests/test_ui.py +++ b/tests/test_ui.py @@ -154,3 +154,11 @@ def test_fail_without_comment_warns_first_then_is_allowed(srv): assert st == 303 _, _, body = req(srv, "GET", base) assert "(no comment)" in body and "Retry" in body + + +def test_state_pill_is_top_right_after_the_numbered_title(srv): + t, loc, _ = _showcase_run(srv) + _, _, body = req(srv, "GET", loc.split("#")[0]) + head = body[body.index("

"):] + assert head.index("1. Read the poem") < head.index("class=pill") # number and title first, state last + assert "justify-content:space-between" in body # pill pushed to the right edge