Add lighthouse showcase pack (v0.1 runnable, v0.2 draft); fix manual-check cycle and blocked-step feedback (RBT-WP-0004-T05)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: sonnet Assistant-Process: 295952@bnt-lap001 Assistant-Session: e93f64ad-516c-46eb-9666-aad8d300c477
This commit is contained in:
parent
f9fb9008bf
commit
b47c948a7e
8 changed files with 387 additions and 12 deletions
31
rtut/ui.py
31
rtut/ui.py
|
|
@ -79,7 +79,12 @@ class App:
|
|||
if msg:
|
||||
out.append(f"<p class=bad>{e(msg)}</p>")
|
||||
blocked = False
|
||||
for s in d["steps"]:
|
||||
waiting_for = ""
|
||||
total = len(d["steps"])
|
||||
done_n = sum(1 for x in d["steps"] if r.state(x["id"])["state"] in ("done", "skipped"))
|
||||
out.append(f"<p class=eyebrow>{done_n} of {total} steps done</p>"
|
||||
f"<progress max={total} value={done_n} style='width:100%'></progress>")
|
||||
for n, s in enumerate(d["steps"], 1):
|
||||
st = r.state(s["id"]); state = st["state"]
|
||||
act = ""
|
||||
cmd = R.command_for(r, s["id"])
|
||||
|
|
@ -87,18 +92,25 @@ class App:
|
|||
url = f"/run/{i}/{e(rid)}/{e(s['id'])}"
|
||||
v = st.get("verification")
|
||||
if state == "todo" and not blocked:
|
||||
act = f"<form method=post action='{url}/start'>{self.hidden()}<button>Start</button></form>"
|
||||
act = f"<form method=post action='{url}/start'>{self.hidden()}<button>Start this step</button></form>"
|
||||
elif state == "todo":
|
||||
act = f"<p class=note>Waiting for: {e(waiting_for)}</p>"
|
||||
elif state == "running":
|
||||
ver = s["verify"]
|
||||
if ver.get("expect", "manual") == "manual":
|
||||
act = (f"<form method=post action='{url}/verify'>{self.hidden()}<label><input type=checkbox name=ok value=1> "
|
||||
f"I confirm: {e(ver['done_when'])}</label> <button>Record check</button></form>")
|
||||
act = (f"<form method=post action='{url}/verify'>{self.hidden()}"
|
||||
f"<p>Is this true? <b>{e(ver['done_when'])}</b></p>"
|
||||
"<button name=ok value=1>Yes, it is</button> <button name=ok value=0>Not yet</button></form>")
|
||||
else:
|
||||
act = (f"<form method=post action='{url}/verify'>{self.hidden()}<input type=hidden name=yes value=1>"
|
||||
f"<p class=note>Runs: <code>{e(R.render(ver['command'], r.data['params'], p))}</code></p>"
|
||||
f"<button>Run check</button></form>")
|
||||
if v:
|
||||
act += f"<p>{'✔ passed' if v['passed'] else '✘ failed'}</p>"
|
||||
if not v:
|
||||
act = "<p class=note>1. Run the command, then check → 2. Mark done to lock it in</p>" + act
|
||||
elif v["passed"]:
|
||||
act += "<p><b>✔ Check passed.</b> Press <b>Mark done</b> to lock it in; the next step opens after that.</p>"
|
||||
else:
|
||||
act += "<p class=bad>✘ Check not passed. Fix the cause, then check again, or mark the step failed.</p>"
|
||||
if v and v["passed"]:
|
||||
ev = "".join(f"<label>{e(n)} <input name='e_{e(n)}' required></label> " for n in s.get("evidence", []))
|
||||
act += f"<form method=post action='{url}/done'>{self.hidden()}{ev}<button>Mark done</button></form>"
|
||||
|
|
@ -106,10 +118,11 @@ class App:
|
|||
"<button>Mark failed</button></form>")
|
||||
elif state == "failed":
|
||||
act = f"<p class=bad>Failed: {e(st.get('note', ''))}</p><form method=post action='{url}/retry'>{self.hidden()}<button>Retry</button></form>"
|
||||
if state not in ("done", "skipped"):
|
||||
if state not in ("done", "skipped") and not blocked:
|
||||
blocked = True
|
||||
waiting_for = f"step {n}, {s['title']}"
|
||||
rb = f"<p class=note>Rollback: {e(s['rollback'])}</p>" if s.get("rollback") else ""
|
||||
out.append(f"<div class='step {state}'><span class=pill>{state}</span> <b>{e(s['title'])}</b> "
|
||||
out.append(f"<div class='step {state}'><span class=pill>{state}</span> <b>{n}. {e(s['title'])}</b> "
|
||||
f"<span class=note>[{e(s['owner'])}] {e(s.get('risk', 'read-only'))}</span>{block}"
|
||||
f"<p class=note>Done when: {e(s['verify']['done_when'])}</p>{rb}{act}</div>")
|
||||
if r.complete:
|
||||
|
|
@ -167,7 +180,7 @@ def make_handler(app: App, port_holder: list):
|
|||
p = app.packs[i]; r = R.load(p, rid)
|
||||
if action == "start": R.start(r, sid)
|
||||
elif action == "verify":
|
||||
R.verify(r, sid, confirm=bool(form.get("yes")), manual_ok=bool(form.get("ok")) if not form.get("yes") else None)
|
||||
R.verify(r, sid, confirm=bool(form.get("yes")), manual_ok=(form.get("ok") == "1") if not form.get("yes") else None)
|
||||
elif action == "done":
|
||||
R.complete(r, sid, {k[2:]: v for k, v in form.items() if k.startswith("e_")})
|
||||
elif action == "fail": R.fail(r, sid, form.get("note", ""))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue