Repository navigation
feat(menu): a Bug report row that saves what an issue needs in one press - #2347
Conversation
Joey-Magnus
left a comment
There was a problem hiding this comment.
This is a thoughtful feature, and the PR is unusually well documented. The redaction rules, the link-length table and the test that compiles vk_bug_report.cpp on its own are all good. I focused on the riskiest parts: the readback on the present path, the threading between the menu, the writer and the replay, the log copy, and what can leak into a report. At the PR's head on Linux, tests/test_bug_report.py, tests/test_capture_dimensions.py and tests/test_capture_slot_ownership.py pass. CI hasn't run yet (only the title check).
- should fix: merge conflict with main in
gpu/vk/vk_replay.cppandgpu/vk/vk_menu.cpp. The menu one is trivial: the Debug tab gained rows, andRowhas an extra trailing field. The replay one matters more: #926 (32693f02) is merged and addedshot_ask()/shot_ask_record()/shot_ask_take()at the same spot indo_present. That's an on-demand screenshot with its own image and buffer, read back only oncecompleted()passes it, and written on a thread, which is almost exactly whatReportShotdoes here. When you rebase, I'd dropReportShotand havebug_reportcallshot_ask(dir + "picture.png", -1, done, ctx)withdonecallingpicture_written. That removes the duplicate readback, and it also avoids the next point. - minor
gpu/vk/vk_replay.cpp:3108(PR head): with a window, the report's first picture callsoffscreen_init(), which allocatesoff_imageat the swapchain's size (about 33 MB at 4K) plus the two shot buffers, and keeps them for the rest of the run, although only the headless path usesoff_image.shot_ask_init()on main allocates only the 1280x720 image and one buffer, so switching to it fixes this too. - should fix
gpu/vk/vk_bug_report.cpp:200-202: iffgetsreads a chunk that starts with a NUL byte,buf.data()is an empty C string,linestays empty, andline.back()is undefined behaviour (an abort under_GLIBCXX_ASSERTIONS, garbage otherwise). Logs from a run that ended in a power loss or a hard kill often end in a run of NUL bytes, and the run before's log is exactly what this report is for. It also undercountsat, which shifts the head/tail cut. Read withfreadinto the buffer and split on'\n'yourself, or at least guard withif (line.empty() || (line.back() != '\n' && ...))and addnbytes fromfgetsby length rather thanstrlen. A test case with a log that ends in a few KB of\0would cover it. - minor
gpu/vk/vk_bug_report.cpp:422: on Windows,CreateDirectoryAsetsGetLastError(), noterrno, sostrerror(errno)in the "could not be made" message will be stale or "No error". UseGetLastError()there (or skip the reason on Windows). - minor
gpu/vk/vk_bug_report.cpp:223-243: switches are filtered by prefix and only paths are left out. As you note, a future switch holding a secret (co-op's room code, a token) would go intoreport.txtand the link. A cheap guard now: leave out the value of any switch whose name containsTOKEN,KEY,SECRET,PASSorROOM, the same way as paths. It's cheaper than remembering to update this file when such a switch lands. - question (for the maintainer, echoing your own question): CONTRIBUTING.md lists
hookshot_env.txtamong the files never to share. The report doesn't attach the file, but it does copy its switch names and non-path values intoreport.txtand the link. That seems fine to me, since the values are toggles and numbers, but the maintainer should decide it explicitly, and if accepted, a line in CONTRIBUTING.md would avoid future confusion.
I checked the rest and it holds up: the picture request and ticket handshake under pic_mu (including withdrawing a request no present took), start()'s compare-exchange allowing one report at a time, the menu row's press placed before the generic !r.value page branch, and the map: line in oot_inventory_refresh (game thread, at most every 500 ms, and only logged on change). Windows' A functions and fopen are fine with UTF-8 paths given the game's UTF-8 manifest (tests/test_utf8_paths.py). Once rebased, please re-run the capture tests, test_bug_report.py and anything that counts the Gameplay or Debug rows.
Joey-Magnus
left a comment
There was a problem hiding this comment.
The earlier review is still open, and the branch now conflicts in six files:
gpu/vk/vk_bug_report.cpp:206-208:fgetsthenline.back()on an empty string is UB when a log contains NUL bytes, which hard-kill logs often do.ReportShotrepeats #926'sshot_ask()readback and callsoffscreen_init()in windowed runs, keeping a swapchain-sized image (~33 MB at 4K) for the rest of the run.strerror(errno)afterCreateDirectoryA(:428) gives a stale reason; useGetLastError().report.txtand the pre-filled issue link includehookshot_env.txtnames and values, which CONTRIBUTING says never to share. At least drop values whose names contain TOKEN, KEY or ROOM.
|
This now conflicts with main in |
Gameplay -> Bug report writes bug-reports/<date>_<time> in the game folder: report.txt with the game problem form's answers under its own headings (version, the map from the log, GPU and driver, CPU/RAM/system, the options and switches changed) and a link that fills the form in; this run's log and the run before's with the home folder and user name taken out of their paths; and a picture of the game's frame without the menu. Nothing is sent and no game file or save goes in. The host logs the map and Link's age when either changes (map: ...), which the report reads back. The picture has a readback of its own (a mapped buffer made at the first report, taken at a present no screenshot takes, written once the GPU is past it): the screenshot path's gate, pending-shot record and consume line stay as they were, which tests/test_capture_dimensions.py and tests/test_capture_slot_ownership.py cut out and run. The link stays within 2000 characters. A player who is not signed in to GitHub is sent to its sign-in page with the whole link inside it, and that page failed (HTTP 400 or 500, or the answers dropped) for links from about 3500 characters of escaped text. When the changes from the defaults do not fit, the link carries the options and how many switches are set; report.txt, attached with the logs, lists them all. Test: tests/test_bug_report.py. Assisted-by: Claude Opus 5.5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thank you for both reviews. Everything is in the new head
The rebase: |
|
The after-crash case now works in the game, on a build of this head's code ( The second start's The folder, read back against the game folder's logs ( So the report's |
hckrman101
left a comment
There was a problem hiding this comment.
Thanks for the update, and for taking both of Joey-Magnus's reviews point by point (#2347 (review) and the follow-up). I read the new head and the discussion.
Conflict: resolved. GitHub reports the PR as mergeable now (14 commits behind main, no conflict in vk_menu.cpp, vk_replay.cpp or host/hos_main.c), so my earlier merge request is answered.
Joey-Magnus's points: all four look addressed in the code.
- The duplicate readback is gone:
vk_replay.cppis +2 lines, and the picture goes through #926'sshot_ask, so nothing swapchain-sized is kept. copy_lognow reads withfreadand splits on\nitself, with every count by length.make_dirreturns the system's reason (GetLastError()on Windows).- Switch values are written only when they cannot hold anything private, and the link carries only names.
The CONTRIBUTING.md question (should it mention the report's switch list) is still the maintainer's to answer.
Privacy / CONTRIBUTING.md: I checked what goes into the folder. It holds report.txt, the two logs and a screenshot of the game: no saves, no game files, no hookshot_options.ini or hookshot_env.txt. Logs and screenshots are allowed by CONTRIBUTING.md, and the home folder and user name are removed from the logs. The environment is filtered by name, with values mostly left out. Nothing sensitive beyond what an issue needs. The residual risk you list (a game folder outside the home named after a person, a machine name in a network path) is real but small, and the README help text states what is in the report.
Still open (blocks merging): CI. tests/test_bug_report.py fails on Windows (Python source checks, windows-2022, part 2/2):
bug report: the copy of a log with NUL bytes differs: b''
So on Windows the new NUL case (case 6) gets an empty hookshot_log.txt copy, while it passes on Linux with both compilers. Either the Windows copy really loses a log with NULs or the test reads it wrongly; please find out which, since the run before's log with NULs is the case this report exists for. It is the same case that fixes Joey-Magnus's fgets point, so I'd like to see it green on Windows. I could not run it on Windows to say why.
The other CI failures are not this PR's: test_env_on.py fails on HOS_FPS_LOG (host/oot_high_fps.c:16) (that file is not touched here, and it is as on main, from #2470), and test_psychov35.py and test_pcache_header_read.py are the known failures on main.
Nit (host/hos_main.c, the new map: block): memcpy(logged, line, sizeof logged) copies the 100 bytes of line including the ones after the terminator, which are uninitialized. strcpy/snprintf into logged would be cleaner.
So: COMMENT for now. Once the Windows test is green I'd be happy to approve; the design and the code otherwise look good to me.
…indows' null device Case 6 of tests/test_bug_report.py wrote its log as nul.log. On Windows NUL with any extension is the null device, so the write went nowhere and the report copied an empty log: "the copy of a log with NUL bytes differs: b''" in the Windows part 2/2 job, while Linux passed. The copy itself reads and writes in binary mode and counts by length on both systems. The log is power-cut.log now, and the test reads its own log back before it asks for the report, so a file that was not written as given fails with a message that says so. Also: the map line's last-logged copy in host/hos_main.c is made with snprintf, not a memcpy of the whole buffer with the bytes after the terminator (review nit). Assisted-by: Claude Fable 5.2 Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
|
@hckrman101 thanks. It is the test, not the copy, as far as I can tell without a Windows machine. The Windows failure. Case 6 named its log In I could not run it on Windows, so On Linux, with Nit. Taken: The other failures. #2575 is the one-line fix for |
|
The Windows job on Python source checks (windows-2022, part 2/2). The one failure left in that job is |
hckrman101
left a comment
There was a problem hiding this comment.
Both open points are fixed in f011b21.
- The Windows failure: you were right that it was the test.
nul.logis the null device on Windows, so nothing was written. The file is nowpower-cut.log, and the added read-back check will say so if a name ever does that again.tests/test_bug_report.pypasses on Windows part 2/2 now (and on Linux). - The
memcpynit: themap:block now usessnprintf(logged, sizeof logged, "%s", line), so no more fixed-size copy fromline.
The only red checks are tests/test_env_on.py (the HOS_FPS_LOG switch, being fixed by #2575), which fails on main too and is not from this PR. The earlier review's checks (conflict gone, Joey-Magnus's points fixed, privacy: report.txt, two logs and a screenshot with home folder and user name redacted and env values filtered) still hold. Good to merge.

What this is for: a player who meets a problem presses one row in the Insert menu, Gameplay → Bug report, and gets a folder with everything the game problem form asks for: the form's answers in
report.txt(version, the map he is in, graphics card and driver version, CPU, RAM and system, the options changed and the switches set), this run's log and the run before's (the crashed one after a restart) with his home folder and user name taken out, and a picture of the game. Maintainers get reports with the log and the hardware from the start instead of asking for them. What is measured: on Linux (Omarchy, an Arch Linux; RTX 4090, NVIDIA 615.78.08), onmainba6eef70: the new test passes with g++ 16 and clang 23 and fails onmain; its cases for the review's points (NUL bytes in a log, a picture that comes late, which switch values are written, the reason a folder cannot be made);tests/run_all.py; headless runs of this head that pressed the row (one pressed it in Kokiri Forest, one after akill -9and a restart: both reports written, read back by a script against the logs they came from (no file holds the home folder or the user name; each log copy is the original line for line apart from those two), the after-crash report'shookshot_log.1.txtis the killed start's whole log, and its picture came through #926'sshot_ask); the length GitHub takes for the link, signed out. Not measured: Windows at run time (compiled and linked only), a windowed run, the link opened in a browser (signed out or in), AMD and Intel drivers' strings, a Steam Deck.Refs #2346 (closed by the maintainer: tracked in this pull request).
Problem
.github/ISSUE_TEMPLATE/1-game-problem.yml) requires the version, where in the game, the graphics card and driver version, CPU, RAM and operating system, andhookshot_log.txt(andhookshot_log.1.txt"if you started the game again after the problem"). The player has to find each one by hand.hookshot_log.txtanswers only part of it: its first line has the version, but the driver is only Vulkan's packed number (vk: device 0: NVIDIA GeForce RTX 4090, Vulkan 1.4, driver 0x99d38200, type 2), there is no line for the system, the CPU or the options changed, and nothing logged where the player was (the host readsSequence_CurrentBanconly for the debug tools).hookshot_log.1.txt(host/hos_main.c, the rotation added because players sent the new run's log and the crash was gone). It still has to be found and attached.fs: mounted content: -> <home>/...,vk: pipeline cache <home>/...), which a player may not want to post.docs/workflow.mdscores such a report at confidence 0.4 and asks for the log first. This gathers what CONTRIBUTING.md already asks ("Include the version, your hardware, where you were andhookshot_log.txt"; "Report the version you actually ran: ... the first line ofhookshot_log.txt"). It changes nothing about where reports go.What changed
gpu/vk/vk_bug_report.h,vk_bug_report.cpp(new, 59 + 602 lines): the packer, without Vulkan and without the menu, so the test compiles it alone. It writesbug-reports/<YYYY-MM-DD_HH-MM-SS>/in the game folder on a thread of its own:report.txt: the form's questions under the form's own###headings, soscripts/hardware_report.py'ssection()reads it as an issue: Hookshot version (HOOKSHOT_VERSION, as the log's first line); Where in the game (the lastmap:line of this run's log, and the run before's, and a request to add what you were doing); Graphics card and driver version (the device andVkPhysicalDeviceDriverProperties'driverName+driverInfo, e.g.NVIDIA GeForce RTX 4090, NVIDIA 615.78.08); CPU, RAM and operating system (the CPU's brand string and threads, RAM,os-release, desktop and session type on Linux;RtlGetVersionand Wine on Windows); Changes from the defaults (each Insert-menu row not at its default as the menu shows it; a microphone chosen by its name is not named; then the switches set, below); hookshot_log.txt (what is attached, the run before's version and date, each log's firstFATAL,CRASHordevice lostline); Screenshots or video; then a link that opens the form with version, where, GPU, system and settings filled in (GitHub fills issue-form fields from query parameters named by the fields' ids).hookshot_env.txtamong the files never to share, so the report never copies it, and of the switches set (the nameshookshot_env.txttakes:RX_,HOS_,HOOKSHOT_,EDEN_,NVN_,SDL_; and what hooks other code in:VK_INSTANCE_LAYERS,MANGOHUD,ENABLE_VKBASALT,LD_PRELOAD...) it writes each name, and the value only when it cannot hold anything private: a number of at most 12 characters, a size such as1920x1080, or on/off, true/false, yes/no, and never for a name withTOKEN,KEY,ROOM,SECRET,PASS,SERVERorUSERin it. Every other value reads(value left out): paths, addresses, scripts. Other variables are not listed at all.hookshot_log.txt(this run's log up to the press) andhookshot_log.1.txt(the run before's; when this run logs elsewhere, e.g. from a terminal, the game folder'shookshot_log.txt). Read by length (fread, split on newlines), so NUL bytes, which a run ended by a power cut or a hard kill can leave, are copied as they are. Each line: the home folder (a whole folder; on Windows either slash and any case) becomes~or%USERPROFILE%, the user's name as a folder of any path<user>. A log over 10 MB keeps its first MB and its last 9 MB (GitHub takes files up to 25 MB).picture.png: 1280x720, the game's next frame, without the menu (below). If none comes within 3 s, the report goes without it and says so; a picture that comes later is deleted again.GetLastError()on Windows,errnoelsewhere).gpu/vk/vk_menu.cpp(+89): the row before Restart and Quit (kBugReportRow = kRestartRow - 1), its help (what goes in, that no saves or game files go in and nothing is sent), its value (Press to save / Saving... / Saved / Not saved), Save in both prompt lines (the full menu's and the compact bar's), the press,changed_rows_text()(rows against a default-constructedOptions),bug_report_save(), and the picture's ask,bug_report_picture(). It follows Save my pipeline list's pattern (feat: Save my pipeline list, the zip and filled-in report for the "Submit your pipelines" issue in one click #2447): its value inrow_value_cell, its line under the help indraw_optionsonce pressed (where the folder is and how to send it: File Explorer on Windows, a file manager on Linux; on a Steam Deck, Desktop Mode), and room for that line's longest form inmeasure_help. The game opens no browser or file manager: Game Mode on a Deck has neither.gpu/vk/vk_replay.cpp(+2):shot_ask_next(), which calls feat(control): drive a running game over a local socket, with a CLI #926'sshot_ask(path, -1, done, ctx)from outside its anonymous namespace (declared invk_internal.h). The report's picture is the control bridge's kind of shot: an image and a buffer of its own (1280x720, made at the first ask), copied fromsrc, the game's frame, which the menu is never drawn into (menu_record_imagedraws only into the screenshots' image), read back once the GPU is past it and written on a thread. No other line ofdo_presentchanges.gpu/vk/vk_main.cpp(+11),vk_internal.h(+6):device_report_text(), and the declaration above.host/hos_main.c(+12):map: <Sequence_CurrentBanc> (child|adult)when the map or the age changes, inoot_inventory_refresh(on Link's update, at most every 500 ms, where the age is already read for the Debug tab). It is where the report's place comes from, and it puts the place into every log. The names are the game's own map names, which the debug tools' teleport lines already print.readme.md: the row in the menu table, a paragraph on what it saves and which values it leaves out, a pointer from "If the problem continues".tests/test_bug_report.py(new), andtests/test_menu_tune.py: its check of the compact bar's prompt line now reads the line with the Bug report in it (the check is otherwise unchanged).hookshot_options.iniorhookshot_env.txtthemselves; no new option or switch; the logs' own rotation; the screenshot path.How to try it
Insert menu (Insert, F1 or Esc, or the menu button) → Gameplay → Bug report → Enter or A.
The row reads Saved and its help names the folder:
bug-reports/<date>_<time>in the game folder, withreport.txt,hookshot_log.txt,hookshot_log.1.txtandpicture.png.How it was tested
2026-11-11, after the two reviews, head
a75f3ca5onmainba6eef70. Rebased twice today: onto #926, then onto #2042, #2378, #2447 and the rest. The conflicts, each kept on both sides: #926'sshot_ask_recordbeside the old readback (which is now gone); #2042's Debug rows where the Bug report row goes before Restart; #2378'srow_value_cell()and #2447's share row, where the row's value cell and prompt went (the row now follows the share row's pattern, above); a forward declaration inhost/hos_main.c. #2042's rules hold for the row: it has no value, sopreset_exemptdoes not apply (tests/test_preset_exempt.pyreads only rows with one), and the branch reads no on/off switch. #2042 also tookTOTK_out of the nameshookshot_env.txttakes; the report follows (the test compares the two lists).Environment: Omarchy (an Arch Linux), kernel 7.2.15-1-omarchy, RTX 4090 with NVIDIA 615.78.08, i9-13900K, 94 GB, g++ 16.2.1 and clang 23.1.3.
The new test on the branch (
python -I -B tests/test_bug_report.py, with--cxx g++and with--cxx clang++; the same line from both):Against
main's source (the test copied into an export ofba6eef70; with both compilers): it fails at its first step, the menu row:And the review's NUL case against the old log copy (
fgetsandline.back(), put back on its own):It compiles
vk_bug_report.cppalone with a driver and writes reports from a made-up game folder inside a made-up home folder (.../home/alice/Games/Hookshot/), with paths of the home and of/run/media/alice/...in the logs, map lines and aCRASH:line in the run before's. It checks: the folder holds exactly the report, both logs and the picture; no file names the home folder, the user as a folder or the game folder's path (alice123andMalicestay);hardware_report.py'ssection,classifyandos_ofread the version,NVIDIA/RTX 40and Linux fromreport.txt; the place is the last map, and the run before's; the switches: values kept (HOS_HEADLESS=1,60,off,3840x2160,-1,1.5) and left out (a path, a drive path, a menu script, an IP address, ahost:port, a 13-digit number, and numbers under ROOM, KEY, SERVER, USER and PASSWORD names), none of those values anywhere inreport.txt,PATHand a token not listed, no%3Din the link; the run before's crash line; the link's fields and its length (with 98 switches: within 2000, the options and the count in it, every switch inreport.txt); the menu's way (a thread, one report at a time); no frame means no picture, said so; a picture that comes after the report went without it is deleted; a start from a terminal; two reports in one second; a 22 MB log cut to its first and last part with its middle's map still found; a log with a NUL in a line and 4 KB of NULs at its end copied byte for byte, the map after the NUL found; a folder that cannot be made, with the system's reason; the redaction's Windows cases (either slash, any case); this PC's system line. And the wiring by text: the row and what its help promises, Save in both prompt lines, the press, the picture asked ofshot_ask_nextand copied from the game's frame without the menu, the host'smap:line, that the switches it lists are the nameshookshot_env.txttakes (env_line_allowed's), the form's labels and ids. Eight runs at once at load 280 all pass (the first version of the menu's case read the report's state too late under load in the full suite; it now holds the report until it has looked).The checks the review named and those that read the menu's rows, on this head (with g++ and clang++ where they compile C++):
test_capture_dimensions.py,test_capture_slot_ownership.py,test_menu_env_overrides.py,test_menu_keys.py,test_pipeline_share.py,test_menu_tune.py,test_stick_dead_zone.py,test_preset_exempt.py(62 rows),test_menu_env_on.py,test_env_on.py,test_fps_stats.py,test_gpu_choice.py,test_menu_restart_slots.py,test_mouse_settings.py: all pass.vk_bug_report.cppalone with-Wall -Wextra -Wpedantic -Werror: no warning from either compiler.python -I -B tests/run_all.pyon Linux, on this head:The one failure is
test_recorder_sync.py, which ran out of its 600 s at load 250-320 (other work ran beside it) and touches nothing of this branch. An earlier run of the whole suite on this branch failedtest_bug_report.pyonce under that load: its menu case read the report's state too late (fixed in the test, above).Merged into the newest
main(fce53453, nine commits later; it merges cleanly):test_bug_report.py(both compilers),test_menu_tune.py,test_pipeline_share.py,test_menu_keys.py,test_menu_env_overrides.py,test_preset_exempt.py(63 rows),test_menu_restart_slots.py, both capture tests: pass.test_env_on.pyfails there and onfce53453alone (HOS_FPS_LOG (host/oot_high_fps.c:15), from fix(fps): keep sound and moving platforms working above a 60 fps cap #2470), not from this branch.Windows:
vk_bug_report.cppwith a small driver compiles and links for x86_64-w64-mingw32 (clang 23 with llvm-mingw 20261104's headers and libraries,-Wall -Wextra -Werror: a PE32+ console executable). Not run.In the game, on a build of this head's code (
v2.1.0-rc.3-177-g9c538c91 (source c4f2afbc); the head differs only in two test files), headless, RTX 4090,RX_VK_PRECOMPILE=0(shaders compiled when first used), load 200 to 320 (other work ran beside it), the save loaded into Kokiri Forest and the menu script pressing Gameplay → Bug report:bug-reports/2026-11-11_16-58-06: report.txt and both logs, no picture, and it says so. Rightly: the game showed no frame from 39 s to 107 s (the save loading, shaders compiled as they came, at load 300), took the scripted keys when frames came again, and stopped once more at 109 skill -9after 110 s, then a second start; the row pressed 63 s after its first framebug-reports/2026-11-11_17-13-48: report.txt, both logs (hookshot_log.1.txtis the killed start's whole log), picture.png (present 1772)bug-reports/2026-11-11_17-25-32: report.txt, both logs, picture.png (present 3063, 138 s)Its folder read back against the game folder's logs (
check_report.py: each copy compared line by line with its original, with the home folder and the user name replaced as the game does):br-menu2's and br-menu3's folders pass the same check (1387 of 1571 and 3230 of 3230 lines; 2861 of 3679 and 3230 of 3230 lines; only the home folder and the user name replaced). A picture's pixel data is not read as text: br-menu3's picture.png has the bytes
4d 4f 4f 4b 49among its pixels (row 176), which an any-case byte search reads as a name; the PNG holds only IHDR, IDAT and IEND chunks. The host name is in no text file of either.Pictures (headless, 1280x720; the first two are the harness's shots with the menu drawn in, the third the report's own file):
bug-reports/2026-11-11_17-25-32) and how to send it.picture.png, taken throughshot_askat present 3063: child Link and Navi on the path in Kokiri Forest, hearts and minimap; no menu, not dimmed.kill -9and the restart: Saved, the folderbug-reports/2026-11-11_17-13-48under the help.picture.png(present 1772): Kokiri Forest from low down, facing the bright sky, hearts and minimap; no menu.The
report.txtthe after-crash run wrote, as a player would attach it (the switches are the test harness's: see which values are written and which are left out):The report.txt that run wrote
return_to%20return_to%20%20%20return_todropped (the answers lost)xxxNot tested
VkPhysicalDeviceDriverPropertieson a Windows driver), its CPU, RAM and system line (__cpuid,GlobalMemoryStatusEx,RtlGetVersion, Wine), the path of the log stderr writes to (GetFinalPathNameByHandleA),GetLastError's reason, the redaction of realC:\Users\...logs, File Explorer: compiled and linked only.curlsigned out (table above). That GitHub fills the form's fields from it is its documented behaviour, not seen here.kill -9, which leaves noCRASH:line, and under that load the first start had not reached a map yet; the test covers theCRASH:line and the run before's map with made-up logs.driverName/driverInfotext (only NVIDIA's was read;hardware_report.pyclassifies typical RADV, AMD and Intel strings correctly when written by hand), a Steam Deck, the AppImage, and the Linux Builder's Play button (since fix(builder): Linux Play leaves the game its hookshot_log.txt again #2279 it gives the game itshookshot_log.txtagain, so the report finds this run's log there; not run here).Risks
alice123kept, values kept and left out) and, on this machine's real logs, by the read-back above. Not guarded: something private a log line carries in another form (a game folder outside the home named after a person, a machine name in a network path), or a future switch whose secret is a short number under a name without those words./etc/os-release, the device's properties, the menu's rows); copying the logs and writing the folder run on a thread of their own, one report at a time (a second press while it saves does nothing). This run's log is copied as far as it was when the copy began. The picture is waited for at most 3 s.vk: present N written to ... (the control bridge)).map:line in every log. It is written only when the map or Link's age changes, fromoot_inventory_refresh(at most every 500 ms, where the age is already read). A log that a player posts now says where he was; the names are the game's own map names, which the debug tools' teleport lines already print.hookshot_log.1.txtby hand then.Overlaps
pr_overlap.py --branch bug-report(run on this head, 2026-11-11): 79 open pull requests touch one of these files; 73 merge cleanly with it. The row stores nothing (noOptionsfield, no ini key, no option id), so no option id can clash. Six conflict in this branch's files, each hunk read:i18n::tr(...), among them the lines ofmeasure_help,row_value_cell's branch for rows without a value, the help line indraw_optionsand the compact bar's prompt (and the same line intests/test_menu_tune.py), where this branch adds the Bug report beside the share row. Whichever lands second wraps the Bug report's texts the same way; both stay.logs/) now merges cleanly, but overlaps in meaning: this branch finds the game folder throughini_path()and the logs in the game folder; after feat(paths): saves and settings in a per-user data folder, caches and logs in the game folder's cache/ and logs/ #2317 the settings are in the data folder and the logs inlogs/. Whichever lands second moves those two reads togame_folder()andlog_path().Questions for you
logs/could be)?hookshot_env.txt(names, and only harmless values). Should CONTRIBUTING.md say so, next to the line that lists the file?report.txtto copy from?Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com