feat(control): keep durable command-line test sessions #47
No reviewers
Labels
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
needs measurements
question
testing wanted
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Longshot!47
Loading…
Reference in a new issue
No description provided.
Delete branch "mooki/Longshot:feat/ctl-sessions"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why
A command-line test should remain usable after its launching client exits, with its log, screenshots and actual shutdown result intact. This is the standard-library session layer, part 1 of the work continued from Nicholas Gower's https://github.com/NotRexed/Hookshot/issues/1025; his agreement to hand it over is still pending in the retained discussion, and the offer to hand it back after acknowledging his later push stands.
What changed
bin, not the root launcher. Development image, executable, user and romfs paths are explicit.How this fits with my workbench
My separate workbench supplies queues, a run wrapper and agent skills. This client is the generic, standard-library part;
--wrapperlets an external admission command own the entire game lifetime without embedding machine policy here. The workbench adds evidence handling and checks, and speaks the same bridge. Its separate MCP server is not this PR. The original GitHub runs used its queue and its fork checks caught the two Windows bugs fixed before publication. It is my tooling, not part of Longshot, not endorsed by its maintainers, and not a dependency.Flags and settings
HOS_CONTROLHOS_HEADLESSHOS_AUDIOHOS_ENV_FILE--runlaunch --runlaunch --rootlaunch --profilelaunch --readylaunch --timeoutlaunch --exelaunch --imagelaunch --romfslaunch --userlaunch --cwdlaunch --wrapperlaunch --savelaunch --slotlaunch --datalaunch --env--exclusive--no-exclusivesequence --hosstop --timeoutstop --terminatelog --lineslog --sincelog --byteslog --expectlog --regexlog --timeout--jsonlaunch --headless--sockMeasurements
Branch state: on main
f41db065cf6667ec638a10aa6990099392d10dca; heada1743d01d9872093731282fd20a1eac9acc6bdcc; whole game-free suite on this head:509 passed, 0 failed, 19 skipped(mainf41db065cf6667ec638a10aa6990099392d10dca:509 passed, 0 failed, 19 skipped); the commits are unchanged by rebases apart from the results table.On the measured commits the branch's only failure was also on main:
tests/test_updater_asset_digest.py, local .NET SDK 10.0.113 missingMicrosoft.AspNetCore.App.Ref (= 10.0.13), errorNU1100. That test left main together with the in-game updater, so the suites in the branch-state block no longer contain it.main:
d4a69456c9(2026-11-12)this PR: feat/ctl-sessions @
596c0a3372Measurement provenance: main @
d4a69456c9. tested client @596c0a3372;44b0bea032adds only these evidence rows.Hardware: Core i9-13900K, 96 GB RAM, Arch Linux 7.2.15; game check on RTX 4090 / NVIDIA 615.78.08.
Scene: game-free Builder/session fixtures; separate fresh-profile Longshot title-menu run, windowless, muted, 1280×720 captures, frame generation off, shader preparation deferred.
Method: whole suites first, then the same 22 new tests against main and branch in before/after/before/after order, fresh HOME each time. Medians below are passing-case counts, not execution speeds. The ordinary shared game run proves lifecycle operations, not frame rates. This is a command-line tool, with no change to the game when the client is not run.
How to reproduce: Run
python -I -B tests/test_longshot_ctl.py GamePaths Sessionsagainst the PR client, then the same tests with LONGSHOT_CTL_SOURCE selecting the pinned main client; interleave twice. For the functional game check use an owned copy, the test profile, present readiness then stable menu state for 30 frames, B for 8 frames, shot and stop; shader preparation was deferred, not timed.Main
d725b3631adds only scripts, docs and tests, with no game-code change; the measuredd4a69456comparisons and pinned game evidence remain valid and were not repeated. Original results below retain their measured commits; the new suite is recorded in the branch-state block.Baseline: main @
d4a69456d4a69456596c0a33Main lacks the new session APIs, so those baseline negatives include
AttributeError: module 'longshot_ctl' has no attribute 'start_session'; they are feature-absence checks, not a claim that main's existing client is broken. Both suites usedtests/run_all.py --jobs 6 --strictwith the repository's default compiler. The main suite is the shared baseline run once for this day's moved pull requests at this commit. These checks have not yet been run on a forge runner.Main additionally failed two timeout/sequence cases in
tests/test_appimage_package_retry.pyunder heavy load; the requested isolated rerun passed all 9 cases (Ran 9 tests in 15.166s,OK). It fails only under heavy load on this PC; timing-dependent. This branch's full run passed that file. Neither full-suite failure has been erased or called green.Real Longshot lifecycle
The client above drove an owned copy of Longshot main
d3bd28050(v2.2.0-rc.1-15-gd3bd28050, source fingerprint2bce0d57). The native code is unchanged by this PR; the donor was copied, never modified. The successful run waited for drawable menu state to persist for 30 frames before input.ready=presenttimed out at frame 0 while shader/pipeline preparation was progressing. The supervisor terminated and reaped its child: exit -15,process_exited:true,stop_method:startup-terminate. No picture or completed preparation claimed.Selected fields copied from the successful replies:
Both attempts had fatal=0, crash=0, device-loss=0 and kernel faults=0, with complete journal coverage. No performance comparison: the successful run's one-minute load was 241.39 → 230.52.
Historical evidence, not relabelled as Longshot: on 2026-11-12 the Hookshot game
ba005ca4with client 3f1da556 completed a 38.4 s Kokiri Forest session, screenshot, reattachment and quit exit 0. Its earlier 72.9 s attempt reached play but stopped at an invalid Linux log expectation. The retained image below belongs to that older successful run.The complete suite was rerun after every source/documentation commit, with the default compiler and fresh HOME. The earlier measurement rows remain labelled by their actual commits. Main's suite was run once for all branches on this commit. No hosted CI or new game run is claimed.
Testing
Tested: on this PC (Arch Linux, RTX 4090 with NVIDIA 615.78.08, i9-13900K), the whole game-free suite and the same 22 new Builder/session tests against main and this PR twice in interleaved order, with a fresh test home each time. The Longshot title-menu check waited for stable menu state for 30 frames, held B for 8 frames, took an acknowledged screenshot, reattached from another client, then stopped and read the finished manifest; the cold-preparation readiness timeout and child reaping are retained too. Tested but not measured: The new Longshot title lifecycle and historical Hookshot gameplay were functional checks, not performance or sampling-freshness measurements.
Not tested: the explicitly listed platforms, integration and runtime cases below remain untested; only the bounded Linux/NVIDIA lifecycle above was run for Longshot.
gameis null. Historical Hookshot gameplay remains separately labelled.Needs other testers:
Screenshots
Nothing on screen changes in this tool. main @
d4a69456has no session-layer comparison picture. this PR @596c0a33client with native game main @d3bd28050: the title-menu lifecycle picture below; not a rendering comparison.Risk and rollback
A wrong path or reused manifest could target the wrong executable or expose private logs. Use only trusted owned run folders; pid-birth checks and the original parent prevent signalling unrelated processes. Stop the owned test session and return to ordinary launch, or revert this client change. Quit has no save-drain barrier; force is opt-in, and no rollback can promise an unwritten save was drained.
Reviewer notes
Read game_exe, start_session, wait_ready, Session log/stop and the supervisor ownership checks first. Confirm Builder bin-first selection, linked-root handling and UTF-8 cursor tests. No game-side protocol, save-safe quit or run-long input lock is added; those limits remain deliberate. Nicholas Gower credit and the pending handover agreement are retained.
Issues
Original pull request: https://github.com/NotRexed/Hookshot/issues/2904.
Original work and credit: https://github.com/NotRexed/Hookshot/issues/1025; command-line-first discussion: https://github.com/NotRexed/Hookshot/pull/764#issuecomment-6729605427.
No corresponding issue exists in the forge's public issue inventory checked for this move. No old GitHub number is used as a forge closing reference.
Checklist
For everyone
type(scope): description).main.python -I -B tests/run_all.pyrun and passing (any failure that also fails onmainis named above).third_party/untouched (a new folder with aPROVENANCE.mdinstead).If applicable
Assisted-by:/Co-Authored-By:trailers.docs/tested-configurations.mdfor each measured run.mainand passing here.tests/that reads changed source updated in this PR, not weakened.Moved from NotRexed/Hookshot#2904.
Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra [email protected]
Co-authored-by: Nicholas Gower [email protected]
Discussion carried over from NotRexed/Hookshot#2904
Every comment that was readable on the original thread when it was copied on 2026-11-12, in order, unchanged except that issue and pull request numbers are written as links to the old repository and names carry no @. Comments by an account that has since been closed there could no longer be read and are missing; where a reply quotes them, the quote remains.
mooki000, 2026-11-12 22:06 UTC (comment, original):
One more commit,
870d3815: a game that exits before it ever listens was sometimes reported as "ready timed out" instead of "exited with code N".The readiness wait checked the deadline before it looked at the child again, so which message you got depended on wall time. It showed on loaded Windows runners in my fork:
tests/test_hookshot_ctl.py(test_ready_levels_and_cleanup, the exit case) failed two runs out of two while testing the next part of this stack, with "ready=play timed out: no game listens" where "exited 7" was expected. This pull request's own checks had passed, so the test was timing-dependent rather than wrong every time.NotRexed/Hookshot#2921 (the draft on top of this) is not rebased yet; it does not need this commit to be read.
Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra [email protected]
feat(control): keep durable command-line test sessionsto WIP: feat(control): keep durable command-line test sessionsBack to work in progress, for its description only. This was opened shortly before #48 merged and follows the earlier template, so it does not pass the new description check (no Flags and settings and no Risk and rollback section, table columns named Before and After). The code and the measurements are unchanged: the whole suite passes on this exact commit apart from one local .NET failure that also fails on main. The description is being moved to the new template and the branch rebased onto
d725b363; it comes back throughpr readyonce the check passes.Rebased onto main
d725b3631as23cc17be6a; all eight carried patches are unchanged, and the newer main changes only scripts, docs and tests, so the earlier measurements retain their original commit labels. The description now follows the new template, including every changed control, reproduction steps, risks and rollback, while keeping both uploaded pictures and the original credit. The whole suite on this exact head finished 510 passed, 1 failed, 20 skipped, with only main's known local .NET reference-pack failure; the description checker passes without WIP.WIP: feat(control): keep durable command-line test sessionsto feat(control): keep durable command-line test sessions9f5f6dd292to23cc17be6afeat(control): keep durable command-line test sessionsto WIP: feat(control): keep durable command-line test sessionsBack to work in progress for two reasons, neither a change to the code or the measurements. The template gained a Testing section with #72 (what was tested, what was not, and which testers are needed, with test requests), which this description does not have yet. And #39's merge added a row to the results table at the same place as this pull request's rows, so the branch conflicts in that one file until it is rebased. Both are being done; it returns through
pr ready.23cc17be6atoa1743d01d9The description now has the current template's Testing section: what was tested, what was not, and which testers are needed; the test request is open (T-8DJG). Rebased onto main
f41db065ckeeping both sides' rows of the results table; whole suite on the new heada1743d01d: 509 passed, 0 failed, 19 skipped. Ready for review.WIP: feat(control): keep durable command-line test sessionsto feat(control): keep durable command-line test sessionsView command line instructions
Checkout
From your project repository, check out a new branch and test the changes.