Docs / For developers
Diagnostics and problem reports
Two ways users feed results back, both without a GitHub token:
- Share working recipe… (game menu,
frameport share-recipe <pkg>): saves the recipe as a user catalog entry and opens a prefilled issue from.github/ISSUE_TEMPLATE/working-config.yml. A maintainer checks it and adds the labelcatalog-accepted. Then.github/workflows/catalog-from-issue.ymlrunsscripts/catalog_from_issue.py, which reads only the YAML block, validates it, and writescatalog/games/<pkg>.yaml, and the workflow opens a PR.- The PR step needs Settings → Actions → "Allow GitHub Actions to create and approve pull requests".
- Create the labels
working-config,catalog-acceptedandbugonce.
- Report a problem… / Collect logs (game menu, Settings, the failure pop-up,
frameport diag report|collect): writes a redacted zip and opens a prefilledbug-report.ymlissue.- GitHub has no API for issue attachments, so the user drags the zip in (25 MB max; the bundle stays under 24 MB).
- Prefilled links are capped at about 7.5k characters. Free text is trimmed first; the recipe is never cut.
Code: src/frameport/diag/ (redact.py, bundle.py, issue.py), agent command collect_diag (agent ≥ 21),
Target.collect_diag, core/applog.py (app log + saved job logs).
#Bundle layout (schema 1)
README.md what's where (for whoever opens it)
manifest.json versions (app, agent, tools, SteamOS build, Proton), games, warnings, redaction counts
app/app.log the app's log (<data>/logs/app.log, rotated 2 MB × 3)
app/jobs/*.log saved GUI job logs (<data>/logs/jobs, last 30): build, install, test, ...
app/settings.json library settings, catalog sources
frame/info.json agent `info` (SteamOS build, Lepton, Proton, installed games, kernel keys)
frame/host.json OpenXR runtime + explicit layers, podman containers, containers.conf, uptime
frame/XRService-*.log the Frame's OpenXR runtime (SteamVR XRService) log, newest
games/<pkg>/entry.json library entry: analysis, recipe, build checks, installs, last_test (store text dropped)
games/<pkg>/recipe.yaml the recipe in catalog form; catalog-<origin>.yaml = the catalog entry it came from
games/<pkg>/triage.json newest local launch log re-triaged with the bundling app's signatures
games/<pkg>/logs/*.log launch-test logs kept on the PC (last 5)
games/<pkg>/package/ stand-in for the game files (no content):
apk_files.json every APK entry + size
AndroidManifest.xml decoded manifest
elf.json per lib/*.so: DT_NEEDED, ovr*/xr*/vrapi_/gl*/JNI exports + imports
files.json, pe.json Rift: file list; PE imports / delay imports of the exe and VR DLLs
games/<pkg>/target/ from the Frame (or the PC): launch.sh, settings.conf, deployment.json, launch.log,
launch-test.log (PC VR), lepton-steamlaunch-<appid>.log, logcat-{main,crash,system,...}.log,
ReviveInjector.txt / steam-<appid>.log / game-log-N.txt (PC VR), files.json (+ missing)
(game-log-N.txt: Unreal Saved/Logs + crash summaries, Unity Player.log / Player-prev.log /
output_log.txt + crash error.log from the Proton prefix, agent v67)
games/<pkg>/target/shaders/ shader dumps (agent v72), when the game wrote any:
fp_vk_shaders/ adapter vk_shader_dump=1 (Vulkan shim): <size>_<sha256>.spv + index.txt
fp_spirv/ adapter zink_shader_dump=1 (OpenGL ES, shader-fix layer under Zink): <size>_<sha256>.spv
Each log keeps at most its last 4 MB (2 MB per file from the Frame). Shader dumps, SPIR-V unchanged (compiled game
shaders, not redacted): Vulkan (agent v74) every module the game's newest run (the last # start in index.txt)
created, last used first, each up to 4 MB and up to 30 MB in all, with that run's index lines, so a module created
well before a GPU hang comes along too (if the zip would pass 24 MB, the least recently used ones are left out
after the logs were cut); OpenGL ES (no index): the newest modules (by time written) up to 4 MB.
index.txt (Vulkan) lists every vkCreateShaderModule as
<seq> <ms since the first module> <unix ms> <size>_<sha256>.spv new|known|again|failed; match the unix time with
the kernel's hangcheck detected gpu lockup line (this-boot-kernel.txt). All modules stay in the game's storage on
the Frame (Android/data/<pkg>/files/fp_vk_shaders/, Files tab → the game's storage).
#Redaction
diag/redact.py runs on every file and on the issue text.
- Exact values: the data dir →
<data>, home dirs →<home>, user names →<user>, PC and Frame host names and saved Frame addresses →<host>, Steam account ids from the Frame'sinfoand the PC's Steam →<steam-id>, the folders holding the user's game dumps →<source>. - Patterns: IPv4 addresses (first octet ≥ 10, so version numbers survive), IPv6, MAC, SteamID64,
userdata/<id>, email addresses (file names likex@123.txtexcluded), and any/home/<u>,/Users/<u>,C:\Users\<u>or/mnt/c/Users/<u>. - Kept: generic accounts that identify no one:
steamos,steamuser(Proton),root,deck.
#Debugging from a bundle (no game, no Frame, no GUI)
frameport diag inspect <zip>(--jsonfor everything). It prints the versions and warnings, the last launch test, and a fresh triage of the newest launch log with the currentcatalog/triage.yaml.- Match the findings and log lines against
docs/PLAYBOOK.md(symptom → cause → fix) anddocs/FRAME_RUNTIME.md. - Check the analysis in
entry.json(engine, XR API,extra: missing ovr symbols, features, Unreal version) andpackage/elf.jsonagainst the heuristics in CLAUDE.md. Comparerecipe.yamlwith catalog games that use the same engine and API. - Compare
manifest.json → env.frame.build_idwith the build the docs describe: SteamOS updates change the runtime. - A new failure signature means adding a patch module, a
triage.yamlsignature, a PLAYBOOK row and a unit test (see Conventions). Thendiag inspecton the same zip should report it.