Repository navigation
Add ui_eval record: start a local demo app, record it, stop it - #4
Merged
Merged
Conversation
record reads a launch file, refuses to run if something already answers at base_url, starts the command without a shell, waits for the ready path, runs the UI script with video and stops only the process group it started. Reports add the server's command, pid, readiness time, exit code and log, and run reports now list recorded videos with hashes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HSV4zUy6rF1vgHFSyUmuva
stop() now signals the process group even after the leader exits, escalates to SIGKILL after a configurable grace for children that ignore SIGTERM, and never waits unbounded. record turns SIGTERM and SIGHUP into cleanup, refuses when anything listens on the port, needs a ready status below 400 without following redirects, reports browser launch failures, and lists only this run's videos. Reports record cwd relative to the repository, and review treats readiness failures as failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HSV4zUy6rF1vgHFSyUmuva
A SIGTERM arriving during stop()'s grace wait aborted it before SIGKILL, leaving children that ignore SIGTERM running, and one arriving between Popen and cleanup skipped stop() entirely. Signals are now deferred in both windows and re-raised once the group is stopped. Playwright is imported only when a browser run starts, the test helper's skip path works without Playwright, and CI allows 180s per check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HSV4zUy6rF1vgHFSyUmuva
Browser-backed UI tests put the stack suite near the old 60 second limit, so local runs and CI now share a default with headroom instead of a CI-only override. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HSV4zUy6rF1vgHFSyUmuva
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HSV4zUy6rF1vgHFSyUmuva
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The demo lane still needed someone to start the app by hand before
ui_eval.py run, and to remember to stop it afterwards.recorddoes the whole pass in one command: start the app, record the run, stop the app.What changed
ui_eval.py record SCRIPT.json --launch demos/<name>/launch.jsoncommandis an argument list run without a shell, with$PYTHONreplaced by the current interpreter.cwdmust be inside the repo, so symlink, absolute and..escapes are rejected. Alsoready_path,ready_timeout_s,stop_grace_sandenv.base_urlmust be on localhost.ready_pathanswers with a status below 400. Redirects aren't followed and proxies aren't used. It re-checks that the process is still alive before the browser starts.run()with video. Each run's videos go in their ownvideo/<run_marker>/folder and are listed with their SHA256.stop_grace_s(default 10), then SIGKILLs anything still running.recorditself are deferred while the server is starting or stopping and re-raised once the group is gone, so the server is never left running.server: the command as given,cwdrelative to the repo, pid, readiness time, exit code, env names without values, andserver.log. It also addsreasons:server_exited_before_readyserver_not_readyserver_exited_during_runbrowser_failed: …stepsandvideos, andreviewreports it as failed.Other
control.py verifytimeout is raised from 60s to 180s. Browser-backed UI tests had pushed the stack suite to about 52s locally.sstack-verify/references/ui-eval.mdhas a "Start and record a local app" section.sstack-demostep 2 and rehearsals userecordfor local apps.tools/sstack/README.mdis updated.Validation
control.py verify changed --base origin/main --jobs 2passes on bb24ad4: docs, 134 stack tests and lint, with the browser tests running in real Chromium.recordstop()is inside its grace waitKnown limits
recordis for apps on localhost only. Hosted Kizen still usesui_eval.py runwith an approved origin.stop_grace_sbefore it's killed.control.py's own timeout kill only reaches the test runner's process group. If a suite times out, test servers in their own sessions can outlive it. With the new 180s default this isn't expected, but the gap is incontrol.py, not inrecord.🤖 Generated with Claude Code
https://claude.ai/code/session_01HSV4zUy6rF1vgHFSyUmuva
Generated by Claude Code